;**********************
;加速度ロガーVer4(車速信号)
;**********************
; Ver1('07/05/28)
; Gsens_Ver2_5に車速信号入力を追加
; sp_clkが来たら車速データを取り込む仕様
;
; Ver3('07/06/23)
; Speedプログラム修正
; sp_clk待ち時間を最小に設定
;
; Ver4('07/06/25)
; Speedのカウント/ウエイトタイムプログラム修正
; Speed_Ver.2_3に対応
;
; Ver5('07/06/25)
; 車速データが実車速化されたので,Speedデータ受信プログラムを仮対応
; Speed_Ver.2_4に対応
;
; Ver11('07/07/02)
; 送信データでY軸データの4桁目(DEC)が0のものを削除
; 送信データで車速データの4桁目(DEC)が0のものを削除
;
; Ver12('07/07/03)
; サンプリング100msに調整
; ほぼ満足いくレベルに完成
; Speed_Ver.2_4に対応
;
; Ver12test('07/07/05)
; 車速パルスカウント16bitに対応して完成 
; Speed_Ver.2_7kijunに対応
;
; Ver13('07/07/05)
; 実車速8bitに対応して完成
; オーバーフロー時の車速は過去データを使用する方法に変更
; Speed_Ver.2_8に対応
;
; Ver14('07/07/17)
; サンプリング周期100ms調整完了
; 加速度ロガー車速対応版完成
; Speed_Ver.2_9に対応
;
; 課題
; 車速送信データが200q/h以上のデータは削除したがいいかも
;**********************
;
;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		; 

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	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を10ms光らせる
	movlw	00AH
	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	datai,w
	movwf	hexl

	incf	addrl,f		; アドレス下位を+1加算
	goto	DATATR12	; 繰り上がらなかったらDATATR12へジャンプ
	incf	addrh,f		; 上位繰上げ
DATATR12
	call	EEPRD		; X上位データ読み出し
	movf	datai,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進変換ルーチン

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

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

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

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

	movf	dechh,w
	movwf	decyhh
	movf	dech,w
	movwf	decyh
	movf	decm,w
	movwf	decym
	movf	decl,w
	movwf	decyl

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

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

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

	movf	dechh,w		;
	movwf	decshh
	movf	dech,w
	movwf	decsh
	movf	decm,w
	movwf	decsm
	movf	decl,w
	movwf	decsl

CHECK_DEC0					;バグ取りフィルタ
	movf	decyhh,w		;
	btfsc	STATUS,Z		;decyhh=0ならZフラグが1になっている。0なら次スキップ
	goto	DATATR33		;Z=1なので読み出しをやめて,出力中止
	movf	decshh,w		;
	btfss	STATUS,Z		;decshh=0ならZフラグが1になっている。1なら次スキップ(千の位が0以外ってこと)
	goto	DATATR33		;Z=0なので読み出しをやめて,出力中止

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

	movlw	00DH
	movwf	txdata
	call	RSTRANS
	movlw	00AH		; 0D,0Aで「改行」
	movwf	txdata
	call	RSTRANS
DATATR33
	bsf		PORTB,6		;確認用LED点滅
	call	WAIT_50M
	bcf		PORTB,6
	call	WAIT_50M

	incfsz	stepl,f		; ステップカウンタを加算
	goto	DATATR1		; 繰上げがなかったらルーチン頭へジャンプ
	incfsz	steph,f		; カウンタ上位を加算
	goto	DATATR1		; 繰上げがなかったらルーチン頭へジャンプ

DATATR3
	bsf		PORTB,6		; 送信終了,LED点灯2s
	call	WAIT_500M
	call	WAIT_500M
	call	WAIT_500M
	call	WAIT_500M
	bcf		PORTB,6

	goto	MENU1

;*********************************
;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	08H			;実車速化に伴い8bit化
	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	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		;車速受信結果格納
	clrf	plsh

	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