;24時間繰り返しタイマー
;電子マスカット http://www.zea.jp/audio
;ishizuka yasuyuki
;2006/12/30

;ポートA0-----NC
;ポートA1-----NC
;ポートA2---->オートONインジケーター
;ポートA3---->オートOFFインジケーター
;ポートB0-----NC
;ポートB1-----NC
;ポートB2<----ONキー
;ポートB3<----OFFキー
;ポートB4---->フォトトライアック(A)
;ポートB5-----NC
;ポートB6-----NC
;ポートB7---->フォトトライアック(K)

;用意したデバイスに合わせてコメント「;」を操作してビルドして下さい。


;-----使用デバイス-------------------------------------------------------------------
	list	P=PIC16F84A
	include  "P16F84A.INC"
;	list	P=PIC16F628A
;	include  "P16F628A.INC"
;	list	P=PIC16F648A
;	include  "P16F648A.INC"

;-----コンフィグビット------------------------------------------------------------------
;発振回路=HSモード
;パワーオンリセット=有効
;ウォッチドッグタイマー=無効
;低電圧リセット=無効（PIC16F84Aは設定なし）
;低電圧プログラム機能=無効（PIC16F84Aは設定なし）
;リセット端子=リセット端子として使用（PIC16F84Aは設定なし）

;PIC16F84Aの時
	__CONFIG _PWRTE_ON &_WDT_OFF &_HS_OSC
;PIC16F628A/PIC16F648Aの時
;	__CONFIG _LVP_OFF &_MCLRE_ON &_BODEN_OFF &_PWRTE_ON &_WDT_OFF &_HS_OSC

;-----レジスタ定義(PIC16F84AもBank0:20h～から使った)-------------------------------------
SAVE_W		EQU	H'0020'	;割込み用Wレジスタセーブ用
SAVE_S		EQU	H'0021'	;割込み用STATUSレジスタセーブ用
TWSCNT_L	EQU	H'0022'	;2秒カウンタ（下位）
TWSCNT_H	EQU	H'0023'	;2秒カウンタ（上位）：2EEhでクリアさせる
DAYCNT_L	EQU	H'0024'	;1日カウンタ（下位）
DAYCNT_H	EQU	H'0025'	;1日カウンタ（上位）：A8C0Hでクリアさせる
TIMERSTA	EQU	H'0026'	;BIT7:ONタイマ有効ビット
				;BIT6:OFFタイマ有効ビット
				;BIT5:未使用
				;BIT4:未使用
				;BIT3:未使用
				;BIT2:未使用
				;BIT1:未使用
				;BIT0:未使用
ONCNT_L		EQU	H'0027'	;ON設定カウンタ（下位）
ONCNT_H		EQU	H'0028'	;ON設定カウンタ（上位）
OFFCNT_L	EQU	H'0029'	;OFF設定カウンタ（下位）
OFFCNT_H	EQU	H'002A'	;OFF設定カウンタ（上位）

EXREG1		EQU	H'002B'	;各種タイマ
EXREG2		EQU	H'002C'	;各種タイマ
EXREG3		EQU	H'002D'	;各種タイマ
EXREG4		EQU	H'002E'	;各種タイマ
EXREG5		EQU	H'002F'	;各種タイマ（使っていないと思う）


;-----プログラムスタート---------------------------------------------------------------
	ORG	H'0000'
	GOTO	STRAT
	ORG	H'0004'
	GOTO	INT

;-----イニシャル設定------------------------------------------------------------------
STRAT
	BCF	INTCON,GIE	;全割込み禁止
;コンパレーターモードOFF:全てデジタルI/Oで使用（PIC16F84Aはコメント行にする）-----------
;	MOVLW	B'00000111'
;	MOVWF	CMCON
;----------------------------------------------------------------------------
	BSF	STATUS,RP0	;Bank1に移動
	CLRF	TRISA		;ポートAは全て出力端子で使用
	MOVLW	B'00001100'
	MOVWF	TRISB		;ポートBはBIT2,3を入力端子、他を出力端子で使用
	MOVLW	B'10000100'
	MOVWF	OPTION_REG	;プルアップ抵抗無効／タイマー0のプリスケーラを32
	BCF	STATUS,RP0	;Bank0に移動
	BSF	INTCON,T0IE	;タイマ0の割込み有効

	CLRF	PORTA		;レジスタクリア（わたしのこだわり）
	CLRF	PORTB
	CLRF	TWSCNT_L
	CLRF	TWSCNT_H
	CLRF	DAYCNT_L
	CLRF	DAYCNT_H
	CLRF	TIMERSTA
	CLRF	ONCNT_L
	CLRF	ONCNT_H
	CLRF	OFFCNT_L
	CLRF	OFFCNT_H
	CLRF	EXREG1
	CLRF	EXREG2
	CLRF	EXREG3
	CLRF	EXREG4
	CLRF	EXREG5

	GOTO	SDOWN

