;            プログラム名　　jairo-2.asm
;
;開発開始　２０１５年　１月　８日　
;　　母親は  distance-1.asm
;処方
;　（１）Ｌ３ＧＤ２０使用ジャイロセンサーモジュールの駆動試験プログラム
;
;
  LIST P=PIC18F252       ;使用するプロセッサを指定する
  #INCLUDE "P18F252.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'  ;
 
;*********************************************
;マクロ命令の定義
;trans   MACRO  ins,inf,ine,outs,outf,oute  ;浮動小数点型データの引き渡しに使用
         ; movff  ins,outs      ;符号の引き渡し
         ; movff  inf+7,outf+7  ;
         ; movff  inf+6,outf+6  ;
         ; movff  inf+5,outf+5  ;
         ; movff  inf+4,outf+4  ;仮数値の引き渡し
         ; movff  inf+3,outf+3  ;
         ; movff  inf+2,outf+2  ;
         ; movff  inf+1,outf+1  ;
         ; movff  inf+0,outf+0  ;
         ; movff  ine,oute      ;指数値の引き渡し
      ; ENDM

trans  MACRO  insig,inf4,inf3,inf2,inf1,inf0,outsig,outf4,outf3,outf2,outf1,outf0
           movff   insig,outsig     ;
           movff   inf4,outf4     ;
           movff   inf3,outf3     ;
           movff   inf2,outf2     ;４桁の変数の引き渡し
           movff   inf1,outf1     ;
           movff   inf0,outf0     ;
         ENDM

ctrans  MACRO  inf4,inf3,inf2,inf1,inf0,outf4,outf3,outf2,outf1,outf0
           movlw   inf4
           movff   WREG,outf4     ;
           movlw   inf3
           movff   WREG,outf3     ;
           movlw   inf2                ;
           movff   WREG,outf2     ;４桁の整数値の引き渡し
           movlw   inf1                ;
           movff   WREG,outf1     ;
           movlw   inf0                ;
           movff   WREG,outf0     ;
         ENDM

;********************************************************************************** 
           org  h'000'  ;バンク０に設ける

;変数の宣言	
temp0     res  1    ;一時的カウンタ変数
temp1     res  1    ;
temp2     res  1    ;
counter   res  1    ;カウンタ変数
current   res  1    ;一時変数
charnum   res  1    ;表示する文字数を入れる
LCD_mode  res  1    ;
sign        res   1  ;
fig10000  res  1   ;正負の
fig1000   res   1  ;１０進数の文字値が納まる
fig100     res  1  ;
fig10      res   1  ;
fig1        res   1  ;

flag        res   1  ;フラッグ用変数
u_sign          res  1  ;データの正負を示す記号＋、ーが納まる  
u_fig10000    res  1  ;
u_fig1000      res  1  ;
u_fig100        res   1  ;
u_fig10         res   1  ;１０進数の値が納まる
u_fig1           res   1  ;
w_sign          res   1
w_fig10000    res   1   ;ワーク変数
w_fig1000     res    1   ;
w_fig100       res   1  ;
w_fig10         res   1  ;
w_fig1          res   1  ;
v_sign          res   1
v_fig10000    res   1   ;ワーク変数
v_fig1000     res    1   ;
v_fig100       res   1  ;
v_fig10         res   1  ;
v_fig1          res   1  ;

x_sign          res  1  ;データの正負を示す記号＋、ーが納まる  
x_fig10000    res  1  ;
x_fig1000      res  1  ;
x_fig100        res   1  ;
x_fig10         res   1  ;１０進数の値が納まる
x_fig1           res   1  ;
y_sign          res   1
y_fig10000    res   1   ;
y_fig1000     res    1   ;
y_fig100       res   1  ;
y_fig10         res   1  ;
y_fig1          res   1  ;
z_sign           res   1  ;
z_fig10000    res   1   ;
z_fig1000     res    1   ;
z_fig100       res   1  ;
z_fig10         res   1  ;
z_fig1          res   1  ;

a_H8bit     res    1  ;
a_L8bit      res    1  ;
b_H8bit     res    1  ;作業用変数
b_L8bit      res    1  ;
c_H8bit     res    1  ;
c_L8bit      res    1  ;

DA_H8bit     res    1  ;ＤＡ変換用変数
DA_L8bit      res    1  ;

x_H8bit  res  1   ;センサーのｘ軸周りの１６ビット角速度データの内の上位８ビットが治まる
x_L8bit  res  1   ;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　下位８ビットが治まる
y_H8bit  res  1   ;センサーのｙ軸周りの１６ビット角速度データの内の上位８ビットが治まる
y_L8bit  res  1   ;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　下位８ビットが治まる
z_H8bit  res  1   ;センサーのｚ軸周りの１６ビット角速度データの内の上位８ビットが治まる
z_L8bit  res  1   ;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　下位８ビットが治まる
H8bit    res  1   ;カレント変数
L8bit    res   1  ;

sum_x_H8bit  res  1  ;  ｘ軸周りの変位角度が納まる 
sum_x_L8bit  res   1  ;
sum_y_H8bit  res  1  ;ｙ軸周りの変位角度が納まる    
sum_y_L8bit  res   1  ;
sum_z_H8bit  res  1  ; ;ｚ軸周りの変位角度が納まる   
sum_z_L8bit  res   1  ;  

sum_counter    res  1  ;
offset_counter  res  1  ;
warmup_counter  res  1  ;

offset_x_H8bit  res  1  ;  ｘ軸周りの変位角度の初期オフセット値が納まる 
offset_x_L8bit  res   1  ;
offset_y_H8bit  res  1  ;ｙ軸周りの変位角度の初期オフセット値が納まる    
offset_y_L8bit  res   1  ;
offset_z_H8bit  res  1  ; ;ｚ軸周りの変位角度の初期オフセット値が納まる   
offset_z_L8bit  res   1  ;  

abs_x_H8bit  res  1  ;  ｘ軸周りの変位角度の絶対値表記が納まる 
abs_x_L8bit  res   1  ;
abs_y_H8bit  res  1  ;ｙ軸周りの変位角度の絶対値表記が納まる    
abs_y_L8bit  res   1  ;
abs_z_H8bit  res  1  ; ;ｚ軸周りの変位角度の絶対値表記が納まる   
abs_z_L8bit  res   1  ;  

delta_x res  1   ;Ｘ軸方向の移動量が収まる
delta_y  res  1   ;Ｙ軸方向の移動量が収まる
delta_z  res  1   ;Ｚ軸方向の移動量が収まる

RXDATA  res  1  ;受信データが納まる
TXDATA  res  1  ;送信データが納まる
work       res  1  ;ワーク変数

;********************************************************************************** 
;********************************************************************************** 
;
;ＬＣＤの制御用ポートの割り当て。
#define contl_E     PORTC,2    ;０=ＬＣＤ不動作、    １=ＬＣＤ動作
#define contl_RW    PORTC,1   ;０=ＬＣＤへ書き込み　１=ＬＣＤから読み出し
#define contl_RS    PORTC,0   ;０=命令、            １=記号／バイト

#define LED_monitor PORTA,4   ;ポートＡの第３ビットをモニターに使用
#define lcd_data    PORTB        ;ＬＣＤデータ用ポートのＢポートにラベル名を付ける。


;ＬＣＤに転送する各命令のコードの定義
;使用するＬＣＤのテクニカルノートを参照すること
;                             ２進数　　　　　処理
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　　改行とリターン

;ＬＣＤに表示する文字コードの定義
column    equ   b'00111010'
degree    equ   b'11011111'
piriod      equ   b'00101110'
charlimit  equ   16             ;ＬＣＤの１行の表示可能文字数
allchar     equ   31             ;ＬＣＤに表示できる総文字数

;ＬＣＤに表示する各文字の文字数
Laboname     equ    15      ;' **Kinno Labo**'   
Devisename   equ    15      ;'  Jairo Sencer'

;定数の宣言

;名前付け
;***********************************************************+*******************
;*******************************************************************************
        org    0                ;スタートアドレス０番地
        goto   start

;************************************************************************************
;************************************************************************************
;割り込み処理
        org   h'0008'           ;ＰＩＣ１８Ｆ２５２の優先割り込み番地
handler
        call  handler_sub       ;

        return

;************************************************************************************
;************************************************************************************
;データテーブル
Labo_title     ;研究室名
       retlw   ' '
       retlw   '*'
       retlw   '*'
       retlw   'K'
       retlw   'i'
       retlw   'n'
       retlw   'n'
       retlw   'o'
       retlw   ' '
       retlw   'L'
       retlw   'a'
       retlw   'b'
       retlw   'o'
       retlw   '*'
       retlw   '*'
       return 

Devise_title   ;デバイス名
       retlw   ' '
       retlw   ' '
       retlw   'J'
       retlw   'a'
       retlw   'i'
       retlw   'r'
       retlw   'o'
       retlw   ' '
       retlw   'S'
       retlw   'e'
       retlw   'n'
       retlw   'c'
       retlw   'e'
       retlw   'r'
       return 

;***********************************************************************************
;***********************************************************************************
;割り込み処理
handler_sub
   ;割り込みに入ったので、一時割り込みを禁止しておく
       bcf    INTCON,GIE    ;全ての割り込みを禁止
       bcf    INTCON,PEIE   ;ペリフェラル割り込みを禁止

       return

;*******************************************************************************
;*******************************************************************************
start
;割り込み条件を設定する。
     movlw  b'00000000'   ;INTCON=(GIE,PEIE,TOIE,INTE,RBIE,TOIF,INTF,RBIF)
     movwf  INTCON        ;GIE   全ての割り込み　　　　　　　＝１　許可、　＝０　不可
                       　　　　   ;PEIE  全てのペリフェラル割り込み　＝１　許可、　＝０　不可     
;ポートの初期設定  
     call   port_initial
     bsf   LED_monitor    ;ＬＥＤ消灯
;ＬＣＤの初期設定   
     call   LCD_initial
;ＬＣＤ画面に初期文章を表示 
     call   first_LCD       ;
     call   wait_1sec      ;一時待ち
     call   wait_1sec      ;一時待ち
     call   clear_out       ;画面クリア
     call   home_out      ;カーソルホーム

     ;call   test_16bit_5_10dec      ;１６ビット２進数を５桁１０進数に変換する試験用。１秒毎にカウントアップ。
     ;call   test_add_sub_5_10dec  ;２つの符号付き５桁１０進数の加減算の試験用。
     ;call   test_add_sub_exe        ;16bit２進数同志の加減算に関する試験用

;ジャイロセンサーとのＳＰＩ通信の確立
     call   jairo_comm_start   ;
;センサーのＸ軸、Ｙ軸、Ｚ軸をイネーブルとする
     call   xyz_enable               ;
;ウオーミングアップ
     movlw 60
     movwf  warmup_counter     ;
warmup_next30
     btg   LED_monitor             ;
     call   wait_1sec   
     decfsz  warmup_counter,1   ;
     goto     warmup_next30      ; 
;平衡状態としているセンサーからＸ軸、Ｙ軸、Ｚ軸のデータを多数回読み出し、平均値を出し、
     call     offset_value_get        ;オフセット値を決める
     ;call     offset_value_disp       ;算出したオフセット値をＬＣＤに表示
     goto test_jump9
;センサーからＸ軸、Ｙ軸、Ｚ軸のデータを読み出すことをエンドレスで行う。
comm_repeat_1
     btg    LED_monitor            ;
     call    home_out               ;カーソルホーム
     call    read_data_repeat      ;２進数符号付き１６ビットのデータをジャイロから読み出す
     call    conv_comp_abs_xyz  ;ｘ、ｙ、ｘの補数１６ビットデータを符号付き絶対値１６ビットに変換する
     ;call   disp_xyz_16bit          ;変換し符号付き絶対値１６ビットをＬＣＤに表示する
     call    offset_manage         ;得られたジャイロの現値に、オフセット処理をして、真値（≒補正値）とする
     ;call    real_value_disp         ;真値をＬＣＤに表示する
     call    sum_degree             ;角速度の総和と、１軸だけのアナログ電圧出力
     call    wait_10msec            ;サンプリング時間間隔を設定
     goto   comm_repeat_1                   

test_jump9
;センサーからＸ軸、Ｙ軸、Ｚ軸の角速度データを読み出すことをエンドレスで行う。
;データをＬＣＤ表示するか、ＤＡ電圧出力するかは選択可、その他も選択可
comm_repeat_2  
     btg    LED_monitor          ;
     call    home_out             ;カーソルホーム
     call    read_data_repeat    ;２進数符号付き１６ビットのデータをジャイロから読み出す
     ;call    disp_xyz_16bit        ;ｘ、ｙ、ｚ軸の１６ビットデータをＬＣＤに表示する
     call    da_data_creat        ;２の補数表示を、ＤＡ変換用に絶対値表示とする
     call    DA_out_xyz          ;絶対値化した各軸のデータをＤＡ変換し、Ｖｏｕｔに出力
     ;call    DA_out_sample      ;ＤＡ変換器での出力例
     ;call    conv_16bit_5dec_LCD_disp  ;各軸の２の補数２進数符号付き１６ビットデータを
                                                 ;符号付き５桁１０進数に変換し、ＬＣＤに表示。
     ;call     offset_value_get    ;オフセット値を求める
     ;call    sum_degree          ;角速度の総和と、１軸だけのアナログ電圧出力
     call    wait_10msec         ;サンプリング時間間隔を設定
     goto   comm_repeat_2                   

