;------------------------------------------------------------------------------
; ドリームライト
;------------------------------------------------------------------------------
; 2016/03/01 Ver.0.09
;  NECリモコンの反応が悪いと思ったら出荷時のクロック校正がずれていた。
;  RATEを色相に反映しないようにした。
;
; 2016/02/24 Ver.0.08
;  各パラメータを最大の240に戻した。必要に応じてRATEで加速させて使う。
;  RATEを色相にも反映させた。
;
; 2016/02/23 Ver.0.07
;  ブラウンアウト電圧が従来機と違い2.0Vに変わっているらしいので、ブラウンアウトを有効にしてWDTは使わないようにした。
;  8bit割り算を使っていなかったので除去。
;
; 2016/02/22 Ver.0.06
;  ブラウンアウトリセットを使わないので完全放電付近になると暴走しているようだ。WDTを有効にした。
;  アップダウンレートを変数化してリモコンで指示できるようにした。輝度と彩度に反映される。
;  EEPROMの初期値を廃止。RGBのPWM専用変数を廃止。
;
; 2016/02/17 Ver.0.05
;  AEHAリモコンに対応。受信ビット数が多いためちらつく。
;  ログ変換テーブルを除去。
;
; 2016/02/14 Ver.0.04
;  リモコンで彩度と輝度を変化させる時は2づつ変化させるようにした。
;
; 2016/02/14 Ver.0.03
;  HSL変換実装
;
; 2016/02/11 Ver.0.02
;  いろいろ修正したが、基本的には0.01と同じ動きをする。
;
; 2016/01/30 Ver.0.01
;  リモコンの解析とPWMの実装が完了。
;  PWMを7bit/120fpsにするとリモコンの割り込みが発生した時にちらつきが出る。
;------------------------------------------------------------------------------
; デバイス	PIC12F675
; 動作周波数	INTRC 4MHz
;------------------------------------------------------------------------------
	LIST	P=12F675,R=DEC,N=0
	INCLUDE	"P12F675.INC"
	ERRORLEVEL	0,-302,-306,-307
	__CONFIG	0x31C4		; FOSC	= INTOSC(GP4:I/O)
					; WDT	= Disable
					; PWRTE	= Enable
					; MCLRE	= GP3:I/O
					; BODEN = Enable
					; CP	= Not_Protect
					; CPD	= Not_Protect
					; BG	= 3
					; クロックの校正時はINTOSC(GP4:CLKOUT)にすると良い

;------------------------------------------------------------------------------
; 変数宣言 0x20 - 0x5F
;------------------------------------------------------------------------------
HUE		EQU	0x20		; 0-119
SATURATION	EQU	0x21		; 0-120
LIGHTNESS	EQU	0x22		; 0-120
RED		EQU	0x23		; RGB
GREEN		EQU	0x24
BLUE		EQU	0x25
PWM_COUNT	EQU	0x26		; PWMカウンタ
GP_OUT		EQU	0x27		; GPIO出力前バッファ
MAX		EQU	0x28
MIN		EQU	0x29
MID		EQU	0x2A
IR_SELECT	EQU	0x2B
RATE		EQU	0x2C		; アップダウンレート

IR_STATE	EQU	0x30		; 遷移状態番号 0=初回割り込み 1=Start/Repeat判定 2=データ受信
IR_FLAG		EQU	0x31
IR_COUNT	EQU	0x32		; 受信ビット数カウンタ
IR_DATA		EQU	0x33		; 受信したデータ
IR_DATA0	EQU	0x34		; CUSTOMER1 受信したデータ
IR_DATA1	EQU	0x35		; CUSTOMER2
IR_DATA2	EQU	0x36		; DATA
IR_DATA3	EQU	0x37		; DATA
IR_DATA4	EQU	0x38		; DATA

; 四則演算用変数
MATH00		EQU	0x40		; LSB
MATH01		EQU	0x41		;  :
MATH02		EQU	0x42		;  :
MATH03		EQU	0x43		;  :
MATH04		EQU	0x44		;  :
MATH05		EQU	0x45		; MSB
MATH20		EQU	MATH04
MATH21		EQU	MATH05
MATH22		EQU	0x46
MATH23		EQU	0x47
MATH10		EQU	0x48
MATH11		EQU	0x49
MATH12		EQU	0x4A
MATH13		EQU	0x4B

