;            プログラム名　   BCI_v3.asm
;       ２０１４年　４月２６日　開始  ４月３０日一応完成
;　　　沢山バグがあった。１０月に修正を行う。特に赤字の部分
;母プログラムは「 BCI_v1.asm」
;（１）ハード的に、サンプル＆ホールド素子を用いることにしたので、Ｄ／Ａ出力回路は不要となっている。
;（２）モニター用ゲートパルス出力波形を反転させる
;（３）サンプル＆ホールド素子用ゲートパルスは数μ秒とし、ＰＯＲＴＢ２を使用する。
;
  LIST P=PIC18F452       ;使用するプロセッサを指定する
  #INCLUDE "P18F452.INC" ;上記プロセッサのためのインクルードファイルを
                         ;呼び出し結合する
;ＰＩＣの初期設定 　　詳細はデータシートのコンフィグレーション・ビットの項を参考すること
                    ;機能の使用、変更を考えていないビットは初期値にしておく
   __CONFIG  H'300001', b'11111110'  ;高速クリスタル、ＰＬＬ発振モード。４倍発振
   __CONFIG  H'300002', b'00001111'  ;ブラウンアウト電圧＝２．５V、　ブラウンアウト＝可
                                     ;パワーアップタイマー＝不可
   __CONFIG  H'300003', b'00000000'  ;ウオッチドックタイマー＝不可
   __CONFIG  H'300005', b'00000001'  ;
   __CONFIG  H'300006', b'10000001'  ;ｂ２＝０で、MCLRの機能を使用可とする
   __CONFIG  H'300008', b'00001111'  ;
   __CONFIG  H'300009', b'11000000'  ;
   __CONFIG  H'30000A', b'00001111'  ;
   __CONFIG  H'30000B', b'11100000'  ;
   __CONFIG  H'30000C', b'00001111'  ;
   __CONFIG  H'30000D', b'01000000'  ;

;ＬＣＤに文を表示するためのマクロ命令の定義
messege  macro  number,title     ;表示文字数、表示文
       local   loop
       clrf    current
       incf    number            ;ｎｕｍｂｅｒ＋１とする
loop  
       movlw   UPPER title       ;サブルーチン　ｔｉｔｌｅのプログラム中
       movwf   TBLPTRU           ;アドレス番地を
       movlw   HIGH title        ;テーブルポインターレジスタ
       movwf   TBLPTRH           ; ＴＢＬＲＰＴＲ群に渡す。
       movlw   LOW title         ;ここでの記述方法だとルックアップテーブルが
       movwf   TBLPTRL           ;メモリアドレスがどこにあっても良い
    
       movff   current,WREG      ;
       rlncf   WREG,1            ;×２倍とする

       addwf   TBLPTRL,1         ;テーブルアドレスポインタレジスタ群
       clrf    WREG              ;ＴＢＬＰＴＲ群を＋１する
       addwfc  TBLPTRH,1         ;
       addwfc  TBLPTRU,1         ;
       TBLRD   *+                ;ポインタで指定したデータをＴＡＢＬＡＴに引き渡し、

       movff   TABLAT,lcd_data   ;ＬＣＤへ出力
       call    lcd_sigout        ;ＬＣＤへ書き込み
       incf    current,1         ;currentを＋１する
       decfsz  number,1          ;numberを－１し、結果が０の時、
       goto    loop              ;下の命令をスキップ      
       endm

;********************************************************************************** 
;********************************************************************************** 
　           ;org  h'0000'
;変数、配列の宣言
CBLOCK    h'000'
 number:8  ;res  8       ;キーパットの数値文字コードを処理して得られた真の数値コードの
                     ;納まる連続した８バイト（８桁分）の配列変数
 char:9    ;res  9       ;キーパット用変数
 xsign   ;res  1       ;第１，０ビットに、先行数値の仮数符号と指数符号が納まる。
 xfig:8    ;res  8       ;先行数値の仮数が納まる。８桁分用意する。
 xexp    ;res  1       ;先行数値の指数値が納まる
 ysign   ;res  1       ;第１，０ビットに、後行数値の仮数符号と指数符号が納まる。
 yfig:8    ;res  8       ;後行数値の仮数が納まる。８桁分用意する。
 yexp    ;res  1       ;後行数値の指数値が納まる
 csign   ;res  1       ;
 cfig:8    ;res  8       ;
 cexp    ;res  1       ;

 value_set          ;設定画面の種類を決める。＝１はプリスケーラ値 
 mode               ;１＝スタート、２＝ストップ、３＝リセット
 k_status           ;(k_status,0)ビット＝ｐａｕｓｅ＝０でポーズを解除、＝１でポーズさせる

 counter_H          ;
 counter_L          ;

 repeat_num         ;固定値の繰り返し回数を納める。２の倍数とする。初期値＝２としておく 
 repeat             ;上記の繰り返し回数の変数を納める  

 u_d_counter     ;res  1  ;メニュー画面で行番号が納まる
 r_l_counter     ;res  1  ;メニュー画面で左右への移動量が納まる。
 cursor_address  ;res  1  ;カーソル座標値
 select_char     ;res  1  ;選択した数値、文字が納まる
ENDC

     CBLOCK h'0070'   ;このディレクチブと下のENDCの間に使用する変数名を定義できる
                      ;数値は使用するプロセッサの一般目的レジスタの開始番地とする
;ＬＣＤ出力用変数
          temp0       ;一時的カウンタ変数
          temp1       ;
          temp2       ;
          temp3       ;
          counter     ;表示した文字数のカウンタ変数
          counter1    ;
          counter2    ; 
          current     ;一時変数
          charnum     ;表示する文字数を入れる
     ENDC

;********************************************************************************** 
;********************************************************************************** 
;クロスキー入力用の各Ｉ／Ｏポートの割り当て。
#define   center    PORTB,0    ;ポートにラベル名を付ける。
#define   up        PORTB,5    ;
#define   down      PORTB,4    ;
#define   right     PORTB,7    ;
#define   left      PORTB,6    ;ポートにラベル名を付ける。

;ＬＣＤの制御用Ｉ／Ｏポートの割り当て、および命名。
#define   contl_E   PORTA,5    ;０=ＬＣＤ不動作、    １=ＬＣＤ動作
#define   contl_RW  PORTB,1    ;０=ＬＣＤへ書き込み　１=ＬＣＤから読み出し
#define   contl_RS  PORTA,3    ;０=命令、            １=記号／バイト

