;------------------------------------------------------------------------------
; ドリームライト2
;------------------------------------------------------------------------------
; バージョン履歴
;------------------------------------------------------------------------------
; 2023/12/06 Ver.0.12	夕焼けモードのハーフを追加、タイマー時間の変更
; 2023/11/20 Ver.0.11	タイマー実行解除のリモコンコードフィルタをつけ忘れていた
;			リモコン操作でちらつくのは、通常スレッドとccp1_handlerで共通のMATH変数を使っているのが原因だった。
;			支障が無いので放置する。
; 2023/11/18 Ver.0.10	夕焼け色に青を追加、上昇タイマーを実装
; 2023/11/18 Ver.0.09	夕焼けタイマー実装
;			割り込みを禁止しているのにリモコンを操作するとなぜかLEDがちらつくことがある
; 2023/11/18 Ver.0.08	夕焼けモード実装
; 2023/11/15 Ver.0.07	完成
; 2023/11/14 Ver.0.06	rgb2hsv実装、残りhue2rgb、hsl2rgb、hsv2rgb
; 2023/11/14 Ver.0.05	rgb2hsl実装
; 2023/11/14 Ver.0.04	rgb2hue実装
; 2023/11/13 Ver.0.03	色変換ルーチン以外を実装
; 2023/11/12 Ver.0.02	プログラムを整理
; 2023/11/06 Ver.0.01	とりあえずRGBで動く
; 2023/10/22 Ver.0.00	回路図作成
;------------------------------------------------------------------------------
; IRP,RP1,RP0を切り替える所で◆ RP=, ● IRP=をコメントに置く
; PCLATHを切り替える所で■ PCLATHをコメントに置く
; サブルーチンからの戻りの時、
;  RP1,RP0は0に戻してリターンする。
;  IRP,PCLATHは戻さずにリターンする。
; ルーチン呼び出しの時もRP=0を基本として記述している。
;------------------------------------------------------------------------------
; デバイス	PIC12F683
; 動作周波数	HS 20MHz
;------------------------------------------------------------------------------
	LIST		P=PIC12F683,R=DEC,N=0
	INCLUDE		"P12F683.INC"
	ERRORLEVEL	0,-302,-306,-307
	__CONFIG 	0x33C2
					; FOSC : HS
					; WDTE : Disable
					; PWRTE: Enable
					; MCLRE: GP3=Input
					; BODEN: Enable
					; CP   : Not Protect
					; CPD  : Not Protect
					; IESO : Disable
					; FCMEN: Disable
;------------------------------------------------------------------------------
; 変数宣言
;------------------------------------------------------------------------------
IR_STATUS	EQU	0x20		; IR受信用変数
IR_FORMAT	EQU	0x21
IR_LENGTH	EQU	0x22
PW0_L		EQU	0x23
PW0_H		EQU	0x24
PW1_L		EQU	0x25
PW1_H		EQU	0x26
THRESHOLD_L	EQU	0x27
THRESHOLD_H	EQU	0x28
BITMASK		EQU	0x29
MASKDATA	EQU	0x2A
NEW_FORMAT	EQU	0x2B
DESTROY_COUNT	EQU	0x2C
KEYCODE		EQU	0x2D
NREPS		EQU	0x2E

MODE		EQU	0x2F		; カラーモード

RGB_R		EQU	0x30		; 色変換格納場所
RGB_G		EQU	0x31
RGB_B		EQU	0x32
HSX_H		EQU	0x33
HSX_S		EQU	0x34
HSX_X		EQU	0x35
MAX		EQU	0x36
MIN		EQU	0x37

LED1_R		EQU	0x38		; LED送信バッファ
LED1_G		EQU	0x39
LED1_B		EQU	0x3A
LED2_R		EQU	0x3B
LED2_G		EQU	0x3C
LED2_B		EQU	0x3D
LED3_R		EQU	0x3E
LED3_G		EQU	0x3F
LED3_B		EQU	0x40
LED4_R		EQU	0x41
LED4_G		EQU	0x42
LED4_B		EQU	0x43
LED5_R		EQU	0x44
LED5_G		EQU	0x45
LED5_B		EQU	0x46
LED6_R		EQU	0x47
LED6_G		EQU	0x48
LED6_B		EQU	0x49


MATH00		EQU	0x4A		; LSB 四則演算用変数
MATH01		EQU	0x4B		; MSB
MATH10		EQU	0x4C
MATH11		EQU	0x4D
MATH20		EQU	0x4E
MATH21		EQU	0x4F
MATH_TEMP	EQU	0x50

SUNSET_VALUE	EQU	0x51

FLAG		EQU	0x5E
INTSRC		EQU	0x5F		; 割り込みマスクと要因のAND
IR_BUFFER	EQU	0x60		;-0x6F 16バイト IR受信バッファ

TMP00		EQU	0x70		; 一時使用変数
TMP01		EQU	0x71
TMP02		EQU	0x72
TMP03		EQU	0x73
TMP10		EQU	0x74
TMP11		EQU	0x75
TMP12		EQU	0x76
TMP13		EQU	0x77
TMP20		EQU	0x78
TMP21		EQU	0x79
TMP22		EQU	0x7A
TMP23		EQU	0x7B

W_		EQU	0x7C		; 割り込みの退避用
STATUS_		EQU	0x7D
PCLATH_		EQU	0x7E
FSR_		EQU	0x7F

;------------------------------------------------------------------------------
; 定数宣言
;------------------------------------------------------------------------------
SIGN		EQU	0		; FLAG	0=POS 1=NEG

LED_OUT		EQU	0		; GPIO
BUZZER		EQU	1

IDENT_1		EQU	0x04		; IR
IDENT_2		EQU	0xFB

M_RGB		EQU	0		; MODE値
M_HSL		EQU	1
M_HSV		EQU	2
M_SUNSET	EQU	3

SUNSET_H1	EQU	8
SUNSET_H2	EQU	145
SUNSET_DAYLIGHT	EQU	224
SUNSET_DARK	EQU	160
SUNSET_FAST	EQU	5		; 0.5秒ごとに減算する 256*0.5=128秒(2分)  224*0.5=112秒
SUNSET_SLOW	EQU	20		; 2.0秒ごとに減算する 256*2.0=512秒(8.5分)224*2.0=448秒(7.5分)

NREPS_THRESH	EQU	8		; リピートがn回以上なら加速値NREPS_SPEEDを適用
NREPS_SPEED	EQU	5

DESTROY_TIMER	EQU	50		;リピート判定後に13.1072ms*DESTROY_TIMER経過してから無効化を実行する

IDLE		EQU	0		; IR_STATUS 値
RECIEVING	EQU	1		; IR_STATUS 値
RECIEVED	EQU	2		; IR_STATUS 値

UNDEF		EQU	0		; IR_FORMAT 値
AEHA		EQU	1		; IR_FORMAT 値
NEC		EQU	2		; IR_FORMAT 値
SONY		EQU	3		; IR_FORMAT 値
REPEAT		EQU	0x10		; IR_FORMAT フラグ

IRMAXLEN	EQU	128		; IR最大保存ビット数 16バイト
MIN_PERCENT	EQU	75
MAX_PERCENT	EQU	133

TRAILER_TIMER	EQU	100000
TRAILER_T1OFFSET EQU	(131072-TRAILER_TIMER)/2

T_AEHA		EQU	4250 / 2	; 1Tの時間
T_NEC		EQU	5620 / 2
T_SONY		EQU	6000 / 2

L1_AEHA		EQU	T_AEHA * 8	; リーダーのメーク時間
L1_NEC		EQU	T_NEC  * 16
L1_SONY		EQU	T_SONY * 4