EEADR_		EQU	0x50		; eeread, eewriteに渡すアドレス
TMP00		EQU	0x51
TMP01		EQU	0x52

W_		EQU	0x5C		; 割り込み退避用
STATUS_		EQU	0x5D
PCLATH_		EQU	0x5E
FSR_		EQU	0x5F

;------------------------------------------------------------------------------
; 定数宣言
;------------------------------------------------------------------------------
LED_RED		EQU	0		; GPIO
LED_GREEN	EQU	1		; GPIO
LED_DEBUG	EQU	4		; GPIO
LED_BLUE	EQU	5		; GPIO
VALID		EQU	0		; IR_FLAG IR_DATAに有効なデータが入っている、リピート時に使用
NEWDATA		EQU	1		; IR_FLAG リモコンが操作され有効なデータがIR_DATAに受信された
IDLE		EQU	2		; IR_FLAG 無通信の判定

;------------------------------------------------------------------------------
; プログラム開始
;------------------------------------------------------------------------------
	ORG	0
	BSF	STATUS,RP0		; ◆ RP=1
	CALL	0x3FF
	MOVWF	OSCCAL
	GOTO	POWER_ON

;------------------------------------------------------------------------------
; 割り込み分岐
;------------------------------------------------------------------------------
	ORG	4			; 割り込み
	MOVWF	W_			; Wセーブ
	SWAPF	STATUS,W		; STATUSセーブ
	MOVWF	STATUS_
	MOVF	PCLATH,W		; PCLATHセーブ
	MOVWF	PCLATH_
	MOVF	FSR,W			; FSRセーブ
	MOVWF	FSR_
	BCF	STATUS,RP0		; ◆RP=0

PWM_CHECK				; 割り込み要因はPWMタイマー?
	BTFSS	INTCON,T0IF
	 GOTO	IR_CHECK
PWM					; PWMカウント
	MOVLW	0xC0			; Timer0に加算してタイムアウトを早める
	IORWF	TMR0,F			;  通常256us周期の所を64us相当に設定している
	BCF	INTCON,T0IF
	INCF	PWM_COUNT,F
	BTFSC	PWM_COUNT,7		; PWMの分解能 2^7=128
	 CLRF	PWM_COUNT		;  フレームレートfps= 1/(64us*128) = 122
	
	MOVLW	0xFF			; 3色の出力判定
	MOVWF	GP_OUT			; カウンタが各色の指定値より少ない場合だけ点灯させる

	MOVF	RED,W
	SUBWF	PWM_COUNT,W
	BTFSS	STATUS,C
	 BCF	GP_OUT,LED_RED

	MOVF	GREEN,W
	SUBWF	PWM_COUNT,W
	BTFSS	STATUS,C
	 BCF	GP_OUT,LED_GREEN

	MOVF	BLUE,W
	SUBWF	PWM_COUNT,W
	BTFSS	STATUS,C
	 BCF	GP_OUT,LED_BLUE
	
	;BTFSC	IR_FLAG,VALID		; 正常なリモコンコードを受信したら点灯(デバッグ)
	; BCF	GP_OUT,LED_DEBUG

	MOVF	GP_OUT,W		; バッファから出力へ転送
	MOVWF	GPIO

IR_CHECK				; 割り込み要因はIRの受信?
	BTFSS	INTCON,INTF
	 GOTO	T1_TIMEOUT
IR
	BCF	INTCON,INTF
	BCF	IR_FLAG,IDLE
	CLRF	PCLATH			; ■ PCLATH
	MOVF	IR_STATE,W		; 受信状態によりジャンプ
	ADDWF	PCL,F
	GOTO	SYNC_1			; 0
	GOTO	SYNC_2			; 1
	GOTO	RECEIVE_NEC		; 2
	GOTO	RECEIVE_AEHA		; 3

