;**********************
;加速度ロガーVer5(232C)
;**********************
; BASEはVer4_14_232c.asm
; RS232C垂れ流し版
;
;Ver.5_1('08/09/28)
; 232C出力にペダル情報追加
; 車速PICからのペダル情報受信追加
;
;Ver.5_2('08/09/28)
;車速変換見直し→失敗
;
;Ver.5_3('08/09/30)
;車速8bit+ペダル4bitを受信する仕様
;
;Ver.5_4('08/10/01)
;ペダル出力値オフセット
;
;Speed_Ver4_4.asmと対応
;**********************
;
;PIC16F84A:4MHz用(1cycle=1μs)
;
;電源を入れて,SW1を押すとデータ送信モード,SW2を押すとデータ計測モード
;SW両方押しで停止モード
;
;⇒データ計測モードSW2
; 計測開始,0.1secごとに**分間まで(メモリいっぱい使用)
; X下位,X上位,Y下位,Y上位の順に4バイトずつ書き込み
; 12000ポイント×4バイト=48000バイト
; 中断操作(ボタンを二つ1秒以上押す)まで繰り返す。
;
;⇒データ送信モードSW1
; 9600bps,8bit,1stopbit
; パリティなし,フロー制御なし
; SW1を押すと,テキストデータが順に流れてくる
;
;
;
; ピン・アサイン
; RA0 →CLK(ADコンバータ)
; RA1 →CS(ADコンバータ)
; RA2 ⇔EEPROM SDA
; RA3 →EEPROM SCLK
; RA4 ←SP_CLK(車速用PIC)
; RB0 ←SP_DATA(車速用PIC)
; RB1 →RS232C送信
; RB2 ←D-OUT(ADコンバータ)
; RB3 →D_IN(ADコンバータ)
; RB4 →SP_REQ車速要求信号(車速用PICへ)
; RB5 ←プッシュSW2;データ記録開始モード
; RB6 →LED(0でOFF,1でON)
; RB7 ←プッシュSW1;データ送信モード
;
;
;***************************************

LIST P=PIC16F84A
INCLUDE "P16F84A.INC"

;****************
; 変数レジスタ定義 0CH〜7FHが汎用レジスタ
;****************

;---------EEPROM関連----------
eeprom equ 0CH ; eeprom ビット書き込み/読み込み用レジスタ
addrl equ 0EH ; eeprom アドレス(下位)
addrh equ 0FH ; eeprom アドレス(上位)
datai equ 10H ; eeprom 読み込み用データ
datao equ 11H ; eeprom 書き込み用データの1バイト目
datao2 equ 12H ; eeprom 書き込み用データの2バイト目
datao3 equ 13H ; eeprom 書き込み用データの1バイト目
datao4 equ 14H ; eeprom 書き込み用データの2バイト目
txbuf equ 16H ; eeprom 変数受け渡し用
count equ 17H ; eeprom ビット・カウンタ

;--------時間待ちループ用----------
counta equ 19H ; 時間待ち用のカウンタ
countb equ 1AH
countc equ 1BH
countd equ 1CH
counte equ 1DH ; 汎用カウンタ
countf equ 1EH

;---------RS-232C用--------
sendt equ 1FH ; RS232C通信ウエイト時間の調整用
bitw equ 20H ; 送信中ビット数のカウント
txdata equ 21H ; 送信データ(8バイト)格納用変数

;---------パルスカウント-----
xplsh equ 2AH ; X軸パルス・カウンタ上位
xplsl equ 2BH ; X軸パルス・カウンタ下位
yplsh equ 2CH ; Y軸パルス・カウンタ上位
yplsl equ 2DH ; Y軸パルス・カウンタ下位

datao5 equ 22H ; eeprom 書き込み用データの1バイト目
datao6 equ 23H ; eeprom 書き込み用データの2バイト目

;--------10進数変換用--------
hexh equ 31H ; 16進数上位
hexl equ 32H ; 16進数下位
decxhh equ 3CH ; 10進数・千の位
decxh equ 2EH ; 10進数・百の位
decxm equ 2FH ; 10進数・十の位
decxl equ 30H ; 10進数・一の位
decyhh equ 43H ; 10進数・千の位
decyh equ 44H ; 10進数・百の位
decym equ 45H ; 10進数・十の位
decyl equ 46H ; 10進数・一の位
decshh equ 47H ; 10進数・千の位
decsh equ 48H ; 10進数・百の位
decsm equ 49H ; 10進数・十の位
decsl equ 4AH ; 10進数・一の位
dechh equ 4BH ; 10進数・千の位
dech equ 4CH ; 10進数・百の位
decm equ 4DH ; 10進数・十の位
decl equ 4EH ; 10進数・一の位
;--------メイン・ルーチン用--------
stepl equ 33H ; ステップ数カウンタ下位(960分カウンタ)
steph equ 34H ; ステップ数カウンタ上位
OUTBUF equ 35H ;
INBUFH equ 36H ;
INBUFL equ 37H ;
COUNT equ 38H ;
COUNT2 equ 3BH ;
Pedal equ 3CH ; ペダル情報
old_plsl equ 3DH ; 前回車速パルス下位
old_plsh equ 3EH ; 前回車速パルス上位
;**********ADコンバータ************
ADCS equ 0x02 ; chip select line A/D
plsl equ 40H ; 車速信号受信データ下位
plsh equ 41H ; 車速信号受信データ上位
countg equ 42H ; 汎用カウンタ
ch_cntl equ 26H ; アナログ入力CH切り替え
d_data1 equ 27H ; AD変換データ格納先
d_data2 equ 28H ; AD変換データ格納先
data_buf equ 29H ;

;*******************
;ビット定義など
;*******************

di equ 7 ; eeprom入力はeepromレジスタの7ビット目
do equ 6 ; eeprom出力はeepromレジスタの6ビット目
sdata equ 2 ; SDA接続ポートはRA2
sclk equ 3 ; SCL接続ポートはRA3
ackf equ 6 ; EEPROM警告LEDはRB4
btime equ D'31' ; RS232C通信速度設定用変数 9600bps@4MHz
; btime=((オシレータ周波数(Hz)/転送スピード(bps)/4)-10)/3
org 0

;**********************
; ポート・セット,初期化
;**********************

bsf STATUS,RP0 ; TRIS設定のためバンクを切り替える
movlw b'00010000' ; PORTA入出力設定:RA4を入力(1)ほかは出力(0)に設定
movwf TRISA
movlw b'10100101' ; PORTB入出力設定:RB0,RB2,RB5,RB7が入力(1),ほかは出力(0)に設定
movwf TRISB
bcf STATUS,RP0 ; TRIS設定が終了したのでバンクを元にもどす

movlw b'00000010' ; PORTA初期化(5V=1,0V=0)
movwf PORTA
movlw b'00000010' ; PORTB初期化(5V=1,0V=0)
movwf PORTB

;****************************
;メインルーチン
;****************************

; SWが押されたか監視,SW1(RB7)でデータ送信モード
; SW2(RB5)でデータ記録開始
; その間,LEDが400ms周期で点滅

MENU1
movlw 0C8H ; カウンタを200にセット
movwf counte
bsf PORTB,6 ; LED点灯
bcf PORTB,4 ; SP_REQ=RB4をLO(初期化)

MENU2
call WAIT_1M ; 1ms時間待ち
; btfss PORTB,7 ; SW1が1(OFF)だったらスキップ
; goto DATATR ; onだったらデータ送信モードへ

btfss PORTB,5 ; SW2が1(OFF)だったらスキップ
goto LOG ; onだったらデータ計測モードへ

decfsz counte,f
goto MENU2 ; 200回ループ

movlw 0C8H ; カウンタを200にセット
movwf counte
bcf PORTB,6 ; LED消灯

MENU3
call WAIT_1M ; 1ms時間待ち
; btfss PORTB,7 ; SW1が1(OFF)だったらスキップ
; goto DATATR ; onだったらデータ送信モードへ

btfss PORTB,5 ; SW2が1(OFF)だったらスキップ
goto LOG ; onだったらデータ計測モードへ

decfsz counte,f
goto MENU3 ; 200回ループ

goto MENU1

;********************************
; データ計測モード
;********************************

;**********初期化***********
LOG
; movlw 060H ; ステップ・カウンタのリセット,計測可能時間の制限
; movwf stepl ; 4バイト(65536(0000H))-12000ステップ(20分,1ステップ0.1s)
; movlw 073H ; 1ずつ加算していき,0になったら記録終了
; movwf steph

; clrf addrl ; eeprom書き込みアドレスリセット
; clrf addrh

;*******データ計測********
LOG0
call Speed ; 車速データ受信
call Gmeas ; 加速度センサ・パルス計測

;*******データの記録********

; movf xplsl,w ; X軸データを前ターン用変数にセット
; movwf datao
; movf xplsh,w
; movwf datao2
; movf yplsl,w ; Y軸データを前ターン用変数にセット
; movwf datao3
; movf yplsh,w
; movwf datao4
; movf plsl,w ; 車速データを前ターン用変数にセット
; movwf datao5
; movf plsh,w
; movwf datao6

call DATATR ;RS232C出力へ

; call EEPWT ;EEPROM書き込み
;
; incfsz addrl,f ;書き込みアドレス+6加算,0なら次をスキップ
; goto skip1
; incf addrh,f
;skip1
; incfsz addrl,f
; goto skip2
; incf addrh,f
;skip2
; incfsz addrl,f
; goto skip3
; incf addrh,f
;skip3
; incfsz addrl,f
; goto skip4
; incf addrh,f
;skip4
; incfsz addrl,f
; goto skip5
; incf addrh,f
;skip5
; incfsz addrl,f
; goto LOG2
; incf addrh,f

;*******カウンタ処理*********
;LOG2
; incfsz stepl,f ;ステップカウンタ加算
; goto LOG3
; incfsz steph,f
; goto LOG4
; goto LOGend

;LOG3
; nop
; nop
;*******SW入力(中断処理)********
LOG4
btfsc PORTB,7
goto LOG5
btfsc PORTB,5
goto LOG6

goto LOGend

LOG5
nop
nop

;********LED点滅**********
LOG6
; bsf PORTB,6 ;LEDを5ms光らせる
; movlw 005H
; movwf countc

LOG7
; call WAIT_1M
; decfsz countc,f
; goto LOG7
; bcf PORTB,6

;********時間あわせループ**********

; movlw 050H ;全体の計測時間の余りをここで消費する
; movwf countc ;50H=80回

;LOG8
; call WAIT_1M
; decfsz countc,f
; goto LOG8
; nop
goto LOG0

;********計測終了(中断)********
LOGend ; 記録終了:停止マーカ(7373H)を書き込む
; call WAIT_50M ; EEPROMに書き込んだばかりなので少し待つ
; movlw 073H
; movwf datao
; movwf datao2 ; 7373Hをセットして
; movwf datao3
; movwf datao4
; movwf datao5
; movwf datao6

; call EEPWT ; EEPROM書き込み

bsf PORTB,6 ; LED1s点灯
call WAIT_500M
call WAIT_500M
bcf PORTB,6
goto MENU1

;********************************
; データ送信モード
;********************************

DATATR
; movlw 060H ;計測モードの値にあわせること
; movwf stepl
; movlw 073H
; movwf steph
;
; clrf addrl
; clrf addrh

DATATR1
; call EEPRD ;X下位データ読み出し
movf xplsl,w
movwf hexl

; incf addrl,f ; アドレス下位を+1加算
; goto DATATR12 ; 繰り上がらなかったらDATATR12へジャンプ
; incf addrh,f ; 上位繰上げ
DATATR12
; call EEPRD ; X上位データ読み出し
movf xplsh,w
movwf hexh ; 10進変換用上位レジスタへ代入

; データが7373Hでないかチェック
; movlw 073H
; subwf hexh,w ; hexh-w→w
; btfss STATUS,Z ; Zフラグが1だったら(=演算結果が0だったら)次をステップ
; goto DATATR15
; movlw 073H
; subwf hexl,w ; hexl-w→w
; btfss STATUS,Z ; Zフラグが1だったら(=演算結果が0だったら)次をステップ
; goto DATATR15

; データが7373Hだった
; goto DATATR3 ; 送信終了

DATATR15
; incfsz addrl,f ; アドレス下位を+1加算
; goto DATATR4 ; 繰り上がらなかったらDATATR4へジャンプ
; incf addrh,f ; 上位繰上げ
DATATR4
call DECTR ; 10進変換ルーチン

movlw "X"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf dechh,w
movwf txdata
call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf dech,w
movwf txdata
call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

; movf dechh,w
; movwf decxhh
; movf dech,w
; movwf decxh
; movf decm,w
; movwf decxm
; movf decl,w
; movwf decxl

; call EEPRD ; Y下位データ読み出し
movf yplsl,w
movwf hexl ; 10進変換用下位レジスタへ代入

; incf addrl,f ; アドレス下位を+1加算
; goto DATATR13 ; 繰り上がらなかったらDATATR13へジャンプ
; incf addrh,f ; 上位繰上げ
DATATR13
; call EEPRD ; Y上位データ読み出し
movf yplsh,w
movwf hexh ; 10進変換用上位レジスタへ代入

; incfsz addrl,f ; アドレス下位を+1加算
; goto DATATR2 ; 繰り上がらなかったらDATATR2へジャンプ
; incf addrh,f ; 上位繰上げ
DATATR2
call DECTR ; 10進変換ルーチン

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw "Y"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf dechh,w
movwf txdata
call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf dech,w
movwf txdata
call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

movf plsl,w
movwf hexl ; 10進変換用下位レジスタへ代入

DATATR14
movlw 00H ; ダミー
; movf plsh,w
movwf hexh ; 10進変換用上位レジスタへ代入

DATATR16
call DECTR ; 10進変換ルーチン

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw "S"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

; movlw 030H ; ASCiiコードに変換(+30H)して
; addwf dechh,w
; movwf txdata
; call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf dech,w
movwf txdata
call RSTRANS ; RS-232C送信

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw "B"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

clrf hexh

btfsc Pedal,3 ;Brk=0?
goto Brk_ON
movlw 0AH
movwf hexl ; 10進変換用下位レジスタへ代入
goto DATATR17

Brk_ON
movlw 0CH
movwf hexl ; 10進変換用下位レジスタへ代入

DATATR17
call DECTR ; 10進変換ルーチン

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw "P"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

btfsc Pedal,2 ;P_Brk=0?
goto P_Brk_ON
movlw 14H
movwf hexl ; 10進変換用下位レジスタへ代入
goto DATATR18

P_Brk_ON
movlw 16H
movwf hexl ; 10進変換用下位レジスタへ代入

DATATR18
call DECTR ; 10進変換ルーチン

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

movlw "A"
movwf txdata ; 文字データを転送用変数に入れて
call RSTRANS ; RS232C出力ルーチン実行

movlw "," ; カンマで区切る
movwf txdata
call RSTRANS

btfss Pedal,1 ;Accel=1?
goto Accel_ON
movlw 1EH
movwf hexl ; 10進変換用下位レジスタへ代入
goto DATATR19

Accel_ON
movlw 20H
movwf hexl ; 10進変換用下位レジスタへ代入

DATATR19
call DECTR ; 10進変換ルーチン

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decm,w
movwf txdata
call RSTRANS

movlw 030H ; ASCiiコードに変換(+30H)して
addwf decl,w
movwf txdata
call RSTRANS

movlw 00DH
movwf txdata
call RSTRANS
movlw 00AH ; 0D,0Aで「改行」
movwf txdata
call RSTRANS

movlw 021H ;時間調整用
movwf countc

bsf PORTB,6 ;確認用LED点滅

DATATR33
call WAIT_1M
decfsz countc,f
goto DATATR33
bcf PORTB,6
call WAIT_1M

return ;LOG0に戻る

;*********************************
;RS-232C送信ルーチン
;txdataの値を送信
;*********************************

RSTRANS
bcf PORTB,1 ; スタートビット送信開始,送信ポートRB1をLOWに

movlw btime ; 転送中時間待ち用カウンタ
movwf sendt ; btimeはあらかじめ転送速度にあわせて定義しておく必要がある。

TRANS10
decfsz sendt,f
goto TRANS10 ; 転送速度(ここでは9600bps)に合わせて時間待ち

movlw 08H
movwf bitw ; 送信の単位は8ビットで1データ,bitwは8ビットカウント用変数
nop

TRANS0
rrf txdata,f ; txdata(送信データ)の最下位ビットをC(キャリ・ビット)に。
nop ; その他のビットはそれぞれ1桁ずつ下位の方(右側)にシフト。

btfss STATUS,C ; Cビットが1だったら送信ポートRB1をHighに,0だったらLowにする。
bcf PORTB,1 ; 下位ビット側から送信することになる。
btfsc STATUS,C
bsf PORTB,1

movlw btime
movwf sendt

TRANS11
decfsz sendt,f
goto TRANS11 ; 転送速度(ここでは9600bps)に合わせて時間待ち

decfsz bitw,f ; ビットカウントを1減らす
goto TRANS0 ; まだ8ビット送信していなかったら次のビットを送信

nop ;nopで時間調整
nop
nop
nop
nop
nop
bsf PORTB,1 ; 最後にストップビットを送信
movlw btime
movwf sendt

TRANS12
decfsz sendt,f ; ストップビット分ウエイト
goto TRANS12

return

;*****************************
;時間待ち用タイマサブルーチン
; WAIT_100U :100μs
; WAIT_1M :1ms
; WAIT_50M :50ms
; WAIT_500M :0.5s
;*****************************

WAIT_100U
movlw 20H
movwf counta
W_LOOP1
decfsz counta,f ; 2+3*32-1=97
goto W_LOOP1
nop
return ; 97+3=100(μs)
WAIT_1M
movlw 0AH ; 10回ループ
movwf countb
W_LOOP2
call WAIT_100U ; 2+(100+5)*10-1=1051
decfsz countb,f
goto W_LOOP2
return ; 1051+2=1053(=1.053ms)
WAIT_50M
movlw 32H ; 50回ループ
movwf countc
W_LOOP3
call WAIT_1M
decfsz countc,f
goto W_LOOP3
return
WAIT_500M
movlw 0AH ; 10回ループ
movwf countd
W_LOOP4
call WAIT_50M
decfsz countd,f
goto W_LOOP4
return

;******************************
;EEPROMデータ書き込みサブルーチン(1度に2バイト書き込む)
; アドレス:addrh,addrl
; データ : datao〜datao6
;******************************

EEPWT
call BSTART ; スタートビット発生

movlw b'10100000' ; コントロールバイト送信
movwf txbuf
call TX
movf addrh,w ; 書き込みアドレス上位を送信
movwf txbuf
call TX
movf addrl,w ; 書き込みアドレス下位を送信
movwf txbuf
call TX
movf datao,w ; X軸下位データバイトの1バイト目を送信
movwf txbuf
call TX
movf datao2,w ; X軸上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao3,w ; Y軸下位データバイトの1バイト目を送信
movwf txbuf
call TX
movf datao4,w ; Y軸上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao5,w ; 車速上位データバイトの2バイト目を送信
movwf txbuf
call TX
movf datao6,w ; 車速上位データバイトの2バイト目を送信
movwf txbuf
call TX

call BSTOP ; ストップビット発生,書き込み処理終了

return

;******************************
;EEPROMデータ読み込みサブルーチン
; アドレス:addrh,addrl
; データ : datai
;******************************

EEPRD
call BSTART ; スタートビット発生

movlw b'10100000' ; コントロールバイト送信(書き込みモード)
movwf txbuf
call TX
movf addrh,w ; 読み込みアドレス上位を送信
movwf txbuf
call TX
movf addrl,w ; 読み込みアドレス下位を送信
movwf txbuf
call TX

call BSTART ; スタートビット発生

movlw b'10100001' ; コントロールバイト送信(読み込みモード)
movwf txbuf
call TX

call RX

call BSTOP ; ストップビット発生

return

;*********バイトデータ送信サブルーチン*********

TX
movlw 008H
movwf count ; 1バイト=8ビット繰り返し用カウンタ
TXLP
bcf eeprom,do ; eeprom書き込み用ビットを0にしておく
btfsc txbuf,7 ; 書き込みデータは本当に0か?
bsf eeprom,do ; 書き込み用データが1だったので,書き込み用ビットを1にする

btfss eeprom,do ; 書き込み用データビットは1か?
goto bitlow
bsf PORTA,sdata ; 書き込み用ビットが1の場合:SDAをHighにする
goto clkout ; クロック操作へジャンプ

bitlow
bcf PORTA,sdata ; 書き込み用ビットが0の場合:SDAをLowにする
nop
clkout
bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする。ここまででビット書き込み完了

rlf txbuf,f ; 送信データバイトをシフトする
decfsz count,f ; 8ビット送信終わったか?
goto TXLP ; 終わるまでループ

;***ACKビット送信****

bsf eeprom,di ; eeprom読み込み用ビットを1にしておく

bsf STATUS,RP0
bsf TRISA,sdata ; SDAポートを入力にする
bcf STATUS,RP0

bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
nop
btfss PORTA,sdata ; SDAポートからの入力をチェック
bcf eeprom,di ; ポートがLowの場合,読み込みビットを0に変更
bcf PORTA,sclk ; SCLをLowにする。
nop

bsf STATUS,RP0

bcf TRISA,sdata ; SDAポートを出力にもどす
bcf STATUS,RP0

nop
btfsc eeprom,di ; 読み込みビットをチェックして失敗(1)していたら
bsf PORTB,ackf ; LEDを点灯する
return

;*******バイトデータ受信サブルーチン*********

RX
clrf datai ; 読み込み用レジスタのクリア
movlw .8 ; set#bits to 8
movwf count
bcf STATUS,0 ; キャリビットを0にする
RXLP
rlf datai,f ; 読み込み用レジ下を左シフト,最下位は0になる
bsf eeprom,di ; eeprom読み込み用ビットを1にする

bsf STATUS,RP0
bsf TRISA,sdata ; SDAポートを入力にする
bcf STATUS,RP0

bsf PORTA,sclk ; SCLをHighにする
nop
nop
nop
nop
nop
btfss PORTA,sdata ; SDAポートからの入力をチェック
bcf eeprom,di ; ポートがLowの場合,読み込みビットを0に変更
bcf PORTA,sclk ; SCLをLowにする。
nop

bsf STATUS,RP0
bcf TRISA,sdata ; SDAポートを出力にもどす
bcf STATUS,RP0

btfsc eeprom,di ; 読み込みビットが1だったら
bsf datai,0 ; 読み込みようレジスタの最下位を1にする
decfsz count,f ; 8ビット受信終わったか?
goto RXLP ; 終わるまでループ

;***ACKビット送信****

bsf eeprom,do ; ACK出力用ビットを1にする
bsf PORTA,sdata ; SDAポートをhighにする
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする

return

;********スタートビット発生サブルーチン********

BSTART
bsf PORTA,sdata ; SDAポートをhighにする
nop
nop
nop
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
bcf PORTA,sdata ; SDAポートをLowにする。SCLがHighの間にSDAがLowになるとスタートビットと認識される
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする
nop
nop
nop
nop
return

;********ストップビット発生サブルーチン********

BSTOP
bcf PORTA,sdata ; SDAポートをLowにする。
nop
nop
nop
bsf PORTA,sclk ; SCLをhighにする
nop
nop
nop
bsf PORTA,sdata ; SDAポートをhighにする。SCLがHighの間にSDAがHighになるとストップビットと認識される
nop
nop
nop
bcf PORTA,sclk ; SCLをLowにする
nop
nop
nop
nop
return

;***********************************************
;10進数に変換するルーチン
;16進データhexh(上位),hexl(下位)の値をdec4(万の位)〜dec0(一の位)に変換する。
;***********************************************

DECTR
clrf dechh
clrf dech
clrf decm
clrf decl

movf hexh,w ; 入力データが0でないか調べる
btfss STATUS,Z ; hexhが0だった場合,Zフラグが1になっている。
goto DEC4 ; hexh(上位データ)が0でなかったら処理開始へ

movf hexl,w ;hexhが0だったのでhexlをチェック
btfss STATUS,Z
goto DEC1 ; hexl(下位データ)が0でなかったら処理開始へ

return ; hexhもhexlも0だったので出力データ0のまま復帰

DEC4 ;hexhが0じゃなかったのでhexlをチェック
movf hexl,w
btfss STATUS,Z ;0だったら次スキップ
goto DEC1 ;hexlが0じゃないのでカウントアップ
goto DEC3 ;0だったのでhexh減算へ
DEC1
call DECUP ;10進データカウントアップ
decfsz hexl,f ;下位データが0でなかったら繰り返す
goto DEC1
DEC3
movf hexh,w ;上位データが0でないか調べる
btfsc STATUS,Z ; Z=0(結果が正)の場合,次をスキップ
goto DEC2 ; Z=1(結果が0)の場合,下位バイト処理へ
decf hexh,f ;hexhを減算して
goto DEC1 ;下位の減算を再開

DEC2
return ;上位も0になったので処理終了

;*******カウントアップサブルーチン****************

DECUP
incf decl,f
movf decl,w
sublw 00AH
btfss STATUS,Z
return

;*****2桁目カウントアップサブルーチン*****

clrf decl
incf decm,f
movf decm,w
sublw 00AH
btfss STATUS,Z
return

;*****3桁目カウントアップサブルーチン*****

clrf decm
incf dech,f
movf dech,w
sublw 00AH
btfss STATUS,Z
return

;*****4桁目カウントアップサブルーチン*****

clrf dech
incf dechh,f
movf dechh,w
sublw 00AH
btfss STATUS,Z
return

;*****4桁目もオーバーフロー*****

clrf dechh
return



;*********************************************
;加速度センサ・パルス計測サブルーチン
; 消費時間:50μs(50.004μs)
; データ :X軸xplsh(上位)xplsl(下位)
; :Y軸yplsh(上位)yplsl(下位)
; :単位10μs
;*********************************************

Gmeas
clrf xplsh
clrf xplsl
clrf yplsh
clrf yplsl
clrf OUTBUF ;reset output buffer

call x_ad_conv
call y_ad_conv

; call WAIT_50M ;100ms周期時間あわせ

return

;**********X軸のADコンバータ通信************
x_ad_conv
clrf INBUFH ;reset input buffer
clrf INBUFL

BEGIN_AD_X
bcf PORTA,1 ;CS=RA1をLO select A/D converter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI シングルエンド
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D2無視
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D1
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI D0
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO

call IN_DATA ;read data from A/D converter
bsf PORTA,1 ;CS=RA1をHI de-select A/D converter
movlw 00FH ;load MSB mask
andwf INBUFH,W ;mask out MSB’s and put result in W
movwf xplsh ;output MSB’s
movf INBUFL,W ;load LSB’s into W
movwf xplsl ;output LSB’s

return ;finished, return to caller

;**********Y軸のADコンバータ通信************

y_ad_conv
clrf INBUFH ;reset input buffer
clrf INBUFL

BEGIN_AD_Y
bcf PORTA,1 ;CS=RA1をLO select A/D converter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bsf PORTB,3 ;D_IN=RB3がHI シングルエンド
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D2
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D1
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO
bcf PORTB,3 ;D_IN=RB3がLO D0
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse

bcf PORTA,0 ;CLK=RA0をLO

call IN_DATA ;read data from A/D converter
bsf PORTA,1 ;CS=RA1をHI de-select A/D converter
movlw 0FH ;load MSB mask
andwf INBUFH,W ;mask out MSB’s and put result in W
movwf yplsh ;output MSB’s
movf INBUFL,W ;load LSB’s into W
movwf yplsl ;output LSB’s

return ;finished, return to caller

;**********ADコンバータ共通************

OUT_CONTROL
movlw 04H
movwf COUNT ;init bit counter
bsf PORTB,3 ;D_IN=RB3がHI 開始ビット
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO

BIT_OUT
rlf OUTBUF,W ;rotate bit into carry
movwf OUTBUF
bcf PORTB,3 ;D_IN=RB3がLO pre-clear data out
btfsc STATUS,C ;check if bit should be set
bsf PORTB,3 ;D_IN=RB3がHI set data out

bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
bcf PORTA,0 ;CLK=RA0をLO

decfsz COUNT ;decrement bit counter
goto BIT_OUT ;output next bit
return ;finished, return to caller

IN_DATA
clrf INBUFL
clrf INBUFH ;reset input buffer
movlw 0DH
movwf COUNT ;init bit counter

bsf PORTA,0 ;CLK=RA0をHI 1サイクル待ち(前回のLOと合計して1.5サイクル)
bcf PORTA,0 ;CLK=RA0をLO

BIT_IN
bsf PORTA,0 ;CLK=RA0をHI set clock to latch bit
bcf STATUS,C ;pre-clear carry
btfsc PORTB,2 ;D_OUT=RB2を check for high or low bit
bsf STATUS,C ;set carry bit

rlf INBUFL,f
rlf INBUFH,f ;rotate bit into position

bcf PORTA,0 ;CLK=RA0をLO drop clock for next bit

decfsz COUNT ;decrement bit counter
goto BIT_IN ;get next bit
return ;return to caller

;*********************************************
;車速データ受信サブルーチン
; データ:plsh(上位)plsl(下位)
; SP_CLK受信ポート=RA4
; SP_REQ送信ポート=RB4
; SP_DATA受信ポート=RB0
;*********************************************
Speed
movlw 0CH ;実車速化に伴い8bit+ペダル4bit
movwf countf ;init bit counter
bcf STATUS,C
bcf PORTB,4 ;SP_REQ=RB4をLO(初期化)
movlw 078H ;C423H=50210μs-DATATR時間220H544μS=C203H
movwf counte ;C203H/2(ワード数で約半分以下)=6978H
movlw 069H ;オーバーフロー用(0km/h判定)
movwf countg ;ただし,車速PICの返答時間までとし,残りの余りは別でWAIT処理する
clrf plsh ;車速
clrf plsl ;車速
clrf Pedal
clrf COUNT

SP_REQ1
btfss PORTA,4 ;SP_CLKがHIなら次をスキップ
goto WAIT_BEFOR ;LOなのでHIになるまで規定時間待つ
bsf PORTB,4 ;SP_REQ=RB4をHI,車速PICはDATATRに移行
;今はCLKはHI,車速応答はHI

SP_REQ2 ;車速PICはBIT_OUT_HI
btfsc PORTA,4 ;SP_CLKがLOなら次をスキップ
goto SP_REQ2 ;HIなのでLOになるまで待つ
;今はCLKはLO,車速応答はHI
btfsc PORTB,0 ;SP_DATAがLOなら次をスキップ
bsf STATUS,C ;set carry bit
rlf plsl,f
; rlf plsh,f
rlf Pedal,f ;ペダル情報受信結果格納

bcf PORTB,4 ;SP_REQ=RB4をLO

CHECK ;今はCLKはLO,車速応答はLO
btfss PORTA,4 ;SP_CLKがHIなら次をスキップ
goto CHECK ;LOなのでHIになるまで待つ
bsf PORTB,4 ;SP_REQ=RB4をHI

decfsz countf ;decrement bit counter
goto SP_REQ2
bcf PORTB,4 ;SP_REQ=RB4をLO


;*********残りWaitTime消費*******
movf COUNT,w ;wait回数を引き算する
andlw 2 ;wait回数とカウントワード分
addwf counte,f
DOWN1
decfsz counte,f
goto DOWN1
movlw 0FFH
movwf counte
decfsz countg,f
goto DOWN1

;*********固定WaitTime消費*******
movlw 0ACH ;DATATR時間と同じ時間(544μs)をここで消費する
movwf counte ;220H-70H-4H=1ACh=428
movlw 001H ;データ転送時間を引き算する
movwf countg ;14ワード×8回=112ワード=70H
DOWN2
decfsz counte,f
goto DOWN2
movlw 0FFH
movwf counte
decfsz countg,f
goto DOWN2

movf plsh,w
movwf old_plsh
movf plsl,w
movwf old_plsl

return

WAIT_BEFOR
incf COUNT ;wait回数カウンタ
decfsz counte,f ;0になったら次をスキップ
goto SP_REQ1
movlw 0FFH
movwf counte
decfsz countg,f
goto SP_REQ1
;******0km/h処理*********
SPEED_ZERO ;カウントオーバフローなので前回のデータを使用する
movf old_plsh,w
movwf plsh
movf old_plsl,w
movwf plsl
return ;カウントオーバフローなので戻る

end