L2_AEHA		EQU	T_AEHA * 4	; リーダーのブレーク時間
L2_NEC		EQU	T_NEC  * 8
L2_SONY		EQU	T_SONY * 1

R_AEHA		EQU	T_AEHA * 8	; リピートリーダーのブレーク時間
R_NEC		EQU	T_NEC  * 4

D1MAX_AEHA	EQU	T_AEHA * 3 / 2	; データのメーク時間の最大(1.5T)
D1MAX_NEC	EQU	T_NEC  * 3 / 2	; D1MAX <= x <= THRESHOLDまでの中途半端な時間は無効データになる点に注意せよ
D1MAX_SONY	EQU	T_SONY * 3 / 2

D2MAX_AEHA	EQU	T_AEHA * 4	; データのブレーク時間の最大
D2MAX_NEC	EQU	T_NEC  * 4
D2MAX_SONY	EQU	T_SONY * 5 / 2	; 2.5T
;------------------------------------------------------------------------------
; 電源ON
;------------------------------------------------------------------------------
	ORG	0
	GOTO	POWER_ON
;------------------------------------------------------------------------------
; 割り込み分岐
;------------------------------------------------------------------------------
	ORG	4
INTRRUPT
	MOVWF	W_			; Wセーブ
	SWAPF	STATUS,W		; STATUSセーブ
	MOVWF	STATUS_
	MOVF	PCLATH,W		; PCLATHセーブ
	MOVWF	PCLATH_
	MOVF	FSR,W			; FSRセーブ
	MOVWF	FSR_

	CLRF	STATUS			; ● IRP=0
	BSF	STATUS,RP0		; ◆ RP=1
	MOVF	PIE1,W
	BCF	STATUS,RP0		; ◆ RP=0
	ANDWF	PIR1,W			; PIEが0でもPIRが立つので、
	MOVWF	INTSRC			;  ANDを取って不要な割り込みハンドラへの分岐を防ぐ。

	BTFSC	INTSRC,CCP1IF		; ここまでの命令はクロック補正をするため位置を動かしてはいけない。
	 GOTO	ccp1_handler
CCP1_RETURN

	BTFSC	INTSRC,TMR1IF		; 割り込み中に他の割り込みが来るかもしれないので、
	 GOTO	timer1_handler		; 念のためすべての要因をチェックする。
TMR1_RETURN

	RLF	INTCON,W		; INTCONも同様
	MOVWF	INTSRC
	SWAPF	INTSRC,F
	MOVF	INTCON,W
	ANDWF	INTSRC,W
	ANDLW	7
	MOVWF	INTSRC
	
	BTFSC	INTSRC,TMR0IF
	 GOTO	timer0_handler
TMR0_RETURN

	MOVF	FSR_,W			; FSRリストア
	MOVWF	FSR
	MOVF	PCLATH_,W		; PCLATHリストア
	MOVWF	PCLATH
	SWAPF	STATUS_,W		; STATUSリストア
	MOVWF	STATUS
	SWAPF	W_,F			; Wリストア
	SWAPF	W_,W
	RETFIE
;------------------------------------------------------------------------------
; [PCL] RGBから色相に変換
;
; 引数
;	RGB_R,RGB_G,RGB_B
;
; 戻り値
;	HSX_H
;
; 使用変数
;	TMP00,01,02,03,10
;------------------------------------------------------------------------------
rgb2hue
	CALL	rgb_maxmin
	MOVWF	TMP10			; TMP10(col)
	MOVF	MIN,W
	SUBWF	MAX,W
	MOVWF	TMP01			; TMP01(diff) = MAX - MIN
	CLRF	PCLATH			; ■ PCLATH
	MOVF	TMP10,W
	ADDWF	PCL,F
	 GOTO	RGB2HUE_0		; MAX = MIN
	 GOTO	RGB2HUE_R
	 GOTO	RGB2HUE_G
	 GOTO	RGB2HUE_B
RGB2HUE_0
	CLRF	HSX_H
	RETURN
RGB2HUE_R
	MOVLW	240			; TMP03(v2)
	MOVWF	TMP03
	MOVF	RGB_B,W			; MATH00(v1) = RGB_G - RGB_B
	SUBWF	RGB_G,W
	GOTO	RGB2HUE_RGB
RGB2HUE_G
	MOVLW	80
	MOVWF	TMP03
	MOVF	RGB_R,W			; MATH00(v1) = RGB_B - RGB_R
	SUBWF	RGB_B,W
	GOTO	RGB2HUE_RGB
RGB2HUE_B
	MOVLW	160
	MOVWF	TMP03
	MOVF	RGB_G,W			; MATH00(v1) = RGB_R - RGB_G
	SUBWF	RGB_R,W
RGB2HUE_RGB
	MOVWF	MATH00
	BCF	FLAG,SIGN
	BTFSS	STATUS,C
	 BSF	FLAG,SIGN
	BTFSS	STATUS,C
	 CALL	neg8
	MOVLW	40			; MATH00 = MATH00(v1) * 40
	MOVWF	MATH10
	CALL	mul8
	MOVF	TMP01,W			; MATH00 = MATH00 / TMP01(diff)
	MOVWF	MATH10
	CLRF	MATH11
	CALL	div16
	BTFSC	FLAG,SIGN
	 CALL	neg16
	MOVF	TMP03,W			; + TMP03(v2)
	MOVWF	MATH10
	CLRF	MATH11
	CALL	add16
	MOVF	MATH00,W
	MOVWF	HSX_H
	MOVLW	240
	MOVWF	MATH10
	CLRF	MATH11
	CALL	sub16
	MOVF	MATH00,W
	BTFSC	STATUS,C
	 MOVWF	HSX_H
	RETURN
;------------------------------------------------------------------------------
; [PCL] メインループ
;------------------------------------------------------------------------------
MAINLOOP
	MOVLW	B'00000010'		; ブザー
	XORWF	GPIO,F
MAINLOOP_NOBZ
	CLRF	IR_STATUS
MAINLOOP_IRPOLL
	MOVLW	RECIEVED		; IR 受信データ処理
	SUBWF	IR_STATUS,W
	BTFSS	STATUS,Z
	 GOTO	MAINLOOP_IRPOLL

	BTFSC	IR_FORMAT,4		; リピートフラグチェック
	 GOTO	LAST_REPEAT

	CALL	ir_to_keycode
	MOVWF	KEYCODE
	CLRF	NREPS
LAST_REPEAT
	INCF	NREPS,F
	CLRF	PCLATH			; ■ PCLATH
	MOVF	KEYCODE,W
	ADDWF	PCL,F
	 GOTO	MAINLOOP_NOBZ		; 0 UNKNOWN
	 GOTO	TO_RGB			; 1 PC
	 GOTO	TO_HSL			; 2 VIDEO
	 GOTO	TO_HSV			; 3 SVIDEO
	 GOTO	UP_1			; 4 BRITE
	 GOTO	UP_2			; 5 CONT
	 GOTO	UP_3			; 6 COLOR
	 GOTO	DOWN_1			; 7 HUE
	 GOTO	DOWN_2			; 8 SYSTEM
	 GOTO	DOWN_3			; 9 RECALL
	 GOTO	TO_DAYLIGHT		; 10 OSD
	 GOTO	TO_SUNSET		; 11 +
	 GOTO	DARKEN			; 12 -
;------------------------------------------------------------------------------
TO_RGB
	MOVLW	M_RGB			; 現在と同じモードなら実行しない
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	MOVLW	M_RGB			; RGBの時は単にモードを切り替えるだけ
	MOVWF	MODE
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
TO_HSL
	MOVLW	M_HSL
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	MOVLW	M_HSL
	MOVWF	MODE
	CALL	rgb2hsl
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
TO_HSV
	MOVLW	M_HSV
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	MOVLW	M_HSV
	MOVWF	MODE
	CALL	rgb2hsv
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
TO_DAYLIGHT
	MOVLW	SUNSET_DAYLIGHT