;モニターLED駆動端子に名称を付ける
#define   monitor   PORTA,2    ;

;トリガー入力端子の名称
#define   trig_in   PORTA,1    ;

;モニター用ゲートパルス出力端子に名前を付ける
#define   Gate_out  PORTB,3

;サンプル＆ホールド素子用ゲートパルス出力端子に名前を付ける
#define   Sample_out  PORTB,2

;ＬＣＤのデータ用Ｉ／Ｏポートの割り当て。
#define   lcd_data  PORTC      ;Ｃポートにラベル名を付ける。

;DA出力ポートの名称
#define   AD_H2bit  PORTE      ;ＡＤ変換値の高位２ビットの出力ポート。ＲＥ２は遊びとする
#define   AD_L8bit  PORTD      ;ＡＤ変換値の低位８ビットの出力ポート。

;その他
#define   pause     k_status,0 ;(k_status,0)ビット＝ｐａｕｓｅ＝０でポーズを解除、＝１でポーズ

;
;ＬＣＤに転送する各命令のコードの定義
;使用するＬＣＤのテクニカルノートを参照すること
;                                ２進数　　　　　処理
clear     equ   1              ; 00000001　　表示をクリア
home      equ   2              ; 00000010　　カーソルをホームへ
shift_l   equ   24             ; 00011000　　表示を左へ移動
shift_r   equ   28             ; 00011100　　表示を右へ移動
crsr_l    equ   16             ; 00010000　　カーソルを左へ移動
crsr_r    equ   20             ; 00010100　　カーソルを右へ移動
crsr_e    equ   32             ; 00100000　　ファンクションをセット
blink_c   equ   11             ; 00001011　　表示オフ、カーソルオン、ブリンクオン
no_crsr   equ   8              ; 00001000　　表示オフ、カーソルオフ、ブリンクオフ
ret_bak   equ   192            ; 11000000　　改行とリターン

;*********************************************************************************
;
          org   0              ;スタートアドレス０番地
          goto  start
 
;*********************************************************************************
;割り込み処理
;遅延時間カウンターであるタイマー０はオーバーフロー機能を利用するが、その割り込み機能は使わない
;割り込み機能はポートＢの状態変化でのみ使用する。
;クロスキーに接続しているＲＢ４，５，６，７ポートの状態変化割り込みを利用する
;
          org   h'0008'         ;ＰＩＣ１８Ｆ４５２の割り込みアドレス
handler
       bcf    T0CON,TMR0ON      ;タイマー０一時停止

hand_loop
      ;Down Key, Up Key の立ち上がり割り込み。どちらのキーがＨレベルになったかを確定する

hand_next10 
       btfss  down
       goto   hand_next20           ;
       goto   hand_next30
hand_next20
       btfss  up                    ;
       goto   hand_next10           ;確定していない。再確認させる    
       goto   hand_next50           ;  
hand_next30                         ;Down key が押された。
       call   wait_exe              ;キーのチャッタリング防止に代用する待ち時間
       bcf    INTCON,RBIF           ;Ｂポートフラッグのクリア
       bsf    T0CON,TMR0ON          ;タイマー再解
       goto   menu1_plane           ;
hand_next50                         ;Up Key が押された。
       call   wait_exe              ;キーのチャッタリング防止に代用する待ち時間
       bcf    INTCON,RBIF           ;Ｂポートフラッグのクリア
       bsf    T0CON,TMR0ON          ;タイマー再解

       ;goto   prescaler             ;遅延時間設定画面へ行く

       call   prescaler_set_plane   ;プリスケーラ値の設定画面を呼び出す
                                    ;画面上でプリスケール値の設定が終わった
       call   recont_1              ;(T0PS2,T0PS1,T0PS0) の値を組み上げる
       btfss  center                ;センターキーが押されるまで、ここで待機。        
       goto   hand_loop             ;
       call   wait_exe              ;キーのチャッタリング防止に代用する待ち時間
 
    ;ＬＣＤ画面に実行中、その他の表示をしておく
       call    clear_out            ;画面のクリア
       call    home_out             ;カーソルをホームへ
       call    first_column         ;
       call    Execute_menu_LCD     ;
       call    second_column
       call    Change_menu_LCD
       call    third_column         ;
       call    Reset2_menu_LCD       ;
       call    fourth_column        ;
       call    End_menu_LCD         ;
 
       bcf     INTCON,RBIF          ;Ｂポートフラッグのクリア
       bsf     T0CON,TMR0ON         ;タイマー再解

       retfie           ;return     ;厳重注意　時には、retfie の使用では不調を来す。理由は不明。

;*********** スタート ************************************************************
start
  ;ポートの初期設定  
      call  port_initial

  ;ＬＣＤの初期設定   
      call  lcd_warmup      ;ＬＣＤが安定するまで待機。　約１秒
      call  LCD_initial

  ;初期値の設定
      movlw  2  ;10  ;50    ;１箇所でのサンプリングの繰り返し回数。
      movwf  repeat_num     ;これによりパルスの送りを遅くできる。
      clrf   PORTB          ;
      clrf   pause          ;

  ;タイマー０の設定
      movlw  b'00000000'    ;
      movwf  T0CON          ;T0CON=(TMR0ON,T08BIT,T0CS,T0SE,PSA,T0PS2,T0PS1,T0PS0)
                            ;カウンタの動作選択　　TMR0ON＝１　可動  　＝０　停止
                            ;カウンタの選択　　　　T08BIT＝１　８ビット  　＝０　１６ビット
                            ;クロックの選択　　　　T0CS＝１　外部クロック　  ＝０　内部クロック
                            ;クロックエッジの選択　T0SE＝１　Ｈ→Ｌ　  ＝０　Ｌ→Ｈ
                            ;プリスケーラの選択　　PSA＝１　未使用　   ＝０　使用
                            ;プリスケール値の選択　(T0PS2,T0PS1,T0PS0)
                            ; (1,1,1)=1:256  から   (0,0,0)=1:2
                            ; (0,1,1)=1:16
  ;メニュー画面１を表示し、パルス送り速度を選択させる 