;-----メインルーチン------------------------------------------------------------------
MAIN
	BTFSS	PORTB,2		;ONキーが押下された
	CALL	ONKEY		;ONキー処理ルーチンへ
	CALL	LEDCON		;LED制御ルーチンへ
	BTFSS	PORTB,3		;OFFキーが押下された
	CALL	OFFKEY		;OFFキー処理ルーチンへ
	CALL	LEDCON		;LED制御ルーチンへ
	GOTO	MAIN

;-----LED制御ルーチン----------------------------------------------------------------
LEDCON
	BTFSS	TIMERSTA,7	;オートONフラグが有効の場合はオートONランプを点灯
	GOTO	LEDCON_1
	BSF	PORTA,2
	GOTO	LEDCON_2
LEDCON_1
	BCF	PORTA,2
LEDCON_2
	BTFSS	TIMERSTA,6	;オートOFFフラグが有効の場合はオートOFFランプを点灯
	GOTO	LEDCON_3
	BSF	PORTA,3
	GOTO	LEDCON_4
LEDCON_3
	BCF	PORTA,3
LEDCON_4
	RETURN

;-----ONキー処理--------------------------------------------------------------------
ONKEY
	CALL	TIM8
	BTFSC	PORTB,2		;確実にスイッチが押下しているか確認
	GOTO	ONKEY_X
	MOVLW	H'00BC'
	MOVWF	EXREG3
ONKEY_1
	CALL	TIM8	
	BTFSC	PORTB,2
	GOTO	ONKEY_3		;約1.5秒以内にスイッチが離された
	DECFSZ	EXREG3,F
	GOTO	ONKEY_1		;約1.5秒以上長押しされた
	BCF	TIMERSTA,7	;オートONフラグクリア
	BCF	PORTA,2		;オートONランプ消灯
ONKEY_2
	CALL	TIM8
	CALL	TIM8
	BTFSS	PORTB,2		;スイッチが離されるのを待つ
	GOTO	ONKEY_2
	GOTO	ONKEY_X
ONKEY_3
	BSF	PORTB,7		;フォトトライアックON
	MOVLW	H'000D'		;約100ミリ秒待つ
	MOVWF	EXREG3
ONKEY_4
	CALL	TIM8
	BTFSS	PORTB,3		;OFFキーが押下された
	GOTO	ONKEY_X
	DECFSZ	EXREG3,F
	GOTO	ONKEY_4
	MOVLW	H'0032'		;約0.4秒間、スイッチの押下を監視
	MOVWF	EXREG3
ONKEY_5
	CALL	TIM8
	BTFSS	PORTB,3		;OFFキーが押下された
	GOTO	ONKEY_X
	BTFSS	PORTB,2
	GOTO	ONKEY_6		;スイッチが押下された
	DECFSZ	EXREG3,F
	GOTO	ONKEY_5
	GOTO	ONKEY_X		;スイッチの押下を確認できない
ONKEY_6
	CALL	TIM8
	CALL	TIM8
	BTFSS	PORTB,2		;スイッチが離されるのを待つ
	GOTO	ONKEY_6
	MOVF	DAYCNT_L,W	;1日カウンタ値をメモリ
	MOVWF	ONCNT_L
	MOVF	DAYCNT_H,W
	MOVWF	ONCNT_H
	BSF	TIMERSTA,7	;オートONフラグセット
	MOVLW	H'0006'		;6回オートONランプをフラッシング
	MOVWF	EXREG4
ONKEY_7
	BSF	PORTA,2
	MOVLW	H'0019'		;約200ミリ秒オートONランプ点灯
	MOVWF	EXREG3
ONKEY_8
	CALL	TIM8
	BTFSS	PORTB,3		;OFFキーが押下された
	GOTO	ONKEY_X
	DECFSZ	EXREG3,F
	GOTO	ONKEY_8
	BCF	PORTA,2
	MOVLW	H'0019'		;約200ミリ秒オートONランプ消灯
	MOVWF	EXREG3
ONKEY_9
	CALL	TIM8
	BTFSS	PORTB,3		;OFFキーが押下された
	GOTO	ONKEY_X
	DECFSZ	EXREG3,F
	GOTO	ONKEY_9
	DECFSZ	EXREG4,F
	GOTO	ONKEY_7
ONKEY_X
	CALL	TCHECK
	RETURN

