; Copyright 2004 Sugihara Toshio.
#include <P12F675.INC>
; PIC12F675
; Clock=XT Clock 4.19MHz
; WDT=off, PowerUpTimer=on
; Protect=off
; GP3=GPIO, BrownOutDetect=off

; 変数の定義
idhi		equ	H'20'	;ベンダーコード上位8bits
idlo		equ	H'21'	;ベンダーコード下位8bits
sendval	equ	H'22'	;送信する値本体
o8c		equ	H'23'	;8bits出力ルーチン内のカウンタ
o8b		equ	H'24'	;8bits出力ルーチン内のバッファ
wtmp		equ	H'25'	;時間稼ぎタイマルーチン用
wtmp2	equ	H'26'	;時間稼ぎタイマルーチン用
ucount	equ	H'27'	;38kHzの回数計算用

; はじまり
	; リセットで始まる場合
	org H'00'
boot
	goto start

	; 割り込みではじまる場合
warikomi
	org H'04'	
	movf GPIO, W	;Read GPIO to stop warikomi status
	clrf INTCON	;割り込み禁止
	retfie

	; 通常の起動
start
 	clrf INTCON	;割り込みの禁止
	clrf STATUS	;bank0を選択
	; I/Oの初期化
	movlw B'00000011'
	movwf GPIO
 	movlw H'07'		; コンパレータを使わない
 	movwf CMCON
	bsf STATUS,RP0	;Select Bank 1
	movlw B'00001011';GP0,1,3が入力
	movwf TRISIO		
	movlw B'01111111'		;プルアップ機能を有効に
	movwf OPTION_REG
	clrf ANSEL		;ADコンバータは使わない
	clrf STATUS		;Select Bank 0
	;出力状態の初期化
	movlw B'00000011'		;I/Oの初期出力状態(プルアップあり)
	movwf GPIO
	; 変数の初期化
	movlw H'00'	; ベンダーコード上位 
	movwf idhi
	movlw H'33'	; ベンダーコード下位
	movwf idlo

; 約3ms秒待つ
	movlw D'200'
	call wait8x
	movlw D'193'
	call wait8x

; ボタン入力待ち
checkBLUE
	btfsc GPIO,1		;青が押された？
	goto checkYEL	;いいえ。
					;はい。
	;IDをセットして送信ルーチンへ行く
	movlw H'01'
	movwf sendval
	goto  sendir

checkYEL
	btfsc GPIO,0		;黄が押された？
	goto checkRED	;いいえ。
					;はい。
	;IDをセットして送信ルーチンへ行く
	movlw H'02'
	movwf sendval
	goto sendir

checkRED
	btfsc GPIO,3		;赤が押された？
	goto waitmode	;いいえ。
					;はい。
	;IDをセットして送信ルーチンへ行く
	movlw H'03'
	movwf sendval
	goto sendir

	;ボタンが放されるまでループする
waitRelease
	movf GPIO,W
	iorlw B'11110100'
	xorlw B'11111111'
	btfss STATUS,Z	;全部離された？
	goto waitRelease	;いいえ。
					;はい。

	;いずれかのボタンが押されるまでスリープ
waitmode
	;I/Oピンを待機時の状態にする
	movlw B'00000011'
	movwf GPIO
	nop
	;スリープ前のリード(この状態から変わると起きる)
	movf GPIO,W	
	bsf STATUS,RP0	;Select Bank 1
	movlw B'00001011'	;GP0,1,3を割り込みの対象に
	movwf IOC
	clrf STATUS		;Select bank 0
	clrf INTCON		;Clear INTCON
	bsf INTCON, 3	;Set Port change enable bit
	bsf INTCON, 7	;Set Global Interrupt Enable bit
	; Sleep する
	sleep
	nop		; 割り込みする前にこれが実行されると思う
	nop		; 割り込みのあとはここから実行される
	;起きた後。
	clrf INTCON	;割り込み禁止
	goto start	;最初に戻って動作開始


	; 赤外線信号を送出する。
sendir
	;リーダコードを送る
	movlw D'172'	;9ms送るための繰り返し数
	movwf ucount
sendirp2
	bsf GPIO,2		;点灯 18
	call wait8c
	nop
	bcf GPIO,2		;消灯 10
	call wait8c
	call wait8c
	nop
	bsf GPIO,2		;点灯　18
	call wait8c
	bcf GPIO,2		;消灯　9
	call wait7c
	call wait7c
	decfsz ucount,F
	goto sendirp2
	nop				;17
	;4.5ms待つ
	movlw D'255'
	call wait8x
	movlw D'255'
	call wait8x
	movlw D'79'
	call wait8x		;4715 = 4.4966ms
	;ベンダーコード先発を送信
	movf idhi,W
	call sendbyte
	;ベンダーコード後発を送信
	movf idlo,W
	call sendbyte
	;データ本体を送出
	movf sendval,W
	call sendbyte
	;データ本体反転を送出
	movf sendval,W
	xorlw H'ff'
	call sendbyte
	;ストップビットを送出
	call sendU
	;100ms休む
	call wait100ms
	goto waitRelease

	;1バイトを送る。LSB Firstなのに注意。
	;データはレジスタに入れておく
sendbyte
	movwf o8b	;書き込むデータ
	movlw D'8'
	movwf o8c
sendbytep2
	call sendU		;山を送る
	call wait0565	;「0」の分待つ
	btfsc o8b,0		
	call wait1125	;1の場合はもう少し待つ
	rrf o8b,F		;データを1bitずらす
	decfsz o8c,F
	goto sendbytep2
	return

; 0.5625ms(=590-2サイクル)の山を送る
; 10出して18休むパターン
sendU
	movlw D'10'
	movwf ucount
sendUp2
	bsf GPIO,2		;点灯 18
	call wait8c
	nop
	bcf GPIO,2		;消灯 10
	call wait8c
	call wait8c
	nop
	bsf GPIO,2		;点灯　18
	call wait8c
	bcf GPIO,2		;消灯　9
	call wait7c
	call wait7c
	decfsz ucount,F
	goto sendUp2
	nop				; 17
	bsf GPIO,2		;18
	call wait8c
	nop
	bcf GPIO,2		;10
	call wait7c
	call wait7c		
	call wait7c
	return			;23

; およそ1.125ms待つ(1180)
wait1125
	movlw D'235'
	movwf wtmp
wait1125p2
	nop
	nop
	decfsz wtmp,F
	goto wait1125p2
	return

; およそ0.561ms待つ(588)
wait0565
	movlw D'194'
	movwf wtmp
wait0565p2
	decfsz wtmp,F
	goto wait0565p2
	return

; およそ100ms待つ (104858)
wait100ms
	movlw D'137'
	movwf wtmp2
	movlw D'43'
	movwf wtmp
wait100ms2
	decfsz wtmp,F
	goto wait100ms2
					;767
	decfsz wtmp2,F
	goto wait100ms2	;770

	return			;771

; 呼び出し、戻しを含めて8*WREGサイクル待つ
; 2以上で呼ぶ必要がある。
wait8x
	movwf wtmp
	decf wtmp,F	;1引く
wait8x2
	goto wait8x3
wait8x3
	goto wait8x4
wait8x4
	nop
	decfsz wtmp,F
	goto wait8x2
	goto wait8x5
wait8x5
	nop
	return

;指定のサイクル待つ(call,return含む)
wait8c
	nop
wait7c
	nop
wait6c
	nop
wait5c
	nop
wait4c
	return
	end