TO_DAYLIGHT1
	MOVWF	TMP00
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSS	STATUS,Z
	 GOTO	TO_DAYLIGHT2
	MOVF	TMP00,W
	SUBWF	SUNSET_VALUE,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
TO_DAYLIGHT2
	CALL	beep
	MOVLW	M_SUNSET
	MOVWF	MODE
	MOVF	TMP00,W
	MOVWF	SUNSET_VALUE
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
TO_SUNSET
	MOVLW	SUNSET_DARK
	GOTO	TO_DAYLIGHT1
;------------------------------------------------------------------------------
DARKEN
	MOVF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	DARKEN_RGB
	ADDLW	255
	BTFSC	STATUS,Z
	 GOTO	DARKEN_HSX
	ADDLW	255
	BTFSC	STATUS,Z
	 GOTO	DARKEN_HSX
DARKEN_SUNSET
	MOVF	SUNSET_VALUE,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	CLRF	SUNSET_VALUE
	GOTO	CALC_SUNSET
DARKEN_RGB
	MOVF	RGB_R,W
	IORWF	RGB_G,W
	IORWF	RGB_B,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	CLRF	RGB_R
	CLRF	RGB_G
	CLRF	RGB_B
	GOTO	POST_INCDEC
DARKEN_HSX
	MOVF	HSX_X,W
	BTFSC	STATUS,Z
	 GOTO	MAINLOOP_NOBZ
	CALL	beep
	CLRF	HSX_X
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
UP_1
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	MOVLW	RGB_R
	BTFSC	STATUS,Z
	 MOVLW	SUNSET_VALUE
	GOTO	UP_COM
UP_2
	MOVLW	SUNSET_FAST
	MOVWF	TMP11
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	SUNRISE
	MOVLW	RGB_G
	GOTO	UP_COM
UP_3
	MOVLW	SUNSET_SLOW
	MOVWF	TMP11
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	SUNRISE
	MOVLW	RGB_B
UP_COM
	CALL	is_HSX			; HSL or HSVの時はFSRの位置を変える

	MOVLW	HSX_H			; HUEは循環するので別ルートで処理する
	SUBWF	FSR,W
	BTFSC	STATUS,Z
	 GOTO	UP_HUE

	MOVLW	255			; 最大値の時は実行しない
	SUBWF	INDF,W			; HUEは239上限で循環するように作り変える
	BTFSS	STATUS,Z
	 GOTO	UP_COM2
	CALL	beep
	GOTO	MAINLOOP_NOBZ
UP_COM2
	CALL	nreps_step
	ADDWF	INDF,W
	BTFSC	STATUS,C
	 MOVLW	255
	MOVWF	INDF
POST_INCDEC
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	CALC_SUNSET
	MOVLW	M_HSL			; HSLかHSVモードの時はRGBに変換してから出力する
	SUBWF	MODE,W
	BTFSC	STATUS,Z
POST_INCDEC2
	 CALL	hsl2rgb
	MOVLW	M_HSV
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 CALL	hsv2rgb
	CALL	copy_all
	CALL	txled_all
	GOTO	MAINLOOP

UP_HUE
	CALL	nreps_step
	ADDWF	INDF,F			; 一旦保存して240以上なら0以上へオフセットさせる
	MOVLW	240
	SUBWF	INDF,W
	MOVLW	256-240
	BTFSC	STATUS,C
	 ADDWF	INDF,F
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
CALC_SUNSET
	CALL	calc_night
	GOTO	POST_INCDEC2

calc_night
	MOVLW	16
	SUBWF	SUNSET_VALUE,W
	MOVLW	SUNSET_H1
	BTFSS	STATUS,C
	 MOVLW	SUNSET_H2
	MOVWF	HSX_H
	MOVF	SUNSET_VALUE,W		; 明度はリニア
	MOVWF	HSX_X
	MOVLW	255
	MOVWF	HSX_S
	MOVLW	128			; 彩度はSUNSET>=128までは255
	SUBWF	SUNSET_VALUE,W
	BTFSC	STATUS,C
	 RETURN
	MOVLW	16
	SUBWF	SUNSET_VALUE,W
	BTFSS	STATUS,C
	 GOTO	NIGHT_BLUE
	BCF	STATUS,C
	RLF	SUNSET_VALUE,W
	MOVWF	HSX_S
	RETURN
NIGHT_BLUE
	MOVF	SUNSET_VALUE,W
	SUBLW	16
	MOVWF	HSX_S
	SWAPF	HSX_S,W
	MOVWF	HSX_S
	RETURN
;------------------------------------------------------------------------------
DOWN_1
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	MOVLW	RGB_R
	BTFSC	STATUS,Z
	 MOVLW	SUNSET_VALUE
	GOTO	DOWN_COM
DOWN_2
	MOVLW	SUNSET_FAST
	MOVWF	TMP11
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	SUNSET
	MOVLW	RGB_G
	GOTO	DOWN_COM
DOWN_3
	MOVLW	SUNSET_SLOW
	MOVWF	TMP11
	MOVLW	M_SUNSET
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	SUNSET
	MOVLW	RGB_B
DOWN_COM
	CALL	is_HSX

	MOVLW	HSX_H
	SUBWF	FSR,W
	BTFSC	STATUS,Z
	 GOTO	DOWN_HUE

	MOVF	INDF,W			; 最小値の時は実行しない
	BTFSS	STATUS,Z		; HUEは239上限で循環するように作り変える
	 GOTO	DOWN_COM2
	CALL	beep
	GOTO	MAINLOOP_NOBZ
DOWN_COM2
	CALL	nreps_step
	SUBWF	INDF,W
	BTFSS	STATUS,C
	 CLRW
	MOVWF	INDF
	GOTO	POST_INCDEC
	
DOWN_HUE
	CALL	nreps_step
	SUBWF	INDF,F			; 一旦保存して0未満なら240未満へオフセットさせる
	MOVLW	240
	SUBWF	INDF,W
	MOVLW	240
	BTFSC	STATUS,C
	 ADDWF	INDF,F
	GOTO	POST_INCDEC
;------------------------------------------------------------------------------
; HSLかHSVモードの時にFSRの位置を変える
;------------------------------------------------------------------------------
is_HSX
	MOVWF	FSR
	MOVLW	M_HSL
	SUBWF	MODE,W
	BTFSC	STATUS,Z
	 GOTO	IS_HSX_TRUE
	MOVLW	M_HSV
	SUBWF	MODE,W
	BTFSS	STATUS,Z
	 RETURN
IS_HSX_TRUE
	MOVLW	HSX_H - RGB_R
	ADDWF	FSR,F
	RETURN
;------------------------------------------------------------------------------
; INC/DECスピードアップ判定 加減算ステップを返す
;------------------------------------------------------------------------------
nreps_step
	MOVLW	NREPS_THRESH
	SUBWF	NREPS,W
	BTFSC	STATUS,C
	 RETLW	NREPS_SPEED
	RETLW	1
;------------------------------------------------------------------------------
;
;------------------------------------------------------------------------------
SUNSET
	MOVF	SUNSET_VALUE,W		; 既に0なら実行しない
	BTFSC	STATUS,Z
	 GOTO	SUNSET_EXIT
	CLRF	IR_STATUS
	CALL	beep
SUNSET_LOOP
	DECF	SUNSET_VALUE,F
	CALL	calc_night
	CALL	hsl2rgb
	CALL	copy_all
	CALL	txled_all

	MOVF	TMP11,W
	MOVWF	TMP12