T1_TIMEOUT				; 割り込み要因は無通信でTimter1がオーバーフロー?
	BTFSS	PIR1,TMR1IF
	 GOTO	INT_RETURN
	BCF	PIR1,TMR1IF
	MOVLW	B'00000100'		; IDLEビットを反転
	XORWF	IR_FLAG,F
	BTFSC	IR_FLAG,IDLE		; IDLEフラグがリセットされた時(2回目の反転=131.072ms経過)は強制的に遷移をリセット
	 GOTO	INT_RETURN
	CLRF	IR_STATE
	CLRF	IR_FLAG

INT_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
;------------------------------------------------------------------------------
; 割り込み中のリモコン受信ルーチン
;------------------------------------------------------------------------------
SYNC_1					; フレーム同期1、パルス幅カウンタリセット
	CLRF	TMR1L
	CLRF	TMR1H
	INCF	IR_STATE,F
	GOTO	T1_TIMEOUT

SYNC_2					; フレーム同期2、スタートorリピートを検出
	CLRF	TMR1L			; なるべく早いうちにカウンタをリセットする
	MOVF	TMR1H,W			; 荒いTMR1Hのカウンタで幅を検出
	SUBLW	15			;  4.200ms以下を切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR

	MOVF	TMR1H,W
	SUBLW	23			;  6.000ms以下はAEHAスタート(5.100ms 12T)
	BTFSC	STATUS,C
	 GOTO	START_AEHA
	
	MOVF	TMR1H,W
	SUBLW	24			;  6.400ms以下は切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR

	MOVF	TMR1H,W
	SUBLW	31			;  8.000ms以下はリピート(6.800ms 16T)
	BTFSC	STATUS,C
	 GOTO	REPEAT

	MOVF	TMR1H,W
	SUBLW	42			;  11.008ms以下を切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR

	MOVF	TMR1H,W
	SUBLW	45			;  11.520ms以下はリピート(11.240ms 20T)
	BTFSC	STATUS,C
	 GOTO	REPEAT
	
	MOVF	TMR1H,W
	SUBLW	51			;  13.312ms以下は切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR

	MOVF	TMR1H,W
	SUBLW	54			;  13.824ms以下はNECスタート(13.488ms 24T)
	BTFSC	STATUS,C
	 GOTO	START_NEC
SYNC_ERROR
	CLRF	IR_STATE		; 同期エラー(IR_STATE=0)
	CLRF	IR_FLAG
	GOTO	T1_TIMEOUT

START_NEC				; NECスタート受信
	CLRF	TMR1H
	MOVLW	2
	MOVWF	IR_STATE
	CLRF	IR_FLAG
	MOVLW	32			; 受信するビット数
	MOVWF	IR_COUNT
	GOTO	T1_TIMEOUT

START_AEHA				; AEHAスタート受信
	CLRF	TMR1H
	MOVLW	3
	MOVWF	IR_STATE
	CLRF	IR_FLAG
	MOVLW	40			; 受信するビット数
	MOVWF	IR_COUNT		; AEHAは可変長のため手元のリモコンに合わせて変更する事
	GOTO	T1_TIMEOUT

REPEAT					; リピート受信
	CLRF	IR_STATE		; これ以上遷移しないので同期に戻る IR_STATE=0
	BCF	IR_FLAG,NEWDATA
	BTFSC	IR_FLAG,VALID		; 前回正常な値を受信している場合は、新データとして有効化する。
	 BSF	IR_FLAG,NEWDATA
	GOTO	T1_TIMEOUT

RECEIVE_NEC				; NECフレーム受信
	CLRF	TMR1L			; なるべく早いうちにカウンタをリセットする
	MOVF	TMR1H,W
	SUBLW	3			; 1.024ms以下を切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理

	MOVF	TMR1H,W
	SUBLW	5			; 1.280ms以下は0(1.124ms 2T)
	BTFSC	STATUS,C
	 GOTO	NEC_RX0
	
	MOVF	TMR1H,W
	SUBLW	7			; 2.048ms以下は切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理

	MOVF	TMR1H,W
	SUBLW	10			; 2.560ms以下は1(2.248ms 4T)
	BTFSC	STATUS,C
	 GOTO	NEC_RX1
	GOTO	SYNC_ERROR		; それ以上は同期エラーと同じ処理