;-----OFFキー処理-------------------------------------------------------------------
OFFKEY
	CALL	TIM8
	BTFSC	PORTB,3		;確実にスイッチが押下しているか確認
	GOTO	OFFKEY_X
	MOVLW	H'00BC'
	MOVWF	EXREG3
OFFKEY_1
	CALL	TIM8	
	BTFSC	PORTB,3
	GOTO	OFFKEY_3	;約1.5秒以内にスイッチが離された
	DECFSZ	EXREG3,F
	GOTO	OFFKEY_1	;約1.5秒以上長押しされた
	BCF	TIMERSTA,6	;オートOFFフラグクリア
	BCF	PORTA,3		;オートOFFランプ消灯
OFFKEY_2
	CALL	TIM8
	CALL	TIM8
	BTFSS	PORTB,3		;スイッチが離されるのを待つ
	GOTO	OFFKEY_2
	GOTO	OFFKEY_X
OFFKEY_3
	BCF	PORTB,7		;フォトトライアックOFF
	MOVLW	H'000D'		;約100ミリ秒待つ
	MOVWF	EXREG3
OFFKEY_4
	CALL	TIM8
	BTFSS	PORTB,2		;ONキーが押下された
	GOTO	OFFKEY_X
	DECFSZ	EXREG3,F
	GOTO	OFFKEY_4
	MOVLW	H'0032'		;約0.4秒間、スイッチの押下を監視
	MOVWF	EXREG3
OFFKEY_5
	CALL	TIM8
	BTFSS	PORTB,2		;ONキーが押下された
	GOTO	OFFKEY_X
	BTFSS	PORTB,3
	GOTO	OFFKEY_6	;スイッチが押下された
	DECFSZ	EXREG3,F
	GOTO	OFFKEY_5
	GOTO	OFFKEY_X	;スイッチの押下を確認できない
OFFKEY_6
	CALL	TIM8
	CALL	TIM8
	BTFSS	PORTB,3		;スイッチが離されるのを待つ
	GOTO	OFFKEY_6
	MOVF	DAYCNT_L,W	;1日カウンタ値をメモリ
	MOVWF	OFFCNT_L
	MOVF	DAYCNT_H,W
	MOVWF	OFFCNT_H
	BSF	TIMERSTA,6	;オートOFFフラグセット
	MOVLW	H'0006'		;6回オートOFFランプをフラッシング
	MOVWF	EXREG4
OFFKEY_7
	BSF	PORTA,3
	MOVLW	H'0019'		;約200ミリ秒オートOFFランプ点灯
	MOVWF	EXREG3
OFFKEY_8
	CALL	TIM8
	BTFSS	PORTB,2		;ONキーが押下された
	GOTO	OFFKEY_X
	DECFSZ	EXREG3,F
	GOTO	OFFKEY_8
	BCF	PORTA,3
	MOVLW	H'0019'		;約200ミリ秒オートOFFランプ消灯
	MOVWF	EXREG3
OFFKEY_9
	CALL	TIM8
	BTFSS	PORTB,2		;ONキーが押下された
	GOTO	OFFKEY_X
	DECFSZ	EXREG3,F
	GOTO	OFFKEY_9
	DECFSZ	EXREG4,F
	GOTO	OFFKEY_7
OFFKEY_X
	CALL	TCHECK
	RETURN

;-----オートON/OFFカウンタ不一致確認--------------------------------------------------
;万が一、ONカウンタとOFFカウンタが一致した場合はOFFカウンタを1つ進める
TCHECK
	MOVF	OFFCNT_L,W
	SUBWF	ONCNT_L,W
	BTFSS	STATUS,Z	;下位が一致しているか確認
	GOTO	TCHECK_9
	MOVF	OFFCNT_H,W
	SUBWF	ONCNT_H,W
	BTFSS	STATUS,Z	;上位が一致しているか確認
	GOTO	TCHECK_9	;ON/OFFが不一致なのでサブルーチンを抜ける
	INCFSZ	OFFCNT_L,F	;一致したのでOFFタイムを1つ進める
	GOTO	TCHECK_1
	INCF	OFFCNT_H,F
TCHECK_1
	MOVF	OFFCNT_L,W
	SUBLW	H'00C0'
	BTFSS	STATUS,Z
	GOTO	TCHECK_9
	MOVF	OFFCNT_H,W
	SUBLW	H'00A8'
	BTFSS	STATUS,Z
	GOTO	TCHECK_9
	CLRF	OFFCNT_L	;A8C0hの場合はクリアする
	CLRF	OFFCNT_H
TCHECK_9
	RETURN

;-----停電表示ルーチン---------------------------------------------------------------
SDOWN
	BSF	PORTA,2		;交互に点滅するように片方を点灯させておく
