;	list p=PIC16F628
#include <P16F628.INC>
;
; Mouse Running Machine
; Version 1.01
; 2005-08-31
; (c) 2005 Sugihara Toshio.
; All rights reserved.

; PIC16F628
; Clock=4.00MHz 1.00Morder/s
; WDT=on
; PowerUpTimer=on
; Protect=off
; Oscllator=XT
; BrownOutDetect=off
; Low Voltage Program=off

; Memory for all banks
bufa		equ	H'70'	; output buffer for port A
bufb		equ	H'71'	; output buffer for port B
waita	equ	H'72'	; wait timer for wait routine
waitb	equ	H'73'	; wait timer for wait routine
writebuf	equ	H'74'	; Buffer for writing
readbuf	equ	H'75'	; Buffer for reading
ecode	equ	H'76'	; Error code

; Memory for bank 0
tmpx		equ	H'21'	; パリティ計算など
rcount	equ	H'22'	; 回数を数える一般用
bcount	equ	H'23'	; ビット数を数える一般用
mvalue	equ	H'24'	; マウスで読んだ値の大きさ
msgn		equ	H'25'	; マウスで読んだ符号

mbyte1	equ	H'26'	;マウスから読み取った動き値(3から4バイト)
mbyte2	equ	H'27'
mbyte3	equ	H'28'
mbyte4	equ	H'29'

ccount	equ	H'2a'	;マウスから読んだ回数
dcount	equ	H'2b'	;チョッパの回数カウンタ
bcbuf	equ	H'2c'	;Bポートのチョッパ出力時の値のバッファ
cnum		equ	H'2d'	;マウスから読むたびに行うチョッパの回数
					;の、左右クリックで決める回数(1..15)
yelcount	equ	H'2e'	;黄色LEDの点滅制御で用いる
mouseid	equ	H'2f'	;マウスのID番号。0x00か0x03を使う。

zplus	equ	H'30'	;マウスのZ方向プラス移動回数残量
zminus	equ	H'31'	;マウスのZ方向マイナス移動回数座hh量
ymode	equ	H'32'	;黄ボタンによる動作モード(0..7)
mbcount	equ	H'33'	;ymodeまわりのループ計算用
tmpy		equ	H'34'	;一時利用用
bmode	equ	H'35'	;青ボタンによる動作モード(0..1)
swnum	equ	H'36'	;中クリック・bmodeの影響を踏まえて決める
					;マウス読み取りあたりのチョッパ回数


; Program starts from 0
boot
	org H'0'
	goto start
warikomi
	org H'4'
	goto start

start
	clrf INTCON	  ;Disable all interruption
; ERROR if WDT overrun
	movlw D'11'
	movwf ecode
	btfss STATUS,4
	goto errorloop
	clrf ecode

; ERROR if Brown out detect reset is done.
;	movlw D'12'
;	movwf ecode
;	bsf STATUS,RP0	;Select Bank 1
;	btfsc PCON,0	;If BOD is NOT detected,
;	clrf ecode	;Error code is cleared.
;	btfss PCON,1	;If Power On Reset is detecerd,
;	clrf ecode	;Error code is cleared.
;	bcf STATUS,RP0	;Select Bank 0
;	movf ecode,W
;	btfss STATUS,Z
;	goto errorloop

; I/O setup
	call ioinit
; Set initial values for memory
	clrf waita
	clrf waitb
	clrf writebuf
	clrf readbuf
	clrf ecode
	clrf bcount
	clrf rcount
	clrf ccount
	clrf dcount
	clrf mouseid
	clrf zplus
	clrf zminus
	clrf ymode
	clrf bmode
	clrf swnum
	movlw D'8'	;初期状態ではチョッパ8回/マウス読み込み
	movwf cnum	;とする。
	
; Initialize the Mouse
mouseinit
	; Wait for 1000ms
	; 黄色LEDを1回光らせる
	movlw D'1'
	call yellowcount	; 750ms
	movlw D'250'
	call waitms

	;リセットの操作を３回繰り返す
	movlw D'3'
	movwf rcount