menu1_plane
      call  clear_out        ;画面のクリア
      call  home_out         ;カーソルをホームへ
      call  first_column
      call  title1_LCD       ;研究室名を表示
      call  second_column
      call  resolu_LCD
      call  third_column
      call  high_LCD 
      call  fourth_column
      call  low_LCD

menu1_loop
      btfsc  center  
      goto   menu1_next50    ;センターキー又はダウンキーが押されるまで待機。
      btfsc  down
      goto   menu1_next30
      goto   menu1_loop
menu1_next30
      bsf    T0CON,T0CS      ;タイマー０のクロックとして、外部を指定。
      goto   menu1_next70
menu1_next50                 ; 
      bcf    T0CON,T0CS      ;タイマー０のクロックは、内部のままとする。 
menu1_next70

prescaler
      call   wait_exe              ;キーのチャッタリング防止に代用する待ち時間
      call   prescaler_set_plane   ;プリスケーラ値の設定画面を呼び出す
                                   ;画面上でプリスケール値の設定が終わった
      call   recont_1              ;(T0PS2,T0PS1,T0PS0) の値を組み上げる
      movff  repeat_num,repeat ;選択値の引き渡し

  ;ジョブ選択画面を表示し、選択させる
      call   job_select
      call   wait_1sec       ;サンプリング開始までの待機時間

  ;遅延時間カウンターであるタイマー０はオーバーフロー機能を利用するが、割り込み機能は使わない
  ;ゲートパルス確定から、次のトリガーパルス入力までの間にポートＢの割り込み機能を使う。
test_loop
      movlw  b'11111111'       ;
      movwf  counter_H         ;
      movff  counter_H,TMR0H   ;
      movlw  b'11111111'       ;
      movwf  counter_L         ;
      movff  counter_L,TMR0L

;********************************************************************************
;********************************************************************************
;以下が主文である。トリガー信号が入力するたび、ゲート信号を少しずつ送らせ、
;信号をサンプリングする
trigger_wait
           btfss  trig_in           ;Hレベルのトリガー信号が来るまで待機
           goto   trigger_wait

           bcf    monitor           ;
           bsf    Gate_out          ;

           movff  counter_H,TMR0H   ;
           movff  counter_L,TMR0L   ;

           bcf    INTCON,TMR0IF     ;フラッグをクリアする。  
           bsf    T0CON,TMR0ON      ;タイマースタート
timer0_wait
           btfss  INTCON,TMR0IF     ;タイマーがオーバーフローすると、このビットがＨとなる
           goto   timer0_wait
           bcf    T0CON,TMR0ON      ;カウンタ停止

           bsf    monitor           ;ゲートパルスが、Ｌレベルとなる。
           bcf    Gate_out          ;

           bsf    Sample_out       ;サンプリング開始
           nop
           nop
           nop
           nop
           nop
           nop
           nop 
           nop
           nop
           nop
           nop
           nop
           nop
           nop 
           bcf    Sample_out       ;データをホールド      

    ;入力信号電圧値をＡＤで読み出す。使用端子はＡＮ０
           bsf    ADCON0,GO      ;ＡＤ変換を開始させる
start_next10
           btfsc  ADCON0,GO      ;GO/DONE が０になるまで待機
           goto   start_next10   ;ＡＤ変換が完了すると０となる
                                 ;ＡＤ変換値を１０ビットＲ－２Ｒに出力する。
           movf   ADRESH,0       ;ＡＤ変換結果の高位２ビットを
           movwf  AD_H2bit       ;AD_H2bitに代入し、DA変換器から出力。
           movf   ADRESL,0       ;ＡＤ変換結果の低位８ビットを
           movwf  AD_L8bit       ;AD_L8bitに代入し、DA変換器から出力。

      ;ここから、次のトリガーパルスが入力する間に、ポートＢの割り込みを可とする
      ;ＬＣＤ画面での処理を可能とする。
           movlw   b'11001000'       ;INTCON=(GIE/GIEH,PEIE/GIEL,TMR0IE,INT0IE,
           movwf   INTCON            ;                    RBIE,TMR0IF,INT0IF,RBIF)

      ;センターキーが押されたときには、ゲート送りを中止させる。ポーズ状態とする。
      ;再び、センターキーが押されたならば、ゲート送りを再開させる。
      ; pause ＝０でポーズを解除（初期値）、＝１でポーズさせる
           btfss  center            ;
           goto   start_next50      ;センターキーが押されていない。
           call   wait_exe          ;センターキーが押された。チャッタリング防止待ち時間

           btfss  pause             ;pause=1の状態で、Ｃ　ｋｅｙが押された。ポーズ解除
           goto   start_next30      ;pause=0の状態で、Ｃ　ｋｅｙが押された。ポーズ実行
           bcf    pause             ;pause=0として、
           goto   start_next50      ;遅延実行に戻す
start_next30
           bsf    pause             ;pause=1として、ポーズ実行
           goto   trigger_wait      ;ポーズである。プリセット値は変更しない          
start_next50
           btfsc  pause             ;pause=1である。
           goto   trigger_wait      ;ポーズである。プリセット値は変更しない

           decfsz repeat,1          ;
           goto   trigger_wait
           call   two_byte_counter  ;プリセット値を－１
           goto   trigger_wait

;******************************************************************************
;******************************************************************************
two_byte_counter
      decf   counter_L,1       ;
      btfsc  STATUS,C          ;
      goto   t_b_c_next20
      decf   counter_H,1       ;
      movff  counter_H,TMR0H   ;
      movlw  b'11111111'       ;
      movwf  counter_L         ;
      movff  counter_L,TMR0L   ;
      movff  repeat_num,repeat ;
      return

t_b_c_next20
      movff  counter_L,TMR0L   ;
      movff  repeat_num,repeat ;
      return

;****************************************************
;ＬＣＤ画面上でプリスケール値の設定が終わった。
;(value_set,r_l_counter,u_d_counter)　から (T0PS2,T0PS1,T0PS0,repeat) の値を組み上げる
;        1    1,2,3,4,5       2,3
;ＬＣＤ画面上で、
;　　　r_l_c　　１　　　２　　　３　　　４　　　５
;u_d_c
;　２　　　   ６４　１２８　２５６　５１２　　１Ｋ
;　３　　　   ２Ｋ　　４Ｋ　　８Ｋ　１６Ｋ　３２Ｋ　
;                   Push  U D R L Key→C K