SUNSET_100ms
	MOVLW	5
	CALL	wait

	MOVLW	RECIEVED		; IR 受信データ処理
	SUBWF	IR_STATUS,W
	BTFSS	STATUS,Z
	 GOTO	SUNSET_100ms_NEXT

	BTFSC	IR_FORMAT,4		; リピートは無視
	 GOTO	SUNSET_NOEXIT
	CALL	ir_to_keycode
	IORLW	0
	BTFSS	STATUS,Z		; 有効なデータを受信した時だけモード解除
	 GOTO	SUNSET_EXIT
SUNSET_NOEXIT
	CLRF	IR_STATUS
	CLRF	KEYCODE
SUNSET_100ms_NEXT
	DECFSZ	TMP12,F
	 GOTO	SUNSET_100ms
SUNSET_NEXT
	MOVF	SUNSET_VALUE,W
	BTFSS	STATUS,Z
	 GOTO	SUNSET_LOOP
	GOTO	MAINLOOP
SUNSET_EXIT
	CALL	beep
	MOVLW	5
	CALL	wait
	CALL	beep
	GOTO	MAINLOOP
;------------------------------------------------------------------------------
SUNRISE
	MOVF	SUNSET_VALUE,W		; 既に255なら実行しない
	SUBLW	255
	BTFSC	STATUS,Z
	 GOTO	SUNSET_EXIT
	CLRF	IR_STATUS
	CALL	beep
SUNRISE_LOOP
	INCF	SUNSET_VALUE,F
	CALL	calc_night
	CALL	hsl2rgb
	CALL	copy_all
	CALL	txled_all

	MOVF	TMP11,W
	MOVWF	TMP12
SUNRISE_100ms
	MOVLW	5
	CALL	wait

	MOVLW	RECIEVED		; IR 受信データ処理
	SUBWF	IR_STATUS,W
	BTFSS	STATUS,Z
	 GOTO	SUNRISE_100ms_NEXT

	BTFSC	IR_FORMAT,4		; リピートは無視
	 GOTO	SUNRISE_NOEXIT
	CALL	ir_to_keycode
	IORLW	0
	BTFSS	STATUS,Z		; 有効なデータを受信した時だけモード解除
	 GOTO	SUNSET_EXIT
SUNRISE_NOEXIT
	CLRF	IR_STATUS
	CLRF	KEYCODE
SUNRISE_100ms_NEXT
	DECFSZ	TMP12,F
	 GOTO	SUNRISE_100ms
SUNRISE_NEXT
	INCFSZ	SUNSET_VALUE,W
	 GOTO	SUNRISE_LOOP
	GOTO	MAINLOOP
;------------------------------------------------------------------------------
; リモコンコードをキーコードに変換
;------------------------------------------------------------------------------
ir_to_keycode
	MOVLW	IDENT_1			; メーカーコード判定
	SUBWF	IR_BUFFER,W
	BTFSS	STATUS,Z
	 RETLW	0
	MOVLW	IDENT_2
	SUBWF	IR_BUFFER+1,W
	BTFSS	STATUS,Z
	 RETLW	0
	COMF	IR_BUFFER+2,W		; データ破損チェック
	SUBWF	IR_BUFFER+3,W
	BTFSS	STATUS,Z
	 RETLW	0

	DECF	IR_BUFFER+2,W		; 0x01 ->11 +
	MOVWF	TMP00
	BTFSC	STATUS,Z
	 RETLW 11
	DECF	TMP00,F			; 0x02 ->10 OSD
	BTFSC	STATUS,Z
	 RETLW 10
	DECF	TMP00,F			; 0x04 ->6 COLOR
	DECF	TMP00,F
	BTFSC	STATUS,Z
	 RETLW 6
	DECF	TMP00,F			; 0x05 ->5 CONT
	BTFSC	STATUS,Z
	 RETLW 5
	MOVLW	5
	SUBWF	TMP00,F			; 0x0A ->3 SVIDEO
	BTFSC	STATUS,Z
	 RETLW 3
	DECF	TMP00,F			; 0x0C ->2 VIDEO
	DECF	TMP00,F	
	BTFSC	STATUS,Z
	 RETLW 2
	DECF	TMP00,F			; 0x0E ->4 BRITE
	DECF	TMP00,F
	BTFSC	STATUS,Z
	 RETLW 4
	MOVLW	4
	SUBWF	TMP00,F			; 0x12 ->12 -
	BTFSC	STATUS,Z
	 RETLW 12
	MOVLW	5
	SUBWF	TMP00,F			; 0x17 ->1 PC
	BTFSC	STATUS,Z
	 RETLW 1
	MOVLW	5
	SUBWF	TMP00,F			; 0x1C ->7 HUE
	BTFSC	STATUS,Z
	 RETLW 7
	DECF	TMP00,F			; 0x1D ->8 SYSTEM
	BTFSC	STATUS,Z
	 RETLW 8
	DECF	TMP00,F			; 0x1E ->9 RECALL
	BTFSC	STATUS,Z
	 RETLW 9
	RETLW	0
;------------------------------------------------------------------------------
; 
;------------------------------------------------------------------------------
rgb2hsl
	CALL	rgb2hue
	MOVF	MAX,W			; L = (max + min) / 2
	ADDWF	MIN,W
	MOVWF	HSX_X
	RRF	HSX_X,F
	MOVF	MAX,W			; IF MAX = MIN THEN
	SUBWF	MIN,W
	BTFSS	STATUS,Z
	 GOTO	RGB2HSL_SAT
RGB2HSL_0				;  SAT = 0
	CLRF	HSX_S
	RETURN
RGB2HSL_SAT				; ELSE
	MOVF	MIN,W
	SUBWF	MAX,W
	MOVWF	MATH00
	MOVLW	255
	MOVWF	MATH10
	CALL	mul8			; TMP01:00(sat) = (max - min) * 255

	MOVF	MAX,W			; MATH11:10(t) = max + min
	ADDWF	MIN,W
	MOVWF	MATH10
	CLRF	MATH11
	BTFSC	STATUS,C
	 INCF	MATH11,F

	MOVLW	128			; IF L >= 128 
	SUBWF	HSX_X,W
	BTFSS	STATUS,C
	 GOTO	RGB2HSL_SAT1

	MOVF	MATH00,W		; sub16の為に退避
	MOVWF	TMP00
	MOVF	MATH01,W
	MOVWF	TMP01

	MOVLW	HIGH 510		; MATH01:00(t) = 510 - MATH11:10(t)
	MOVWF	MATH01
	MOVLW	LOW 510
	MOVWF	MATH00
	CALL	sub16
	MOVF	MATH00,W
	MOVWF	MATH10
	MOVF	MATH01,W
	MOVWF	MATH11

	MOVF	TMP00,W		
	MOVWF	MATH00
	MOVF	TMP01,W
	MOVWF	MATH01
RGB2HSL_SAT1
	CALL	div16			; SAT / T
	MOVF	MATH00,W
	MOVWF	HSX_S
	RETURN	
;------------------------------------------------------------------------------
rgb2hsv
	CALL	rgb2hue
	MOVF	MAX,W			; VAL
	MOVWF	HSX_X
	MOVF	MAX,W			; IF MAX = MIN THEN
	SUBWF	MIN,W
	BTFSS	STATUS,Z
	 GOTO	RGB2HSV_SAT
RGB2HSV_0				;  SAT = 0
	CLRF	HSX_S
	RETURN
RGB2HSV_SAT				; ELSE
	MOVF	MIN,W
	SUBWF	MAX,W
	MOVWF	MATH00
	MOVLW	255
	MOVWF	MATH10
	CALL	mul8
	MOVF	MAX,W
	MOVWF	MATH10
	CLRF	MATH11
	CALL	div16
	MOVF	MATH00,W
	MOVWF	HSX_S	
	RETURN