;***********************************************************
;真値をＬＣＤに表示する
;入力　　x_H8bit,x_L8bit、 y_H8bit,y_L8bit、 z_H8bit,z_L8bit  
real_value_disp
     call      home_out
     call      first_column       ;１行目に補正値を表示してみる
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'01011000'       ;文字’Ｘ’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movff   x_H8bit,work       ;
     call      Disp_8bit             ;
     movff   x_L8bit,work       ;
     call      Disp_8bit            ;

     call      second_column    ;２行目に補正値を表示してみる
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'01011001'       ;文字’Ｙ’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movff   y_H8bit,work       ;
     call      Disp_8bit             ;
     movff   y_L8bit,work        ;
     call      Disp_8bit            ;

     call      third_column      ;３行目に補正値を表示してみる
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout         ;
     movlw  b'01011010'      ;文字’Ｚ’を表示
     movwf  lcd_data           ;W→lcd_data
     call      lcd_sigout         ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movff   z_H8bit,work       ;
     call      Disp_8bit             ;
     movff   z_L8bit,work       ;
     call      Disp_8bit            ;

     return

;**************************************************************
;得られたジャイロの現値に、オフセット処理をして、真値（≒補正値）とする
;入力　　x_H8bit,x_L8bit、 y_H8bit,y_L8bit、 z_H8bit,z_L8bit  
;   offset_x_H8bit,offset_x_L8bit,  offset_y_H8bit,offset_y_L8bit, offset_z_H8bit,  offset_z_L8bit                         
;出力    x_H8bit,x_L8bit、 y_H8bit,y_L8bit、 z_H8bit,z_L8bit  
offset_manage
     ;オフセット処理を行う。　現値＋オフセット値→真値（補正値）     ;
     movff  x_H8bit,a_H8bit           ;現値
     movff  x_L8bit,a_L8bit             ;ｘ軸周り
     movff  offset_x_H8bit,b_H8bit    ;オフセット値
     movff  offset_x_L8bit,b_L8bit     ;
     btg     b_H8bit,7                    ;演算のため、オフセット値の符号を替える。＋→－、－→＋
     call     add_sub_16bit_exe         ;符号付き絶対値１６ビットの加減算
     movff  c_H8bit,x_H8bit            ;補正値
     movff  c_L8bit,x_L8bit             ;

     movff  y_H8bit,a_H8bit           ;現値
     movff  y_L8bit,a_L8bit             ;ｙ軸周り
     movff  offset_y_H8bit,b_H8bit    ;オフセット値
     movff  offset_y_L8bit,b_L8bit     ;
     btg     b_H8bit,7                    ;演算のため、オフセット値の符号を替える。＋→－、－→＋
     call     add_sub_16bit_exe         ;符号付き絶対値１６ビットの加減算
     movff  c_H8bit,y_H8bit            ;補正値
     movff  c_L8bit,y_L8bit             ;

     movff  z_H8bit,a_H8bit           ;現値
     movff  z_L8bit,a_L8bit             ;ｚ軸周り
     movff  offset_z_H8bit,b_H8bit    ;オフセット値
     movff  offset_z_L8bit,b_L8bit     ;
     btg     b_H8bit,7                    ;演算のため、オフセット値の符号を替える。＋→－、－→＋
     call     add_sub_16bit_exe         ;符号付き絶対値１６ビットの加減算
     movff  c_H8bit,z_H8bit            ;補正値
     movff  c_L8bit,z_L8bit             ;

     return

;**************************************************
;ｘ、ｙ、ｚの２進数符号付き１６ビットのデータを符号付き絶対値に変換
;入力　x_H8bit,x_L8bit,   y_H8bit,y_L8bit,   z_H8bit,z_L8bit
;出力  x_H8bit,x_L8bit,   y_H8bit,y_L8bit,   z_H8bit,z_L8bit
conv_comp_abs_xyz
     movff  x_H8bit,a_H8bit     ;
     movff  x_L8bit,a_L8bit     ;ｘ軸に関する
     call     conv_comp_abs    ;符号付き補数表示を、符号付き絶対値表示とする
     movff  a_H8bit,x_H8bit     ;
     movff  a_L8bit,x_L8bit     ;

     movff  y_H8bit,a_H8bit     ;
     movff  y_L8bit,a_L8bit     ;ｙ軸に関する
     call     conv_comp_abs    ;符号付き補数表示を、符号付き絶対値表示とする
     movff  a_H8bit,y_H8bit     ;
     movff  a_L8bit,y_L8bit     ;

     movff  z_H8bit,a_H8bit     ;
     movff  z_L8bit,a_L8bit     ;ｚ軸に関する
     call     conv_comp_abs    ;符号付き補数表示を、符号付き絶対値表示とする
     movff  a_H8bit,z_H8bit     ;
     movff  a_L8bit,z_L8bit     ;

     return

;*****************************************************
;符号付き補数表示を、符号付き絶対値表示とする
;入力　　ａ群 (a_H8bit,a_L8bit)
;出力　　ａ群 (a_H8bit,a_L8bit)
conv_comp_abs
      btfss    a_H8bit,7            ;
      goto     conv_ca_next20   ;a群は正値である。処理不用。
      comf    a_H8bit              ;a群は負値である。補数表示なので、
      comf    a_L8bit               ;反値＋１の処理をして、正規表現とする。
      incf      a_L8bit,1            ;
      btfsc     STATUS,C         ;
      incf      a_H8bit,1            ;キャリアーが会った時の処理。
      bsf       a_H8bit,7            ;負数表現なので、１６ビット目を１とする。
conv_ca_next20   ;

      return

;******************************************************
;ジャイロには、ｘ、ｙ、ｚ各々の出力にゼロでは無いオフセットがある。それに対する対策
;ジャイロを平衡状態として、オフセット値を算出する
;２回の積算では、結果は右へ１回シフト。４回では、右へ２回シフト、８回では、３回
;１６回では、右へ４回シフト。３２回では、５回。　　　　　
;
;出力　ｘ軸のオフセット値　offset_x_H8bit、 offset_x_L8bit  
;　　　　ｙ軸のオフセット値　offset_y_H8bit、 offset_y_L8bit
;　　　  ｚ軸のオフセット値　offset_z_H8bit、 offset_z_L8bit  
offset_value_get
     clrf   sum_x_H8bit   ;初期値をクリアしておく
     clrf   sum_x_L8bit   ;
     clrf   sum_y_H8bit   ;初期値をクリアしておく
     clrf   sum_y_L8bit   ;
     clrf   sum_z_H8bit   ;初期値をクリアしておく
     clrf   sum_z_L8bit   ;
     movlw  16     ;
     movwf  sum_counter    ;オフセット値を求めるためのサンプリング回数

offset_next100
     btg      LED_monitor
     call      read_data_repeat     ;
     ;call      home_out             ;カーソルホーム  
     ;call      disp_xyz_16bit         ;
     call      conv_comp_abs_xyz  ;３軸の２進数符号付き１６ビットのデータを符号付き絶対値に変換
     call      sum_degree           ;３軸周りの加速度の総和
     ;call      wait_10msec          ;サンプリング時間間隔を設定

     call      wait_100msec          
    
     decfsz  sum_counter,1       ;
     goto     offset_next100       ;

    ;ｘ軸に関して
     movlw  4                     ;　　回積算したので、　　分の１とする
     movwf  offset_counter    ;
offset_next200
     bcf      STATUS,C         ;右に　桁だけ桁下ろしする。
     btfsc    sum_x_H8bit,0     ;
     bsf       STATUS,C         ; sum_x_H8bit,0→C
     rrcf      sum_x_L8bit        ;
     rrcf      sum_x_H8bit       ;
     decfsz  offset_counter,1  ;
     goto     offset_next200        ;

     bcf      sum_x_H8bit,7      ;
     btfsc    sum_x_H8bit,3      ;右に　桁下ろししたので、第　ビット目に符号が入っている
     bsf      sum_x_H8bit,7       ;符号ビットの確定
     bcf      sum_x_H8bit,3  ;
     bcf      sum_x_H8bit,4  ;
     bcf      sum_x_H8bit,5  ;
     bcf      sum_x_H8bit,6  ;
     movff   sum_x_H8bit,offset_x_H8bit  ;ｘ軸に関するオフセット値の上位８ビットとなる
     movff   sum_x_L8bit,offset_x_L8bit   ;ｘ軸に関するオフセット値の下位８ビットとなる

    ;ｙ軸に関して
     movlw  4                     ;　　回積算したので、　　分の１とする
     movwf  offset_counter    ;
offset_next300
     bcf      STATUS,C         ;右に４桁だけ桁下ろしする。
     btfsc    sum_y_H8bit,0     ;
     bsf       STATUS,C         ; sum_y_H8bit,0→C
     rrcf      sum_y_L8bit        ;
     rrcf      sum_y_H8bit       ;
     decfsz  offset_counter,1  ;
     goto     offset_next300        ;

     bcf      sum_y_H8bit,7      ;符号ビットの確定
     btfsc    sum_y_H8bit,3      ;右に４桁桁下ろししたので、第３ビット目に符号が入っている
     bsf      sum_y_H8bit,7       ;
     bcf      sum_y_H8bit,3  ;
     bcf      sum_y_H8bit,4  ;
     bcf      sum_y_H8bit,5  ;
     bcf      sum_y_H8bit,6  ;
     movff   sum_y_H8bit,offset_y_H8bit  ;ｙ軸に関するオフセット値の上位８ビットとなる
     movff   sum_y_L8bit,offset_y_L8bit   ;ｙ軸に関するオフセット値の下位８ビットとなる

    ;ｚ軸に関して
     movlw  4                     ;　　回積算したので、　　分の１とする
     movwf  offset_counter    ;
offset_next400
     bcf      STATUS,C         ;右に４桁だけ桁下ろしする。
     btfsc    sum_z_H8bit,0     ;
     bsf       STATUS,C         ; sum_z_H8bit,0→C
     rrcf      sum_z_L8bit        ;
     rrcf      sum_z_H8bit       ;
     decfsz  offset_counter,1  ;
     goto     offset_next400        ;

     bcf      sum_z_H8bit,7      ;符号ビットの確定
     btfsc    sum_z_H8bit,3      ;右に４桁桁下ろししたので、第３ビット目に符号が入っている
     bsf      sum_z_H8bit,7       ;
     bcf      sum_z_H8bit,3  ;
     bcf      sum_z_H8bit,4  ;
     bcf      sum_z_H8bit,5  ;
     bcf      sum_z_H8bit,6  ;
     movff   sum_z_H8bit,offset_z_H8bit  ;ｚ軸に関するオフセット値の上位８ビットとなる
     movff   sum_z_L8bit,offset_z_L8bit   ;ｚ軸に関するオフセット値の下位８ビットとなる

     return

;*************************************************************
;算出したオフセット値をＬＣＤに表示
;入力　sum_x_H8bit,sum_x_L8bit,  sum_y_H8bit,sum_y_L8bit,  sum_z_H8bit,sum_z_L8bit
offset_value_disp       
     call      home_out         ;
     ;ｘ軸に関してのオフセット値の表示
     call      first_column       ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'01011000'       ;文字’Ｘ’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout          ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data             ;W→lcd_data
     call      lcd_sigout           ;
     movff   sum_x_H8bit,work   ;
     call      Disp_8bit             ;
     movff   sum_x_L8bit,work  ;
     call      Disp_8bit            ;

     ;ｙ軸に関してのオフセット値の表示
     call      second_column       ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout         ;
     movlw  b'01011001'       ;文字’Ｙ’を表示
     movwf  lcd_data             ;W→lcd_data
     call      lcd_sigout           ;
     movlw  b'00100000'        ;文字’　’を表示
     movwf  lcd_data             ;W→lcd_data
     call      lcd_sigout       ;
     movff   sum_y_H8bit,work   ;
     call      Disp_8bit             ;
     movff   sum_y_L8bit,work  ;
     call      Disp_8bit            ;

     ;ｚ軸に関してのオフセット値の表示
     call      third_column    ;
     movlw  b'00100000'       ;文字’　’を表示
     movwf  lcd_data            ;W→lcd_data
     call      lcd_sigout         ;
     movlw  b'01011010'   ;文字’Ｚ’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movff   sum_z_H8bit,work   ;
     call      Disp_8bit             ;
     movff   sum_z_L8bit,work  ;
     call      Disp_8bit            ;

     call      wait_1sec   
     call      wait_1sec

     return