recont_1
       movlw  1            ;
       cpfseq value_set    ; 
       goto   re_1_end

    ;ＬＣＤ画面の２行目の値の選択処理
       movlw  2
       cpfseq u_d_counter  ;
       goto   re_1_next50

       movlw  1
       cpfseq r_l_counter
       goto   re_1_next10
       bsf    T0CON,T0PS2        ;r_l_counter=1,u_d_counter=2である。、１：６４の場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(1,0,1) 
       bsf    T0CON,T0PS0        ;
  　　 movlw  16
       movwf  repeat_num
       goto   re_1_end
re_1_next10
       movlw  2
       cpfseq r_l_counter
       goto   re_1_next20
       bsf    T0CON,T0PS2        ;r_l_counter=2,u_d_counter=2である。、１：１２８の場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(1,0,1) 
       bsf    T0CON,T0PS0        ;
       movlw  32
       movwf  repeat_num
goto   re_1_end      
re_1_next20 
       movlw  3
       cpfseq r_l_counter
       goto   re_1_next30        ;
       bsf    T0CON,T0PS2        ;r_l_counter=3,u_d_counter=2である。、１：２５６の場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(1,0,1) 
       bsf    T0CON,T0PS0        ;
       movlw  64
       movwf  repeat_num
goto   re_1_end     
  
re_1_next30
       movlw  4
       cpfseq r_l_counter
       goto   re_1_next40
       bsf    T0CON,T0PS2        ;r_l_counter=4,u_d_counter=2である。、１：５１２の場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(1,0,1) 
       bsf    T0CON,T0PS0        ;
       movlw  128
       movwf  repeat_num
       goto   re_1_end      
re_1_next40 
       movlw  5
       cpfseq r_l_counter
       goto   re_1_end               ;r_l_counterの値は５までなので
       bsf    T0CON,T0PS2        ;r_l_counter=5,u_d_counter=2である。、１：１ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(1,0,1) 
       bsf    T0CON,T0PS0        ;
       movlw  256
       movwf  repeat_num
       goto   re_1_end       

re_1_next50
    ;ＬＣＤ画面の３行目の値の選択処理
       movlw  3
       cpfseq u_d_counter  ;
       goto   re_1_end

       movlw  1
       cpfseq r_l_counter
       goto   re_1_next60
       bcf    T0CON,T0PS2        ;r_l_counter=1,u_d_counter=3である。、１：２ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(0,0,0) 
       bcf    T0CON,T0PS0        ;
       movlw  16
       movwf  repeat_num
       goto   re_1_end
re_1_next60
       movlw  2
       cpfseq r_l_counter
       goto   re_1_next70
       bcf    T0CON,T0PS2        ;r_l_counter=2,u_d_counter=3である。、１：４ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(0,0,0) 
       bcf    T0CON,T0PS0        ;
       movlw  32
       movwf  repeat_num
       goto   re_1_end      
re_1_next70 
       movlw  3
       cpfseq r_l_counter
       goto   re_1_next80        ;
       bcf    T0CON,T0PS2        ;r_l_counter=3,u_d_counter=3である。、１：８ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(0,0,0) 
       bcf    T0CON,T0PS0        ;
       movlw  64
       movwf  repeat_num
       goto   re_1_end       
re_1_next80
       movlw  4
       cpfseq r_l_counter
       goto   re_1_next90
       bcf    T0CON,T0PS2        ;r_l_counter=4,u_d_counter=3である。、１：１６ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(0,0,0) 
       bcf    T0CON,T0PS0        ;
       movlw  128
       movwf  repeat_num
       goto   re_1_end      
re_1_next90 
       movlw  5
       cpfseq r_l_counter
       goto   re_1_end           ;r_l_counterの値は５までなので
       bcf    T0CON,T0PS2        ;r_l_counter=5,u_d_counter=3である。、１：３２ｋの場合である  
       bcf    T0CON,T0PS1        ;(T0PS2,T0PS1,T0PS0) =(0,0,0) 
       bcf    T0CON,T0PS0        ;
       movlw  255
       movwf  repeat_num
       goto   re_1_end       

re_1_end

      return

;****************************************************
;実効画面の表示
job_select
       call    clear_out           ;画面のクリア
       call    home_out            ;カーソルをホームへ

       call    first_column        ;
       call    Start_menu_LCD      ;
       call    second_column       ;
       call    pushC_menu_LCD      ;
       call    third_column        ;
       call    Reset_menu_LCD      ;
       call    fourth_column       ;
       call    pushU_menu_LCD      ;

      ;Ｃｅｎｔｅｒ　Ｋｅｙ、Ｕｐ　ｋｅｙが押されたかの検査
job_sel_wait
       btfss   center
       goto    job_sel_next20
       goto    center2_push   ;実行中画面へ行く
job_sel_next20
       btfss   up
       goto    job_sel_wait   ;キーが押されるまで待機

       call   prescaler_set_plane   ;プリスケーラ値の設定画面を呼び出す
                                    ;画面上でプリスケール値の設定が終わった
       call   recont_1              ;(T0PS2,T0PS1,T0PS0) の値を組み上げる

      ;クロスキーが押されたかどうかの検査。
      ;アップ、ダウン、センターキーを監視する
menu2_loop                
       btfss   down           ;
       goto    m2next10
       goto    down2_push     ;ダウンキーが押された。
m2next10
       btfss   up
       goto    m2next20
       goto    up2_push       ;アップキーが押された。
m2next20
       btfss   center  
       goto    menu2_loop     ;未だどのキーも押されていない。押されるまでエンドレス。
       goto    center2_push   ;センターキーが押された。

down2_push
       incf    u_d_counter,1  ;ダウンキーが押された。アップダウンカウンタを＋１する
       movlw   4              ;
       cpfsgt  u_d_counter    ;u_d_counter>4
       goto    m2next100
       decf    u_d_counter,1  ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＜＝４に制限
       goto    m2next100
up2_push
       decf    u_d_counter,1  ;アップキーが押された。アップダウンカウンタを－１する
       movlw   1              ;
       cpfslt  u_d_counter    ;u_d_counter<1
       goto    m2next100
       incf    u_d_counter,1  ;1<=u_d_counterに制限
       goto    m2next100

