;***** ROM_EraseTimer.asm *************************************************
;
;	EP-ROM イレーサー用タイマー
;
;	Copyright (C) 2016   by M.Yamamoto. All rights reserved.
;
;     ( coding:  Ver. 0.00   2016/07/06  by M.Yamamoto )
;	coding:  Ver. 1.00   2016/07/09  初期バージョン
;	bugfix:  Ver. x.xx
;
;******************************************************* PicAsm 0239 ******

;	Device: PIC12F635	Clock: 8MHz (Internal OSC)

;	PIC12F635 のピンと用途

;		① Vdd	電源 +5V DC		⑧ Vss	電源 GND
;		② GP5	START SW 入力		⑦ GP0	BCD-0 bit 入力
;		③ GP4	TIMER 出力	　	⑥ GP1	BCD-1 bit 入力
;		④ GP3	BCD-3 bit 入力		⑤ GP2	BCD-2 bit 入力

;	      GP3 は入力専用で、出力ポートには使えない。

;==========================================================================

		list		P=PIC12F635	;デバイス情報
		include        "P12F635.INC"	;インクルードファイル
		errorlevel	-302		;Eliminate bank warning

		__config	_CPD_OFF & _CP_OFF & _BOD_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_OSC_NOCLKOUT

;==========================================================================
;		変数、定数の定義とレジスタ割付け
;==========================================================================

		radix	dec

tm0_h_val	equ	256 - 200		;ハードタイマー０カウント値 (4 / 8MHz * 200 = 100μS)
xx		equ	-689			;補正値
tm0_s_val_h	equ	high (10000 + xx)	;ソフトタイマー０の high カウント値
tm0_s_val_l	equ	low  (10000 + xx)	;ソフトタイマー０の low  カウント値
tmout		equ	4			;GP4: タイムアウト出力
stsw		equ	5			;GP5: START(CANCEL) スイッチ

		cblock	h'40'
tm0_cnt_h					;ソフトタイマー０の high カウンタ
tm0_cnt_l					;ソフトタイマー０の low  カウンタ
start_flg					;START フラグ（カウント中表示）
min_cnt						;タイマー"分"カウンタ
sec_cnt						;タイマー"秒"カウンタ
wt1cnt						;ウェイト用ループカウンタ
wt2cnt						;ウェイト用ループカウンタ
wt3cnt						;ウェイト用ループカウンタ
		endc

		cblock	h'70'
w_save						;W レジスタの退避用
s_save						;STATUS レジスタの退避用
		endc

;==========================================================================
;		プログラム開始
;==========================================================================

		org	h'0000'		;リセットベクタ
		goto	start

		org	h'0004'		;割り込みベクタ
		goto	interrupt

;==========================================================================
;		初期化処理
;==========================================================================

start
		clrf	STATUS		;STATUS クリア
	 	clrf	INTCON		;INTCON クリア

		; GPIO をデジタルI/O に設定

		clrf	GPIO
		movlw	h'07'		;Comparator mode Off
		movwf	CMCON0		;GP2-0 はデジタルI/O

		bsf	STATUS,RP0	;バンク 1
		movlw	h'2f'		;GP4: 出力, GP0-GP3,GP5: 入力
		movwf	TRISIO

		; 内部クロックを 8 MHz に設定

		movlw	h'70'		;CLOCK=8MHz
		movwf	OSCCON

		; タイマー０割り込みの設定

		movlw	h'88'		;プリスケーラ: 使用しない
		movwf	OPTION_REG

		bcf	STATUS,RP0	;バンク 0
		clrf	TMR0		;TMR0 クリア
		bcf	INTCON,T0IE	;T0IE: タイマー０割り込みを禁止
		bsf	INTCON,GIE	;GIE: グローバル割り込み許可

		; 各変数の初期設定

		clrf	start_flg	;START フラグの初期設定

;==========================================================================
;		メイン・ルーチン
;==========================================================================

;		START スイッチは CANCEL スイッチも兼ねている		
;		カウント動作前に ON すると START スイッチとして機能
;		カウント動作中に ON すると CANCEL スイッチとして機能