NEC_RX0
	BCF	STATUS,C
	GOTO	NEC_RXSHIFT
NEC_RX1
	BSF	STATUS,C
NEC_RXSHIFT
	CLRF	TMR1H
	RRF	IR_DATA3,F
	RRF	IR_DATA2,F
	RRF	IR_DATA1,F
	RRF	IR_DATA0,F
	DECFSZ	IR_COUNT,F
	 GOTO	T1_TIMEOUT
NEC_VALIDATE				; カスタマーコードの検証
	MOVLW	0x04			; CC#1
	SUBWF	IR_DATA0,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	MOVLW	0xFB			; CC#2
	SUBWF	IR_DATA1,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	
	COMF	IR_DATA2,W		; データの検証
	XORWF	IR_DATA3,W		; 反転されたデータとXORを取り0になったら一致していると判断。
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	MOVF	IR_DATA2,W
	MOVWF	IR_DATA
	CLRF	IR_STATE
	BSF	IR_FLAG,VALID
	BSF	IR_FLAG,NEWDATA
	GOTO	T1_TIMEOUT

RECEIVE_AEHA				; フレーム受信
	CLRF	TMR1L			; なるべく早いうちにカウンタをリセットする
	MOVF	TMR1H,W
	SUBLW	1			; 0.256ms以下を切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理

	MOVF	TMR1H,W
	SUBLW	3			; 1.000ms以下は0(0.850ms 2T)
	BTFSC	STATUS,C
	 GOTO	AEHA_RX0
	
	MOVF	TMR1H,W
	SUBLW	4			; 1.280ms以下は切り捨て
	BTFSC	STATUS,C
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理

	MOVF	TMR1H,W
	SUBLW	7			; 2.048ms以下は1(1.700ms 4T)
	BTFSC	STATUS,C
	 GOTO	AEHA_RX1
	GOTO	SYNC_ERROR		; それ以上は同期エラーと同じ処理

AEHA_RX0
	BCF	STATUS,C
	GOTO	AEHA_RXSHIFT
AEHA_RX1
	BSF	STATUS,C
AEHA_RXSHIFT
	CLRF	TMR1H
	RRF	IR_DATA4,F		; 受信するバイト数はリモコンに合わせて変更する
	RRF	IR_DATA3,F
	RRF	IR_DATA2,F
	RRF	IR_DATA1,F
	RRF	IR_DATA0,F
	DECFSZ	IR_COUNT,F
	 GOTO	T1_TIMEOUT
AEHA_VALIDATE				; カスタマーコードの検証
	MOVLW	0x2C			; CC#1
	SUBWF	IR_DATA0,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	MOVLW	0x52			; CC#2
	SUBWF	IR_DATA1,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	MOVLW	0x09			; CC#3
	SUBWF	IR_DATA2,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理

	MOVLW	9			; リモコンコードに合わせて実装 HK9327K用
	XORWF	IR_DATA3,W		; XORを取ってゼロになれば一致していると判断
	XORWF	IR_DATA4,W
	BTFSS	STATUS,Z
	 GOTO	SYNC_ERROR		; 同期エラーと同じ処理
	MOVF	IR_DATA3,W
	MOVWF	IR_DATA
	CLRF	IR_STATE
	BSF	IR_FLAG,VALID
	BSF	IR_FLAG,NEWDATA
	GOTO	T1_TIMEOUT

