;**********************
;車速計Ver.2
;**********************
; Ver2('07/06/19)
; パルス間の時間を40μsごとにカウントする
; 50ms間メインPICに出力
;
; Ver3('07/06/23)
; 車速応答(RB7)待ち時間を長めに調整
;
; Ver4('07/06/25)
; 車速カウントを速度に演算するプログラムを追加
; Gsen_Ver4_5に対応
;
; Ver5('07/07/03)
; 10進化ルーチン修正
;
; Ver6kijun('07/07/04)
; FGで車速計測間隔調整済み
;
; Ver7kijun('07/07/04)
; FGで車速カウントプログラム完成
;
; Ver8('07/07/05)
; 車速の10進化とメインPICの8bit対応とフィルタ追加
; Gsen_Ver4_13に対応
;
; Ver9('07/07/17)
; 車速調整完了
; Gsen_Ver4_14に対応
;**********************
;
;PIC16F84A:4MHz用(1cycle=1μs)
;
;MR-SはエンジンECUから4パルスで出力される
;60km/h=637rpm=2548パルス/min,42.5パルス/s
;
; Gsens_Ver4と組み合わせて使用する
; Gsens_Ver4に50ms間出力信号を出し,応答信号がきたら,そのときの車速データを出力する
;
;
; ピン・アサイン
; RA0 →CLK(メインPICへ)
; RA1 →
; RA2 ⇔
; RA3 →LED
; RA4 
; RB0 ←
; RB1 →車速データ送信(メインPICへ)
; RB2 ←車速信号入力
; RB3 →
; RB4
; RB5 ←
; RB6 →
; 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分間パルス積算下位
;**********ADコンバータ************
;ADCS		equ		0x02	; chip select line A/D
;PCLATH		equ		40H		; for Page0 operation
;SSPCON		equ		41H		; for Bank0 operation
;FSR		equ		42H		; 
;ch_cntl	equ		26H		; アナログ入力CH切り替え
;d_data		equ		27H		; AD変換データ格納先
;d_data2	equ		28H		; AD変換データ格納先
COUNT		equ		29H		; 

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

			org		0

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

	bsf		STATUS,RP0		; TRIS設定のためバンクを切り替える
	movlw	b'00000000'		; PORTA入出力設定:入力(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

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

; 別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
	call	WAIT_1M
		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	08H
	movwf	COUNT		;init bit counter
;	movlw	92H			;確認用2282H=8850=4km/h
;	movwf	plsl
;	movlw	22H
;	movwf	plsh

BIT_OUT_HI					;今はCLKはHI,車速応答はHI
	rlf		div3a,f		;rotate bit into carry
;	rlf		plsh,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

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

;	movlw	08H
;	movwf	COUNT		;init bit counter

;BIT_OUT_LO					;今はCLKはHI,車速応答はHI
;	rlf		plsl,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
;CHECK2
;	btfsc	PORTB,7		;車速応答=RB7がLOなら次をスキップ
;	goto	CHECK2		;HIなのでLOになるまで待つ
;							;今はCLKはLO,車速応答はLO
;	bsf		PORTA,0		;CLK=RA0をHI
;clk_check_LO
;	btfss	PORTB,7		;車速要求=RB7がHIなら次をスキップ
;	goto	clk_check_LO	;LOなのでHIになるまで待つ
;							;今はCLKはHI,車速応答はHI
;	decfsz	COUNT		;decrement bit counter
;	goto	BIT_OUT_LO	;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