m2next100   
       call   wait_exe       ;キーのチャッタリング防止に代用する待ち時間
       movlw  2              ;
       cpfseq u_d_counter    ;
       goto   m2next110      ;
       call   second_column  ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＝２である。２行目でブリンク
       movlw  2
       movwf  mode           ;スタート処理である
       goto   m2next200      ;
m2next110
       movlw  3              ;
       cpfseq u_d_counter    ;
       goto   m2next120
       call   third_column   ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＝３である。３行目でブリンク
       movlw  3
       movwf  mode           ;ストップ処理である
       goto   m2next200      ;
m2next120
       movlw  4              ;
       cpfseq u_d_counter    ;
       goto   m2next200      ;
       call   fourth_column  ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＝４である。４行目でブリンク
       movlw  4
       movwf  mode           ;リターン処理である
       goto   m2next200      ;

m2next200
       goto   menu2_loop     ;

center2_push                 ;センターキーは決定キーである。
    ;ＬＣＤ画面に実行中、その他の表示をしておく
       call    clear_out           ;画面のクリア
       call    home_out            ;カーソルをホームへ

       call    first_column        ;
       call    Execute_menu_LCD    ;
       call    second_column
       call    Change_menu_LCD
       call    third_column        ;
       call    Reset2_menu_LCD     ;
       call    fourth_column       ;
       call    End_menu_LCD        ;
       return

;**********
Execute_menu_LCD
       movlw   20                  ;表示する文字数を取り込む
       movwf   charnum,0           ;
       messege charnum,exe_moji    ;
       call    lcdwait_min         ;少し時間待機させる 
       return
exe_moji
       addwf   PCL,1               ;
       dt      " Execute / Pause    "   
       return 

;**********
Change_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,change_moji ;
       call    lcdwait_min          ;少し時間待機させる 
       return
change_moji
       addwf   PCL,1                ;
       dt      "  Change Push C Key "   
       return 

;**********
Reset2_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,reset2_moji    ;
       call    lcdwait_min          ;少し時間待機させる 
       return
reset2_moji
       addwf   PCL,1                ;
       dt      " Reset   Push U Key "   
       return 
;**********
End_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,end_moji    ;
       call    lcdwait_min          ;少し時間待機させる 
       return
end_moji
       addwf   PCL,1                ;
       dt      " End     Push D Key "   
       return 

;**********
Start_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
                                                          
       movlw   2                    ;****************　ＤＶ＝　の値を表示する
       cpfseq  u_d_counter          ;  u_d_counter  2,3     r_l_counter  1,2,3,4,5
       goto    dv_next30
       movlw   1
       cpfseq  r_l_counter
       goto    dv_next21
       messege charnum,start_moji_64     ;
       call    lcdwait_min               ;少し時間待機させる 
       return
dv_next21
       movlw   2
       cpfseq  r_l_counter
       goto    dv_next22
       messege charnum,start_moji_128     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next22
       movlw   3
       cpfseq  r_l_counter
       goto    dv_next23
       messege charnum,start_moji_256     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next23
       movlw   4
       cpfseq  r_l_counter
       goto    dv_next24
       messege charnum,start_moji_512     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next24
       ;movlw   5
       ;cpfseq  r_l_counter
       messege charnum,start_moji_1k     ;
       call    lcdwait_min                ;少し時間待機させる 
       return

dv_next30
       movlw   1
       cpfseq  r_l_counter
       goto    dv_next31
       messege charnum,start_moji_2k     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next31
       movlw   2
       cpfseq  r_l_counter
       goto    dv_next32
       messege charnum,start_moji_4k     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next32
       movlw   3
       cpfseq  r_l_counter
       goto    dv_next33
       messege charnum,start_moji_8k     ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next33
       movlw   4
       cpfseq  r_l_counter
       goto    dv_next34
       messege charnum,start_moji_16k    ;
       call    lcdwait_min                ;少し時間待機させる 
       return
dv_next34
       ;movlw   5
       ;cpfseq  r_l_counter
       messege charnum,start_moji_32k    ;
       call    lcdwait_min                ;少し時間待機させる 
       return 

start_moji_64
       addwf   PCL,1                ;
       dt      " Start  DV=   64    "   
       return
start_moji_128
       addwf   PCL,1                ;
       dt      " Start  DV=  128    "   
       return
start_moji_256
       addwf   PCL,1                ;
       dt      " Start  DV=  256    "   
       return
start_moji_512
       addwf   PCL,1                ;
       dt      " Start  DV=  512    "   
       return
start_moji_1k
       addwf   PCL,1                ;
       dt      " Start  DV=   1k    "   
       return
start_moji_2k
       addwf   PCL,1                ;
       dt      " Start  DV=   2k    "   
       return
start_moji_4k
       addwf   PCL,1                ;
       dt      " Start  DV=   4k    "   
       return
start_moji_8k
       addwf   PCL,1                ;
       dt      " Start  DV=   8k    "   
       return
start_moji_16k
       addwf   PCL,1                ;
       dt      " Start  DV=  16k    "   
       return
start_moji_32k
       addwf   PCL,1                ;
       dt      " Start  DV=  32k    "   
       return

;**********
pushC_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,pushC_moji    ;
       call    lcdwait_min          ;少し時間待機させる 
       return
pushC_moji
       addwf   PCL,1                ;
       dt      "    Push Center Key "   
       return 

;**********
Reset_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,reset_moji   ;
       call    lcdwait_min          ;少し時間待機させる 
       return
reset_moji
       addwf   PCL,1                ;
       dt      " Reset Value        "   
       return 

;**********
pushU_menu_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,pushU_moji   ;
       call    lcdwait_min          ;少し時間待機させる 
       return
pushU_moji
       addwf   PCL,1                ;
       dt      "    Push Up Key     "   
       return 