;------------------------------------------------------------------------------
; 電源投入時の初期化
;------------------------------------------------------------------------------
POWER_ON				; 電源ON
	BCF	STATUS,RP0		; ◆ RP=0
	MOVLW	B'00110011'		; 5,4,1,0:BDGR_LED 2:/IR_INT
	MOVWF	GPIO
	MOVLW	0x07			; コンパレータOFF
	MOVWF	CMCON
	CLRF	TMR1L
	CLRF	TMR1H
	MOVLW	B'00000001'		; IRのパルス幅計測タイマー
	MOVWF	T1CON

	BSF	STATUS,RP0		; ◆ RP=1
	MOVLW	B'00011000'		; GPIOプルアップ,立下げ割り込み,T0ソース=内部,プリスケーラ=WDT 1:1
	MOVWF	OPTION_REG		; bit3:FPS = 0:61Hz 1:122Hz
	CLRF	ANSEL			; A/D OFF
	MOVLW	B'00001100'
	MOVWF	TRISIO			; 5,4,1,0:BDGR_LED 2:/IR_INT
	MOVLW	B'00000001'
	MOVWF	PIE1			; Timer1割り込み
	
	BCF	STATUS,RP0		; ◆ RP=0
	CLRF	PWM_COUNT		; ループ前 変数初期化
	CLRF	IR_STATE
	CLRF	IR_FLAG
	CLRF	IR_SELECT
	MOVLW	0
	MOVWF	HUE
	MOVLW	0
	MOVWF	SATURATION
	MOVLW	0
	MOVWF	LIGHTNESS
	MOVLW	1
	MOVWF	RATE
	CALL	hsl2rgb
	
	CLRF	TMR0
	MOVLW	B'11110000'		; GIE,PEIE,T0IE,INTE
	MOVWF	INTCON
;------------------------------------------------------------------------------
; メインループ
;------------------------------------------------------------------------------
MAINLOOP
	BTFSS	IR_FLAG,NEWDATA		; リモコン入力があるまで待機
	 GOTO	MAINLOOP
	MOVF	IR_DATA,W
	MOVWF	TMP00
	BCF	IR_FLAG,NEWDATA
;---- ちっこいリモコン
B_PC
	MOVLW	0x17
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_VIDEO
	;B_PC
	GOTO	MAINLOOP
B_VIDEO
	MOVLW	0x0C
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_SVIDEO
	;B_VIDEO
	GOTO	MAINLOOP
B_SVIDEO
	MOVLW	0x0A
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_BRITE
	;B_SVIDEO
	GOTO	MAINLOOP
B_BRITE
	MOVLW	0x0E
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_CONT
	;B_BRITE			; HUE++
INCR_HUE
	MOVLW	1
	ADDWF	HUE,F			; 角度を循環させる
	MOVLW	240			; 240以上の時は差分を取って循環させる
	SUBWF	HUE,W
	MOVLW	256-240
	BTFSC	STATUS,C
	 ADDWF	HUE,F
	CALL	hsl2rgb
	GOTO	MAINLOOP
B_CONT
	MOVLW	0x05
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_COLOR
	;B_CONT				; SATURATION+=RATE
	MOVLW	SATURATION
	GOTO	INCR_SAT_LIT
B_COLOR
	MOVLW	0x04
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_HUE
	;B_COLOR			; LIGHTNESS+=RATE
	MOVLW	LIGHTNESS
INCR_SAT_LIT
	MOVWF	FSR
	MOVF	RATE,W
	ADDWF	INDF,F
	MOVLW	241			; 241以上の時は240にリセット
	SUBWF	INDF,W
	MOVLW	240
	BTFSC	STATUS,C
	 MOVWF	INDF
	CALL	hsl2rgb
	GOTO	MAINLOOP
B_HUE
	MOVLW	0x1C
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_SYSTEM
	;B_HUE				; HUE--
DECR_HUE
	MOVLW	1			; 角度を循環させる
	SUBWF	HUE,F			; 桁下がりしていたら差分を取って循環させる
	MOVLW	256-240
	BTFSS	STATUS,C
	 SUBWF	HUE,F
	CALL	hsl2rgb
	GOTO	MAINLOOP
B_SYSTEM
	MOVLW	0x1D
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_RECALL
	;B_SYSTEM			; SATURATION-=RATE
	MOVLW	SATURATION
	GOTO	DECR_SAT_LIT
B_RECALL
	MOVLW	0x1E
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_OSD
	;B_RECALL			; LIGHTNESS-=RATE
	MOVLW	LIGHTNESS