mouseinitp2
	; リセットコマンドを送る
	movlw H'ff'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	; 1.00秒待つ
	; 黄色LEDを1回光らせる
	movlw D'1'
	call yellowcount	; 750ms
	movlw D'250'
	call waitms

	;3回までループする
	decfsz rcount,F
	goto mouseinitp2

	;マウスのデバイスIDをチェック
	movlw H'f2'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	;"00"だったらOK
	movf readbuf,W
	movwf mouseid
	xorlw H'00'
	btfss STATUS,Z
	goto errorloopNEQ		;デバイスIDがH'00'でない場合

	; 0x03モードのマウスかどうかを判定
	movlw H'f3'	;set sample rate
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movlw D'200'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movlw H'f3'	;set sample rate
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movlw D'100'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movlw H'f3'	;set sample rate
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movlw D'80'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	;マウスのデバイスIDを再度チェック
	movlw H'f2'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movf readbuf,W
	movwf mouseid	;0x00 または0x03が入る
	
	;Sample rate を 100 に設定。
	movlw H'f3'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	movlw D'100'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	;Resolution を 4count/mmに設定
	movlw H'e8'	;(set resolution)
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	movlw H'02'	;(4 count/mm)
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	
	; リモートモードに設定
	movlw H'f0'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop

	; 現在のcnumを表示してから動作開始
	movf cnum,W		;そのままの値を
	call yellowcount	;表示

mainloop
	; マウス読み込み
	movlw H'eb'
	call sendmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	;1バイトめ読み込み
	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movf readbuf,W
	movwf mbyte1
	;2バイトめ読み込み
	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movf readbuf,W
	movwf mbyte2
	;3バイトめ読み込み
	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movf readbuf,W
	movwf mbyte3
	;0x03マウスの場合は4バイトめを読み込み
	clrf mbyte4
	movf mouseid,W
	xorlw H'03'
	btfss STATUS,Z	;0x03マウスでなければ
	goto mousereadp2	;読まないで次へ
	; 4バイトめ読み込み(0x03マウス)
	call readmousebyte
	movf ecode,W
	btfss STATUS,Z
	goto errorloop
	movf readbuf,W
	movwf mbyte4
	
