;
;	NEC フォーマットで 8 bit の信号が来たときにデコードする回路
;
;                                    by T. Yabu
;
;	2009.8.31	初版作成
;

#define PIC819
;#define PIC84A

#ifdef PIC819
	LIST	P=PIC16F819
	INCLUDE	P16F819.INC
	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF & _BODEN_ON & _MCLR_ON & _LVP_OFF
#endif

#ifdef PIC84A
	LIST P=PIC16F84A
	INCLUDE P16F84A.INC
	__CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _CP_OFF
#endif

; BODEN    ブラウンアウト検出 ON 有効 ／ OFF 無効
;          電源電圧が下がったときにリセットするか否か
; MCLR_ON  Master Clear ピンを使用／使用しない
; LVP      Low Voltage Program 有効／無効
; CP       Code Protect
; CPD      EEPROM の読み出しプロテクト

cblock	0x20
	c1,c2,c3
	buf
	count,i
endc

;--------- 初期設定 ----------

ifdef PIC819

	banksel	INTCON
	clrf	INTCON			; 割り込み禁止

	banksel	ADCON1
	movlw	B'00000110'		; PORTA は全てデジタル入力 
	movwf	ADCON1
endif

	banksel	TRISA
	movlw	B'00011111'		; PORTA は全て入力
	movwf	TRISA
	movlw	B'00000000'		; PORTB は全て出力
	movwf	TRISB

	banksel	PORTB
	movlw	B'00000000'		; 最初は 0 を出力
	movwf	PORTB

;------ ループ開始点------
;
;	受光素子の出力は反転することに注意
;	無信号時は 1 を出力
;
	banksel	PORTA

LOOP_TOP

;	ヘッダである 9 ms の 0 を検出する

L1
	call	FIND_ZERO

;	0 の長さをカウントする

	movlw	D'0'
	movwf	count
L2
	call	DELAY_100us
	incf	count,F

	btfss	PORTA,1		; 1 が来たなら 80 より大きいかチェックする
	goto	L2

	movlw	D'80'		; 80 より大きいかどうか比較する
	subwf	count,W		; Wreg = count - Wreg
						; 結果が正または 0 のとき C が立つ
	btfss	STATUS,C
	goto	L1	

	call	FIND_ZERO

;	8 bit 読み込んで buf に入れる
;	1 の長さが 0 か 1 を表す

	movlw	D'8'
	movwf	i
	clrf	buf
L22
;	1 の時間をカウントする

	call	FIND_ONE
	movlw	D'0'
	movwf	count
L3
	call	DELAY_100us
	incf	count
;	count が 20 を超えたら何らかのエラーが発生したと考えられるので、
;	処理を中断する
	movlw	D'20'
	subwf	count,W		; Wreg = count - Wreg
						; 結果が正または 0 のとき C が立つ
	btfsc	STATUS,C	
	goto	LOOP_TOP

;	0 が来るまで待つ
	btfsc	PORTA,1
	goto	L3

;	count の大きさにより 0 か 1 かを判断する
	movlw	D'10'
	subwf	count,W		; Wreg = count - 10
						; 結果が正または 0 のとき C が立つ		
	btfss	STATUS,C
	goto	SHORT
LONG
	rlf		buf
	bsf		buf,0
	goto	CONT
SHORT
	rlf		buf
	bcf		buf,0
CONT
	decfsz	i,F
	goto	L22

	movf	buf,W
	movwf	PORTB

	goto	LOOP_TOP

;------ 0 を見つける ------

FIND_ZERO
	btfsc	PORTA,1
	goto	FIND_ZERO
	return

;------ 1 を見つける ------

FIND_ONE
	btfss	PORTA,1
	goto	FIND_ONE
	return

;--------- ディレイ -----------
;
;	PIC のディレイの考え方
;
;	4 クロックで 1 サイクル
;	10M のとき 1 サイクルは 0.4 us
;	20M のとき 1 サイクルは 0.2 us
;
;	MOV, NOP        : 1 サイクル
;	DECFSZ			: 通常 1 サイクル。次の goto と合わせると 3 サイクル
;					  LOOP を抜けるときは、次の命令を NOP にするので 2 サイクル
;	GOTO, RETURN, CALL : 2 サイクル
;
;	ループを 100 回まわる場合、最後の 1 回のみ GOTO では
;	なく NOP になるので、-1 サイクルとなる。

;   上位のルーチンと合わせて 100 us のディレイを作る
;	上位のルーチンが単純なループのとき
;   call, decfsz, goto で 5 サイクル
;
;	このルーチンは 2 + 164 * 3 - 1 + 2 = 495 サイクル

DELAY_100us
	movlw	D'164'
	movwf	c1
LOOP_100us
	decfsz	c1,F
	goto	LOOP_100us
	return

END
