;**********************
;車速計Ver.4(ペダル入力)
;**********************
;
; Gsen_Ver5に対応
;
; Ver1('08/09/28)
; ペダル入力に対しLED点灯追加
; 車速動作チェック完了
;
; Ver2('08/09/29)
; ペダル信号通信出力追加
;
; Ver3('08/09/29)
; 送信データ加算処理見直し
; 
; Ver.4('08/09/30)
; 送信データ12ビット化
;
; Gsen_Ver5_3_232c.asmと対応
;**********************
;
;PIC16F84A:4MHz用(1cycle=1μs)
;
;MR-SはエンジンECUから4パルスで出力される
;60km/h=637rpm=2548パルス/min,42.5パルス/s
;
; Gsens_Ver5と組み合わせて使用する
; Gsens_Ver5に50ms間出力信号を出し,応答信号がきたら,そのときの車速データを出力する
;
;
; ピン・アサイン
; RA0 →CLK(メインPICへ)
; RA1 →LED(P-Brk)
; RA2 →LED(Brk)
; RA3 →LED(PIC動作確認用)
; RA4 
; RB0 
; RB1 →車速データ送信(メインPICへ)
; RB2 ←車速信号入力
; RB3 ←P-Brk入力
; RB4 ←Brk入力
; RB5 ←Accel入力
; RB6 →LED(Accel)
; RB7 ←車速応答信号入力(メインPICから)
;
;
;***************************************

LIST P=PIC16F84A
INCLUDE "P16F84A.INC"

;****************
; 変数レジスタ定義
;****************

;---------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
countg equ 1FH
counth equ 20H
counti equ 21H

;---------パルスカウント-----
SPplsh equ 2AH ; 車速パルス・カウンタ上位
SPplsl equ 2BH ; 車速パルス・カウンタ下位
spsig equ 2CH ; Y軸パルス・カウンタ上位
spsigc equ 2DH ; Y軸パルス・カウンタ下位
plsh equ 22H ; パルス幅カウンタ上位
plsl equ 23H ; パルス幅カウンタ下位

;--------10進数変換用--------
divl1 equ 31H ; 内部計算用1
divl2 equ 32H ; 内部計算用2
div1a equ 2EH ; 基準時間下位
div1b equ 2FH ; 基準時間上位
div2a equ 30H ; 割る数下位8bit
div2b equ 33H ; 割る数上位8bit
div3a equ 34H ; 答え下位
div3b equ 35H ; 答え上位
div4a equ 36H ; 余り下位
div4b equ 37H ; 余り上位
diverr equ 38H ; エラー
;COUNT2 equ 3BH ;
;dechh equ 3CH ; 10進数・千の位
;int2h equ 3DH ; 1分間パルス積算上位
;int2l equ 3EH ; 1分間パルス積算下位
;*********ペダル信号バッファ************
Brk equ 40H ;
P_Brk equ 41H ;
Accel equ 42H ;
Pedal equ 26H ;
;OFF equ 27H ; 00H
;d_data2 equ 28H ; AD変換データ格納先
COUNT equ 29H ;

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

org 0

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

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

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

clrf SPplsh
clrf SPplsl
clrf Brk
clrf P_Brk
clrf Accel

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

; 別PICからの要求(車速要求)がRB7=HIでデータ送信モード
; 車速信号(RB2)のパルス幅をカウント
; 車速送信(RB1)

MENU1
call sp_data ; 車速カウントルーチンへ
call cal_palus ; 実車速計算へ

MENU4
movlw 080H ;13880H=80000μs
movwf counte ;オーバーフロー用(0km/h判定)
movlw 038H
movwf countf
movlw 001H
movwf counti

MENU2
bsf PORTA,0 ;CLK=RA0をHI generate clock pulse
btfss PORTB,7 ;車速応答=RB7がHIなら次をスキップ
goto MENU3
call DATATR ; HI(1)だったらデータ送信モードへ
goto MENU1

MENU3 ;応答がないので待ち
decfsz counte,f ;0になったら次をスキップ
goto MENU2
movlw 0FFH ;
movwf counte ;
decfsz countf,f ;
goto MENU2
movlw 0FFH ;
movwf countf ;
decfsz counti,f ;
goto MENU2
bcf PORTA,0 ;CLK=RA0をLO
nop
goto MENU1

;********************************
; 車速カウントルーチン
;********************************
;**********初期化***********
sp_data
bcf PORTA,3 ;LEDを消灯(点いている場合があるので)
clrf plsh
clrf plsl
; movlw 001H ;車速がLOのとき1回待つ
; movwf countg ;
clrf countd ;パルスカウント実行フラグ(0=初回,1=実行済み)
movlw 0B3H ;22H*B3H=8850回(4km/h),オーバーフロー用(0km/h判定)
movwf counte ;
movlw 022H ;
movwf countc ;
; movlw 00AH ;
; movwf countf ;

;*******データ計測********
sp_check
btfsc PORTB,2 ;車速信号=RB2はLO(0)か?
goto first_hilo ;HIなのでloを待ってからカウント
goto first_lohi ;LOなのでhiを待ってからカウント

; decfsz countg,f ;0になったら次をスキップ
; goto sp_check
; goto SPEED_ZERO ;LOのままなので車速0と判断

SP_STOP
nop
bsf PORTA,3 ; 確認用LED点灯
call WAIT_1M
bcf PORTA,3

Brk_Check
btfsc PORTB,4 ;Brk信号=RB4はLO(0)か?
goto Brk_clr ;HIなのでLED消灯処理
bsf PORTA,2 ;LOなので点灯
movlw 0FFH ;送信用バッファに記録
movwf Brk
goto P_Brk_Check ;

Brk_clr
bcf PORTA,2 ;HIなのでLED消灯
movlw 000H ;送信用バッファに記録
movwf Brk

P_Brk_Check
btfsc PORTB,3 ;Brk信号=RB4はLO(0)か?
goto P_Brk_clr ;HIなのでLED消灯処理
bsf PORTA,1 ;LOなので点灯
movlw 0FFH ;送信用バッファに記録
movwf P_Brk
goto Accel_Check ;

P_Brk_clr
bcf PORTA,1 ;HIなのでLED消灯
movlw 000H ;送信用バッファに記録
movwf P_Brk

Accel_Check
btfss PORTB,5 ;Brk信号=RB4はHI(1)か?
goto Accel_clr ;LOなのでLED消灯処理
bsf PORTB,6 ;HIなので点灯
movlw 0FFH ;送信用バッファに記録
movwf Accel
goto Pedal_fin ;

Accel_clr
bcf PORTB,6 ;LOなのでLED消灯
movlw 000H ;送信用バッファに記録
movwf Accel

Pedal_fin

return

;---------------------------------------------------------------------------------------
;設定車速パルス間のカウンター(SP_cnt*は40us)
;パルス取得〜終了までのカウント
;-------------------------------------
first_lohi
btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt1
goto SP_cnt00 ;オーバーフローダウン
goto SP_cnt1
SP_cnt00
decfsz counte,f ;0になったら次をスキップ
goto first_lohi
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto first_lohi
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt11

; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ
goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ



;======LOからHIになるのを待ってからカウント開始のパターン========
SP_cnt1
decfsz counte,f ;0になったら次をスキップ
goto SP_cnt11
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto SP_cnt11
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt11

; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ
goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt2 ; LOカウントへ

SP_cnt11
call COUNT_UP ; HIパルス時間をカウント
call wait40us_4MHz ; 40us待機(実質call〜ret=27us)
btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→次スキップ、無→SP_cnt1
goto SP_cnt1
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならLOカウントへ
; goto SP_STOP ; LOカウントを実行済み(1)なので終了処理へ
; incf countd,f ; カウント実行フラグを1
goto SP_cnt2 ; LOカウントへ

;パルス終了〜取得までのカウント
SP_cnt2
decfsz counte,f ;0になったら次をスキップ
goto SP_cnt12
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto SP_cnt12
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt12
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならHIカウントへ
goto SPEED_ZERO ; HIカウントを実行済み(1)なのでSEED_ZERO処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt1 ; HIカウントへ

SP_cnt12
call COUNT_UP ; LOパルス時間をカウント
call wait40us_4MHz ; 40us待機(実質call〜ret=27us)
btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt2
goto SP_cnt2
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならHIカウントへ
goto SP_STOP ; HIカウントを実行済み(1)なので終了処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt1 ; HIカウントへ


;======HIからLOになるのを待ってからカウント開始のパターン========
first_hilo
btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→SP_cnt01、無→次スキップ
goto SP_cnt01 ;オーバーフローダウン
goto SP_cnt20
SP_cnt01
decfsz counte,f ;0になったら次をスキップ
goto first_hilo
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto first_hilo
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt11

; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ
goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ

;パルス終了〜取得までのカウント
SP_cnt20
decfsz counte,f ;0になったら次をスキップ
goto SP_cnt21
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto SP_cnt21
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt12
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならHIカウントへ
goto SPEED_ZERO ; HIカウントを実行済み(1)なのでSEED_ZERO処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt1 ; HIカウントへ

SP_cnt21
call COUNT_UP ; LOパルス時間をカウント
call wait40us_4MHz ; 40us待機(実質call〜ret=10us)
btfss PORTB,2 ; 車速信号=RB2はHI(1)か?; 車速信号有→次スキップ、無→SP_cnt20
goto SP_cnt20
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならHIカウントへ
; goto SP_STOP ; HIカウントを実行済み(1)なので終了処理へ
; incf countd,f ; カウント実行フラグを1
goto SP_cnt22 ; HIカウントへ

SP_cnt22
decfsz counte,f ;0になったら次をスキップ
goto SP_cnt23
movlw 0FFH ;
movwf counte ;
decfsz countc,f ;0になったら次をスキップ
goto SP_cnt23
; movlw 0FFH ;
; movwf countc ;
; decfsz countf,f ;0になったら次をスキップ
; goto SP_cnt11

; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら車速0処理へ,未実行(0)ならLOカウントへ
goto SPEED_ZERO ; LOカウントを実行済み(1)なのでSEED_ZERO処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt2 ; LOカウントへ

SP_cnt23
call COUNT_UP ; HIパルス時間をカウント
call wait40us_4MHz ; 40us待機(実質call〜ret=27us)
btfsc PORTB,2 ; 車速信号=RB2はLO(0)か?; 車速信号有→SP_cnt22、無→次スキップ
goto SP_cnt22
; btfsc countd,0 ; パルスカウント済み(0ビットが1)なら終了処理へ,未実行(0)ならLOカウントへ
goto SP_STOP ; LOカウントを実行済み(1)なので終了処理へ
; incf countd,f ; カウント実行フラグを1
; goto SP_cnt20 ; LOカウントへ

;--------------------------------------------------------------------------------
;【 4MHz用】パルス測定タイマー(基準40usecのOFF時間) : 完成版(Call〜ret=27.0us)
;--------------------------------------------------------------------------------
wait40us_4MHz
movlw 06H ;パルスカウント間隔はここでコントロール
movwf counth
W_LOOP5
decfsz counth,f ; 2+3*9-1=28
goto W_LOOP5
nop
return

;******パルスカウント*********
COUNT_UP
incfsz plsl
goto rtn
incf plsh
return
rtn
nop
return

;******0km/h処理*********
SPEED_ZERO
clrf plsl
clrf plsh
goto SP_STOP

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

DATATR
movlw 04H
movwf COUNT ;init bit counter
clrf Pedal

;ペダル状態調査
btfss Brk,1 ;Brkビット1が1か?
goto p_check2 ;0なのでビット3は0のまま
bsf Pedal,7 ;バッファのビット7を1

p_check2
btfss P_Brk,1 ;P_Brkビット1が1か?
goto p_check3 ;0なのでビット2は0のまま
bsf Pedal,6 ;バッファのビット6を1

p_check3
btfsc Accel,1 ;Accelビット1が0か?
goto BIT_OUT_HI ;1なのでビット2は0のまま
bsf Pedal,5 ;バッファのビット5を1

;p_check4 ;ペダルバッファができたのでdiv3aの上位にAND
; movf Pedal,w ;
; iorwf div3a,w ;div3aの上位にpedalを加える
; movwf div3a

BIT_OUT_HI ;今はCLKはHI,車速応答はHI
; rlf div3a,f ;rotate bit into carry
rlf Pedal,f ;rotate bit into carry
bcf PORTB,1 ;車速出力=RB1を0(初期化)
btfsc STATUS,C ;check if bit should be set
bsf PORTB,1 ;車速出力=RB1を1
bcf PORTA,0 ;CLK=RA0をLO
CHECK1
btfsc PORTB,7 ;車速応答=RB7がLOなら次をスキップ
goto CHECK1 ;HIなのでLOになるまで待つ
;今はCLKはLO,車速応答はLO
bsf PORTA,0 ;CLK=RA0をHI
clk_check_HI
btfss PORTB,7 ;車速要求=RB7がHIなら次をスキップ
goto clk_check_HI ;LOなのでHIになるまで待つ
;今はCLKはHI,車速応答はHI
decfsz COUNT ;decrement bit counter
goto BIT_OUT_HI ;output next bit

movlw 08H
movwf COUNT ;init bit counter

BIT_OUT_HI2 ;今はCLKはHI,車速応答はHI
rlf div3a,f ;rotate bit into carry
bcf PORTB,1 ;車速出力=RB1を0(初期化)
btfsc STATUS,C ;check if bit should be set
bsf PORTB,1 ;車速出力=RB1を1
bcf PORTA,0 ;CLK=RA0をLO
CHECK12
btfsc PORTB,7 ;車速応答=RB7がLOなら次をスキップ
goto CHECK12 ;HIなのでLOになるまで待つ
;今はCLKはLO,車速応答はLO
bsf PORTA,0 ;CLK=RA0をHI
clk_check_HI2
btfss PORTB,7 ;車速要求=RB7がHIなら次をスキップ
goto clk_check_HI2 ;LOなのでHIになるまで待つ
;今はCLKはHI,車速応答はHI
decfsz COUNT ;decrement bit counter
goto BIT_OUT_HI2 ;output next bit

bcf PORTA,0 ;CLK=RA0をLO
;今はCLKはLO,車速応答はLO
return ;finished, return to caller

;*****************************
;時間待ち用タイマサブルーチン
; 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

;---------------------------------------------------------------------------------------
; 16bitの割算
; 車速パルス数から速度計算

cal_palus
movlw 092H
movwf div1b ;基準時間40us( HEX(927C) = DEC(37500) )
movlw 07CH
movwf div1a
movf plsh,w
; movlw 022H ;確認用2292H=8850パルス=4km/h
movwf div2b ;割る数上位8bit
movf plsl,w
; movlw 092H ;確認用
movwf div2a ;割る数下位8bit
call div16 ;割算実施( 解 = div3b,a 余 = div4b,a )
return
;16bit割算
div16
movlw 10H ;10H=16
movwf divl1 ;内部計算用1
movf div2a,0 ;割る数下位8bit
movwf div4a ;余り下位8bit
movf div2b,0 ;割る数上位8bit
movwf div4b ;余り上位8bit
di1601
rlf div4a,1 ;1bit左シフト,余り下位
rlf div4b,1 ;1bit左シフト,余り上位
btfsc STATUS,C ;Cフラグ確認
goto di1602 ;割る数の上位ビット位置検索
decfsz divl1,1 ;
goto di1601 ;
movlw 1 ;
movwf diverr ;割る数 = 0 → エラー
return
di1602
clrf div3a ;答え下位8bit,解セット用変数クリア
clrf div3b ;答え上位8bit
clrf div4a ;余り下位8bit,ワーク用変数クリア
clrf div4b ;余り上位8bit
movlw 10h ;
movwf divl2 ;内部計算用2
movf divl1,0 ;内部計算用1
subwf divl2,1 ;残ループ数
di1603
bcf STATUS,C ;Cフラグ = 0
rlf div1a,1 ;
rlf div1b,1 ;
rlf div4a,1 ;
rlf div4b,1 ;
decfsz divl1,1 ;割られる数を初期位置までシフト
goto di1603 ;
di1604 ;現位置での減算が可否確認
movf div2b,0 ;
subwf div4b,0 ;
btfss STATUS,C ;
goto di1606 ;
movf div4b,0 ;
subwf div2b,0 ;
btfss STATUS,C ;
goto di1605 ;
movf div2a,0 ;
subwf div4a,0 ;
btfss STATUS,C ;
goto di1606 ;
di1605
movf div2a,0 ;
subwf div4a,1 ;ワークから下位を引く
btfss STATUS,C ;Cフラグ = 1 → skip
decf div4b,1 ;上位 -1
movf div2b,0 ;
subwf div4b,1 ;ワークから上位を引く
bsf STATUS,C ;Cフラグ = 1
goto di1607 ;
di1606
bcf STATUS,C ;Cフラグ = 0
di1607
rlf div3a,1 ;Cフラグの内容を解にシフト
rlf div3b,1 ;
movf divl2,1 ;divl2 = 0 の確認
btfsc STATUS,2 ;2bitは何のビットか後で確認すること
goto di1608 ;最下位まで処理したなら終了
decf divl2,1 ;bit位置を1つ下げる(右へ)
bcf STATUS,C ;Cフラグ = 0
rlf div1a,1 ;ワークへ1bit左シフト
rlf div1b,1 ;
rlf div4a,1 ;
rlf div4b,1 ;
goto di1604 ;
di1608
clrf diverr ;正常終了
return

end