DECR_SAT_LIT
	MOVWF	FSR
	MOVF	RATE,W
	SUBWF	INDF,F
	BTFSS	STATUS,C
	 CLRF	INDF
	CALL	hsl2rgb
	GOTO	MAINLOOP
B_OSD
	MOVLW	0x02
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_PLUS
	;B_OSD				; RATE=2
	MOVLW	2
	MOVWF	RATE
	GOTO	MAINLOOP
B_PLUS
	MOVLW	0x01
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_MINUS
	;B_PLUS				; 彩度=100% 輝度=50%
	MOVLW	240
	MOVWF	SATURATION
	MOVLW	120
	MOVWF	LIGHTNESS
	CALL	hsl2rgb
	GOTO	MAINLOOP
B_MINUS
	MOVLW	0x12
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_ON
	;B_MINUS			; 輝度=0%
	CLRF	LIGHTNESS
	CALL	hsl2rgb
	MOVLW	1
	MOVWF	RATE
	GOTO	MAINLOOP
;---- HK9327K
B_ON
	MOVLW	0x3C
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_FAVORITE
	; 全灯
	MOVLW	LIGHTNESS		; 輝度選択、輝度+
	MOVWF	IR_SELECT
	GOTO	CMD_UP
B_FAVORITE
	MOVLW	0x3D
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_SMALL
	; お好み
	MOVLW	HUE			; 色相選択、色相+
	MOVWF	IR_SELECT
	GOTO	CMD_UP
B_SMALL
	MOVLW	0x3E
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_DOWN
	; 豆球
	MOVLW	SATURATION		; 彩度選択、彩度+
	MOVWF	IR_SELECT
	GOTO	CMD_UP
B_DOWN
	MOVLW	0x3B
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_UP
	; 暗く
	MOVF	IR_SELECT,W		; 選択データ-
	BTFSC	STATUS,Z		; IR_SELECTがセットされていない場合は実行しない
	 GOTO	MAINLOOP
	MOVF	IR_SELECT,W
	SUBLW	HUE			; 色相は変化が違うので個別で飛ばす
	BTFSC	STATUS,Z
	 GOTO	DECR_HUE
	MOVLW	2
	MOVWF	RATE
	MOVF	IR_SELECT,W
	GOTO	DECR_SAT_LIT
B_UP
	MOVLW	0x3A
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	B_OFF
	; 明るく
CMD_UP
	MOVF	IR_SELECT,W		; 選択データ+
	BTFSC	STATUS,Z		; IR_SELECTがセットされていない場合は実行しない
	 GOTO	MAINLOOP
	MOVF	IR_SELECT,W
	SUBLW	HUE			; 色相は変化が違うので個別で飛ばす
	BTFSC	STATUS,Z
	 GOTO	INCR_HUE
	MOVLW	2
	MOVWF	RATE
	MOVF	IR_SELECT,W
	GOTO	INCR_SAT_LIT
B_OFF
	MOVLW	0x3F
	SUBWF	TMP00,W
	BTFSS	STATUS,Z
	 GOTO	MAINLOOP
	; 消灯
	CLRF	LIGHTNESS		; 輝度=0%
	CALL	hsl2rgb
	MOVLW	1
	MOVWF	RATE
	GOTO	MAINLOOP

;------------------------------------------------------------------------------
; HSL->RGB変換
;  http://www.peko-step.com/tool/hslrgb.html#ppick3
;------------------------------------------------------------------------------
hsl2rgb
	MOVLW	120
	SUBWF	LIGHTNESS,W		; if L < 120
	MOVF	LIGHTNESS,W		;  w = L
	BTFSS	STATUS,C		; else
	 GOTO	HSL2RGB2
	MOVF	LIGHTNESS,W		;  w = 240 - L
	SUBLW	240