;****************************************************
;角速度値を積算し、変位角度を産出する。値をアナログ電圧としても出力させる
;　θ＝ＳＵＭ（Δωｉ×τ）
;　　τは当面１で良い。
;　　当面、ｘ軸周りについて取り扱う
;　入力データ　　Ｊａｉｒｏからのｘ軸周りの角速度値を符号付き（最高位ビット　０＝’＋’、１＝’－’）
;　　　　　　　　　　絶対値１６ビット表記したものと、その前回までの総和変数
;                 x_H8bit,x_L8bit,            y_H8bit,y_L8bit,            z_H8bit,z_L8bit
;                 sum_x_H8bit,sum_L8bit,  sum_y_H8bit,sum_L8bit,  sum_z_H8bit,sum_L8bit
;
;　出力データ　　３軸周りの変位角度値
;                 　sum_x_H8bit,sum_x_L8bit,   sum_y_H8bit,sum_L8bit,  sum_z_H8bit,sum_L8bit
sum_degree
      movff   x_H8bit,a_H8bit        ;
      movff   x_L8bit,a_L8bit         ;データの引き渡し
      movff   sum_x_H8bit,b_H8bit  ;
      movff   sum_x_L8bit,b_L8bit   ;
      call      add_sub_16bit_exe
      movff   c_H8bit,sum_x_H8bit  ;データの引き渡し
      movff   c_L8bit,sum_x_L8bit   ;

      movff   y_H8bit,a_H8bit        ;
      movff   y_L8bit,a_L8bit         ;データの引き渡し
      movff   sum_y_H8bit,b_H8bit  ;
      movff   sum_y_L8bit,b_L8bit   ;
      call      add_sub_16bit_exe
      movff   c_H8bit,sum_y_H8bit  ;データの引き渡し
      movff   c_L8bit,sum_y_L8bit   ;

      movff   z_H8bit,a_H8bit        ;
      movff   z_L8bit,a_L8bit         ;データの引き渡し
      movff   sum_z_H8bit,b_H8bit  ;
      movff   sum_z_L8bit,b_L8bit   ;
      call      add_sub_16bit_exe
      movff   c_H8bit,sum_z_H8bit  ;データの引き渡し
      movff   c_L8bit,sum_z_L8bit   ;

     call    sum_da_data_creat       ;符号付き絶対値２進数を、ＤＡ変換用に符号無し絶対値表記とする
     call    sum_DA_out_xyz         ;絶対値化したデータをＤＡ変換し、Ｖｏｕｔに出力。３軸の内の１軸だけ

     return