;------------------------------------------------------------------------------
hsl2rgb
	MOVLW	128			; IF L >= 128 
	SUBWF	HSX_X,W
	MOVF	HSX_X,W			; W = LIG
	BTFSS	STATUS,C
	 GOTO	HSL2RGB_LIG
	MOVF	HSX_X,W			; W = 255 - LIG
	SUBLW	255
HSL2RGB_LIG
	MOVWF	MATH00			; MATH00 = W * SAT
	MOVF	HSX_S,W
	MOVWF	MATH10
	CALL	mul8

	CLRF	MATH11			; MATH00 = MATH00 / 255
	MOVLW	255
	MOVWF	MATH10
	CALL	div16

	MOVF	MATH00,W		; MAX = LIG + MATH00
	ADDWF	HSX_X,W
	MOVWF	MAX

	MOVF	MATH00,W		; MIN = LIG - MATH00
	SUBWF	HSX_X,W
	MOVWF	MIN
	CALL	hue2rgb
	RETURN
;------------------------------------------------------------------------------
hsv2rgb
	MOVF	HSX_X,W			; MAX = VAL
	MOVWF	MAX
	MOVWF	MATH00			; MATH00 = MAX * SAT
	MOVF	HSX_S,W
	MOVWF	MATH10
	CALL	mul8
	MOVLW	255
	MOVWF	MATH10
	CLRF	MATH11
	CALL	div16
	MOVF	MATH00,W
	SUBWF	MAX,W
	MOVWF	MIN
	CALL	hue2rgb
	RETURN
;------------------------------------------------------------------------------
hue2rgb
	MOVF	HSX_H,W
	ADDLW	256-200
	BTFSC	STATUS,C
	 GOTO	HUE2RGB_200
	ADDLW	40
	BTFSC	STATUS,C
	 GOTO	HUE2RGB_160
	ADDLW	40
	BTFSC	STATUS,C
	 GOTO	HUE2RGB_120
	ADDLW	40
	BTFSC	STATUS,C
	 GOTO	HUE2RGB_80
	ADDLW	40
	BTFSC	STATUS,C
	 GOTO	HUE2RGB_40
HUE2RGB_0
	MOVF	MAX,W
	MOVWF	RGB_R
	MOVF	MIN,W
	MOVWF	RGB_B
	MOVLW	RGB_G
	MOVWF	FSR
	MOVF	HSX_H,W
	GOTO	HUE2RGB_COM
HUE2RGB_40
	MOVF	MAX,W
	MOVWF	RGB_G
	MOVF	MIN,W
	MOVWF	RGB_B
	MOVLW	RGB_R
	MOVWF	FSR
	MOVF	HSX_H,W
	SUBLW	80
	GOTO	HUE2RGB_COM
HUE2RGB_80
	MOVF	MAX,W
	MOVWF	RGB_G
	MOVF	MIN,W
	MOVWF	RGB_R
	MOVLW	RGB_B
	MOVWF	FSR
	MOVLW	80
	SUBWF	HSX_H,W
	GOTO	HUE2RGB_COM
HUE2RGB_120
	MOVF	MAX,W
	MOVWF	RGB_B
	MOVF	MIN,W
	MOVWF	RGB_R
	MOVLW	RGB_G
	MOVWF	FSR
	MOVF	HSX_H,W
	SUBLW	160
	GOTO	HUE2RGB_COM
HUE2RGB_160
	MOVF	MAX,W
	MOVWF	RGB_B
	MOVF	MIN,W
	MOVWF	RGB_G
	MOVLW	RGB_R
	MOVWF	FSR
	MOVLW	160
	SUBWF	HSX_H,W
	GOTO	HUE2RGB_COM
HUE2RGB_200
	MOVF	MAX,W
	MOVWF	RGB_R
	MOVF	MIN,W
	MOVWF	RGB_G
	MOVLW	RGB_B
	MOVWF	FSR
	MOVF	HSX_H,W
	SUBLW	240
HUE2RGB_COM
	MOVWF	MATH00			; H
	MOVF	MIN,W
	SUBWF	MAX,W
	MOVWF	MATH10
	CALL	mul8			; h * (max - min)
	CLRF	MATH11
	MOVLW	40
	MOVWF	MATH10
	CALL	div16			; h * (max - min) / 40
	MOVF	MATH00,W
	ADDWF	MIN,W			; + MIN
	MOVWF	INDF			; = DEST
	RETURN
;------------------------------------------------------------------------------
; RGB_xを全LEDのバッファにコピー
;------------------------------------------------------------------------------
copy_all
	MOVF	RGB_R,W
	MOVWF	LED1_R
	MOVWF	LED2_R
	MOVWF	LED3_R
	MOVWF	LED4_R
	MOVWF	LED5_R
	MOVWF	LED6_R
	MOVF	RGB_G,W
	MOVWF	LED1_G
	MOVWF	LED2_G
	MOVWF	LED3_G
	MOVWF	LED4_G
	MOVWF	LED5_G
	MOVWF	LED6_G
	MOVF	RGB_B,W
	MOVWF	LED1_B
	MOVWF	LED2_B
	MOVWF	LED3_B
	MOVWF	LED4_B
	MOVWF	LED5_B
	MOVWF	LED6_B
	RETURN
;------------------------------------------------------------------------------
; LEDバッファをすべて送信
;------------------------------------------------------------------------------
txled_all
	BCF	INTCON,GIE
	MOVLW	LED1_R
	MOVWF	FSR
	MOVLW	24
	MOVWF	TMP02
TXLEDALL_LOOP
	CALL	txled
	INCF	FSR,F
	DECFSZ	TMP02,F
	 GOTO	TXLEDALL_LOOP
	BSF	INTCON,GIE
	RETURN
;------------------------------------------------------------------------------
; FSR/INDFの値をLEDに送信
;------------------------------------------------------------------------------
txled
	MOVF	INDF,W
	MOVWF	TMP00
	MOVLW	8
	MOVWF	TMP01
TXLEDLOOP
	RLF	TMP00,F
	BTFSS	STATUS,C
	 CALL	BIT0
	BTFSC	STATUS,C
	 CALL	BIT1
	DECFSZ	TMP01,F
	 GOTO	TXLEDLOOP
	RETURN

BIT0
	BSF	GPIO,LED_OUT
	NOP
	BCF	GPIO,LED_OUT
	RETURN
	
BIT1
	BSF	GPIO,LED_OUT
	NOP
	NOP
	NOP
	NOP
	NOP
	NOP
	BCF	GPIO,LED_OUT
	RETURN
;------------------------------------------------------------------------------
; 8bit 2の補数符号変換
;
; 引数
;	MATH00
;
; 戻り値
;	MATH00
;------------------------------------------------------------------------------
neg8
	COMF	MATH00,F
	INCF	MATH00,F
	RETURN
;------------------------------------------------------------------------------
; 16bit 2の補数符号変換
;
; 引数
;	MATH00	LSB
;	MATH01	MSB
;
; 戻り値
;	MATH00	LSB
;	MATH01	MSB
;------------------------------------------------------------------------------
neg16
	COMF	MATH00,F
	COMF	MATH01,F
	INCF	MATH00,F
	BTFSC	STATUS,Z
	 INCF	MATH01,F
	RETURN