HSL2RGB2
	MOVWF	MATH00
	MOVF	SATURATION,W
	MOVWF	MATH10
	CALL	mul8			; math0 = w * S
	MOVLW	240
	MOVWF	MATH10
	CLRF	MATH11
	CALL	div16			; math0 = math0 / 240
	MOVF	LIGHTNESS,W
	ADDWF	MATH00,W
	MOVWF	MAX			; 仮MAX = L + math0
	MOVF	MATH00,W
	SUBWF	LIGHTNESS,W
	MOVWF	MIN			; 仮MIN = L - math0
	MOVLW	LOW 0x0087		; 0x0087 とは 127 / 240 * 256の固定小数点表記
	MOVWF	MATH10
	MOVLW	HIGH 0x0087
	MOVWF	MATH11
	CLRF	MATH01
	MOVF	MAX,W
	MOVWF	MATH00
	CALL	mul16
	MOVF	MATH01,W
	MOVWF	MAX			; MAX = 仮MAX * (127 * 256 / 240) / 256
	CLRF	MATH01
	MOVF	MIN,W
	MOVWF	MATH00
	CALL	mul16
	MOVF	MATH01,W
	MOVWF	MIN			; MIN = 仮MIN * (127 * 256 / 240) / 256

	MOVLW	40			; HUEの角度の条件分岐
	SUBWF	HUE,W
	BTFSS	STATUS,C
	 GOTO	H2CALC_000
	MOVLW	80
	SUBWF	HUE,W
	BTFSS	STATUS,C
	 GOTO	H2CALC_060
	MOVLW	120
	SUBWF	HUE,W
	BTFSS	STATUS,C
	 GOTO	H2CALC_120
	MOVLW	160
	SUBWF	HUE,W
	BTFSS	STATUS,C
	 GOTO	H2CALC_180
	MOVLW	200
	SUBWF	HUE,W
	BTFSS	STATUS,C
	 GOTO	H2CALC_240
	GOTO	H2CALC_300
H2CALC_000
	CLRF	TMP01
	MOVF	HUE,W
	GOTO	CONV_RGB
H2CALC_060
	MOVLW	1
	MOVWF	TMP01
	MOVF	HUE,W
	SUBLW	80
	GOTO	CONV_RGB
H2CALC_120
	MOVLW	2
	MOVWF	TMP01
	MOVLW	80
	SUBWF	HUE,W
	GOTO	CONV_RGB
H2CALC_180
	MOVLW	3
	MOVWF	TMP01
	MOVF	HUE,W
	SUBLW	160
	GOTO	CONV_RGB
H2CALC_240
	MOVLW	4
	MOVWF	TMP01
	MOVLW	160
	SUBWF	HUE,W
	GOTO	CONV_RGB
H2CALC_300
	MOVLW	5
	MOVWF	TMP01
	MOVF	HUE,W
	SUBLW	240
CONV_RGB
	MOVWF	MATH00
	MOVF	MIN,W			; 誤差防止のため割り算をあとに持ってくる。
	SUBWF	MAX,W			;  前 MID = H / 40 * (MAX - MIN) + MIN
	MOVWF	MATH10			;  後 MID = H * (MAX - MIN) / 40 + MIN 
	CALL	mul8
	MOVLW	40
	MOVWF	MATH10
	CLRF	MATH11
	CALL	div16
	MOVF	MATH00,W
	ADDWF	MIN,W
	MOVWF	MID

	MOVLW	HIGH CONV_RGB2		; ここ以降でページをまたがないように注意
	MOVWF	PCLATH			; ■ PCLATH
	MOVLW	LOW CONV_RGB2
	ADDWF	TMP01,W
	MOVWF	PCL
CONV_RGB2
	GOTO	CONVRGB_000		; 赤
	GOTO	CONVRGB_060		; 黄
	GOTO	CONVRGB_120		; 緑
	GOTO	CONVRGB_180		; シアン
	GOTO	CONVRGB_240		; 青
	GOTO	CONVRGB_300		; マゼンタ

CONVRGB_000
	MOVF	MAX,W
	MOVWF	RED
	MOVF	MID,W
	MOVWF	GREEN
	MOVF	MIN,W
	MOVWF	BLUE
	RETURN

CONVRGB_060
	MOVF	MID,W
	MOVWF	RED
	MOVF	MAX,W
	MOVWF	GREEN
	MOVF	MIN,W
	MOVWF	BLUE
	RETURN