main
		btfsc	start_flg,0	;START フラグ = ON （カウント中）か？
		goto	m01		;Yes

		btfsc	GPIO,stsw	;START スイッチ = ON か？
		goto	main		;No

		; START スイッチ = ON の処理

		movf	GPIO,W		;TIMER スイッチの読み込み
		xorlw	0fh		;下４ビットをビット反転させて
		andlw	0fh		;取り出す
		btfsc	STATUS,Z	;値 > 0 か？
		movlw	10h		;No. 10h = 16 を設定
		movwf	min_cnt		;タイマー"分"カウンタに設定
		movlw	60
		movwf	sec_cnt		;タイマー"秒"カウンタの設定
		bsf	start_flg,0	;START フラグをセット（カウント中表示）

		bsf	GPIO,tmout	;GP4: 出力開始

		movlw	tm0_h_val	;ハードタイマー０カウント値
		movwf	TMR0		;タイマー０ TMR0 の設定
		movlw	tm0_s_val_h	;ソフトタイマー０の high カウント値
		movwf	tm0_cnt_h	;ソフトタイマー０の high カウンタの設定
		movlw	tm0_s_val_l	;ソフトタイマー０の low  カウント値
		movwf	tm0_cnt_l	;ソフトタイマー０の low  カウンタの設定
		bsf	INTCON,T0IE	;タイマー０割り込みを許可

		call	wait_500ms	;500m 秒 ウェイトルーチン
		goto	main

		; カウント中の処理

m01		movf	min_cnt,W
		btfsc	STATUS,Z	;タイマー"分"カウンタ = 0 か？
		goto	m02		;Yes

		btfsc	GPIO,stsw	;START スイッチ = ON （キャンセル操作）か？
		goto	main		;No

		; 終了処理

m02		bcf	INTCON,T0IE	;タイマー０割り込みを禁止
		bcf	GPIO,tmout	;GP4: 出力停止 = タイムアウト
		clrf	start_flg	;START フラグをクリア

		call	wait_500ms	;500m 秒 ウェイトルーチン
		goto	main

;==========================================================================
;		ウェイト・ルーチン (8 MHz)
;==========================================================================

		; 500m 秒 ウェイトルーチン
wait_500ms
		movlw	20		;1
		movwf	wt1cnt		;1

w500m01		movlw	250		;1
		movwf	wt2cnt		;1

w500m02		movlw	39		;1
		movwf	wt3cnt		;1

w500m03		nop			;1
		nop			;1
		decfsz	wt3cnt,F	;1,2
		goto	w500m03		;2,0	1+1+(1+1+1+2)*38+(1+1+2+0)=196
		nop			;1	1+196=197

		decfsz	wt2cnt,F	;1,2
		goto	w500m02		;2,0	1+1+(197+1+2)*249+(197+2+0)=50001

		decfsz	wt1cnt,F	;1,2
		goto	w500m01		;2,0	1+1+(50001+1+2)*19+(50001+2+0)=1000081

		return			;2	1000081+2=1000083
					;Total	1000083/8MHz*4 = 0.5000415 S = 500.0415 mS

;==========================================================================
;		割り込み処理
;==========================================================================

interrupt
		; レジスタの保存

		movwf	w_save		;W レジスタの保存
		movf	STATUS,W
		movwf	s_save		;STATUS レジスタの保存

		bcf	STATUS,RP0	;バンク 0
		btfss	INTCON,T0IF	;タイマー０割り込み か？
		goto	int_end		;No. (Illegal interrupt)

		; タイマー０割り込み処理

int_t0		bcf	INTCON,T0IF	;タイマー０割込みフラグをクリア

		movlw	tm0_h_val	;ハードタイマー０カウント値
		movwf	TMR0		;タイマー０ TMR0 の設定

		movlw	1
		subwf	tm0_cnt_l,F	;ソフトタイマー０の low  カウンタ - 1
		btfsc	STATUS,Z	;ソフトタイマー０の low  カウンタ = 0 か？
		goto	int01		;Yes

		btfsc	STATUS,C	;ソフトタイマー０の low  カウンタ > 0 か？
		goto	int_end		;Yes

		subwf	tm0_cnt_h,F	;ソフトタイマー０の high カウンタ - 1
		goto	int_end	

int01		movf	tm0_cnt_h,F
		btfss	STATUS,Z	;ソフトタイマー０の high カウンタ = 0 か？
		goto	int_end		;No

		movlw	tm0_s_val_h	;ソフトタイマー０の high カウント値
		movwf	tm0_cnt_h	;ソフトタイマー０の high カウンタの設定
		movlw	tm0_s_val_l	;ソフトタイマー０の low  カウント値
		movwf	tm0_cnt_l	;ソフトタイマー０の low  カウンタの設定

		decfsz	sec_cnt,F	;タイマー"秒"カウンタ - 1 = 0 か？
		goto	int_end		;No

		movlw	60
		movwf	sec_cnt		;タイマー"秒"カウンタの設定
		decf	min_cnt,F	;タイマー"分"カウンタ - 1

		; レジスタの復帰

int_end		movf	s_save,W
		movwf	STATUS		;STATUS レジスタの復帰
		swapf	w_save,F
		swapf	w_save,W	;W レジスタの復帰

		retfie

;==========================================================================

		end			;プログラムの終了