;******************************************************************************
;プリスケーラ値設定
;　　６４～３２Ｋまで、倍々値を設定可変
;１回のトリガパルス入力毎に、ゲートパルスの送りを指定した量分遅らせる。
;ＬＣＤ画面上で、
;　　　　６４　１２８　２５６　５１２　　１Ｋ
;　　　　２Ｋ　　４Ｋ　　８Ｋ　１６Ｋ　３２Ｋ　の数値を表示し、選択させる
;カーソルの位置を、読み出し　(value_set,r_l_counter,u_d_counter)　に代入しておく
;       　　　　　　　          1    1,2,3,4,5       2,3
prescaler_set_plane
       movlw   1
       movwf   value_set           ;プリスケーラ設定であることの通知

       call    clear_out           ;画面のクリア
       call    home_out            ;カーソルをホームへ
       call    first_column        ;
       call    title_prescale_LCD  ;
       call    second_column       ;
       call    prescale_1g_LCD     ;
       call    third_column        ;
       call    prescale_2g_LCD     ;
       call    fourth_column       ;
       call    prescale_3g_LCD     ;

       call    second_column       ;カーソルを２行目の１欄において、ブリンクさせておく
       movlw   1                   ;値を１として、１欄目であることを示す
       movwf   r_l_counter         ;
       movlw   2
       movwf   u_d_counter         ;値を２として、２行目であることを示す

      ;クロスキーが押されたかどうかの検査。
      ;アップ、ダウン、ライト、レフト、センターキーを監視する
menu3_loop                
       btfss   down           ;
       goto    m3next10
       goto    down3_push     ;ダウンキーが押された。
m3next10
       btfss   up
       goto    m3next20
       goto    up3_push       ;アップキーが押された。
m3next20
       btfss   right          ;
       goto    m3next30
       goto    right3_push    ;ライトキーが押された。
m3next30
       btfss   left
       goto    m3next40
       goto    left3_push     ;レフトキーが押された。
m3next40
       btfss   center  
       goto    menu3_loop     ;未だどのクロスキーも押されていない。押されるまでエンドレス。
       goto    center3_push   ;センターキーが押された。

down3_push
       incf    u_d_counter,1  ;ダウンキーが押された。アップダウンカウンタを＋１する
       movlw   3              ;
       cpfsgt  u_d_counter    ;u_d_counter>3
       goto    m3next100
       decf    u_d_counter,1  ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＜＝３に制限する。
       goto    m3next100   
up3_push
       decf    u_d_counter,1  ;アップキーが押された。アップダウンカウンタを－１する
       movlw   2              ;
       cpfslt  u_d_counter    ;u_d_counter<2
       goto    m3next100
       incf    u_d_counter,1  ;２＜＝ｕ＿ｄ＿ｃｏｕｎｔｅｒに制限
       goto    m3next100

right3_push
       incf    r_l_counter,1  ;ライトキーが押された。ライトレフトカウンタを＋１する
       movlw   5              ;
       cpfsgt  r_l_counter    ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＞５
       goto    m3next100
       decf    r_l_counter,1  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＜＝５に制限
       goto    m3next100
left3_push
       decf    r_l_counter,1  ;レフトキーが押された。ライトレフトカウンタを－１する
       movlw   1              ;
       cpfslt  r_l_counter    ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＜１
       goto    m3next100
       incf    r_l_counter,1  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＝１を最低値とする
       goto    m3next100      ;

center3_push ;センターキーは決定キーである。
      ;value_set,u_d_counter,r_l_counter の値の組み合わせが決まった
       call    wait_exe       ;キーのチャッタリング防止に代用する待ち時間
       return                 ;設定画面終了
 
m3next100   
       call   wait_exe       ;キーのチャッタリング防止に代用する待ち時間
       movlw  2              ;
       cpfseq u_d_counter    ;
       goto   m3next110      ;
       call   second_column  ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＝２である。２行目でブリンク
       goto   m3next200      ;
m3next110
       movlw  3              ;
       cpfseq u_d_counter    ;
       goto   m3next200
       call   third_column   ;ｕ＿ｄ＿ｃｏｕｎｔｅｒ＝３である。３行目でブリンク
       goto   m3next200      ;

m3next200
       movlw  2                ;
       cpfseq r_l_counter      ;
       goto   m3next210
       call   cursole_4_right  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＝２である。４桁目でブリンク
       goto   menu3_loop       ;
m3next210
       movlw  3                ;
       cpfseq r_l_counter      ;
       goto   m3next220        ;
       call   cursole_4_right  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＝３である。８桁目でブリンク
       call   cursole_4_right  ;
       goto   menu3_loop       ;
m3next220
       movlw  4                ;
       cpfseq r_l_counter      ;
       goto   m3next230
       call   cursole_4_right  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＝４である。１２桁目でブリンク
       call   cursole_4_right  ;
       call   cursole_4_right  ;
       goto   menu3_loop       ;
m3next230
       movlw  5                ;
       cpfseq r_l_counter      ;
       goto   menu3_loop       ;
       call   cursole_4_right  ;ｒ＿ｌ＿ｃｏｕｎｔｅｒ＝５である。１６桁目でブリンク
       call   cursole_4_right  ;
       call   cursole_4_right  ;
       call   cursole_4_right  ;
       goto   menu3_loop       ;

       return

;************************
;ＬＣＤに表示
title_prescale_LCD
       movlw   20                      ;表示する文字数を取り込む
       movwf   charnum,0               ;
       messege charnum,title_prescale  ;
       call    lcdwait_min             ;少し時間待機させる 
       return

title_prescale
       addwf   PCL,1                   ;
       dt      " Prescale Value Set "   
       return 

;**********
prescale_1g_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,prescale_1g  ;
       call    lcdwait_min          ;少し時間待機させる 
       return

prescale_1g
       addwf   PCL,1                ;
       dt      "  64 128 256 512  1K"   
       return 

;**********
prescale_2g_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,prescale_2g  ;
       call    lcdwait_min          ;少し時間待機させる 
       return

prescale_2g
       addwf   PCL,1                ;
       dt      "  2K  4K  8K 16K 32K"   
       return 

;**********
prescale_3g_LCD
       movlw   20                   ;表示する文字数を取り込む
       movwf   charnum,0            ;
       messege charnum,prescale_3g  ;
       call    lcdwait_min          ;少し時間待機させる 
       return

prescale_3g
       addwf   PCL,1                ;
       dt      "Push U D R L last C "   
       return 

;************************
;ＬＣＤの１行目に　研究室タイトル　表示
title1_LCD
       movlw   20                     ;表示する文字数を取り込む
       movwf   charnum,0              ;
       messege charnum,labo_title     ;
       call    lcdwait_min            ;少し時間待機させる 
       return