;------------------------------------------------------------------------------
; 16bit 加算
;
; 引数
;	MATH00	LSB 足される数
;	MATH01	MSB
;	MATH10	LSB 足す数(非破壊)
;	MATH11	MSB
;
; 戻り値
;	MATH00	LSB 和
;	MATH01	MSB
;	C	キャリーフラグ
;	Z	ゼロフラグ
;------------------------------------------------------------------------------
add16
	MOVF	MATH10,W		; 下位加算
	ADDWF	MATH00,F

	MOVF	MATH11,W		; 下位キャリー処理
	BTFSC	STATUS,C
	 INCF	MATH11,W
	ADDWF	MATH01,F		; 上位加算
	
	MOVF	MATH00,W		; 全ビットゼロ検出
	IORWF	MATH01,W
	RETURN
;------------------------------------------------------------------------------
; 16bit 減算
;
; 引数
;	MATH00	LSB 引かれる数
;	MATH01	MSB
;	MATH10	LSB 引く数(非破壊)
;	MATH11	MSB
;
; 戻り値
;	MATH00	LSB 差
;	MATH01	MSB
;	C	キャリーフラグ
;	Z	ゼロフラグ
;------------------------------------------------------------------------------
sub16
	MOVF	MATH10,W		; 下位減算
	SUBWF	MATH00,F

	MOVF	MATH11,W		; 下位ボロー処理
	BTFSS	STATUS,C
	 INCF	MATH11,W
	SUBWF	MATH01,F		; 上位減算
	
	MOVF	MATH00,W		; 全ビットゼロ検出
	IORWF	MATH01,W
	RETURN
;------------------------------------------------------------------------------
; 8bit 乗算 http://elm-chan.org/docs/avrlib/mul08.txt, Microchip AN526
;
; 引数
;	MATH00	乗数
;	MATH10	被乗数(非破壊)
;
; 戻り値
;	MATH00	LSB 積
;	MATH01	MSB
;------------------------------------------------------------------------------
mul8
	CLRF	MATH01
	MOVLW	9
	MOVWF	MATH_TEMP
	MOVF	MATH10,W
	BCF	STATUS,C
mul8_1
	BTFSC	STATUS,C
	 ADDWF	MATH01,F
mul8_2
	RRF	MATH01,F
	RRF	MATH00,F
	DECFSZ	MATH_TEMP,F
	 GOTO	mul8_1
	RETURN
;------------------------------------------------------------------------------
; 16bit 割り算 http://elm-chan.org/docs/avrlib/div16.txt
;
; 引数
;	MATH00	LSB 割られる数(0x0000..0xffff)
;	MATH01	MSB
;	MATH10	LSB 割る数(0x0001..0x7fff)(非破壊)
;	MATH11	MSB
;
; 戻り値
;	MATH00	LSB 商
;	MATH01	MSB
;	MATH20	LSB 余り
;	MATH21	MSB
;
; 使用変数
;	TMP00
;------------------------------------------------------------------------------
div16
	CLRF	MATH20		; clr	mod0		initialize variables
	CLRF	MATH21		; clr	mod1		mod = 0;
	MOVLW	16		; ldi	lc,16		lc = 16;
	MOVWF	TMP00
DIV16_1				;---- calcurating loop
	BCF	STATUS,C	; lsl	var10		var1 = var1 << 1;
	RLF	MATH00,F
	RLF	MATH01,F	; rol	var11
	RLF	MATH20,F	; rol	mod0		mod = mod << 1 + carry;
	RLF	MATH21,F	; rol	mod1
	MOVF	MATH10,W	; cp	mod0,var20	if (mod < var2) {
	SUBWF	MATH20,W
	MOVF	MATH11,W
	BTFSS	STATUS,C	; cpc	mod1,var21
	 INCF	MATH11,W	;  Cフラグを足す
	SUBWF	MATH21,W
	BTFSS	STATUS,C
	 GOTO	DIV16_2		; brcs	PC+4		} else {
	INCF	MATH00,F	; inc	var10		  var1++;
	MOVF	MATH10,W	; sub	mod0,var20	  mod -= var2;
	SUBWF	MATH20,F
	MOVF	MATH11,W	; sbc	mod1,var21
	BTFSS	STATUS,C	;  Cフラグを足す
	 INCF	MATH11,W
	SUBWF	MATH21,F
DIV16_2				;			}
	DECFSZ	TMP00,F		; dec	lc		if (--lc > 0)
	 GOTO	DIV16_1		; brne	PC-11		  continue loop;
	RETURN
;------------------------------------------------------------------------------
; RGBの最大値、最小値と最大値の色名を求める
;	同一値はR>G>Bの優先順位となる
;
; 引数
;	RGB_R,RGB_G,RGB_B
;
; 戻り値
;	MAX	最大値
;	MIN	最小値
;	W	色名 0=同一, 1=R, 2=G, 3=B
; 使用変数
;	TMP00,01,02,03,10
;------------------------------------------------------------------------------
rgb_maxmin
	CLRF	TMP00			; R点数
	CLRF	TMP01			; G点数
	CLRF	TMP02			; B点数
	CLRF	TMP03			; 同一点数
	CLRF	TMP10

	MOVF	RGB_G,W 		; R-G
	SUBWF	RGB_R,W
	BTFSC	STATUS,Z
	 INCF	TMP03,F			;  R==G
	BTFSC	STATUS,C
	 INCF	TMP00,F			;  R>=G
	BTFSS	STATUS,C
	 INCF	TMP01,F			;  R<G

	MOVF	RGB_B,W			; R-B
	SUBWF	RGB_R,W
	BTFSC	STATUS,Z
	 INCF	TMP03,F			;  R==B
	BTFSC	STATUS,C
	 INCF	TMP00,F			;  R>=B
	BTFSS	STATUS,C
	 INCF	TMP02,F			;  R<B

	MOVF	RGB_B,W			; G-B
	SUBWF	RGB_G,W
	BTFSC	STATUS,C
	 INCF	TMP01,F			; G>=B
	BTFSS	STATUS,C
	 INCF	TMP02,F			; G<B

	MOVF	TMP00,F			; MIN
	BTFSC	STATUS,Z
	 MOVF	RGB_R,W
	MOVF	TMP01,F
	BTFSC	STATUS,Z
	 MOVF	RGB_G,W
	MOVF	TMP02,F
	BTFSC	STATUS,Z
	 MOVF	RGB_B,W
	MOVWF	MIN

rgb_maxR
	INCF	TMP10,F
	BTFSS	TMP00,1			; MAX
	 GOTO	rgb_maxG
	MOVF	RGB_R,W
	GOTO	rgb_maxmin_1
rgb_maxG
	INCF	TMP10,F
	BTFSS	TMP01,1
	 GOTO	rgb_maxB
	MOVF	RGB_G,W
	GOTO	rgb_maxmin_1
rgb_maxB
	INCF	TMP10,F
	MOVF	RGB_B,W
rgb_maxmin_1
	MOVWF	MAX
	MOVF	TMP10,W			; EQU
	BTFSC	TMP03,1
	 CLRW
	RETURN
;------------------------------------------------------------------------------
; 各種ウェイト
;------------------------------------------------------------------------------
led_reset				; 50us固定ウェイト
	BCF	GPIO,LED_OUT
	MOVLW	-61
WA1
	ADDLW	1
	BTFSS	STATUS,C
	 GOTO	WA1
	RETURN
;------------------------------------------------------------------------------
wait_20ms
	MOVLW	1
wait					; W=1あたり約20ms、最大5.12秒
	MOVWF	TMP20
WAIT_0
	MOVLW	130
	MOVWF	TMP21
MWAIT_1
	CLRF	TMP22
MWAIT_2
	DECFSZ	TMP22,F
	 GOTO	MWAIT_2
	DECFSZ	TMP21,F
	 GOTO	MWAIT_1
	DECFSZ	TMP20,F
	 GOTO	WAIT_0
	RETURN
;------------------------------------------------------------------------------
beep
	MOVLW	50
	MOVWF	TMP20