CONVRGB_120
	MOVF	MIN,W
	MOVWF	RED
	MOVF	MAX,W
	MOVWF	GREEN
	MOVF	MID,W
	MOVWF	BLUE
	RETURN

CONVRGB_180
	MOVF	MIN,W
	MOVWF	RED
	MOVF	MID,W
	MOVWF	GREEN
	MOVF	MAX,W
	MOVWF	BLUE
	RETURN

CONVRGB_240
	MOVF	MID,W
	MOVWF	RED
	MOVF	MIN,W
	MOVWF	GREEN
	MOVF	MAX,W
	MOVWF	BLUE
	RETURN

CONVRGB_300
	MOVF	MAX,W
	MOVWF	RED
	MOVF	MIN,W
	MOVWF	GREEN
	MOVF	MID,W
	MOVWF	BLUE
	RETURN

;------------------------------------------------------------------------------
; 8bit 掛け算 http://elm-chan.org/docs/avrlib/mul08.txt
;
; 引数
;	MATH00	掛けられる数
;	MATH10	掛ける数(非破壊)
;
; 戻り値
;	MATH00	LSB 積
;	MATH01	MSB
;
; 使用変数
;	TMP00
;------------------------------------------------------------------------------
mul8
	CLRF	MATH01			; sub	var11,var11	initialize variables
	MOVLW	9			; ldi	lc,9		lc = 9;
	MOVWF	TMP00
	BCF	STATUS,C
MUL8_1					; ---- calcurating loop
	BTFSS	STATUS,C		; brcc	PC+2
	GOTO	MUL8_2
	MOVF	MATH10,W		; add	var11,var20
	ADDWF	MATH01,F
MUL8_2
	RRF	MATH01,F		; ror	var11
	RRF	MATH00,F		; ror	var10
	DECFSZ	TMP00,F			; dec	lc		if (--lc > 0)
	GOTO	MUL8_1			; brne	PC-5		  continue loop;
	RETURN

;------------------------------------------------------------------------------
; 16bit 掛け算 http://elm-chan.org/docs/avrlib/mul16.txt
;
; 引数
;	MATH00	LSB 掛けられる数
;	MATH01	MSB
;	MATH10	LSB 掛ける数(非破壊)
;	MATH11	MSB
;
; 戻り値
;	MATH00	LSB 積
;	MATH01
;	MATH02
;	MATH03	MSB
;
; 使用変数
;	TMP00
;------------------------------------------------------------------------------
mul16
	CLRF	MATH03			; sub	var13,var13	initialize variables
	CLRF	MATH02			; sub	var12,var12
	MOVLW	17			; ldi	lc,17		lc = 17;
	MOVWF	TMP00
	BCF	STATUS,C
MUL16_1					; ---- calcurating loop
	BTFSS	STATUS,C		; brcc	PC+3
	GOTO	MUL16_2
	MOVF	MATH10,W		; add	var12,var20
	ADDWF	MATH02,F
	MOVF	MATH11,W		; adc	var13,var21
	BTFSC	STATUS,C		;  Cフラグを足す
	INCF	MATH11,W
	ADDWF	MATH03,F
MUL16_2
	RRF	MATH03,F		; ror	var13
	RRF	MATH02,F		; ror	var12
	RRF	MATH01,F		; ror	var11
	RRF	MATH00,F		; ror	var10
	DECFSZ	TMP00,F
	GOTO	MUL16_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

;------------------------------------------------------------------------------
; EEPROMアクセスルーチン
;  eeread	内蔵EEPROMのアドレスEEADR_から読み出してデータをWに入れる
;		読み出し後にEEADR_をインクリメントして戻る
;------------------------------------------------------------------------------
eeread
	BSF	STATUS,RP0		; ◆ RP=1
	MOVF	EEADR_,W
	MOVWF	EEADR
	INCF	EEADR_,F		; 読み出し後Zフラグが使えるように先にインクリメントしておく。
	BSF	EECON1,RD
	MOVF	EEDATA,W
	BCF	STATUS,RP0		; ◆ RP=0
	RETURN

;------------------------------------------------------------------------------
; EEPROMの初期値
;------------------------------------------------------------------------------
	ORG	0x2100	

	END