labo_title
       addwf   PCL,1                  ;
       dt      "    Golden Labo     " ;
       return 

;************************
;ＬＣＤの２行目に表示
resolu_LCD
       movlw   20                     ;表示する文字数を取り込む
       movwf   charnum,0              ;
       messege charnum,resolu_title   ;
       call    lcdwait_min            ;少し時間待機させる 
       return

resolu_title
       addwf   PCL,1                  ;
       dt      " Select Resolution  " ;
       return 

;************************
;ＬＣＤの３行目に表示
high_LCD
       movlw   20                     ;表示する文字数を取り込む
       movwf   charnum,0              ;
       messege charnum,high_title   ;
       call    lcdwait_min            ;少し時間待機させる 
       return

high_title
       addwf   PCL,1                  ;
       dt      "   High   Push C Key" ;
       return 

;************************
;ＬＣＤの４行目に表示
low_LCD
       movlw   20                     ;表示する文字数を取り込む
       movwf   charnum,0              ;
       messege charnum,low_title     ;
       call    lcdwait_min            ;少し時間待機させる 
       return

low_title
       addwf   PCL,1                  ;
       dt      "   Low    Push D Key" ;
       return 

;********************************************************************************
;カーソルの位置決めルーチン
;１行目に表示
first_column
       movlw   b'00000000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E 
       return

;２行目に表示
second_column
       movlw   b'11000000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E  
       return

;３行目に表示
third_column
       movlw   b'10010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E
       return

;４行目に表示
fourth_column
       movlw   b'11010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E
       return

;;カーソルを任意のアドレスに移動
;any_address
 ;      bcf     contl_RS     ;
 ;      bcf     contl_RW     ;
 ;      bsf     contl_E      ;
 ;      call    lcdwait_max  ;
 ;      bcf     contl_E
 ;      return

;カーソルを１桁右に移動
cursole_right
       movlw   b'00010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E 
       return

;カーソルを１桁左に移動
cursole_left
       movlw   b'00010000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcdwait_max  ;
       bcf     contl_E  
       return

;カーソルを４桁右に移動
cursole_4_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       return

;カーソルを６桁右に移動
cursole_6_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       call  cursole_right
       return

;*************　初期設定ルーチン集  ************************************************
;ポートの初期設定
port_initial 
  ;Ａポートは
       movlw   b'00010011'      ;ＲＡ０はＡＮ０としてＡＤ入力端子，ＲＡ１はトリガ入
       movwf   TRISA            ;力端子。ＲＡ２はモニター出力端子
                                ;ＲＡ４はＴ０ＣＫＩとして使用。入力端子
                                ;ＲＡ３，ＲＡ５はＬＣＤ制御出力端子
       movlw   b'10001110'      ;ＡＮ０／ＲＡ０がアナログ入力。残りはデジタル入出力端子    
       movwf   ADCON1           ;b7=1 で１０ビットデータは右詰指定。
                                ;  ADRESH=(000000xy), ADRESL=(abcdefgh)
                                ;

    ;ＡＤ変換器の初期設定
                           ;ADCON0=(ADCS1,ADCS0,CHS2,CHS1,CHS0,GO/DONE,-,ADON)
      bsf   ADCON0,ADCS1   ;  (ADCS1,ADCS0)=(1,0)　クロック１０ＭＨｚのとき使用できる組み合わせ。
      bcf   ADCON0,ADCS0   ;   この２つで、ＡＤ変換クロックを基準クロックの３２分の１とする
      bcf   ADCON0,CHS2    ;(CHS2,CHS1,CHS0)=(0,0,0) で、ＡＮ０端子の入力電圧をＡＤ変換
      bcf   ADCON0,CHS1    ;  GO/DONE  ADON=1 の時、=1 ならば、ＡＤ変換中、 =0 ならば、変換完了
      bcf   ADCON0,CHS0    ;           ＡＤ変換が完了すると、このビットは自動的に０となる
                           ;  ADON =1 の時、ＡＤ変換器をオンとする、=0 の時、ＡＤ変換器をオフする
                           ;従って、以降でＡＤ変換を行うには　ADON=1 とし、GO/DONE が０になるまで
                           ;待機させ、GO/DONE が０になったら、ADRESHとADRESLを読み出せばよい。
      bsf   ADCON0,ADON    ;ＡＤ変換器オン
 
  ;ＢポートはＲＢ０,４，５，６，７がクロスキーからの入力端子。
                                ;ＲＢ２は出力端子で、サンプル＆ホールド素子用ゲートパルスの出力端子。
                                ;ＲＢ１はＬＣＤのＲ／Ｗ制御端子として使用。出力端子。
                                ;ＲＢ３は　Ｇａｔｅ　Ｐｕｌｓｅ　出力端子。
       movlw   b'11110001'      ;Ｗに２進数の１１１１０００１を入れる
       movwf   TRISB            ;Ｂポートのデータ方向管理レジスタTRISBに
                                ;上の値を代入し、各端子を設定する。
  ;Ｃポートは全てＬＣＤへのデータ出力端子。
       movlw   b'00000000'      ;Ｗに２進数の００００００００を入れる
       movwf   TRISC            ;Ｃポートのデータ方向管理レジスタTRISCに
                                ;上の値を代入し、各端子を設定する。
 
  ;Ｄポートは全てＲ－２Ｒへのデータ出力端子
       movlw   b'00000000'      ;Ｗに２進数の００００００００を入れる
       movwf   TRISD            ;Ｄポートのデータ方向管理レジスタTRISDに
                                ;上の値を代入し、各端子を設定する。
  ;ＥポートはＲＥ０，ＲＥ１はＲ－２Ｒへのデータ出力端子、ＲＥ２は空きとして置くべし
       movlw   b'00000000'      ;
       movwf   TRISE            ;

       return