SDOWN_1
	MOVLW	H'0016'		;約3HzでLEDを交互に点滅
	MOVWF	EXREG3
	COMF	PORTA,F		;ポートAを反転
SDOWN_2
	CALL	TIM8
	BTFSS	PORTB,2		;ONスイッチが押下されたか確認
	GOTO	SDOWN_3		;このループを抜ける
	BTFSS	PORTB,3		;OFFスイッチが押下されたか確認
	GOTO	SDOWN_3		;このループを抜ける
	DECFSZ	EXREG3,F
	GOTO	SDOWN_2
	GOTO	SDOWN_1
SDOWN_3
	CLRF	PORTA		;ポートAをクリアしておく
	BSF	INTCON,GIE	;全割込み有効
	GOTO	MAIN

;-----タイムディレイ（約8ミリ秒）---------------------------------------------------------
;-----1+1+40+40+200*40+200*2*40+40+40*2+2=24204（約7.88ミリ秒）
TIM8
	MOVLW	H'0028'		;1ステップ
	MOVWF	EXREG1		;1ステップ
TIM8_1
	MOVLW	H'00C8'		;25ステップ
	MOVWF	EXREG2		;25ステップ
TIM8_2
	DECFSZ	EXREG2,F	;200*25ステップ
	GOTO	TIM8_2		;200*2*25ステップ
	DECFSZ	EXREG1,F	;25ステップ
	GOTO	TIM8_1		;25*2ステップ
	RETURN			;2ステップ

;-----割込みルーチン-----------------------------------------------------------------
INT
	MOVWF	SAVE_W		;Wレジスタ一時保存
	SWAPF	STATUS,W
	MOVWF	SAVE_S		;STATUSレジスタ一時保存
	BCF	INTCON,T0IF	;タイマ0割込みフラグクリア

;-----2秒カウンタ---------------------------
	INCFSZ	TWSCNT_L,F	;下位カウントアップ
	GOTO	INT_1		;桁上がり
	INCF	TWSCNT_H,F	;上位カウントアップ
INT_1
	MOVF	TWSCNT_L,W
	SUBLW	H'00EE'
	BTFSS	STATUS,Z
	GOTO	INT_END
	MOVF	TWSCNT_H,W
	SUBLW	H'0002'
	BTFSS	STATUS,Z
	GOTO	INT_END
	CLRF	TWSCNT_L	;750回（2EEh）割込みに入った（2秒になった）
	CLRF	TWSCNT_H

;-----1日カウンタ--------------------------
	INCFSZ	DAYCNT_L,F	;下位カウントアップ
	GOTO	INT_2		;桁上がり
	INCF	DAYCNT_H,F	;上位カウントアップ
INT_2
	MOVF	DAYCNT_L,W
	SUBLW	H'00C0'
	BTFSS	STATUS,Z
	GOTO	INT_3
	MOVF	DAYCNT_H,W
	SUBLW	H'00A8'
	BTFSS	STATUS,Z
	GOTO	INT_3
	CLRF	DAYCNT_L	;43200回（A8C0h）割込みに入った（1日経過）
	CLRF	DAYCNT_H

;-----ONカウンタ一致確認-------------------
INT_3
	BTFSS	TIMERSTA,7	;オートONフラグを確認して有効ならば一致するか確認する
	GOTO	INT_4
	MOVF	DAYCNT_L,W	
	SUBWF	ONCNT_L,W
	BTFSS	STATUS,Z	;下位が一致しているか確認
	GOTO	INT_4
	MOVF	DAYCNT_H,W
	SUBWF	ONCNT_H,W
	BTFSS	STATUS,Z	;上位が一致しているか確認
	GOTO	INT_4
	BSF	PORTB,7		;一致しているのでトラアックをON

;-----OFFカウンタ一致確認-------------------
INT_4
	BTFSS	TIMERSTA,6	;オートOFFフラグを確認して有効ならば一致するか確認する
	GOTO	INT_END
	MOVF	DAYCNT_L,W	
	SUBWF	OFFCNT_L,W
	BTFSS	STATUS,Z	;下位が一致しているか確認
	GOTO	INT_END
	MOVF	DAYCNT_H,W
	SUBWF	OFFCNT_H,W
	BTFSS	STATUS,Z	;上位が一致しているか確認
	GOTO	INT_END
	BCF	PORTB,7		;一致しているのでトラアックをOFF

;-----割込み終了の為のレジスタ復帰----------
INT_END
	SWAPF	SAVE_S,W
	MOVWF	STATUS		;STATUSレジスタ復帰
	SWAPF	SAVE_W,F	;SAVE_Wレジスタ反転上書き
	SWAPF	SAVE_W,W	;SAVE_Wレジスタを反転してWレジスタへ転送
	RETFIE


END