mousereadp2
	; Y移動量またはX移動量をセット
	movf mbyte3,W	;Y移動量をセット
	btfsc bmode,1	;bmodeのビット1が上がっている場合は
	movf mbyte2,W	;X移動量を
	movwf tmpx		;セット
	; YまたはXの符号・オーバーフローをセット
	movf mbyte1,W
	movwf tmpy
	btfss bmode,1	;bmodeのビット1が下がっている場合は
	rrf tmpy,F		;(Yのフラグをずらすために)tmpyを右シフト。
					;これで
					;符号はbit4に入る。
					;オーバーフローはbit6に入る。

	;マウスの符号により処理を分ける
	btfsc tmpy, 4
	goto mloadsgn1
	;符号が"0"(正または0）の場合
	clrf msgn	;符号変数のセット
	;大きさのセット
	movf tmpx,W
	movwf mvalue
	;オーバーフロー時は255とする
	movlw D'255'
	btfsc tmpy,6		;オーバーフローの場合は
	movwf mvalue		;値を255にする。
	goto buttonread

mloadsgn1
	;符号が"1"(負)の場合
	movlw D'1'
	movwf msgn	;符号変数のセット
	;大きさのセット
	movf tmpx,W
	sublw D'0'
	movwf mvalue
	; "0"は256だが、255を代入する
	movf mvalue,W
	btfsc STATUS,Z	;0だったら
	decf mvalue,F	;255にする。
	;オーバーフロー時は255とする
	movlw D'255'
	btfsc tmpy,6		;オーバーフローの場合は
	movwf mvalue		;値を255にする。

; マウスのボタンを読み、利用する
buttonread
	;左ボタン(チョッパ回数UP:上限15)
	btfss mbyte1, 0
	goto buttonreadp2
	;左を押した
	incf cnum,F	;cnum++
	btfsc cnum,4	;16になったら
	decf cnum,F	;15にする
	;新しい回数を黄色LEDで表示
	movf cnum,W		;そのままの値を
	call yellowcount	;表示

buttonreadp2
	;右ボタン(チョッパ回数DOWN:下限1)
	btfss mbyte1, 1
	goto zread
	;右を押した
	decf cnum,F		;cnumから1をひく
	btfsc STATUS,Z	;0になったら
	incf cnum,F		;1にする。
	;新しい回数を黄色LEDで表示
	movf cnum,W		;そのままの値を
	call yellowcount	;表示

zread
	;Z軸の読み込み
	movf mbyte4,W
	btfsc STATUS,Z	;値が0(Z機能がない場合を含む)
	goto zreadp4		;だと、何もしない。
	;符号の判別
	btfsc mbyte4, 7	;符号が"1"(負)の場合は
	goto zreadp3		;ジャンプ
	;符号は"0"(正)
	movlw D'8'
	movwf zplus
	clrf zminus
	goto zreadp4
zreadp3
	;符号は"1"(負)
	movlw D'8'
	movwf zminus
	clrf zplus
zreadp4
	;zplus,zminusの値に従いmvalueとmsgnを操作
	;zplusによる"-128"のセット
	movf zplus,W
	btfsc STATUS,Z	;0のときは
	goto zreadp5		;何もせずに抜ける
	;zplusによる値の更新(-128)
	movlw D'1'
	movwf msgn	;マイナス
	movlw D'128'
	movwf mvalue
	decf zplus,F
zreadp5
	;zminusによる"+128"のセット
	movf zminus,W
	btfsc STATUS,Z	;0のときは
	goto sgnchange ;何もせずに抜ける
	;zminusによる値の更新(+128)
	movlw D'0'
	movwf msgn	;プラス
	movlw D'128'
	movwf mvalue
	decf zminus,F

sgnchange
	; ymodeによる符号・値の操作
	movlw B'00110000'	;msgnが0のときmvalueを0にする場合
	btfsc msgn,0
	movlw B'00001100'	;msgnが1のときmvalueを0にする場合
	movwf tmpy
	movlw B'10001010'	;msgnが0のときの符号変化列
	btfsc msgn,0
	movlw B'10010001'	;msgnが1のときの符号変化列
	movwf tmpx
	; ymodeにより符号を選択
	movf ymode,W
	movwf mbcount
	btfsc STATUS,Z		;ymodeが0だったら
	goto sgnchangep3		;シフト移動はしない
sgnchangep2
	;シフト移動で、選択するビットをbit0に動かす
	rrf tmpy,F	;値をリセットするか
	rrf tmpx,F	;符号をどうするか
	decfsz mbcount,F
	goto sgnchangep2
sgnchangep3
	;値のリセット
	btfsc tmpy,0	;該当のビットが1なら
	clrf mvalue	;mvalueを0にする
	;符号のセット
	bcf msgn,0
	btfsc tmpx,0
	bsf msgn,0

zreadp6
	; Bポートむけの既存値をチョッパ用バッファにセット
	movf bufb, W
	movwf bcbuf
	;msgnに従いI/O書き込み希望値を決める
	btfsc msgn,0
	goto zreadp7
	;符号が"0"(正)の場合
	bsf bcbuf, 2
	bcf bcbuf, 3
	bsf bcbuf, 6
	goto buttonreadp3
zreadp7
	;符号が"1"(負)の場合
	bcf bcbuf, 2
	bsf bcbuf, 3
	bsf bcbuf, 6

; チョッパの回数を中クリックをふまえて決定
buttonreadp3
	;基準となるチョッパ回数をセット
	movf cnum,W
	movwf swnum
	;中ボタンを押すとチョッパ回数を2倍化する。
	bcf STATUS,0		;Carry bitを下げる
	btfsc mbyte1,2	;中ボタンを押していると
	rlf swnum,F		;左シフトして2倍化する
; bmodeの値をふまえてmvalueを操作
	;bmodeのbit0が"1"の場合、mvalueを2倍化する
	movlw D'255'
	bcf STATUS,0		;Carry bitを下げる
	btfsc bmode,0	;bmodeのbit0が"1"の場合
	rlf mvalue,F		;2倍にする。
	btfsc STATUS,0	;桁あふれが生じたら
	movwf mvalue		;255を入れる。
	
;インバータ（チョッパとして利用）の出力
invout
	;波形の繰り返し回数を設定
	movf swnum,W
	movwf dcount
invoutp1
	;チョッパ出力
	;大きさが0なら「ストップ」にジャンプ
	movf mvalue,W
	btfsc STATUS,Z
	goto invoutstop

	;決めた値をポートBに出す
	movf bcbuf,W
	movwf bufb
	movwf PORTB
	;mvalue * 4us 程度待つ
	movf mvalue,W
	movwf waitb
invoutp2
	clrwdt
	decfsz waitb,F
	goto invoutp2

invoutstop
	;チョッパ出力の「ストップ」
	bcf bufb, 2
	bcf bufb, 3
	bcf bufb, 6	;黄色LEDが消える
	movf bufb,W
	movwf PORTB
	;256 - (出力時の待ち回数) 回ループして待つ
	movf mvalue,W
	sublw D'0'
	movwf waitb	;"0"のときは256回待つ
invoutstopp2
	clrwdt
	decfsz waitb,F
	goto invoutstopp2
	;指定数波形を繰り返す
	decfsz dcount,F
	goto invoutp1

	;黄色ボタンでymodeを0から7の範囲内で進める
checkybutton
	btfsc PORTB, 4 ;黄ボタン
	goto checkbbutton
	;黄ボタンを押した
	incf ymode,F		;1増やす
	btfsc ymode,3	;8になったら
	clrf ymode		;0にする
	;新しい回数を黄色LEDで表示
	incf ymode,W		;変数値に1を足した回数だけ
	call yellowcount	;点滅させる。

	;青色ボタンでbmodeを0から3の範囲内で進める
checkbbutton
	btfsc PORTB, 5 ; 青ボタン
	goto checkccount
	;青ボタンを押した
	incf bmode,F		;bmodeに1を足す。
	btfsc bmode,2	;4になったら
	clrf bmode		;0にする。
	;新しい回数を黄色LEDで表示
	incf bmode,W		;変数値に1を足した回数だけ
	call yellowcount	;点滅させる。

	; マウスの読み込みを256回繰り返したらI/Oを初期化する
checkccount
	incf ccount,F
	btfsc STATUS,Z
	call ioinit

	; メインループに戻って繰り返す
	goto mainloop

; Error loop for "Not equal"
; Error code is 9
errorloopNEQ
	movlw D'9'
	movwf ecode
	goto errorloop

; Error Loop
; Red LED turns on.
; Wait for RESET
errorloop
	;Initialize I/O
	call ioinit
	;Turn on Red LED.
	bsf bufb,7
	movf bufb,W
	movwf PORTB
	; エラーコードを黄色LEDに出力
	movf ecode,W
	call yellowcount
	goto errorloop

; Wレジスタに指定した回数黄色LEDを点滅させる。
; 点滅後は500msほど休む
yellowcount
	;回数をセーブ
	movwf yelcount
	;回数が0の場合は出さない
	movf yelcount,W
	btfsc STATUS,Z		;回数が0のときは
	goto yellowcountend	;何も出さない

yellowcountp2
	;黄色LEDをつける
	bsf bufb,6
	movf bufb,W
	movwf PORTB
	;125ms待つ
	movlw D'125'
	call waitms
	;黄色LEDを消す
	bcf bufb,6
	movf bufb,W
	movwf PORTB
	;125ms待つ
	movlw D'125'
	call waitms
	;yelcount回まで繰り返す
	decfsz yelcount,F
	goto yellowcountp2

	;表示終了後
yellowcountend
	;Wait for 500 (ms)
	movlw D'250'
	call waitms
	movlw D'250'
	call waitms
	return

; Send a byte to mouse and receive ACK(H'FA')
; Data to send is set at W register.
; If error occurs, ecode becomes NOT zero.
; If succeed, ecode becomes zero.
sendmousebyte
	;Save value to write
	movwf writebuf
	; Make PortA latch safe
	bcf bufa, 3 ;Data
	bcf bufa, 4 ;Clock
	movf bufa,W
	movwf PORTA
	; set Clock Low for 200us
	call clocklow
	call wait100us
	call wait100us
	; set Data Low
	call datalow
	; Release Clock
	call clockhigh
	; Wait Clock Low till 15ms
	movlw D'15'
	movwf waita
sendmousebytep2
	movlw D'167'
	movwf waitb
sendmousebytep3
	clrwdt
	;Check if Clock is low
	btfss PORTA, 4 ;Clock
	goto sendmousebytep4	; Clock becomes low!

	decfsz waitb,F
	goto sendmousebytep3
	decfsz waita,F
	goto sendmousebytep2
	; エラー「デバイスがクロックを引き始めない」
	movlw D'1'
	movwf ecode
	goto sendmousereturn

;After clock becomes low,
sendmousebytep4
	movlw D'8'
	movwf bcount		;Bits to send
	movlw D'1'		;For parity calculation.
	movwf tmpx		;For Odd parity
sendmousebytep5
	; Calculate parity value
	btfsc writebuf,0
	incf tmpx,F
	; Set a bit to send
	btfsc writebuf,0
	goto sendmousebytep6
	; Send "0"
	call datalow	; send "0"
	goto sendmousebytep7
sendmousebytep6
	call datahigh ; send "1"
sendmousebytep7
	;Wait for clock rise (Max 100us)
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto sendmousereturn
	;Wait for clock down (Max 100us)
	call clockdownwait
	movf ecode,W
	btfss STATUS,Z
	goto sendmousereturn
	;Set next value
	rrf writebuf,F
	;Check if 8 bytes are sent
	decfsz bcount,F
	goto sendmousebytep5

	;Send parity bit
	btfsc tmpx,0
	goto sendmousebytep8
	call datalow	;send "0"
	goto sendmousebytep9
sendmousebytep8
	call datahigh ;send "1"
sendmousebytep9
	;Wait for clock rise
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto sendmousereturn
	;Wait for clock down
	call clockdownwait
	movf ecode,W
	btfss STATUS,Z
	goto sendmousereturn

	;Send stop bit
	call datahigh
	;Wait for clock rise
	call clockupwait
	movf ecode,W
	btfss STATUS,Z		;then error is detected.
	goto sendmousereturn
	;Wait for clock down
	call clockdownwait
	movf ecode,W
	btfss STATUS,Z		;then error is detected.
	goto sendmousereturn
	
	;Check ACK bit
	movlw D'4'			;Error code for ACK
	movwf ecode
	btfsc PORTA, 3		; If data bit is up,
	goto sendmousereturn	; error is detected,
	clrf ecode

	;Wait for clock to rise
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto sendmousereturn

	; Send 1 byte to the device is done here,
	; then receive a ACK message from the device

	call readmousebyte
	movf ecode,W
	btfss STATUS,Z			;If read error is detected,
	goto sendmousereturn05	;value "5" is set.
	;Check value if it is H'fa'
	movf readbuf,W
	xorlw H'fa'
	btfss STATUS,Z			;If readbuf is not H'fa',
	goto sendmousereturn05	;error is detected.

	; Reading is done, and ACK is
	; detected successfully.
	clrf ecode	;succeed!
	goto sendmousereturn

; マウスからの読み取りルーチンを終了する
;	ecodeが持ちうる値とその意味
	;0 正常
	;1 クロックをマウスが最初にさげない
	;2 クロックをマウスがあげない
	;3 クロックをマウスがさげない
	;4 ACKビットがこない
	;5 ACKバイト(FA)がこないかエラー
sendmousereturn
	call datahigh
	call clockhigh
	return

; Set error code (5) and return
sendmousereturn05
	movlw D'5'
	movwf ecode
	goto sendmousereturn

; Read a byte from the mouse device.
; Error code is set in ecode (succeed=0).
; Read value is set to the readbuf.
readmousebyte
	; Make PortA latch safe
	bcf bufa, 3 ;Data
	bcf bufa, 4 ;Clock
	movf bufa,W
	movwf PORTA
	;パリティ変数の初期化
	clrf tmpx
	;Wait for up to 20ms
	movlw D'20'
	movwf waita
readmousebytep2
	movlw D'167'
	movwf waitb
readmousebytep3
	clrwdt
	;Check if Clock is low
	btfss PORTA,4		;If the Clock is low,
	goto readmousebytep4	;go to next stage.

	decfsz waitb,F
	goto readmousebytep3
	decfsz waita,F
	goto readmousebytep2
	; Error detected.
	movlw D'6'	;Clock is not generated from device.
	movwf ecode
	goto readmousereturn

; クロックが下がってから
readmousebytep4
	; スタートビットを受け取る
	movlw D'10'
	movwf ecode
	btfsc PORTA,3		;If data is high,
	goto readmousereturn	;Error 10 is detected.
	clrf ecode

	; クロックがあがって下がるのを待つ
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	call clockdownwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	;データビットを受け取る
	movlw D'8'
	movwf bcount
readmousebytep5
	rrf readbuf,F	;以前の値を右シフト
	;1ビット読み込む
	bcf readbuf,7
	btfsc PORTA,3
	bsf readbuf,7
	;パリティビットの計算
	btfsc readbuf,7
	incf tmpx,F
	; クロックがあがって下がるのを待つ
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	call clockdownwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	; 8bit読むまで回る
	decfsz bcount,F
	goto readmousebytep5

	; パリティビットを受け取る
	btfsc PORTA,3
	incf tmpx,F
	; パリティがあっているか調べる
	movlw D'7'	;エラーコード
	movwf ecode
	btfss tmpx,0			;奇パリティが0だと
	goto readmousereturn	;エラーになる。
	clrf ecode

	; クロックがあがって下がるのを待つ
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	call clockdownwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	; ストップビットを受け取る
	movlw D'8'	;エラーコード
	movwf ecode
	btfss PORTA,3		;stop bitが0になっていたら
	goto readmousereturn	;エラーとなる。
	clrf ecode

	;クロックがあがるのを待つ
	call clockupwait
	movf ecode,W
	btfss STATUS,Z
	goto readmousereturn

	; 読み込みは正常に終了
	clrf ecode
	goto readmousereturn

; ecodeに入りうるエラー番号
; 0 正常終了
; 6 デバイスがクロックを20ms待っても下げない
; 2 クロックをマウスがあげない
; 3 クロックをマウスがさげない
; 7 パリティビットが不整合
; 8 ストップビットが違っている
;10 スタートビットが違っている
readmousereturn
	call datahigh
	call clockhigh
	return


; Wait for Wreg(ms)
; (4b+4)a+4サイクルかかる
; 1000a + 4 (us)かかる
waitms
	movwf waita

	;ここから4b+1サイクル
waitmsp2
	movlw D'249'
	movwf waitb
waitmsp3
	clrwdt
	decfsz waitb,F
	goto waitmsp3
	;ここまで4b+1サイクル

	decfsz waita,F
	goto waitmsp2

	return

; Wait for 100us
; consume 101 orders (including call and return)
wait100us
	movlw D'24'
	movwf waitb
wait100usp2
	clrwdt
	decfsz waitb,F
	goto wait100usp2
	return

;Wait for clock up for up to 100us
;ecode = succeed:0 error:2
clockupwait
	clrf ecode
	movlw D'17'
	movwf waitb
clockupwaitp2
	clrwdt
	btfsc PORTA,4
	return
	decfsz waitb,F
	goto clockupwaitp2
	movlw D'2'
	movwf ecode
	return

;Wait for clock down for up to 100us
;ecode = succeed:0 error:3
clockdownwait
	clrf ecode
	movlw D'17'
	movwf waitb
clockdownwaitp2
	clrwdt
	btfss PORTA,4
	return
	decfsz waitb,F
	goto clockdownwaitp2	
	movlw D'3'
	movwf ecode
	return

clocklow
	bcf PORTA, 4
	bsf STATUS,RP0	;Select Bank 1
	bcf TRISA, 4 ;Set Clock as Output 
	bcf STATUS,RP0	;Select Bank 0
	bcf PORTA, 4
	return

clockhigh
	bsf STATUS,RP0	;Select Bank 1
	bsf TRISA, 4 ;Set Clock as Input 
	bcf STATUS,RP0	;Select Bank 0
	return

datalow
	bcf PORTA,3
	bsf STATUS,RP0	;Select Bank 1
	bcf TRISA, 3 ;Set Data as Output 
	bcf STATUS,RP0	;Select Bank 0
	bcf PORTA,3
	return

datahigh
	bsf STATUS,RP0	;Select Bank 1
	bsf TRISA, 3 ;Set Data as Input 
	bcf STATUS,RP0	;Select Bank 0
	return

; I/O initialization
; A3,A4,B2,B3 are inputs
; A,B are set as 0.
; bufa, bufb also become 0.
; (Blue LED is on.)
ioinit
	clrwdt
	clrf STATUS	  ;Select bank 0
	clrf INTCON
	clrf PORTA
	clrf PORTB
	movlw B'00111000' ;Choose bank 1
	movwf STATUS
	movlw B'00000111' ;TMR0 overflows 15.26Hz (1/256)
	movwf OPTION_REG	 ;Pull Up is on.
	movlw B'00011000' ;A3,A4 are input.
	movwf TRISA
	movlw B'00110000' ;B2,B3 are output.
	movwf TRISB
	movlw H'ff'		; Erase POR and BOD code
	movwf PCON
	bcf STATUS,RP0	;choose bank 0
	movlw H'7'		;Comparator is off.
	movwf CMCON		
	clrf PORTA
	clrf PORTB
	clrf bufa
	clrf bufb
	return
	end