;**********************************
;ＬＣＤの初期設定 
LCD_initial   
       call    lcdwait_max       ;無駄時間ループﾟ 
  ;ＬＣＤの初期設定
       movlw   b'00111000'       ;Ｗレジスタの値を変数temp2に代入
       movwf   lcd_data          ;データ長８ビット、デューティ比を１／１６、
                                 ;フォントサイズを５＊７にそれぞれ設定
       call    lcd_comout        ;命令をＬＣＤに転送
  ;画面をクリアし、カーソルをホームへ戻す
       movlw   b'00000001'       ;clear             ;
       movwf   lcd_data          ;
       call    lcd_comout        ;ＬＥＤの命令処理を実行する
       movlw   b'00000010'       ;home              ;同上
       movwf   lcd_data          ;
       call    lcd_comout        ;
  ;ＬＣＤ画面でカーソルをブリンクさせる
       movlw   b'00001111'       ;
       movwf   lcd_data          ;表示オン、カーソルオン、ブリンクオンに設定
       call    lcd_comout        ;命令をＬＣＤに転送
  ;データの書き込み時、カーソルをインクリメントする
       movlw   b'00000110'       ;
       movwf   lcd_data          ;文字入力時にカーソルアドレスを＋１する
       call    lcd_comout        ;命令をＬＣＤに転送
       return

;**********************************************************************************
;ＬＣＤ制御用各種ルーチン
clear_out   ;ＬＣＤ画面のクリア
       movlw    clear             ;画面クリアのコードの取り込み
       movwf    lcd_data          ;ＬＣＤへ送る
       call     lcd_comout  
       return 

;**********************    
home_out       ;カーソルをホームへ
       movlw   b'00000010'       ;
       movwf   lcd_data          ;
       call    lcd_comout        ;
       return

;**********************    
crsr_r_out       ;カーソルを右へ１つ移動
       movlw   crsr_r    ;
       movwf   lcd_data          ;
       call    lcd_comout        ;
       return

;**********************    
crsr_l_out       ;カーソルを左へ１つ移動
       movlw   crsr_l       ;
       movwf   lcd_data          ;
       call    lcd_comout        ;
       return

;**********************    
careturn_out   ;ＬＣＤに改行させる
       movlw    ret_bak           ;キャリッジリターンのコードを取り込み、
       movwf    lcd_data          ;ＬＣＤへ送る
       call     lcd_comout  
       return

;********************** 
lcd_comout   ;ＬＣＤへの命令の書き込みルーチン
       bcf      contl_RS          ;RS=0として、命令コードの指定
       bcf      contl_RW          ;RW=0として、書き込みの指定
       bsf      contl_E           ;E =1として、ＬＣＤの動作起動
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       bcf      contl_E           ;E =0として、ＬＣＤの動作停止
       call     lcdwait_max       ;
       return

;********************** 
lcd_sigout   ;ＬＣＤへの記号の書き込みルーチン
       bsf      contl_RS,0        ;RS=1として、記号コードの指定
       bcf      contl_RW,0        ;RW=0として、書き込みの指定
       bsf      contl_E,0         ;E =1として、ＬＣＤの動作起動
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       nop
       bcf      contl_E,0         ;E =0として、ＬＣＤの動作停止
       call     lcdwait_min       ;
       return

;********************** 
lcdwait_max   ;ＬＣＤ表示時の時間遅延　大
       movlw   0                  ;２０ＭＨｚクロック時
       movwf   temp0              ;２５６×１２８回ループ
       movlw   255  ;128          ;４０ＭＨｚクロック時
       movwf   temp1              ;２５６×２５５回とする          
maxloop 
       decfsz  temp0,1            ;
       goto    maxloop            ;
       decfsz  temp1,1
       goto    maxloop
       return   

;********************** 
lcdwait_min  ;ＬＣＤ表示時の時間遅延　小
       movlw   8                  ;２０ＭＨｚクロック時
       movwf   temp0              ;８×３６回ループ
       movlw   72 ;36             ;４０ＭＨｚクロック時
       movwf   temp1              ;８×７２回とする         
minloop
       decfsz  temp0,1            ;
       goto    minloop            ;
       decfsz  temp1,1
       goto    minloop
       return   

;****************************************************************************
;プログラムの実行を少し待機させるためのルーチン
wait_exe   
          movlw   0                 ;２０ＭＨｚクロック時
          movwf   temp0             ;２５６×２５６×４回で、約０．１６秒
          movwf   temp1             ;４０ＭＨｚクロック時
          movlw   8  ;4             ;２５６×２５６×８回とする
          movwf   temp2         
waitloop  decfsz  temp0,1           ;
          goto    waitloop          ;
          decfsz  temp1,1
          goto    waitloop
          decfsz  temp2,1
          goto    waitloop
          return                    ;

;****************************************************************************
;ＬＣＤのウオームアップ時間を稼ぎ
lcd_warmup   
          movlw   0                 ;２０ＭＨｚクロック時
          movwf   temp0             ;２５６×２５６×２４回で約１秒
          movwf   temp1             ;４０ＭＨｚ時は
          movlw   128  ;48  ;24           ;２５６×２５６×４８回とする
          movwf   temp2         
lwloop    decfsz  temp0,1           ;
          goto    lwloop            ;
          decfsz  temp1,1
          goto    lwloop
          decfsz  temp2,1
          goto    lwloop
          return                    ;

;****************************************************************************
;遅延時間幅の設定　１０ＭＨｚセラロック使用。４倍発振＝４０ＭＨｚ
;１秒間の遅延時間
wait_1sec
         movlw  0
         movwf  temp0
         movwf  temp1
         movlw  54   ;20
         movwf  temp2
waitloop_1sec
         decfsz temp0,1
         goto   waitloop_1sec
         decfsz temp1,1
         goto   waitloop_1sec
         decfsz temp2,1
         goto   waitloop_1sec
         return

;*****************************
;５０μ秒間の遅延時間
delay_50usec
         movlw   160    
         movwf   temp0
d50uloop0 
         decfsz  temp0,1
         goto    d50uloop0
         return

;*****************************
;２０μ秒間の遅延時間
delay_20usec
         movlw   63   ;60   ;24  
         movwf   temp0
d20uloop0 
         decfsz  temp0,1
         goto    d20uloop0
         return

;*****************************
;１０μ秒間の遅延時間
delay_10usec
         movlw   30   
         movwf   temp0
d10uloop0 
         decfsz  temp0,1
         goto    d10uloop0
         return

;*****************************
;５μ秒間の遅延時間
delay_5usec
         movlw   14   
         movwf   temp0
d5uloop0 
         decfsz  temp0,1
         goto    d5uloop0
         return

;****************************************************************************
;****************************************************************************

      end
       