;**************************************************************************
;**************************************************************************
;DA_out_xyzを変位角度で使用できるようにした。
;　ＤＡからの出力は１ポートのみ使用。従って、Ｘ，Ｙ，Ｚのどれか１つを選択すること
;　入力変数　abs_x_H8bit, abs_x_L8bit,  abs_y_H8bit,abs_y_L8bit,  abs_z_H8bit,abs_z_L8bit    
sum_DA_out_xyz
    movff  abs_x_H8bit,DA_H8bit  ;Ｘ軸の絶対値２進数１６ビットを、ＤＡ用変数に代入
    movff  abs_x_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）
    ;movff  abs_y_H8bit,DA_H8bit  ;Ｙ軸の絶対値２進数１６ビットを、ＤＡ用変数に代入
    ;movff  abs_y_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）
    ;movff  abs_z_H8bit,DA_H8bit  ;Ｚ軸の絶対値２進数１６ビットを、ＤＡ用変数に代入
    ;movff  abs_z_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）

    swapf  DA_L8bit,1          ;(ｃｃｃｃ ｄｄｄｄ）→（dddd ｃｃｃｃ）　　
    bcf     DA_L8bit,4          ;（ddd0 ｃｃｃｃ）　　
    bcf     DA_L8bit,5          ;（dd00 ｃｃｃｃ）　　
    bcf     DA_L8bit,6          ;（d000 ｃｃｃｃ）　　
    bcf     DA_L8bit,7          ;（0000 ｃｃｃｃ）　　
    btfsc   DA_H8bit,0         ;０ならば、ジャンプ
    bsf      DA_L8bit,4         ;（000b ｃｃｃｃ）　　
    btfsc   DA_H8bit,1         ;０ならば、ジャンプ
    bsf      DA_L8bit,5         ;（00bb ｃｃｃｃ）　　
    btfsc   DA_H8bit,2         ;０ならば、ジャンプ
    bsf      DA_L8bit,6         ;（0bbb ｃｃｃｃ）　　
    btfsc   DA_H8bit,3         ;０ならば、ジャンプ
    bsf      DA_L8bit,7         ;（bbbb ｃｃｃｃ）　

    swapf  DA_H8bit,1        ;(ａａａａ　ｂｂｂｂ）→(bbbb aaaa)
    bcf     DA_H8bit,4          ;(bbb0 aaaa)　　
    bcf     DA_H8bit,5          ;(bb00 aaaa)　　
    bcf     DA_H8bit,6          ;(b000 aaaa)　　
    bcf     DA_H8bit,7          ;(0000 aaaa)　　

    call    DA_out_exe     ;実測データをＤＡ変換し、Ｖｏｕｔに出力

    return

;******************************************************************
;Ｊａｉｒｏの各軸のデータ（プラスマイナスに振れる）をＤＡ変換し、Ｖｏｕｔに出力
;　ＤＡ変換器はプラス出力のみ。各軸の０Ｖデータは、ＤＡのＶｒｅｆＡ／２に対応させている
;　ＤＡからの出力は１ポートのみ使用。従って、Ｘ，Ｙ，Ｚのどれか１つを選択すること
DA_out_xyz
    movff  x_H8bit,DA_H8bit  ;Ｘ軸の２進数１６ビットを、ＤＡ用変数に代入
    movff  x_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）
    ;movff  y_H8bit,DA_H8bit  ;Ｙ軸の２進数１６ビットを、ＤＡ用変数に代入
    ;movff  y_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）
    ;movff  z_H8bit,DA_H8bit  ;Ｚ軸の２進数１６ビットを、ＤＡ用変数に代入
    ;movff  z_L8bit,DA_L8bit   ;　　（ａａａａ　ｂｂｂｂ）＋（ｃｃｃｃ　ｄｄｄｄ）　４ビット右送りする
                                    ;→　（００００　ａａａａ）＋（ｂｂｂｂ　ｃｃｃｃ）

    swapf  DA_L8bit,1          ;(ｃｃｃｃ ｄｄｄｄ）→（dddd ｃｃｃｃ）　　
    bcf     DA_L8bit,4          ;（ddd0 ｃｃｃｃ）　　
    bcf     DA_L8bit,5          ;（dd00 ｃｃｃｃ）　　
    bcf     DA_L8bit,6          ;（d000 ｃｃｃｃ）　　
    bcf     DA_L8bit,7          ;（0000 ｃｃｃｃ）　　
    btfsc   DA_H8bit,0         ;０ならば、ジャンプ
    bsf      DA_L8bit,4         ;（000b ｃｃｃｃ）　　
    btfsc   DA_H8bit,1         ;０ならば、ジャンプ
    bsf      DA_L8bit,5         ;（00bb ｃｃｃｃ）　　
    btfsc   DA_H8bit,2         ;０ならば、ジャンプ
    bsf      DA_L8bit,6         ;（0bbb ｃｃｃｃ）　　
    btfsc   DA_H8bit,3         ;０ならば、ジャンプ
    bsf      DA_L8bit,7         ;（bbbb ｃｃｃｃ）　

    swapf  DA_H8bit,1        ;(ａａａａ　ｂｂｂｂ）→(bbbb aaaa)
    bcf     DA_H8bit,4          ;(bbb0 aaaa)　　
    bcf     DA_H8bit,5          ;(bb00 aaaa)　　
    bcf     DA_H8bit,6          ;(b000 aaaa)　　
    bcf     DA_H8bit,7          ;(0000 aaaa)　　

    call    DA_out_exe     ;実測データをＤＡ変換し、Ｖｏｕｔに出力

    return

;********************************************************
;実測データをＤＡ変換し、ＶｏｕｔＡに出力
;　　実測値０Ｖは　Ｖｄｄ／２で出力。０Ｖ以上ならば、その値以上、
;　　　　　　　　　　　　　　　　　　　　　０Ｖ以下ならば、その値以下、で出力　
;入力データ　　DA_H8bit,DA_L8bit
DA_out_exe
     bcf      PORTA,3  ;おまじない。これがあると予定通りの出力が得られる。
     nop                   ;
     nop                   ;これが無いと、３つのデータの内、最初のデータが出力されないよ。理由？？？
     bsf      PORTA,3  ;

     call      DA_trans         ;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送る

     return

;****************************************************

;ＤＡ変換器から、３つのデータを繰り返して出力させるプログラム例
;３つのデータがＤＡのＶｏｕｔＡから、連続し、エンドレスで出力されます。
;　（００００１０００　１０１０１０１０）　（０００００１０００　１０１０１０１０）　（００００００１００　１０１０１０１０）
; 注意　ＤＡ変換器は１２ビットなので、上記１６ビットの内、下位１２ビットが有効値
;　　　　　　　　　　　　　　　　　左端４ビットはコンフィグレーションビット（制御ビット）
DA_out_sample
     bcf      PORTA,3  ;おまじない。これがあると予定通りの出力が得られる。
     nop                   ;
     nop                   ;これが無いと、３つのデータの内、最初のデータが出力されないよ。理由？？？
     bsf      PORTA,3  ;

     movlw   b'00001111'     ;ＤＡ変換器へのデータ　a_H8bit+a_L8bit の１６ビットの内、下位１２ビット有効
     movwf   DA_H8bit         ;「ＸＸＸＸａｂｃｄｅｆｇｈｉｊｋｌ」で、Ｘは無視、ａ～ｌは０又は１。
     movlw   b'11111111'     ; ＶｒｅｆＡの電圧が出るはず
     movwf   DA_L8bit          ;
     call       DA_trans         ;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送る

     movlw   b'00000111'     ;ＤＡ変換器へのデータ　a_H8bit+a_L8bit の１６ビットの内、下位１２ビット有効
     movwf   DA_H8bit         ;「ＸＸＸＸａｂｃｄｅｆｇｈｉｊｋｌ」で、Ｘは無視、ａ～ｌは０又は１。
     movlw   b'11111111'      ;ＶｒｅＡ／２の電圧が出るはず
     movwf   DA_L8bit          ;
     call       DA_trans          ;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送る

     movlw   b'00000000'     ;ＤＡ変換器へのデータ　a_H8bit+a_L8bit の１６ビットの内、下位１２ビット有効
     movwf   DA_H8bit         ;「ＸＸＸＸａｂｃｄｅｆｇｈｉｊｋｌ」で、Ｘは無視、ａ～ｌは０又は１。
     movlw   b'00000000'      ;０Ｖの電圧が出るはず
     movwf   DA_L8bit          ;
     call       DA_trans          ;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送る

     movlw   b'00000011'     ;ＤＡ変換器へのデータ　a_H8bit+a_L8bit の１６ビットの内、下位１２ビット有効
     movwf   DA_H8bit         ;「ＸＸＸＸａｂｃｄｅｆｇｈｉｊｋｌ」で、Ｘは無視、ａ～ｌは０又は１。
     movlw   b'11111111'      ;ＶｒｅＡ／４の電圧が出るはず
     movwf   DA_L8bit          ;
     call       DA_trans          ;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送る

     return

;******************************************************
;ＤＡ変換器へＳＰＩ通信で、シリアルデータを送り続ける
;ＤＡ変換への書き込み手順は、ＭＣＰ４９２Ｘのテクニカルノートの１９頁参照
;送信データ　 A/B,BUF,GA,SHDN,D11,D10,D9,D8,   D7,D6,D5,D4,D3,D2,D1,D0
DA_trans

    bsf       PORTA,5              ;スレーブであるＪａｉｒｏのＣＳ端子をＨレベルとして、切り離す
    bcf       PORTA,3              ;ＤＡ変換器のＣＳ端子をＬレベルとする。接続する。
                                         ;a_H8bit+a_L8bitで１６ビット。上位バイトの内、上位４ビットは、コンフィグデータ。
    bcf       DA_H8bit,7            ;ＤＡ変換器の内のＡの変換器を使用。ＭＣＰにはＡ，Ｂ２つの変換器がある
    bcf       DA_H8bit,6            ;参照バッファは使わない。？？？
    bsf       DA_H8bit,5            ;出力電圧は１＝１×、０＝２×　　
    bsf       DA_H8bit,4            ;出力ダウン制御。　　？？？
    movff    DA_H8bit,TXDATA  ;送信用変数に入れる
    movf     TXDATA,W           ;通信データ取りだし
    movwf   SSPBUF              ;送信中
da_comm_next_1                   ;
    btfss     SSPSTAT,BF        ;送信時　送信中でＳＳＰＢＵＦ使用中＝１
    goto     da_comm_next_1     ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須

    movff    DA_L8bit,TXDATA   ;送信用変数に入れる
    movf     TXDATA,W            ;通信データ取りだし
    movwf   SSPBUF               ;通信バッファにデータを入れる。送信中
da_comm_next_2     ;
    btfss     SSPSTAT,BF         ;送信時　送信中でＳＳＰＢＵＦ使用中＝１
    goto     da_comm_next_2      ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須

    call       wait_10us              ;
    bsf       PORTA,3               ;ＤＡ変換器のＣＳ端子をＨレベルとする。ＶｏｕｔＡに出力される。且つ、切り離す。
    call       wait_10us              ;

    return

;***************************************************
;各軸の２の補数２進数符号付き１６ビットデータを符号付き５桁１０進数に変換し、ＬＣＤに表示する。
conv_16bit_5dec_LCD_disp  
      movff   x_H8bit,H8bit      ;データの引き渡し
      movff   x_L8bit,L8bit       ;
      call      Conv_16bit_5dec  ;２進数１６ビットデータを１０進数５桁（－３２７６７～＋３２７６７）に変換する。
                                       ;但し、最高位の１６ビット目は符号ビット。０＝＋、１＝－。
                                       ;入力　　H8bit,L8bit
                                       ;出力　　sign,fig10000,fig1000,fig100,fig10,fig1
      trans   sign,fig10000,fig1000,fig100,fig10,fig1,x_sign,x_fig10000,x_fig1000,x_fig100,x_fig10,x_fig1
  
      movff   y_H8bit,H8bit       ;データの引き渡し
      movff   y_L8bit,L8bit        ;
      call     Conv_16bit_5dec    ;
      trans   sign,fig10000,fig1000,fig100,fig10,fig1,y_sign,y_fig10000,y_fig1000,y_fig100,y_fig10,y_fig1

      movff   z_H8bit,H8bit        ;データの引き渡し
      movff   z_L8bit,L8bit         ;
      call     Conv_16bit_5dec    ;
      trans   sign,fig10000,fig1000,fig100,fig10,fig1,z_sign,z_fig10000,z_fig1000,z_fig100,z_fig10,z_fig1

      call     disp_xyz_10dec       ;;ｘ、ｙ、ｘ各軸の符号付き５桁１０進数を、ＬＣＤに表示してみよう                 

      return

;*********************************************
;da_data_creatを変位角度で使えるようにする
;符号付き絶対値２進数を、ＤＡ変換用に符号無し絶対値表示とする
;　入力変数　sum_x_H8bit, sum_x_L8bit,  sum_y_H8bit,sum_y_L8bit,  sum_z_H8bit,sum_z_L8bit    
;　出力変数　abs_x_H8bit, abs_x_L8bit,  abs_y_H8bit,abs_y_L8bit,  abs_z_H8bit,abs_z_L8bit    
sum_da_data_creat
     movff   sum_x_H8bit,abs_x_H8bit  ;データの引き渡し
     movff   sum_x_L8bit,abs_x_L8bit  ;
     movff   sum_y_H8bit,abs_y_H8bit  ;データの引き渡し
     movff   sum_y_L8bit,abs_y_L8bit  ;
     movff   sum_z_H8bit,abs_z_H8bit  ;データの引き渡し
     movff   sum_z_L8bit,abs_z_L8bit  ;

     btfss  sum_x_H8bit,7     ;Ｘ軸データ
     goto   sum_da_data10    ; 
     comf   abs_x_H8bit       ;負値に対する処理
     comf   abs_x_L8bit       ;補数をとる
     goto   sum_da_data20    ;
sum_da_data10
     bsf     abs_x_H8bit,7      ;正値である処理
sum_da_data20

     btfss  sum_y_H8bit,7     ;Ｙ軸データ
     goto   sum_da_data30    ; 
     comf   abs_y_H8bit       ;負値に対する処理
     comf   abs_y_L8bit       ;補数をとる
     goto   sum_da_data40    ;
sum_da_data30
     bsf    abs_y_H8bit,7       ;正値である処理
sum_da_data40

     btfss  sum_z_H8bit,7     ;Ｚ軸データ
     goto   sum_da_data50    ; 
     comf   abs_z_H8bit       ;負値に対する処理
     comf   abs_z_L8bit        ;補数をとる
     goto   sum_da_data60    ;
sum_da_data50
     bsf     abs_z_H8bit,7      ;正値である処理
sum_da_data60

     return

;*********************************************
;２の補数表示で、符号ビットである最左端ビットが
;　０ならば、１とし　　→正値　１０００００００　００００００００～１１１１１１１１　１１１１１１１１
;　１ならば、０とする。→負値　００００００００　００００００００～０１１１１１１１　１１１１１１１１
;                   １０進数では　　０（最小値）～３２７６８（中間値）～６５５３５（最大値）
;　これにより、「正値～負値」が、「１１．．．１１～００．．００」で表現される
;　入力変数　ジャイロからの生データであり　 x_H8bit, x_L8bit,  y_H8bit,y_L8bit,  z_H8bit,z_L8bit    
;　出力変数　　　　　　　　　　　　　　　　　　 x_H8bit, x_L8bit,  y_H8bit,y_L8bit,  z_H8bit,z_L8bit    
da_data_creat
     btfss  x_H8bit,7     ;Ｘ軸データ
     goto   da_data10    ; 
     bcf     x_H8bit,7    ;負値である処理
     goto   da_data20    ;
da_data10
     bsf     x_H8bit,7    ;正値である処理
da_data20

     btfss  y_H8bit,7     ;Ｙ軸データ
     goto   da_data30    ; 
     bcf     y_H8bit,7    ;負値である処理
     goto   da_data40    ;
da_data30
     bsf     y_H8bit,7    ;正値である処理
da_data40

     btfss  z_H8bit,7     ;Ｚ軸データ
     goto   da_data50    ; 
     bcf     z_H8bit,7    ;負値である処理
     goto   da_data60    ;
da_data50
     bsf     z_H8bit,7    ;正値である処理
da_data60

     return

;******************************************
;16bit２進数同志の加減算に関する試験用
test_add_sub_exe  
     movlw  b'00101010'  ;
     movwf  a_H8bit        ;
     movlw  b'11010101'  ;
     movwf  a_L8bit        ;
     movlw  b'11010101'  ;
     movwf  b_H8bit        ;
     movlw  b'10101010'  ;
     movwf  b_L8bit        ;

     movff  a_H8bit,work       ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  a_L8bit,work        ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

     call     second_column     ;カーソルを２行目に移動
     call     wait_50us          ;
     movff  b_H8bit,work       ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  b_L8bit,work        ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

     call     add_sub_16bit_exe   ;１６ビット２進数の加減算の試験用。

     call     third_column         ;カーソルを３行目に移動
     call     wait_50us          ;
     movff  c_H8bit,work       ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  c_L8bit,work        ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

endless1
     ;btg    LED_monitor
     call    wait_1sec
     goto    endless1  

     return

;**************************
;符号付き（最高位ビット　０＝’＋’、１＝’－’）絶対値表記１６ビット同志の加減算
;
;入力     a_H8bit,a_L8bit,b_H8bit,b_L8bit
;出力     c_H8bit,c_L8bit 　　　　
;場合分け
;（１）（＋ａ群、＋ｂ群）　２バイトの単純加算
;（２））（－ａ群、－ｂ群）＝－（＋ａ群、＋ｂ群）　（１）を利用し、２バイトの単純加算の後、符号を’－’とする。
;（３））（＋ａ群、－ｂ群）　２バイトの単純加算
;       ｜ａ｜＞＝｜ｂ｜の時、ａ群－ｂ群の２バイトの単純減算。
;　　　　｜ａ｜＜｜ｂ｜の時、ｂ群－ａ群の２バイトの単純減算の後、符号を’－’とする。
;（４））（－ａ群、＋ｂ群）＝－（＋ａ群、－ｂ群）　（３）を利用し、結果の符号を逆とする
add_sub_16bit_exe

   ;正値、負値の組み合わせで場合分けをする
      btfsc    a_H8bit,7         ;
      goto     a_s_next50       ;ａ群は負値
      btfsc    b_H8bit,7         ;ａ群は正値
      goto     a_s_next80      ;ｂ群は負値
      goto     a_s_next60      ;ｂ群は正値
a_s_next50  ;ａ群は負値
      btfsc    b_H8bit,7         ;
      goto    a_s_next70       ;ｂ群は負値
      goto    a_s_next90       ;ｂ群は正値

a_s_next60   ;（＋ａ群、＋ｂ群）である。Ⅰ型　
      call      sub_pa_pb         ;（＋ａ群、＋ｂ群）の加算
      bcf      c_H8bit,7          ;’＋’を保証
      goto     a_s_next500

a_s_next70   ;（－ａ群、－ｂ群）＝－（＋ａ群、＋ｂ群）である。Ⅰ型を利用できる
      call      sub_pa_pb         ;（＋ａ群、＋ｂ群）の加算
      bsf      c_H8bit,7          ;’－’を保証
      goto     a_s_next500

a_s_next80   ;（＋ａ群、－ｂ群）である。Ⅱ型　
      call     comp_16bit        ;２進数１６ビットの大小比較
      btfsc   flag,0               ;ｆｌａｇ，０　ａ群＞＝ｂ群の時、０。ａ群＜ｂ群の時、１
      goto    a_s_next86
    ;ａ群＞＝ｂ群の時である。a_L8bit<b_L8bitの時もある
      call      sub_pa_mb         ;（＋ａ群、－ｂ群）の減算　
      bcf       c_H8bit,7         ;’＋’を保証
      goto     a_s_next500      ;
a_s_next86
    ;ａ群＜ｂ群である。ａ群とｂ群を入れ替え、sub_pa_mb を利用する。
      movff   a_H8bit,c_H8bit   ;
      movff   b_H8bit,a_H8bit   ;
      movff   c_H8bit,b_H8bit   ;
      movff   a_L8bit,c_L8bit    ;
      movff   b_L8bit,a_L8bit    ;
      movff   c_L8bit,b_L8bit    ;
      call      sub_pa_mb         ;（＋ａ群、－ｂ群）の減算
      bsf       c_H8bit,7          ;’－’を保証
      goto     a_s_next500

a_s_next90   ;（－ａ群、＋ｂ群）＝－（＋ａ群、－ｂ群）である。Ⅱ型を利用できる
      call      comp_16bit        ;２進数１６ビットの大小比較
      btfsc    flag,0               ;ｆｌａｇ，０　ａ群＞＝ｂ群の時、０。ａ群＜ｂ群の時、１
      goto     a_s_next88
    ;ａ群＞＝ｂ群の時である。a_L8bit<b_L8bitの時もある
      call      sub_pa_mb         ;（＋ａ群、－ｂ群）の減算　
      bsf      c_H8bit,7           ;’－’を保証
      goto     a_s_next500       ;
a_s_next88
    ;ａ群＜ｂ群である。ａ群とｂ群を入れ替え、sub_pa_mb を利用する。
      movff   a_H8bit,c_H8bit    ;
      movff   b_H8bit,a_H8bit    ;
      movff   c_H8bit,b_H8bit    ;
      movff   a_L8bit,c_L8bit     ;
      movff   b_L8bit,a_L8bit     ;
      movff   c_L8bit,b_L8bit     ;
      call      sub_pa_mb          ;（＋ａ群、－ｂ群）の減算
      bcf       c_H8bit,7           ;’＋’を保証

a_s_next500  
                                       ;
         return

;*************************************************
;（＋ａ群、－ｂ群）の減算　
;注意　a_L8bit<b_L8bitの時もある。
sub_pa_mb
      bcf      a_H8bit,7   ;数値の絶対値化保証
      bcf      b_H8bit,7   ;
      movf    b_L8bit,0          ;
      cpfslt   a_L8bit            ;a_L8bit<b_L8bitの時、
      goto     s_p_m_next10    ;
      goto     s_p_m_next20    ;Ｈビットからの桁下ろしが必要
s_p_m_next10    ;a_L8bit>b_L8bitの時である。そのまま、ａ群－ｂ群を実行できる。
      movf    b_L8bit,0           ;
      subwf   a_L8bit,0          ;a_H8bit-b_H8bit
      movwf  c_L8bit            ;       →c_H8bit 
      movf    b_H8bit,0          ;
      subwf   a_H8bit,0          ;a_H8bit-b_H8bit
      movwf  c_H8bit            ;     →c_H8bit 
      goto     s_p_m_next50  ;
s_p_m_next20    ;a_L8bit<b_L8bitの時である
      movf    b_L8bit,0           ;桁下ろしをする
      sublw   b'11111111'      ;b'11111111'-b_L8bit→W
      addwf   a_L8bit,1           ;b'11111111'-b_L8bit+a_L8bit→a_L8bit
      incf      a_L8bit,1           ;
      movff    a_L8bit,c_L8bit   ;
      decf     a_H8bit,1          ;桁下ろしの部分。終了。
      movf    b_H8bit,0           ;
      subwf   a_H8bit,0           ;a_H8bit-b_H8bit→W
      movwf   c_H8bit            ;   W→c_H8bit

s_p_m_next50

      return
;*********************************************************
;（＋ａ群、＋ｂ群）の加算
sub_pa_pb       
      bcf      a_H8bit,7   ;数値の絶対値化保証
      bcf      b_H8bit,7   ;
      movf    b_L8bit,0         ;b_L8bit→W
      addwf   a_L8bit,1         ;a_L8bit+b_L8bit→a_L8bit 
      btfsc   STATUS,C        ;
      incf     a_H8bit,1          ;キャリーがあれば、桁上げ処理　a_H8bit+1t→a_H8bit 
      movff   a_L8bit,c_L8bit   ;a_L8bit(=a_L8bit+b_L8bit)→c_L8bit 
      movf    b_H8bit,0         ;b_H8bit→W
      addwf   a_H8bit,1          ;a_H8bit+b_H8bit→a_H8bit 
      movff   a_H8bit,c_H8bit  ;a_H8bit(=a_H8bit+b_H8bit)→c_H8bit 

      return

;**********************************************************
;２進数１６ビットの大小比較
;入力　　ａ群、ｂ群
;結果ビット　ｆｌａｇ，０　ａ群＞＝ｂ群の時、０。ａ群＜ｂ群の時、１
comp_16bit
      bcf      a_H8bit,7   ;数値の絶対値化保証
      bcf      b_H8bit,7   ;
      movf    b_H8bit,0   ;b_H8bit→W
      cpfslt    a_H8bit     ;a_H8bit<b_H8bitの時、スキップ
      goto     comp16_next10   ;
      goto     comp16_next80   ;a_H8bit<b_H8bit
comp16_next10    ;a_H8bit>=b_H8bitである
      movf    b_H8bit,0            ;
      cpfseq  a_H8bit              ;a_H8bit=b_H8bitの検査。＝の時、スキップ。
      goto     comp16_next90   ;
    ;a_H8bit=b_H8bitである。下位バイトでの大小比較をする。
      movf    b_L8bit,0            ;b_L8bit→W
      cpfslt    a_L8bit               ;a_L8bit<b_L8bitの時、スキップ
      goto     comp16_next90   ;a_L8bit>=b_L8bitである
      goto     comp16_next80   ;a_L8bit<b_L8bit

comp16_next80
    ;ａ群値＜ｂ群値が決定。終了
      bsf    flag,0                   ;ステータスを１と定義
      goto  comp16_next100

comp16_next90
    ;ａ群値＞＝ｂ群値が決定。終了
      bcf    flag,0                   ;ステータスを０と定義

comp16_next100

       return

;**********************************************************
;２つの符号付き５桁１０進数の加減算の試験用。注意　ルーチン内でエンドレスだよ。
test_add_sub_5_10dec     
test_loop  
     movlw   b'00101101'  ;
     movwf   u_sign
     movlw   2
     movwf   u_fig10000  ;
     movlw   9
     movwf   u_fig1000  ;
     movlw   9
     movwf   u_fig100  ;
     movlw   9
     movwf   u_fig10  ;
     movlw   9
     movwf   u_fig1  ;

     movlw   b'00101011'  ;
     movwf   w_sign
     movlw   1
     movwf   w_fig10000  ;
     movlw   9
     movwf   w_fig1000  ;
     movlw   7
     movwf   w_fig100  ;
     movlw   5
     movwf   w_fig10  ;
     movlw   3
     movwf   w_fig1  ;

     call    clear_out       ;画面クリア
     call    wait_1sec      ;
     call    home_out      ;カーソルホーム

     trans  u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
     movff  u_sign,lcd_data
     call     lcd_sigout
     call     Disp_5dec
     trans  w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
     movff  w_sign,lcd_data
     call     lcd_sigout
     call     Disp_5dec

      call   add_sub_exe   ;符号付き、５桁１０進数の加減算
          ;入力変数　u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
          ;              w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1 
          ;出力変数  w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
          ;
          ;　文字’＋’＝ｂ００１０１０１１，　’－’＝ｂ００１０１１０１。従って、第２ビット目だけで識別できる。
     call    third_column
     call    wait_50us
     trans  w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
     movff  w_sign,lcd_data
     call     lcd_sigout
     call     Disp_5dec

     call     wait_1sec
     goto   test_loop

     return

;*******************************************************************
;符号付き、５桁１０進数の加減算
;入力変数　u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
;              w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1 
;出力変数  w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
;
;　文字’＋’＝ｂ００１０１０１１，　’－’＝ｂ００１０１１０１。従って、第２ビット目だけで識別できる。
;処理のアルゴリズム
;　（１）＋ｕ＋w　加算式を利用し、ｕ＋wを計算し、ｗに代入し、符号を付けて、結果は「＋ｗ」
;　（２）－ｕ－w＝－（＋ｕ＋ｗ）　計算（１）を利用し、ｗに代入し、符号を付けて、結果は「－ｗ」
;　（３）＋ｕ－w　ｕ＞＝wの時、減算式を利用し、ｕ－wを計算し、ｗに代入し、符号を付けて、結果は「＋ｗ」
;　　　　　　　　　　ｕ＜wの時、減算式を利用し、w－ｕを計算し、ｗに代入し、符号を付けて、結果は「－ｗ」　
;　（４）－ｕ＋ｗ＝－（＋ｕ－w）　計算（３）を利用し、ｕ＞＝ｗの時、逆符号を付けて、結果は「－ｗ」
;　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　ｕ＜wの時、逆符号を付けて、結果は「＋ｗ」　
add_sub_exe
       btfsc   u_sign,1        ;１＝’＋’、０＝’－’
       goto    as_next100   ;ｕ群が正値の処理へ
       goto    as_next200   ;ｕ群が負値の処理へ
as_next100                    ;ｕ群は正値である
       btfsc   w_sign,1       ;
       goto    as_next300  ;ｗ群も正値の処理へ
       goto    as_next400  ;ｗ群が負値の処理へ
as_next200                    ;ｕ群は負値である
       btfsc   w_sign,1       ;
       goto    as_next500  ;ｗ群が正値の処理へ
       goto    as_next600  ;ｗ群も負値の処理へ

as_next300  ;ｕ群は正値。ｗ群も正値である。正値同士の加算を行おう。
      call       add_5dec      ;結果はｗ群が保持。
      movlw   b'00101011'   ;
      movwf  w_sign           ;文字’＋’を保証
      goto     as_next900    ;

as_next400  ;ｕ群は正値。ｗ群は負値である。
      ;ｕ群とｗ群の大小比較
      call     comp_5_10dec   ;結果はflag,0にある
      btfsc   flag,0               ;
      goto    as_next450       ;
   ;｜ｕ群｜＞＝｜ｗ｜群である。ｕ群－ｗ群を実行。差の結果は正値
      call        sub_5dec        ;１０進数５桁の減算を実行。結果はｗ群が保持。
      movlw    b'00101011'     ;
      movwf    w_sign            ;符号＋を保証
      goto       as_next900      ;
as_next450 
   ;｜ｕ群｜＜｜ｗ｜群である。ｗ群とｕ群を入れ替え、ｕ群－ｗ群を実行。差の結果は負値
      trans   u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1,v_sign,v_fig10000,v_fig1000,v_fig100,v_fig10,v_fig1
      trans   w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1,u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      trans   v_sign,v_fig10000,v_fig1000,v_fig100,v_fig10,v_fig1,w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
                                ;値の入れ替え
      call        sub_5dec             ;１０進数５桁の減算を実行。結果はｗ群が保持。
      movlw    b'00101101'          ;
      movwf    w_sign                 ;符号－を保証
      goto       as_next900           ;

as_next500                ;ｕ群は負値。ｗ群は正値である。
      ;ｕ群とｗ群の大小比較
      call     comp_5_10dec   ;結果はflag,0にある
      btfsc   flag,0               ;
      goto    as_next550       ;
   ;｜ｕ群｜＞＝｜ｗ｜群である。ｕ群－ｗ群を実行。差の結果は負値
      call        sub_5dec        ;１０進数５桁の減算を実行。結果はｗ群が保持。
      movlw    b'00101101'     ;
      movwf    w_sign            ;符号－を保証
      goto       as_next900      ;
as_next550 
   ;｜ｕ群｜＜｜ｗ｜群である。ｗ群とｕ群を入れ替え、ｕ群－ｗ群を実行。差の結果は正値
      trans   u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1,v_sign,v_fig10000,v_fig1000,v_fig100,v_fig10,v_fig1
      trans   w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1,u_sign,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      trans   v_sign,v_fig10000,v_fig1000,v_fig100,v_fig10,v_fig1,w_sign,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
                                ;値の入れ替え
      call        sub_5dec             ;１０進数５桁の減算を実行。結果はｗ群が保持。
      movlw    b'00101011'          ;
      movwf    w_sign                 ;符号＋を保証
      goto       as_next900           ;

as_next600   ;ｕ群は負値。ｗ群も正値である。正値の加算とみなして、符号をマイナスとする。
      call      add_5dec      ;結果はｗ群が保持。
      movlw  b'00101101'   ;
      movwf  w_sign          ;文字’ー’を保証

as_next900

       return

;***********************************************************
;２つの５桁１０進数の絶対値での大小比較
;入力変数　u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
;              w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1 
comp_5_10dec
      movf    w_fig10000,0          ;w_fig10000→W  ;
      cpfslt   u_fig10000           ;u_fig10000<w_fig10000の時、スキップ。
      goto     com_next10         ;
      goto     com_next80          ;
com_next10     ; u_fig10000>=w_fig10000である
      movf    w_fig10000,0          ;w_fig10000→W  ;
      cpfseq  u_fig10000          ;u_fig10000=w_fig10000の検査
      goto     com_next90         ;
   ;u_fig10000=w_fig10000である。下の桁を調べる。
      movf     w_fig1000,0           ;w_fig1000→W  ;
      cpfslt    u_fig1000            ;u_fig1000<w_fig1000の時、スキップ。
      goto      com_next20        ;
      goto      com_next80         ;
com_next20     ; u_fig1000>=w_fig1000である
      movf     w_fig1000,0           ;w_fig1000→W  ;
      cpfseq   u_fig1000           ;u_fig1000=w_fig1000の検査
      goto      com_next90         ;
   ;u_fig1000=w_fig1000である。下の桁を調べる。
      movf     w_fig100,0           ;w_fig100→W  ;
      cpfslt    u_fig100            ;u_fig100<w_fig100の時、スキップ。
      goto      com_next30       ;
      goto      com_next80       ;
com_next30     ; u_fig100>=w_fig100である
      movf     w_fig100,0           ;w_fig100→W  ;
      cpfseq   u_fig100            ;u_fig100=w_fig100の検査
      goto      com_next90        ;
   ;u_fig100=w_fig100である。下の桁を調べる。
      movf     w_fig10,0             ;w_fig10→W  ;
      cpfslt    u_fig10              ;u_fig10<w_fig10の時、スキップ。
      goto      com_next40        ;
      goto      com_next80        ;
com_next40     ; u_fig10>=w_fig10である
      movf     w_fig10,0             ;w_fig10→W  ;
      cpfseq   u_fig10              ;u_fig10=w_fig10の検査
      goto      com_next90        ;
   ;u_fig10=w_fig10である。下の桁を調べる。
      movf     w_fig1,0               ;w_fig1→W  ;
      cpfslt    u_fig1                ;u_fig1<w_fig1の時、スキップ。
      goto      com_next50        ;
      goto      com_next80        ;
com_next50     ; u_fig1>=w_fig1である
      movf     w_fig1,0               ;w_fig1→W  ;
      cpfseq   u_fig1                ;u_fig1=w_fig1の検査
      goto      com_next90        ;
   ;u_fig1=w_fig1である。u群値＝w群値が決定。終了
      bcf        flag,0                ;ステータスを０と定義
      return

com_next80  
   ;u群値＜w群値が決定。終了
      bsf       flag,0                 ;ステータスを１と定義
      return

com_next90
   ;ｕ群値＞ｗ群値が決定。終了
      bcf       flag,0                 ;ステータスを０と定義
      return

;***********************************************************
;５桁１０進数正値同志の減算。ただし、当面、　前者値＞＝後者値とする
;入力　u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1＞＝w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
;出力　w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
;演算の方法　ｕ群で全ての桁で桁落としをしておく。その後、ｗ群で引く。結果に９以上の桁があるかもしれないので、
;　　　　　　　　桁上げをして、終了。
sub_5dec
   ;ｕ群値がゼロならば、ｗ群値もゼロなので、即終了。
       tstfsz   u_fig10000    ;値がゼロならば、次の命令をスキップ
       goto     s5_next10    ;
       tstfsz   u_fig1000      ;
       goto     s5_next20     ;
       tstfsz   u_fig100       ;
       goto     s5_next30     ;
       tstfsz   u_fig10         ;
       goto     s5_next40     ;
       tstfsz   u_fig1 ;
       goto     s5_next50     ;最下位桁だけが０でないので、桁卸し不要。
       goto     s5_next900    ;ｕ群値がゼロ．当然ｗ群値もゼロ。即、終了

s5_next10    ;ｕ群で４桁で桁落としをしておく
        decf    u_fig10000,1  ;桁落とし
        movlw  10              ;
        addwf   u_fig1000,1   ;下位桁を＋１０する
s5_next20    ;ｕ群で３桁で桁落としをしておく
        decf    u_fig1000,1  ;桁落とし
        movlw  10              ;
        addwf   u_fig100,1   ;下位桁を＋１０する
s5_next30    ;ｕ群で２桁で桁落としをしておく
        decf    u_fig100,1  ;桁落とし
        movlw  10              ;
        addwf   u_fig10,1   ;下位桁を＋１０する
s5_next40    ;ｕ群で１桁で桁落としをしておく
        decf    u_fig10,1  ;桁落とし
        movlw  10              ;
        addwf   u_fig1,1   ;下位桁を＋１０する
s5_next50

   ;ｕ群－ｗ群の計算を実行する
      movf     w_fig1,0             ;w_fig1→W
      subwf    u_fig1,0              ;u_fig1-w_fig1→w。
      movwf   w_fig1                ;w→w_fig1
      movf     w_fig10,0            ;w_fig10→W
      subwf    u_fig10,0            ;u_fig10-w_fig10→w。
      movwf   w_fig10              ;w→w_fig10
      movf     w_fig100,0           ;w_fig100→W
      subwf    u_fig100,0           ;u_fig100-w_fig100→w。
      movwf   w_fig100             ;w→w_fig100
      movf     w_fig1000,0          ;w_fig1000→W
      subwf    u_fig1000,0          ;u_fig1000-w_fig1000→w。
      movwf   w_fig1000            ;w→w_fig1000
      movf     w_fig10000,0        ;w_fig10000→W
      subwf    u_fig10000,0        ;u_fig10000-w_fig10000→w。
      movwf   w_fig10000          ;w→w_fig10000

   ;各桁に９以上の数値がある場合がある。最終的に、桁上げをしておく
      movlw   10              ;１０→Ｗ
      cpfslt    w_fig1          ;ｆ＜Ｗならば、スキップ
      goto     s5_next300    ;
      goto     s5_next310    ; 
s5_next300
      subwf    w_fig1,1       ;w_fig1-10→w_fig1。
      incf       w_fig10,1     ;桁送り
s5_next310     ;桁送り無し
      movlw   10               ;
      cpfslt    w_fig10         ;
      goto     s5_next320    ;
      goto     s5_next330    ; 
s5_next320
      subwf    w_fig10,1      ;w_fig10-10→w_fig10。
      incf       w_fig100,1     ;桁送り
s5_next330     ;桁送り無し
      movlw   10               ;
      cpfslt    w_fig100       ;
      goto     s5_next340    ;
      goto     s5_next350    ; 
s5_next340
      subwf    w_fig100,1     ;w_fig100-10→w_fig100。
      incf       w_fig1000,1     ;桁送り
s5_next350     ;桁送り無し
      movlw   10              ;
      cpfslt    w_fig1000     ;
      goto     s5_next360    ;
      goto     s5_next370    ; 
s5_next360
      subwf    w_fig1000,1    ;w_fig1000-10→w_fig1000。
      incf       w_fig10000,1     ;桁送り
s5_next370     ;桁送り無し

s5_next900

       return

;*******************************************************************
;ｘ、ｙ、ｘ各軸の符号付き５桁１０進数を、ＬＣＤに表示してみよう
disp_xyz_10dec
      call     fourth_column      ;カーソルを第４行に移動
      call     wait_50us

      trans   x_sign,x_fig10000,x_fig1000,x_fig100,x_fig10,x_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
      movff  sign,lcd_data         ;
      call     lcd_sigout            ;ＬＣＤの第１欄に符号を表示。
      call     Disp_5dec            ;５桁１０進数をＬＣＤに表示

      trans   y_sign,y_fig10000,y_fig1000,y_fig100,y_fig10,y_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
      movff  sign,lcd_data         ;
      call     lcd_sigout            ;ＬＣＤの第１欄に符号を表示。
      call     Disp_5dec            ;５桁１０進数をＬＣＤに表示

      trans   z_sign,z_fig10000,z_fig1000,z_fig100,z_fig10,z_fig1,sign,fig10000,fig1000,fig100,fig10,fig1
      movff  sign,lcd_data         ;
      call     lcd_sigout            ;ＬＣＤの第１欄に符号を表示。
      call     Disp_5dec            ;５桁１０進数をＬＣＤに表示

      return

;*******************************************************************
;１６ビットデータ→正負５桁１０進数に変換し、ＬＣＤにも表示。試験用。
test_16bit_5_10dec
         ;１６ビットダミーデータの設定と表示
     clrf   H8bit
     clrf   L8bit
disp_repeat
     call     clear_out       ;画面クリア
     call     home_out      ;カーソルホーム
     movff  H8bit,work   
     call     Disp_8bit
     movff  L8bit,work 
     call     Disp_8bit    ;
     call     Conv_16bit_5dec
     call     second_column
     call     wait_50us
     movff  sign,lcd_data  ;
     call     lcd_sigout     ;ＬＣＤの第１欄に符号を表示。

     call   Disp_5dec
     call   wait_1sec
     incf  L8bit,1         ;
     btfsc  STATUS,C   ;L8bitがキャリーオーバーすると、Ｃ＝１
     incf   H8bit,1        ;その時は、H8bitを桁上げする。

     goto   disp_repeat

     return

;***********************************************************
;５桁１０進数正値同志の加算
;入力　u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1　w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
;出力　w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
add_5dec
  ;各桁ごとの基本の加算
       movf   u_fig1,0         ;u_fig1→W
       addwf  w_fig1,1         ;u_fig1+w_fig1→w_fig1 １桁目　１の位
       movf   u_fig10,0        ;u_fig10→W
       addwf  w_fig10,1         ;u_fig10+w_fig10→w_fig10　２桁目　十の位
       movf   u_fig100,0       ;u_fig100→W
       addwf  w_fig100,1       ;u_fig100+w_fig100→w_fig100　３桁目　百の位
       movf   u_fig1000,0     ;u_fig1000→W
       addwf  w_fig1000,1     ;u_fig1000+w_fig1000→w_fig1000　４桁目　千の位
       movf   u_fig10000,0   ;u_fig10000→W
       addwf  w_fig10000,1   ;u_fig10000+w_fig10000→w_fig10000　４桁目　万の位
  ;各位に十以上の値がある場合には、桁上げ処理が必要
       movlw  10    ;
       cpfslt   w_fig1   ;
       goto   a5_next10   ;w_fig1>=10の時。桁上げ処理へ
       goto   a5_next12    ;w_fig1<10である。処理不要
a5_next10
       subwf  w_fig1,1       ;w_fig1-10→w_fig1
       incf    w_fig10,1      ;w_fig10を＋１して桁送り。
a5_next12
       movlw  10             ;
       cpfslt   w_fig10         ;
       goto   a5_next14    ;w_fig10>=10の時。桁上げ処理へ
       goto   a5_next16    ;w_fig10<10である。処理不要
a5_next14
       subwf  w_fig10,1       ;w_fig10-10→w_fig10
       incf    w_fig100,1      ;w_fig100を＋１して桁送り。
a5_next16
       movlw  10    ;
       cpfslt   w_fig100   ;
       goto   a5_next18   ;w_fig100>=10の時。桁上げ処理へ
       goto   a5_next20    ;w_fig100<10である。処理不要
a5_next18
       subwf  w_fig100,1       ;w_fig100-10→w_fig100
       incf    w_fig1000,1      ;w_fig1000を＋１して桁送り。
a5_next20
       movlw  10    ;
       cpfslt   w_fig1000   ;
       goto   a5_next22   ;w_fig1000>=10の時。桁上げ処理へ
       goto   a5_next24    ;w_fig1000<10である。処理不要
a5_next22
       subwf  w_fig1000,1       ;w_fig1000-10→w_fig1000
       incf    w_fig10000,1      ;w_fig10000を＋１して桁送り。
a5_next24

       return

;*******************************************************
;２進数１６ビットデータを１０進数５桁（－３２７６７～＋３２７６７）に変換する。
;但し、最高位の１６ビット目は符号ビット。０＝＋、１＝－。
;入力　　H8bit,L8bit
;出力　　sign,fig10000,fig1000,fig100,fig10,fig1
Conv_16bit_5dec

   clrf   u_fig10000
   clrf   u_fig1000
   clrf   u_fig100
   clrf   u_fig10
   clrf   u_fig1
   clrf   w_fig10000
   clrf   w_fig1000
   clrf   w_fig100
   clrf   w_fig10
   clrf   w_fig1

  ;数値の正負の検査
      btfsc    H8bit,7    ;
      goto     conv_next2  ;
      goto     conv_next4  ;
conv_next2  ;第１６ビット目が’１’なので、負値である。２の補数表示。正常に戻すには反値＋１
      movlw  b'00101101'  ;マイナスーの８ビットデータ値
      movwf  sign            ;を代入
      comf   H8bit,1         ;２の補数表示のデータを、反値データに変換
      comf   L8bit,1         ;２の補数表示のデータを、反値データに変換   
      incf     L8bit,1         ;反値に＋１する
      btfsc   STATUS,C    ;キャリーが発生したならば、桁上げをする
      incf     H8bit,1         ;＋１する
      goto    conv_next8

conv_next4  ;第１６ビット目が’０’なので、正値である  
      movlw  b'00101011'  ;プラス＋の８ビットデータ値
      movwf  sign            ;を代入

conv_next8
    ;１５ビット目の処理。１ならば、１００００００００００００００ｂ＝１６３８４ｄを代入。
      btfss    H8bit,6   ;
      goto     conv_next10  
      ctrans   1,6,3,8,4,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
conv_next10
  ;１４ビット目の処理。１ならば、１０００００００００００００ｂ＝０８１９２ｄを加算する。
      btfss     H8bit,5   ;
      goto     conv_next20  
      ctrans   0,8,1,9,2,w_fig10000,w_fig1000,w_fig100,w_fig10,w_fig1
      call        add_5dec  ;u_fig+w_fig→w_fig
conv_next20
  ;１３ビット目の処理。１ならば、１００００００００００００ｂ＝０４０９６ｄを加算する。
      btfss     H8bit,4   ;
      goto     conv_next30  
      ctrans   0,4,0,9,6,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next30
  ;１２ビット目の処理。１ならば、１０００００００００００ｂ＝０２０４８ｄを加算する。
      btfss     H8bit,3   ;
      goto     conv_next40  
      ctrans   0,2,0,4,8,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next40
  ;１１ビット目の処理。１ならば、１００００００００００ｂ＝０１０２４ｄを加算する。
      btfss     H8bit,2   ;
      goto     conv_next50  
      ctrans   0,1,0,2,4,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next50
  ;１０ビット目の処理。１ならば、１０００００００００ｂ＝００５１２ｄを加算する。
      btfss     H8bit,1   ;
      goto     conv_next60  
      ctrans   0,0,5,1,2,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1 
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next60
  ;９ビット目の処理。１ならば、１００００００００ｂ＝００２５６ｄを加算する。
      btfss   H8bit,0   ;
      goto   conv_next70  
      ctrans   0,0,2,5,6,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next70
  ;８ビット目の処理。１ならば、１０００００００ｂ＝００１２８ｄを加算する。
      btfss     L8bit,7   ;
      goto     conv_next80  
      ctrans   0,0,1,2,8,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next80
  ;７ビット目の処理。１ならば、１００００００ｂ＝０００６４ｄを加算する。
      btfss     L8bit,6   ;
      goto     conv_next90  
      ctrans   0,0,0,6,4,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next90
  ;６ビット目の処理。１ならば、１０００００ｂ＝０００３２ｄを加算する。
      btfss     L8bit,5   ;
      goto     conv_next100  
      ctrans   0,0,0,3,2,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next100
  ;５ビット目の処理。１ならば、１００００ｂ＝０００１６ｄを加算する。
      btfss     L8bit,4   ;
      goto     conv_next110  
      ctrans   0,0,0,1,6,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next110
  ;４ビット目の処理。１ならば、１０００ｂ＝００００８ｄを加算する。
      btfss     L8bit,3   ;
      goto     conv_next120  
      ctrans   0,0,0,0,8,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next120
  ;３ビット目の処理。１ならば、１００ｂ＝００００４ｄを加算する。
      btfss   L8bit,2   ;
      goto   conv_next130
      ctrans  0,0,0,0,4,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next130
  ;２ビット目の処理。１ならば、１０ｂ＝００００２ｄを加算する。
      btfss   L8bit,1   ;
      goto   conv_next140
      ctrans  0,0,0,0,2,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next140
  ;１ビット目の処理。１ならば、１ｂ＝００００１ｄを加算する。
      btfss   L8bit,0   ;
      goto   conv_next150
      ctrans 0,0,0,0,1,u_fig10000,u_fig1000,u_fig100,u_fig10,u_fig1
      call       add_5dec     ;u_fig+w_fig→w_fig
conv_next150
      movff   w_fig10000,fig10000  ;
      movff   w_fig1000,fig1000  ;
      movff   w_fig100,fig100  ;
      movff   w_fig10,fig10  ;
      movff   w_fig1,fig1  ;

      return

;***************************************************
;１０進数５桁をＬＣＤに表示
;入力　　fig10000,fig1000,fig100,fig10,fig1
Disp_5dec
   movff fig10000,WREG   ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;W→lcd_data
   call      lcd_sigout      ;

   movff fig1000,WREG   ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;W→lcd_data
   call      lcd_sigout      ;
 
   movff fig100,WREG   ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;W→lcd_data
   call      lcd_sigout      ;

   movff fig10,WREG   ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;W→lcd_data
   call      lcd_sigout      ;

   movff fig1,WREG   ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;W→lcd_data
   call      lcd_sigout      ;

   return

;********************************************************************
;ＪａｉｒｏとのＳＰＩ通信
;センサーのレジスタのアドレスは処理設定ビットを含めた２バイト（８ビット＋８ビット）で指定する必要がある。
;　Ｌ３ＧＤ２０の技術資料の２６頁参照のこと。
;センサーと通信ができているかの確認部
jairo_comm_start
     bcf   PORTA,5   ;ＣＳ→Ｌレベルへ。送信開始

     movlw   b'10001111'     ;処理ビット＋レジスタアドレス
                                    ;最高位ビットの’１’は読み出し命令。
                                    ;下位の’０００１１１１’＝０ＦＨは[WHO_AM_I]名のレジスタ番地
     movwf  TXDATA          ;送信用変数に入れる
     movf    TXDATA,W       ;通信データ取りだし
     movwf  SSPBUF          ;データ送信中 
ja_comm_next_1
     btfss    SSPSTAT,BF    ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     ja_comm_next_1    ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須。

     movlw   b'10101010'     ;ダミービット。１６ビットの下位８ビット。
     movwf  TXDATA          ;送信用変数に入れる
     movf    TXDATA,W       ;通信データ取りだし
     movwf  SSPBUF          ;データ送信中 
ja_comm_next_2
     btfss    SSPSTAT,BF    ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     ja_comm_next_2    ;送信完了でＳＳＰＢＵＦは空＝０。

     call   wait_50us           ;
     bsf   PORTA,5            ;ＣＳ→Ｈレベルへ。送信終了。
     
;ここで、センサーからレジスタ内容がＰＩＣに送信され、レジスタＳＳＰＢＵＦに納まっているはず
;その内容をＬＣＤに表示させてみよう
     ;movff  SSPBUF,work   ;
     ;call     home_out   ;カーソルをホームに戻す。時間が少しかかるよ。
     ;call     Disp_8bit

     return

;************************************************************
xyz_enable
;’１１０１０１００’が読み取れたので、次に、Ｘ軸Ｙ軸Ｚ軸をイネーブルとする処理を行う。
;センサーのレジスタへの書き込み処理。　資料の２７頁参照。
     bcf   PORTA,5   ;ＣＳ→Ｌレベルへ。送信開始

     movlw   b'00100000'     ;処理ビット＋レジスタアドレス
                                    ;最高位ビットの’０’は書き込み命令。
                                    ;下位の’1０００００’＝２０Ｈは[ＣＴＲＬ＿ＲＥＧ１]名のレジスタ番地
     movwf  TXDATA          ;送信用変数に入れる
     movf    TXDATA,W       ;通信データ取りだし
     movwf  SSPBUF          ;データ送信中 
comm_next_10
     btfss    SSPSTAT,BF    ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_10  ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須。

     movlw   b'00001111'     ;＝０ＦＨ。書き込みデータ。資料の３１頁参照。
     movwf  TXDATA          ;送信用変数に入れる
     movf    TXDATA,W       ;通信データ取りだし
     movwf  SSPBUF          ;データ送信中 
comm_next_12
     btfss    SSPSTAT,BF    ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_12  ;送信完了でＳＳＰＢＵＦは空＝０。

     call   wait_50us           ;
     bsf   PORTA,5            ;ＣＳ→Ｈレベルへ。送信終了。

     return

;****************************************************
;３組の２進１６ビットデータをＬＣＤに表示する
;入力　x_H8bit,xL8bit,y_H8bit,y_L8bit,z_H8bit,z_L8bit
;
disp_xyz_16bit
     call      first_column   ;カーソルを１行目に移動
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'01011000'   ;文字’Ｘ’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;

     movff  x_H8bit,work      ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  x_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

     call   second_column     ;カーソルを２行目に移動
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'01011001'   ;文字’Ｙ’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data       ;W→lcd_data
     call      lcd_sigout       ;

     movff  y_H8bit,work      ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  y_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

     call   third_column     ;カーソルを３行目に移動
     movlw  b'00100000'   ;文字’　’を表示
     movwf  lcd_data        ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'01011010'    ;文字’Ｚ’を表示
     movwf  lcd_data         ;W→lcd_data
     call      lcd_sigout       ;
     movlw  b'00100000'    ;文字’　’を表示
     movwf  lcd_data         ;W→lcd_data
     call      lcd_sigout       ;

     movff  z_H8bit,work      ;
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう
     movff  z_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

 ;    call     home_out             ;カーソルをホームに戻す。時間が少しかかるよ。

     return

;*****************************************************
;’００１０００００’を送り出したので、Ｘ軸Ｙ軸Ｚ軸がイネーブルとなったはず。
;各軸のデータを読み出そう。
;出力　x_H8bit,xL8bit,y_H8bit,y_L8bit,z_H8bit,z_L8bit
;
read_data_repeat
;Ｘ軸周りの角速度の読み出し
  ;   call      first_column   ;カーソルを１行目に移動
 ;    movlw  b'00100000'   ;文字’　’を表示
  ;   movwf  lcd_data       ;W→lcd_data
  ;   call      lcd_sigout       ;
  ;   movlw  b'01011000'   ;文字’Ｘ’を表示
   ;  movwf  lcd_data       ;W→lcd_data
  ;   call      lcd_sigout       ;
  ;   movlw  b'00100000'   ;文字’　’を表示
  ;   movwf  lcd_data       ;W→lcd_data
  ;   call      lcd_sigout       ;

     movlw    b'10101001'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１００１’は[ＯＵＴ＿Ｘ＿Ｈ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_H8bit
     movff  SSPBUF,x_H8bit   ;予定の変数に代入

 ;    movff  x_H8bit,work      ;
;     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

     movlw    b'10101000'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１０００’は[ＯＵＴ＿Ｘ＿Ｌ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_L8bit
     movff  SSPBUF,x_L8bit   ;予定の変数に代入

 ;    movff  x_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
 ;    call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう

;Ｙ軸周りの角速度の読み出し
 ;    call   second_column     ;カーソルを２行目に移動
 ;    movlw  b'00100000'   ;文字’　’を表示
;     movwf  lcd_data       ;W→lcd_data
;     call      lcd_sigout       ;
 ;    movlw  b'01011001'   ;文字’Ｙ’を表示
 ;    movwf  lcd_data       ;W→lcd_data
;     call      lcd_sigout       ;
;     movlw  b'00100000'   ;文字’　’を表示
 ;    movwf  lcd_data       ;W→lcd_data
 ;    call      lcd_sigout       ;

     movlw    b'10101011'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１０１１’は[ＯＵＴ＿Ｙ＿Ｈ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_H8bit
     movff  SSPBUF,y_H8bit   ;予定の変数に代入

 ;    movff  y_H8bit,work      ;
 ;    call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう


     movlw    b'10101010'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１０１０’は[ＯＵＴ＿Ｙ＿Ｌ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_L8bit
     movff  SSPBUF,y_L8bit   ;予定の変数に代入 

;     movff  y_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
;     call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう


;Ｚ軸周りの角速度の読み出し
 ;    call   third_column     ;カーソルを３行目に移動
;     movlw  b'00100000'   ;文字’　’を表示
 ;    movwf  lcd_data        ;W→lcd_data
 ;    call      lcd_sigout       ;
 ;    movlw  b'01011010'    ;文字’Ｚ’を表示
 ;    movwf  lcd_data         ;W→lcd_data
 ;    call      lcd_sigout       ;
 ;    movlw  b'00100000'    ;文字’　’を表示
 ;    movwf  lcd_data         ;W→lcd_data
 ;    call      lcd_sigout       ;

     movlw    b'10101101'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１１０１’は[ＯＵＴ＿Ｚ＿Ｈ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_H8bit
     movff  SSPBUF,z_H8bit   ;予定の変数に代入

 ;    movff  z_H8bit,work      ;
 ;    call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう


     movlw    b'10101100'     ;最高位ビットの’１’は読み出し命令。
                                     ;下位の’１０１１００’は[ＯＵＴ＿Ｚ＿Ｌ]名のレジスタ番地
     movwf  TXDATA           ;送信用変数に入れる
     call   read_angle_velocity_L8bit
     movff  SSPBUF,z_L8bit   ;予定の変数に代入

 ;    movff  z_L8bit,work      ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ
 ;    call     Disp_8bit            ;その内容をＬＣＤに表示させてみよう


 ;    call     home_out             ;カーソルをホームに戻す。時間が少しかかるよ。

     return

;****************************************************
read_angle_velocity_H8bit
;まず、上位バイトを。
     bcf   PORTA,5              ;ＣＳ→Ｌレベルへ。送信開始
    
     movf    TXDATA,W        ;通信データ取りだし
     movwf  SSPBUF           ;データ送信中 
comm_next_20
     btfss    SSPSTAT,BF     ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_20   ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須。

     movlw   b'10101010'      ;ダミービット。１６ビットの下位８ビット。
     movwf  TXDATA           ;送信用変数に入れる
     movf    TXDATA,W        ;通信データ取りだし
     movwf  SSPBUF           ;データ送信中 
comm_next_22
     btfss    SSPSTAT,BF     ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_22   ;送信完了でＳＳＰＢＵＦは空＝０。

     call   wait_50us             ;
     bsf   PORTA,5              ;ＣＳ→Ｈレベルへ。送信終了。

;ここで、センサーからレジスタ内容がＰＩＣに送信され、レジスタＳＳＰＢＵＦに納まっているはず
;その内容をＬＣＤに表示させてみよう
    ; movff  SSPBUF,work      ;
    ; call     Disp_8bit

     return

;******************************************************* 
read_angle_velocity_L8bit
;次に、Ｘ軸の下位バイトを。
     bcf   PORTA,5              ;ＣＳ→Ｌレベルへ。送信開始

     movf    TXDATA,W        ;通信データ取りだし
     movwf  SSPBUF           ;データ送信中 
comm_next_24
     btfss    SSPSTAT,BF     ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_24   ;送信完了でＳＳＰＢＵＦは空＝０。このループは必須。

     movlw   b'10101010'      ;ダミービット。１６ビットの下位８ビット。
     movwf  TXDATA           ;送信用変数に入れる
     movf    TXDATA,W        ;通信データ取りだし
     movwf  SSPBUF           ;データ送信中 
comm_next_26
     btfss    SSPSTAT,BF     ;送信時　送信中でＳＳＰＢＵＦ使用中＝１、
     goto     comm_next_26   ;送信完了でＳＳＰＢＵＦは空＝０。

     call   wait_50us            ;
     bsf   PORTA,5             ;ＣＳ→Ｈレベルへ。送信終了。

;ここで、センサーからレジスタ内容がＰＩＣに送信され、レジスタＳＳＰＢＵＦに納まっているはず
;その内容をＬＣＤに表示させてみよう
    ; movff  SSPBUF,work    ;
    ; call     Disp_8bit           ;上位８ビットに下位８ビットを連続表示。合計１６ビットデータ

     return

;********************************************************************************
;カーソルの位置決めルーチン
;１行目に表示
first_column
       movlw   b'00000000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_max  ;
       bcf     contl_E 
       return

;２行目に表示
second_column
       movlw   b'11000000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_max  ;
       bcf     contl_E  
       return

;３行目に表示
third_column
       movlw   b'10010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_max  ;
       bcf     contl_E
       return

;４行目に表示
fourth_column
       movlw   b'11010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_max  ;
       bcf     contl_E
       return

;;カーソルを任意のアドレスに移動
;any_address
 ;      bcf     contl_RS     ;
 ;      bcf     contl_RW     ;
 ;      bsf     contl_E      ;
 ;      call    lcd_wait_max  ;
 ;      bcf     contl_E
 ;      return

;カーソルを１桁右に移動
cursole_right
       movlw   b'00010100'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_max  ;
       bcf     contl_E 
       return

;カーソルを１桁左に移動
cursole_left
       movlw   b'00010000'  ;
       movwf   lcd_data     ;
       bcf     contl_RS     ;
       bcf     contl_RW     ;
       bsf     contl_E      ;
       call    lcd_wait_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

;*****************************************************
;２進数８ビットデータをＬＣＤに表示する。
Disp_8bit
;入力　work
   rlncf   work,1               ;キャリー無しの左送り。低位ビットの８桁目に注目
   call     LCD_2bit_disp
   rlncf    work,1              ;低位ビットの７桁目に注目  
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの６桁目に注目 
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの５桁目に注目 
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの４桁目に注目 
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの３桁目に注目  
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの２桁目に注目
   call     LCD_2bit_disp
   rlncf    work,1             ;低位ビットの１桁目に注目 
   call     LCD_2bit_disp

   return

;*************************************************
LCD_2bit_disp
   btfsc   work,0          ;内容がゼロならば、スキップ
   goto    L2d_next10
   movlw  0                ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data       ;文字０を表示させる
   call      lcd_sigout      ;
   goto    L2d_next20
L2d_next10
   movlw  1                ;
   bsf      WREG,5        ;数値変数を文字変数とする
   bsf      WREG,4        ;
   movwf  lcd_data        ;文字１を表示させる
   call      lcd_sigout     ;
L2d_next20

   return
 
;***********************************************************************
;*************　初期設定ルーチン集  ****************************************
;ポートの初期設定
port_initial 
       clrf   PORTA
       clrf   PORTB
       clrf   PORTC
    ;Ａポート（６ビット）　
       movlw  b'00001111'       ;全てデジタル端子とする。
       movwf  ADCON1          ;
       movlw  b'00000000'       ;Ｗに２進数の00000000を入れる。ＲＡ５は出力端子。
       movwf  TRISA              ;ＲＡ４を出力端子でＬＥＤモニター端子として設定
                                       ;ＲＡ３はＤＡ変換器のＣＳ端子に接続。チップセレクト出力端子
                                       ;ＲＡ２はＤＡ変換器のＬＤＡＣ端子に接続。出力端子
       bsf     PORTA,5            ;初期値　ＣＳ＝Ｈ
       bsf     PORTA,3            ;初期値　ＣＳ＝Ｈ
       bsf     PORTA,2            ;初期値　ＣＳ＝Ｈ

   ;Ｂポートは全て（８ビット）出力端子。ＬＣＤ用データ・命令コード端子
       movlw  b'00000000'       ;Ｗに２進数の00000000を入れる
       movwf  TRISB              ;
   ;ＣポートはＲＣ３→ＳＣＫ（出力），ＲＣ４→ＳＤＩ（入力），ＲＣ５→ＳＤＯ（出力）に設定
   ;　　　　　　ＲＣ０→ＲＳ（出力），ＲＣ１→Ｒ／Ｗ（出力）、ＲＣ２→Ｅ（出力）に設定　
       movlw  b'00010000'       ;
       movwf  TRISC             ;

;ＳＰＩ通信設定
;　　SSPCON1=(WCOL,SSPOV,SSPEN,CKP,SSPM3,SSPM2,SSPM1,SSPM0)
;
       bcf   SSPCON1,SSPM3   ;(SSPM3,SSPM2,SSPM1,SSPM0)=(0,0,0,0)
       bcf   SSPCON1,SSPM2   ;ＳＰＩのマスターモード設定
       bsf   SSPCON1,SSPM1   ;クロック　Ｆｏｓｃ／６４に設定
       bcf   SSPCON1,SSPM0   ;
       bsf   SSPCON1,SSPEN    ;ＳＳＰモジュール使用可とする
       bsf   SSPCON1,CKP       ;正論理

       return

;********************************
;ＬＣＤの初期設定 
LCD_initial   
       call    wait_exe          ;ＬＣＤモジュールのウオーミングアップ時間の保証
    ;ＬＣＤの初期設定
       movlw   b'00111000'       ;Ｗレジスタの値を変数temp2に代入
       movwf   lcd_data            ;データ長８ビット、デューティ比を１／１６、
                                        ;フォントサイズを５＊７にそれぞれ設定
       call       lcd_comout        ;命令をＬＣＤに転送
    ;画面をクリアし、カーソルをホームへ戻す
       movlw   clear                 ;
       movwf   lcd_data             ;
       call       lcd_comout        ;ＬＥＤの命令処理を実行する
       movlw   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

;********************************* 
;研究室名を表示
Labo_out
       clrf    current           ;初期値を０にしておく
laboloop   
       movlw   UPPER Labo_title  ;サブルーチン　Ｌａｂｏ＿ｔｉｔｌｅのプログラム中
       movwf   TBLPTRU           ;アドレス番地を
       movlw   HIGH Labo_title    ;テーブルポインターレジスタ
       movwf   TBLPTRH           ; ＴＢＬＲＰＴＲ群に渡す。
       movlw   LOW Labo_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  charnum,1           ;charnumを－１し、結果が０の時、
       goto     laboloop             ;下の命令をスキップ      
       return

;********************************
;実行文を表示
Devise_out
       clrf    current           ;初期値を０にしておく
deviseloop   
       movlw   UPPER Devise_title    ;サブルーチン　Ｄｅｖｉｓｅ＿ｔｉｔｌｅのプログラム中
       movwf   TBLPTRU               ;アドレス番地を
       movlw   HIGH Devise_title      ;テーブルポインターレジスタ
       movwf   TBLPTRH               ; ＴＢＬＲＰＴＲ群に渡す。
       movlw   LOW Devise_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  charnum,1           ;charnumを－１し、結果が０の時、
       goto     deviseloop           ;下の命令をスキップ      
       return

;********************************************************************************
;*************  ＬＣＤ制御用各種ルーチン  ***************************************
;画面のクリア　　 約１．５ｍｓかかる
clear_out
       movlw   clear             ;画面クリアのコードの取り込み
       movwf   lcd_data          ;ＬＣＤへ送る
       call    lcd_comout  
       return   

;カーソルホーム　 約１．５ｍｓかかる
home_out
       movlw   home              ;カーソルホームのコードの取り込み
       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          ;ＬＣＤへ送る
       bcf     contl_RS          ;0として、命令コードの指定
       bcf     contl_RW          ;0として、書き込みの指定
       bsf     contl_E           ;1として、ＬＣＤの動作起動
       nop
       nop
       nop                       ;１０ＭＨｚ時は、ｎｏｐ　２つ
       nop                       ;２０ＭＨｚでは　４つとしてみる
       nop
       nop
       nop                       ;
       nop                       ;４０ＭＨｚでは　８つとしてみる
       bcf     contl_E           ;0として、ＬＣＤの動作停止
       call    lcd_wait_min      ;
       return

;時間のかかる命令の書き込みルーチン
lcd_comout
       bcf     contl_RS          ;0として、命令コードの指定
       bcf     contl_RW          ;0として、書き込みの指定
       bsf     contl_E           ;1として、ＬＣＤの動作起動
       nop
       nop                       ;
       nop                       ;１０ＭＨｚ時は、ｎｏｐ　３つ
       nop                       ;２０ＭＨｚでは、６つとしてみる
       nop                       ;
       nop
       nop
       nop                       ;
       nop                       ;
       nop                       ;４０ＭＨｚでは、１２個としてみる
       nop                       ;
       nop
       bcf     contl_E           ;0として、ＬＣＤの動作停止
       call    lcd_wait_max      ;処理時間の保証
       return
;ＬＣＤへの記号の書き込みルーチン
lcd_sigout
       bsf     contl_RS          ;1として、記号コードの指定
       bcf     contl_RW          ;0として、書き込みの指定
       bsf     contl_E           ;1として、ＬＣＤの動作起動
       nop
       nop                       ;１０ＭＨｚ時は、ｎｏｐ　３つ
       nop                       ;２０ＭＨｚでは、６つとしてみる
       nop                       ;
       nop                       ;
       nop
       nop
       nop                       ;
       nop                       ;４０ＭＨｚでは、１２個としてみる
       nop                       ;
       nop                       ;
       nop
       bcf     contl_E           ;0として、ＬＣＤの動作停止
       call    lcd_wait_min      ;処理時間の保証
       return
;命令処理の時間稼ぎ
    ;長時間用
lcd_wait_max
       movlw   0           ;１０ＭＨｚ時、（２５６，６）で約２ｍｓ
       movwf   temp0       ;
       movlw   24  ;12  ;6      ;２０ＭＨｚでは（２５６，１２）としてみる 
       movwf   temp1       ;４０ＭＨｚでは（２５６，２４）としてみる 
maxloop 
       decfsz  temp0,1     ;
       goto    maxloop     ;
       decfsz  temp1,1
       goto    maxloop
       return   
    ;短時間用
lcd_wait_min
       movlw   8           ;１０ＭＨｚ時は、（８，６）で正常
       movwf   temp0       ;
       movlw   24  ;12  ;6           ;２０ＭＨｚでは、（８，１２）としてみる 
       movwf   temp1       ;４０ＭＨｚでは、（８，２４）としてみる 
minloop  
       decfsz  temp0,1     ;
       goto    minloop     ;
       decfsz  temp1,1
       goto    minloop
 
       return   

;*********************************************************
;時間遅延ルーチン
;１μｓ幅
wait_1us
       movlw   2  ;3         ;
       movwf   temp0       ;
waitloop_1us1 
       decfsz  temp0,1     ;
       goto    waitloop_1us1   ;
       return   

;*********************************************************
;時間遅延ルーチン
;１０μｓ幅
wait_10us
       movlw   4   ;19          ;
       movwf   temp1       ; 
waitloop_10us2
       movlw   7           ;
       movwf   temp0       ;
waitloop_10us1 
       decfsz  temp0,1     ;
       goto    waitloop_10us1   ;
       decfsz  temp1,1
       goto    waitloop_10us2
       return   

;*********************************************************
;時間遅延ルーチン
;５０μｓ幅
wait_50us
       movlw   19          ;
       movwf   temp1       ; 
waitloop_50us2
       movlw   7           ;
       movwf   temp0       ;
waitloop_50us1 
       decfsz  temp0,1     ;
       goto    waitloop_50us1   ;
       decfsz  temp1,1
       goto    waitloop_50us2
       return   

;*********************************************************
;１０ｍ秒幅の時間遅延ルーチン
wait_10msec
       movlw   200   ;19          ;
       movwf   temp1       ; 
waitloop_10ms2
       movlw   160   ;70           ;
       movwf   temp0       ;
waitloop_10ms1 
       decfsz  temp0,1     ;
       goto    waitloop_10ms1   ;
       decfsz  temp1,1
       goto    waitloop_10ms2
       return   

;***************************
１００ｍ秒だけ;待機させるためのルーチン
wait_100msec   ;
       movlw   0           ;
       movwf   temp0       ;
       movwf   temp1       ;
       movlw   4   ;40         ;
       movwf   temp2       ;         
waitloop_100msec 
       decfsz  temp0,1     ;
       goto    waitloop_100msec    ;
       decfsz  temp1,1
       goto    waitloop_100msec
       decfsz  temp2,1
       goto    waitloop_100msec

       return              ;

;***************************
wait_1sec   ;待機させるためのルーチン
       movlw   0           ;
       movwf   temp0       ;
       movwf   temp1       ;
       movlw   40 ;60  ;20          ;
       movwf   temp2       ;         
waitloop_1sec 
       decfsz  temp0,1     ;
       goto    waitloop_1sec    ;
       decfsz  temp1,1
       goto    waitloop_1sec
       decfsz  temp2,1
       goto    waitloop_1sec

       return              ;

;*********  初期画面表示  **************************************************
first_LCD
   ;研究室名表示
      movlw    Laboname     ;文字数をcharnumに取り込む
      movwf    charnum
      call        Labo_out     ;１行目に表示
      call        careturn_out ;改行する

   ;デバイス名表示
      movlw    Devisename   ;文字数をcharnumに取り込む
      movwf    charnum
      call        Devise_out   ;２行目に表示
      return

;*************  その他  ****************************************************
wait_exe   ;ＬＣＤのプログラムの実行を少し待機させるためのルーチン
       movlw   0           ;（０，０，４）の組み合わせで、約２００ｍｓの遅延時間
       movwf   temp0       ;（０，０，１）ならば、約５０ｍｓ
       movwf   temp1
       movlw   2  ;1       ２００６年１０月６日ＧＰＳ－３号の論文にページ注釈あり
       movwf   temp2         
waitloop 
       decfsz  temp0,1     ;
       goto    waitloop    ;
       decfsz  temp1,1
       goto    waitloop
       decfsz  temp2,1
       goto    waitloop
       return              ;

;****************************************************************************
;****************************************************************************
 
       end
       