BAIT_0
	MOVLW	B'00000010'		; ブザー
	XORWF	GPIO,F
	MOVLW	1
	MOVWF	TMP21
BWAIT_1
	CLRF	TMP22
BWAIT_2
	DECFSZ	TMP22,F
	 GOTO	BWAIT_2
	DECFSZ	TMP21,F
	 GOTO	BWAIT_1
	DECFSZ	TMP20,F
	 GOTO	BAIT_0
	RETURN
;------------------------------------------------------------------------------
; 割り込みハンドラ
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
; Timer0割り込み
;
;  IRのリピートコード後、データを無効化するためのタイマ。
;  リピート判定後に13.1072ms*DESTROY_TIMER経過してから無効化される。
;  データを無効化したくない場合は、TMR0IEを0にするとよい。
;------------------------------------------------------------------------------
timer0_handler
	BCF	INTCON,TMR0IF
	DECFSZ	DESTROY_COUNT,F
	 GOTO	TMR0_RETURN
	BCF	INTCON,TMR0IE		; 不要なので止める
	CLRF	KEYCODE
	GOTO	TMR0_RETURN
;------------------------------------------------------------------------------
; TIMER1オーバーフロー割り込み
;
;  CCPでIR信号の立ち上がり検出から12.0ms経過すると、トレーラと判断し受信完了状態へ移行させる。
;------------------------------------------------------------------------------
timer1_handler
	BCF	PIR1,TMR1IF
	BSF	STATUS,RP0		; ◆ RP=1
	BCF	PIE1,TMR1IE		; 不要なので止める
	BCF	STATUS,RP0		; ◆ RP=0
	
	DECF	IR_STATUS,W		; RECIEVING(1)の時はRECIEVED(2)に移行
	BTFSC	STATUS,Z
	 INCF	IR_STATUS,F
	GOTO	TMR1_RETURN
;------------------------------------------------------------------------------
; CCP1トリガ割り込み
;
;  IR受信ルーチン
;  http://elm-chan.org/docs/ir_format.html
;  http://elm-chan.org/fsw/irctrl/00index.html
;------------------------------------------------------------------------------
ccp1_handler
	MOVLW	LOW(TRAILER_T1OFFSET+21) ; CCP割り込み発生時にTMR1をクリアしたことにする
	MOVWF	TMR1L			 ; TMR1は10.0msでオーバーフローするようにオフセットを加える
	MOVLW	HIGH(TRAILER_T1OFFSET+21)
	MOVWF	TMR1H

	MOVF	PW0_L,W			; 以前のパルス幅を保存
	MOVWF	PW1_L
	MOVF	PW0_H,W
	MOVWF	PW1_H

	MOVLW	LOW TRAILER_T1OFFSET
	SUBWF	CCPR1L,W		; キャプチャの値から10.0ms用のオフセットを引いて取得
	MOVWF	PW0_L
	MOVLW	HIGH TRAILER_T1OFFSET
	BTFSS	STATUS,C
	 ADDLW	1
	SUBWF	CCPR1H,W
	MOVWF	PW0_H

	MOVLW	B'00000001'		; トリガエッジ変更
	XORWF	CCP1CON,F
	BTFSS	CCP1CON,CCP1M0
	 GOTO	CCP1_RISE
CCP1_FALL				; 立ち下りトリガで飛んできた時
	BSF	STATUS,RP0		; ◆ RP=1
	BCF	PIE1,TMR1IE		; トレーラ判定タイマ割り込み停止
	BCF	STATUS,RP0		; ◆ RP=0
	
	MOVLW	RECIEVED		; 前回の受信データが取り出されていない場合は中断する
	SUBWF	IR_STATUS,W
	BTFSC	STATUS,Z
	 GOTO	CCP1_END
	
	CLRF	NEW_FORMAT
AEHA_LEADER				; データ中にリーダーが来た場合、データよりも優先して検出するようになっている
	MOVF	PW1_L,W			; 前回のパルス幅でAEHAチェック
	MOVWF	MATH10
	MOVF	PW1_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L1_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	NEC_LEADER

	MOVLW	LOW  (L1_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	NEC_LEADER

	RRF	MATH11,F		; データ0/1の閾値 = リーダー幅(8T) / 4
	RRF	MATH10,F
	RRF	MATH11,W
	ANDLW	B'00111111'
	MOVWF	THRESHOLD_H
	RRF	MATH10,W
	MOVWF	THRESHOLD_L
AEHA_LEADER2	
	MOVF	PW0_L,W			; 今回のパルス幅でリピートチェック
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L2_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	AEHA_REPEAT

	MOVLW	LOW  (L2_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	AEHA_REPEAT

	MOVLW	AEHA
	MOVWF	NEW_FORMAT
	GOTO	LEADER_END

AEHA_REPEAT
	MOVLW	LOW  (R_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (R_AEHA * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	NEC_LEADER

	MOVLW	LOW  (R_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (R_AEHA * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	NEC_LEADER

	MOVLW	AEHA + REPEAT
	MOVWF	NEW_FORMAT
	GOTO	LEADER_END

NEC_LEADER	
	MOVF	PW1_L,W			; 前回のパルス幅でNECチェック
	MOVWF	MATH10
	MOVF	PW1_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L1_NEC * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_NEC * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	SONY_LEADER
	
	MOVLW	LOW  (L1_NEC * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_NEC * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	SONY_LEADER
	
	RRF	MATH11,F		; データ0/1の閾値 = リーダー幅(16T) / 8
	RRF	MATH10,F
	RRF	MATH11,F
	RRF	MATH10,F
	RRF	MATH11,W
	ANDLW	B'00011111'
	MOVWF	THRESHOLD_H
	RRF	MATH10,W
	MOVWF	THRESHOLD_L
NEC_LEADER2
	MOVF	PW0_L,W			; 今回のパルス幅でリピートチェック
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L2_NEC * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_NEC * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	NEC_REPEAT
	MOVLW	LOW  (L2_NEC * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_NEC * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	NEC_REPEAT

	MOVLW	NEC
	MOVWF	NEW_FORMAT
	GOTO	LEADER_END

NEC_REPEAT
	MOVLW	LOW  (R_NEC * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (R_NEC * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	SONY_LEADER

	MOVLW	LOW  (R_NEC * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (R_NEC * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	SONY_LEADER

	MOVLW	NEC + REPEAT
	MOVWF	NEW_FORMAT
	GOTO	LEADER_END

SONY_LEADER	
	MOVF	PW1_L,W			; 前回のパルス幅でSONYチェック
	MOVWF	MATH10
	MOVF	PW1_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L1_SONY * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_SONY * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	LEADER_END

	MOVLW	LOW  (L1_SONY * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L1_SONY * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	LEADER_END

	RRF	MATH11,F		; データ0/1の閾値 = リーダー幅(4T) / 4 + リーダー幅(4T) / 8
	RRF	MATH10,F		;                 = 1.5T
	RRF	MATH11,W
	ANDLW	B'00111111'
	MOVWF	MATH11
	MOVWF	THRESHOLD_H
	RRF	MATH10,W
	MOVWF	THRESHOLD_L

	BCF	STATUS,C		; *0.5部分の加算
	RRF	MATH11,F
	RRF	MATH10,W
	ADDWF	THRESHOLD_L,F		; 下位加算
	MOVF	MATH11,W		; 最終キャリー処理
	BTFSC	STATUS,C
	 INCF	MATH11,W
	ADDWF	THRESHOLD_H,F		; 上位加算
SONY_LEADER2
	MOVF	PW0_L,W			; 今回のパルス幅チェック
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11

	MOVLW	LOW  (L2_SONY * MIN_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_SONY * MIN_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSC	STATUS,C
	 GOTO	LEADER_END
	MOVLW	LOW  (L2_SONY * MAX_PERCENT / 100)
	MOVWF	MATH00
	MOVLW	HIGH (L2_SONY * MAX_PERCENT / 100)
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	LEADER_END

	MOVLW	SONY
	MOVWF	NEW_FORMAT

LEADER_END
	MOVF	NEW_FORMAT,W		; リーダーが検出できなかった時はデータビットとする
	BTFSC	STATUS,Z
	 GOTO	DATABIT
	MOVWF	IR_FORMAT
	CLRF	IR_LENGTH
	MOVLW	1
	MOVWF	BITMASK
	MOVLW	RECIEVING
	MOVWF	IR_STATUS
	
	CLRF	TMR0			; リピート時にしばらくしてからデータを消す場合は以下の5行を有効にする
	BCF	INTCON,TMR0IF		; 13.1072ms * DESTROY_TIMER 後に破棄される
	BSF	INTCON,TMR0IE		; |
	MOVLW	DESTROY_TIMER		; |
	MOVWF	DESTROY_COUNT		; v
	GOTO	CCP1_END

DATABIT
	MOVLW	RECIEVING
	SUBWF	IR_STATUS,W
	BTFSS	STATUS,Z
	 GOTO	INVALID_DATA

	MOVLW	SONY
	SUBWF	IR_FORMAT,W
	BTFSS	STATUS,Z
	 GOTO	DATA_AEHA

	MOVF	PW0_L,W			; SONYデータのパルス幅チェック
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11

	MOVLW	LOW  D1MAX_SONY
	MOVWF	MATH00
	MOVLW	HIGH D1MAX_SONY
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA
	GOTO	CCP1_END

DATA_AEHA
	MOVLW	AEHA
	SUBWF	IR_FORMAT,W
	BTFSS	STATUS,Z
	 GOTO	DATA_NEC

	MOVF	PW1_L,W			; AEHAデータのパルス幅チェック
	MOVWF	MATH10
	MOVF	PW1_H,W
	MOVWF	MATH11
	MOVLW	LOW  D1MAX_AEHA
	MOVWF	MATH00
	MOVLW	HIGH D1MAX_AEHA
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA

	MOVF	PW0_L,W
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11
	MOVLW	LOW  D2MAX_AEHA
	MOVWF	MATH00
	MOVLW	HIGH D2MAX_AEHA
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA
	GOTO	VALID_DATA

DATA_NEC
	MOVLW	NEC
	SUBWF	IR_FORMAT,W
	BTFSS	STATUS,Z
	 GOTO	INVALID_DATA

	MOVF	PW1_L,W			; NECデータのパルス幅チェック
	MOVWF	MATH10
	MOVF	PW1_H,W
	MOVWF	MATH11
	MOVLW	LOW  D1MAX_NEC
	MOVWF	MATH00
	MOVLW	HIGH D1MAX_NEC
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA

	MOVF	PW0_L,W
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11
	MOVLW	LOW  D2MAX_NEC
	MOVWF	MATH00
	MOVLW	HIGH D2MAX_NEC
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA
	
VALID_DATA
	MOVLW	IRMAXLEN		; 最大受信長チェック
	SUBWF	IR_LENGTH,W
	BTFSC	STATUS,C
	 GOTO	CCP1_END

	RRF	IR_LENGTH,W		; 格納アドレス計算
	MOVWF	FSR
	RRF	FSR,F
	RRF	FSR,W
	ANDLW	B'00011111'
	ADDLW	LOW IR_BUFFER
	MOVWF	FSR

	rrf	BITMASK,W
	COMF	BITMASK,W		; マスクを使って当該ビット以外のデータを取得
	btfsc	STATUS,C		; 初回ビットの時は0を代入
	 clrw
	ANDWF	INDF,W
	MOVWF	MASKDATA

	MOVF	PW0_L,W			; 閾値より長い発光時間はビットを1にする
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11
	MOVF	THRESHOLD_L,W
	MOVWF	MATH00
	MOVF	THRESHOLD_H,W
	MOVWF	MATH01
	CALL	sub16
	MOVF	MASKDATA,W
	BTFSS	STATUS,C
	 IORWF	BITMASK,W
	MOVWF	INDF

	BCF	STATUS,C		; マスクを次の桁に更新
	RLF	BITMASK,F
	MOVLW	1
	BTFSC	STATUS,C
	 MOVWF	BITMASK
	INCF	IR_LENGTH,F		; 長さ更新
	GOTO	CCP1_END

INVALID_DATA
	CLRF	IR_FORMAT		; リーダーが検出できずRECIEVINGでもなかった場合、無効データとしてアイドルに戻る。
	CLRF	IR_STATUS
	GOTO	CCP1_END


CCP1_RISE				; 立ち上りトリガで飛んできた時
	BSF	STATUS,RP0		; ◆ RP=1
	BSF	PIE1,TMR1IE		; トレーラ判定タイマ割り込み許可
	BCF	STATUS,RP0		; ◆ RP=0

	MOVLW	SONY
	SUBWF	IR_FORMAT,W
	BTFSS	STATUS,Z
	 GOTO	CCP1_END
	
	MOVLW	RECIEVING
	SUBWF	IR_STATUS,W
	BTFSS	STATUS,Z
	 GOTO	CCP1_END

	MOVF	PW0_L,W			; SONYデータのパルス幅チェック
	MOVWF	MATH10
	MOVF	PW0_H,W
	MOVWF	MATH11
	MOVLW	LOW  D2MAX_SONY
	MOVWF	MATH00
	MOVLW	HIGH D2MAX_SONY
	MOVWF	MATH01
	CALL	sub16
	BTFSS	STATUS,C
	 GOTO	INVALID_DATA
	GOTO	VALID_DATA

CCP1_END
	BCF	PIR1,CCP1IF
	GOTO	CCP1_RETURN
;------------------------------------------------------------------------------
; システムリセット、メインループ前処理
;------------------------------------------------------------------------------
POWER_ON
	CLRF	GPIO
	MOVLW	7
	MOVWF	CMCON0

	BSF	STATUS,RP0		; ◆ RP=1
	CLRF	ANSEL
	MOVLW	B'00111100'		; [54]OSC_IN [3]TP_IN [2]IR_CCP1 [1]BUZZER [0]LED_OUT
	MOVWF	TRISIO

	MOVLW	B'01010111'		; GPIOプルアップ有効、TMR0内部クロック、プリスケーラ1:256
	MOVWF	OPTION_REG

	BCF	STATUS,RP0		; ◆ RP=0
	BSF	T1CON,TMR1ON		; TIMER1有効 タイムアウト:13.1072ms(CCP割り込み時に10.0msでタイムアウトするようオフセットを加えてある)

	MOVLW	B'00000100'		; CCP
	MOVWF	CCP1CON			; 立下りモードから開始

	MOVLW	B'11000000'		; 全割り込み停止(TMR0IE)、GIE,PEIE有効
	BSF	STATUS,RP0		; ◆ RP=1
	CLRF	PIE1			; 全割り込み停止(CCP1IE/TMR1IE)
	BCF	STATUS,RP0		; ◆ RP=0
	MOVWF	INTCON
	
	CLRF	IR_FORMAT
	CLRF	KEYCODE

	CLRF	MODE			; M_RGB
	CLRF	RGB_R			; 初期カラー
	MOVLW	3
	MOVWF	RGB_G
	MOVLW	6
	MOVWF	RGB_B
	CALL	copy_all
	CALL	txled_all

	BSF	STATUS,RP0		; ◆ RP=1
	BSF	PIE1,CCP1IE		; リモコン受信スタート
	BCF	STATUS,RP0		; ◆ RP=0
	GOTO	MAINLOOP
;------------------------------------------------------------------------------

	END