;***** StopWatchTimer.asm *************************************************
;
;	長時間ストップウオッチ／タイマー（アップ／ダウンカウンタ）
;
;	Copyright (C) 2010   by M.Yamamoto. All rights reserved.
;
;     ( coding:  Ver. 0.00   2010/07/02  by M.Yamamoto )
;	coding:  Ver. 1.00   2010/07/09  初期バージョン
;	update:  Ver. 1.01   2010/07/11  X'tal 4→20MHzに変更、ブザー追加
;	update:  Ver. 1.02   2010/07/13  タイマー設定値の記憶モード追加
;	update:  Ver. 1.03   2010/07/14  時間遅れをソフト的に修正
;	bugfix:  Ver. 1.04   2010/07/17  "HH"→"DL"の桁上げ時に誤表示を修正
;	update:  Ver. 1.05   2017/03/31  LCD表示形式の修正  
;
;******************************************************* PicAsm 0223 ******

;	Device: PIC16F648A	Clock: 20MHz (クリスタル)

#ifdef comment

 <機能概要>

・本装置は、数秒台のある程度正確な時間測定から、数時間の長時間の時間測定を可能とする、ストップ
　ウオッチ機能（アップカウンタ）を第一の目的として設計作成したものである。
・第二の目的としてのタイマー機能（ダウンカウンタ）は、おまけ的な存在ではあるが、ストップウオッ
　チ機能と同程度の精度を有する。
・設計上、数秒台の時間測定では１／１００秒までを可能とした。また、長時間測定では９９日２３時間
　５９分５９秒９９まで表示可能（ストップウオッチの場合）としているが、それ以上の３桁目の日表示
　はできないが１００日以上の測定も連続無制限に可能である。
・ただし、タイマー機能では表示上または設定値の問題から、９９日２３時５９分５９秒９９が設定最大
　の時間となる。

・本装置は、電源スイッチをオンすると、"ピポッ" と開始ブザー音を出力後、液晶（ＬＣＤ）にデモとし
　て、"  StopWatch /   "、" Timer ver.x.xx "、"  by m.yamamoto " の文字列が、交互に１.５秒づつ
　連続３回表示される。
・その後、１.５秒間無表示の後、" 00 00:00:00.00 " の初期時間が表示され、各種スイッチの入力待ち
　となる。このとき、SELECT スイッチが StopWatch 側に設定されている場合は表示はそのままで、スタ
　ート信号 "L"（LINE 入力の場合）*(注) または START/STOP スイッチのオン（START）を待つ。
・一方、SELECT スイッチが Timer 側に設定されている場合は、初期設定として " 00 00:00:00.00 " 表
　示の左端の "0"（十台の日）がブリンク表示され、タイマー時間の設定値の入力待ちとなる。
・この設定値の入力待ちの状態では、←（LEFT）／ →（RIGHT）スイッチの操作によって、設定する桁を
　自由に変更でき該当の桁をブリンク表示する。そして該当の桁を選択後、↑（UPPER）／ ↓（LOWER）ス
　イッチの操作によって、タイマー時間の設定値を入力する。
・各桁の設定値の入力範囲は、基本的に "０" から "９９日２３時５９分５９秒９９" が最大である。↑
　（UPPER）スイッチの操作では、１回押すごとにブリンク表示の該当の桁を１づつインクリメントする。
　また ↓（LOWER）スイッチの操作では、同様に１づつデクリメントする。
・↑（UPPER）スイッチの操作では、各桁の最大値を超えると "０" に戻る。また ↓（LOWER）スイッチの
　操作では、各桁の最小値の "０" を超えると各桁の最大値に戻る。
・ただし "時" の入力では、"００" から "２９" まで変更が可能であるが、"２４" 以上を入力した場合
　には、その後 ←（LEFT）／ →（RIGHT）スイッチの操作を行なっても他桁への移行はできず、"ブッ" 
　というブザー音とともに赤色ＬＥＤが瞬間点滅して、エラー表示をする。またこの場合の START/STOP 
　スイッチのオン（START）操作も同様である。

・ストップウオッチ／タイマー機能ともに、スタート信号 "L"（LINE 入力の場合）*(注) または START/
　STOP スイッチのオン（START）操作により、それぞれ各機能を開始し、ストップウオッチ機能では "０"
　から１／１００秒単位でカウントアップし、またタイマー機能では設定値から１／１００秒単位でカウ
　ントダウンする。
　*(注) ＰＩＣのポートでは、LINE 端子の後にインバータ（74HC00）が入っているため、スタート信号は
　　　　"H" となる。
・各機能ともに、ひたすらカウントアップまたはカウントダウンをし続ける。やがてストップウオッチ機
　能ではスタート信号が "H"（LINE 入力の場合）、または START/STOP スイッチがオフ（STOP）操作され
　ることにより、カウントアップ動作を停止する。
・一方、タイマー機能では設定値がオール "０" に至るとカウントダウン動作を停止する。またはカウン
　トダウン動作中に START/STOP スイッチがオフ（STOP）操作されることによっても、同様にカウントダ
　ウン動作を中止して停止する。このタイマー機能でも LINE 入力の信号で同様のスタート／ストップ動
　作を行なわせることが可能であるが、そういう使用は想定していない。
・各機能ともにそれぞれの動作が停止すると、"ポッポッポッポッ" というブザー音に合わせて赤色ＬＥＤ
　が点滅し、その後点灯し続けて各機能の動作が停止したことを表示する。
・各機能の動作が停止したことを確認（液晶（ＬＣＤ）の表示値等）した後、CLEAR スイッチ（↓（LOWER）
　スイッチと兼用）を操作すると、赤色ＬＥＤが消灯するとともに液晶（ＬＣＤ）の表示が "０" クリア
　されて初期状態に戻る。
・この初期状態では、SELECT スイッチの操作（StopWatch／Timer）は自由であり、それぞれ選択された機
　能の初期の液晶（ＬＣＤ）表示が行なわれる。したがって、タイマー機能で各桁を設定後、START/STOP 
　スイッチのオン（START）操作前に SELECT スイッチを StopWatch 側に操作すると、設定は "０" クリ
　アされてしまうので注意を要する。

 <タイマー設定値の記憶モード追加>
・タイマー機能を使用する場合において、よく利用するタイマー時間のその設定値を予め記憶しておくこ
　とにより、次回からは簡単にその設定値を読み出して利用することが可能である。
・まず設定値を記憶するには、通常のタイマー時間の設定後、←（LEFT）スイッチと →（RIGHT）スイッ
　チを同時に押下することにより、<タイマー設定値の記憶モード> に移行する。"ピポッ" というブザー
　音に合わせて赤色ＬＥＤが点滅し、その後点灯し続けてこの記憶モードに移行したことを知らせる。
・次に ↑（UPPER）／ WR スイッチを操作することによって、現在液晶（ＬＣＤ）に表示されているタイ
　マー時間の設定値が EEPROM に書き込まれ記憶される。したがって一度記憶された内容は次に別の設定
　値が上書きされるまで、たとえ電源をＯＦＦしても記憶され続ける。またこの時の ↑（UPPER）／ WR 
　スイッチの操作によって、点灯していた赤色ＬＥＤは消燈し、<タイマー設定値の記憶モード> から再び
　通常のタイマー時間の設定モードに戻ったことを知らせる。
・この記憶させたタイマー時間の設定値を読み出すには、通常のタイマー時間の設定モード時に、同様に
　←（LEFT）スイッチと →（RIGHT）スイッチを同時に押下することによって、まず <タイマー設定値の
　記憶モード> に移行させ、次に ↓（LOWER）／ RD スイッチを操作することによって、EEPROM に記憶さ
　れている内容が読み出されて液晶（ＬＣＤ）に表示される。またこの時の ↓（LOWER）／ RD スイッチ
　の操作によって、点灯していた赤色ＬＥＤが消燈し、再び通常のタイマー時間の設定モードに戻ること
　は書き込み時と同様である。

#endif

;==========================================================================

	list		p=pic16f648a	;デバイス情報
	include		p16f648a.inc	;インクルードファイル
	errorlevel	-302		;Eliminate bank warning

	__config _CP_OFF & _DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC

;==========================================================================
;		変数、定数の定義とレジスタ割付
;==========================================================================

#define 	ver_no	"1.05"

		radix	dec

SW		equ	PORTA		;各スイッチ入力ポート
TRIS_SW		equ	TRISA		;各スイッチ入力ポートの入出力切り替え
LCD		equ	PORTB		;LCD 制御用ポート
TRIS_LCD	equ	TRISB		;LCD 制御用ポートの入出力切り替え

_swL		equ	0		;LEFT  ← スイッチ
_swR		equ	1		;RIGHT → スイッチ
_swU		equ	2		;UPPER ↑ スイッチ
_swLO		equ	3		;LOWER ↓ スイッチ
_swC		equ	3		;CLEAR    スイッチ
_swS		equ	4		;SELECT   スイッチ
_st		equ	5		;スタート信号 (START/STOP スイッチ)

_E		equ	0		;LCD E:   動作起動信号
_RW		equ	1		;LCD R/W: 読み出し／書き込み選択信号
_RS		equ	2		;LCD RS:  レジスタ選択信号

_BF		equ	7		;LCD ビジーフラグ

_END		equ	3		;END 表示 LED
_BZ		equ	3		;BEEP 音出力ポート

;#define 	debug
#ifndef debug
xx		equ	28		;補正値
basic_high	equ	high (65536 - 50000 + xx)	;0.2μS * 50000 = 0.01 S = 10 mS
basic_low	equ	low  (65536 - 50000 + xx)	;
#else
basic_high	equ	high (65536 - 500)		;0.2μS * 500 = 100 μS = 0.1 mS
basic_low	equ	low  (65536 - 500)		;
#endif

buh		equ	high (65536 - 9555)	;ド (261.63 Hz)
bul		equ	low  (65536 - 9555)	;
pih		equ	high (65536 - 6377)	;ソ (392.00 Hz)
pil		equ	low  (65536 - 6377)	;
poh		equ	high (65536 - 4777)	;ド (523.26 Hz)
pol		equ	low  (65536 - 4777)	;

bulcnt		equ	70		;音長
pilcnt		equ	70		;音長
polcnt		equ	70		;音長

		cblock	h'20'
addr_high				;読み出すデータの high アドレス
addr_low				;読み出すデータの low アドレス
const_high				;音階用分周定数 high の保存
const_low				;音階用分周定数 low の保存

beepflg					;bit0: ビープ音フラグ
lcdtmp					;LCD への入出力データの一時保存
disp_cnt				;スタートメッセージの表示回数
loop_cnt				;繰り返しカウンタ
work					;ワーク

wt1cnt					;ウェイト用ループカウンタ
wt2cnt					;ウェイト用ループカウンタ
wt3cnt					;ウェイト用ループカウンタ
wt4cnt					;ウェイト用ループカウンタ

dspdigit2				;表示桁指定フラグ
					;bit1: "DH" 桁の指定
					;bit0: "DL" 桁の指定
dspdigit				;表示桁指定フラグ
					;bit7: "HH" 桁の指定
					;bit6: "HL" 桁の指定
					;bit5: "MH" 桁の指定
					;bit4: "ML" 桁の指定
					;bit3: "SH" 桁の指定
					;bit2: "SL" 桁の指定
					;bit1: "XH" 桁の指定
					;bit0:  桁上がり指定
updtflg					;更新フラグ
					;bit1: タイムアウトフラグ
					;bit0: 更新フラグ
dsp_point				;表示位置ポインタ
msb_dgt					;表示する最上位桁

bcd_dd					;日 BCD カウンタ
bcd_hh					;時 BCD カウンタ
bcd_mm					;分 BCD カウンタ
bcd_ss					;秒 BCD カウンタ
bcd_xx					;秒以下 BCD カウンタ
		endc

		cblock	h'70'
s_save					;STATUS レジスタの退避用
p_save					;PCLATH レジスタの退避用
f_save					;FSR レジスタの退避用
w_save					;W レジスタの退避用
		endc

;==========================================================================
;		マクロ命令定義
;==========================================================================

;		LCD メッセージデータ表示マクロ

Disp_Lcd	macro	@com,@msg,@x
		movlw	@com
		call	lcd_cmd		;LCD へコマンドを出力
	#if 	@x == 0
	#else
		movlw	high @msg	;メッセージデータの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low @msg	;メッセージデータの先頭アドレスの low アドレス
		movwf	addr_low	;
	#endif
		call	lcd_disp	;メッセージデータ１行表示
		endm

;==========================================================================
;		プログラム開始
;==========================================================================

		org	0		;リセットベクタ
		goto	init
		org	4		;割り込みベクタ
		goto	interrupt

		org	h'08'

;==========================================================================
;		初期化処理
;==========================================================================

init
		; PIC16F648A 初期設定

		bcf	STATUS,RP1
		bcf	STATUS,RP0	;バンク0 を選択
		clrf	PORTA		;
		movlw	b'00000111'	;RA3-0 を Digital I/O
		movwf	CMCON		;CMCON の設定

		bsf	STATUS,RP0	;バンク1 を選択
		movlw	b'00111111'	;RA5-0 を 入力
       		movwf	TRIS_SW		;SW ポートの I/0 設定
       		clrf	TRIS_LCD	;RB0-7: 出力, LCD ポートの I/0 設定

		movlw	h'80'		;プルアップ抵抗を使用しない
		movwf	OPTION_REG	;OPTION_REG の設定

		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク0 を選択

		movlw	b'00000001'	;bit7-6: 未使用
					;bit5-4:00 プリスケーラのスケール値 1:1
					;bit3:0 専用の発振器を使う場合に指定
					;bit2:0 外部入力クロック指定時に有効
					;bit1:0 内部クロックを使う
					;bit0:1 タイマー１を動作
		movwf	T1CON		;T1CON の設定

		bsf	INTCON,PEIE	;PEIE 周辺機器割り込みを許可
		bsf	INTCON,GIE	;GIE  グローバル割り込み許可

		clrf	LCD		;LCD 制御用ポート

		; S-10551D(LCD) 初期設定, スタートメッセージの表示

		call	lcd_init	;LCD 初期設定 

		movlw	b'00001100'	;表示ON
		call	lcd_cmd		;LCD へコマンドを出力

		clrf	beepflg		;ビープ音フラグ
		call	buzzer_pipo	;"ピポッ" ブザー音出力

		movlw	3
		movwf	disp_cnt
ini01
;		dt	"  StopWa",0,"tch /   ",0	を表示
		Disp_Lcd	b'00000010',start_msg,1	;カーソルホーム
		Disp_Lcd	b'11000000',         ,0	;DDRAM アドレスセット
		call	wait_1sec
		call	wait_500ms

;		dt	" Timer v",0,"er.x.xx ",0	を表示
		Disp_Lcd	b'00000010',         ,0	;カーソルホーム
		Disp_Lcd	b'11000000',         ,0	;DDRAM アドレスセット
		call	wait_1sec
		call	wait_500ms

;		dt	"  by m.y",0,"amamoto ",0	を表示
		Disp_Lcd	b'00000010',         ,0	;カーソルホーム
		Disp_Lcd	b'11000000',         ,0	;DDRAM アドレスセット
		call	wait_1sec
		call	wait_500ms
		decfsz	disp_cnt,F
		goto	ini01

		movlw	b'00000001'	;表示クリア
		call	lcd_cmd		;LCD へコマンドを出力
		call	wait_1sec
		goto	main

;==========================================================================
;		LCD（ S-10551D の場合 ）表示用 各種メッセージ等
;==========================================================================

		; スタートメッセージ

start_msg	dt	"  StopWa",0,"tch /   ",0
		dt	" Timer v",0,"er.",ver_no," ",0
		;	 01234567     89ABCDEF
		dt	"  by m.y",0,"amamoto ",0

		; ストップウオッチ／タイマー進行メッセージ

		;         DD HH:M     M:SS.XX
time_msg	dt	" 00 00:0",0,"0:00.00 ",0
		;	 01234567     89ABCDEF

		; 表示位置テーブル
disp_tbl
		addwf	PCL,F
		;	0     1     2     3     4     5     6     7     8     9
		dt	h'01',h'02',h'04',h'05',h'07',h'40',h'42',h'43',h'45',h'46'
disp_tbl_end

;==========================================================================
;		メインプログラム
;==========================================================================

		; 進行メッセージの表示

main		call	wait_500ms	;チャタリングを吸収

		movlw	b'00001100'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=0: 非ブリンク

;		dt	" 00 00:0",0,"0:00.00 ",0	を表示
		Disp_Lcd	b'00000010',time_msg,1	;カーソルホーム
		Disp_Lcd	b'11000000',        ,0	;DDRAM アドレスセット

		; 各変数の初期設定

		clrf	bcd_dd		;日 BCD カウンタ
		clrf	bcd_hh		;時 BCD カウンタ
		clrf	bcd_mm		;分 BCD カウンタ
		clrf	bcd_ss		;秒 BCD カウンタ
		clrf	bcd_xx		;秒以下 BCD カウンタ
		clrf	updtflg		;更新フラグ

		; ストップウオッチの処理

main01		btfsc	SW,_swS		;SELECT スイッチ = TIMER = OFF('H') か？
		goto	main02		;Yes

		btfsc	SW,_st		;スタート信号 = 'H' か？
		goto	main05		;Yes
		goto	main01		;No

		; タイマーの処理

main02		call	wait_500ms	;チャタリングを吸収

		clrf	dsp_point	;ブリンク位置ポインタの初期設定

		movlw	b'00001101'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=1: ブリンク

main03		movf	dsp_point,W	;ブリンク位置ポインタ値を W へロード
		call	disp_tbl	;ブリンク位置テーブル読み出し
		iorlw	h'80'		;DDRAM のアドレス(ブリンク位置)をセット
		call	lcd_cmd		;LCD へコマンドを出力

		btfss	SW,_swL		;←(LEFT)スイッチ = ON か？
		call	left_switch	;Yes

		btfss	SW,_swR		;→(RIGHT)スイッチ = ON か？
		call	right_switch	;Yes

		btfss	SW,_swU		;↑(UPPER)スイッチ = ON か？
		call	upper_switch	;Yes

		btfss	SW,_swLO	;↓(LOWER)スイッチ = ON か？
		call	lower_switch	;Yes

		btfss	SW,_swS		;SELECT スイッチ = STOPWATCH = ON('L') か？
		goto	main		;Yes

		btfss	SW,_st		;スタート信号 = 'H' か？
		goto	main03		;No

		movf	bcd_hh,W	;時 BCD カウンタ
		sublw	h'24' - 1	;h'24' - 1 - W
		btfsc	STATUS,C	;W < h'24' か？
		goto	main04		;Yes

		call	buzzer_bu	;"ブッ" ブザー音出力
		goto	main03		;Error

main04		movlw	b'00001100'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=0: 非ブリンク

		; ストップウオッチ／タイマーの処理

main05		call	time_control	;ストップウオッチ／タイマー処理

		call	buzzer_po4	;"ポッポッポッポッ" ブザー音出力
		bsf	LCD,_END	;END 表示 LED 点灯

		btfsc	SW,_swC		;CLEAR スイッチ = ON か？
		goto	$ - 1		;No

		bcf	LCD,_END	;END 表示 LED 消灯
		goto	main

;==========================================================================
;		ストップウオッチ／タイマーの処理
;==========================================================================

time_control
		; タイマー１割り込みの初期設定

		movlw	basic_high	;
		movwf	TMR1H		;TMR1H に設定
		movlw	basic_low	;
		movwf	TMR1L		;TMR1L に設定

		bsf	STATUS,RP0	;バンク 1
		bsf	PIE1,TMR1IE	;タイマー１割り込みを許可
		bcf	STATUS,RP0	;バンク 0

		; 表示する最上位桁の決定

cont01		btfss	updtflg,0	;更新フラグはセット か？
		goto	cont05		;No

		clrf	updtflg		;更新フラグをリセット
		clrf	msb_dgt		;表示する最上位桁のクリア
		rrf	dspdigit,F	;"XL" 桁をパス

		movlw	7
		movwf	loop_cnt	;繰り返しカウンタ = 7 を設定

cont02		rrf	dspdigit,F	;"XH","SL","SH","ML","MH","HL","HH" のチェック
		btfss	STATUS,C	;桁の指定 bit = 1 か？
		goto	cont04		;No

		incf	msb_dgt,F	;最上位桁 +1 更新
		decfsz	loop_cnt,F
		goto	cont02

		movlw	2
		movwf	loop_cnt	;繰り返しカウンタ = 2 を設定

cont03		rrf	dspdigit2,F	;"DL","DH" のチェック
		btfss	STATUS,C	;桁の指定 bit = 1 か？
		goto	cont04		;No

		incf	msb_dgt,F	;最上位桁 +1 更新
		decfsz	loop_cnt,F
		goto	cont03

cont04		movf	msb_dgt,W
		sublw	9		;9 - W
		movwf	dsp_point	;表示位置ポインタの設定

		call	time_display	;LCD への "DD HH:MM:SS.XX" 表示

cont05		btfsc	updtflg,1	;タイムアウトフラグ(タイマー処理で使用) = ON か？
		goto	cont06		;Yes

		btfsc	SW,_st		;スタート信号 = 'L' か？
		goto	cont01		;No

cont06		bsf	STATUS,RP0	;バンク 1
		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク 0

		return

;==========================================================================

		; LCD への "DD HH:MM:SS.XX" 表示

		;	0     1     2     3     4     5     6     7     8     9
;		dt	h'01',h'02',h'04',h'05',h'07',h'40',h'42',h'43',h'45',h'46'

time_display
		movf	dsp_point,W
		call	disp_tbl	;表示位置テーブル
		iorlw	h'80'		;DDRAM のアドレスをセット
		call	lcd_cmd		;LCD へコマンドを出力

		rrf	dsp_point,W
		andlw	h'07'		;インデックス値
		addlw	bcd_dd		;+ BCD カウンタの先頭番地
		movwf	FSR		;間接アドレスの先頭番地の設定

		btfsc	dsp_point,0	;奇数 か？
		goto	disp02		;Yes

disp01		swapf	INDF,W		;上位４ビット
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力
		incf	dsp_point,F

		movlw	5
		subwf	dsp_point,W
		btfss	STATUS,Z	;dsp_point = 5 か？
		goto	disp02		;No

		movlw	h'c0'		;DDRAM のアドレス(40)をセット
		call	lcd_cmd		;LCD へコマンドを出力

disp02		movf	INDF,W		;下位４ビット
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力
		incf	dsp_point,F
		incf	FSR,F		;間接アドレスの更新

		movlw	10
		subwf	dsp_point,W
		btfsc	STATUS,Z	;dsp_point = 10 か？
		goto	disp04		;Yes

		movlw	2
		subwf	dsp_point,W
		movlw	" "
		btfsc	STATUS,Z	;dsp_point = 2 か？
		goto	disp03		;Yes

		movlw	8
		subwf	dsp_point,W
		movlw	"."
		btfsc	STATUS,Z	;dsp_point = 8 か？
		goto	disp03		;Yes

		movlw	":"

disp03		call	lcd_data	;LCD へデータを１文字出力
		goto	disp01

disp04		return

;==========================================================================
;		←(LEFT) 左スイッチの処理
;==========================================================================

left_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swL		;入力(LEFT ←)スイッチ = ON か？
		goto	lefsw03		;No

		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 150ms
		btfsc	SW,_swR		;入力(RIGHT →)スイッチ = ON か？
		goto	lefsw01		;No

		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swR		;入力(RIGHT →)スイッチ = ON か？
		goto	lefsw01		;No
					;(LEFT ←) = ON and (RIGHT →) = ON の時
		call	eep_mode	;タイマー設定値の記憶モードへ
		goto	lefsw03

lefsw01		movlw	2
		subwf	dsp_point,W
		btfss	STATUS,Z	;dsp_point = 2 か？
		goto	lefsw02		;No

		movf	bcd_hh,W	;時 BCD カウンタ
		sublw	h'24' - 1	;h'24' - 1 - W
		btfsc	STATUS,C	;W < h'24' か？
		goto	lefsw02		;Yes

		call	buzzer_bu	;"ブッ" ブザー音出力
		goto	lefsw03		;Error

lefsw02		decf	dsp_point,F	;ブリンク位置ポインタ -1
		incf	dsp_point,W
		btfss	STATUS,Z	;(dsp_point < 0) か？
		goto	lefsw03		;No

		movlw	disp_tbl_end - disp_tbl - 2
		movwf	dsp_point	;ブリンク位置ポインタの初期設定

lefsw03		return

;==========================================================================

		; タイマー設定値の記憶モード（書き込み／読み出し）
eep_mode
		call	buzzer_pipo	;"ピポッ" ブザー音出力
		bsf	LCD,_END	;EEP MODE 表示 LED 点灯

		bsf	STATUS,RP0	;バンク1
		movlw	eep_size
		movwf	EEADR		;EEPROM の記録アドレスを設定
		bcf	STATUS,RP0	;バンク0

		movlw	bcd_dd		;BCD カウンタの先頭アドレスを
		movwf	FSR		;間接アドレスに設定

eep01		btfss	SW,_swLO	;↓(LOWER)スイッチ = ON か？
		goto	eep03		;Yes

		btfsc	SW,_swU		;↑(UPPER)スイッチ = ON か？
		goto	eep01		;No

		; EEPROM データの書き込み

eep02		movf	INDF,W		;BCD カウンタデータの読み出し

		bsf	STATUS,RP0	;バンク1
		movwf	EEDATA		;書き込みデータを設定
		bsf	EECON1,WREN	;書き込みイネーブル = ON
		movlw	h'55'
		movwf	EECON2		;h'55' を EECON2 に書き込む
		movlw	h'aa'
		movwf	EECON2		;h'aa' を EECON2 に書き込む
		bsf	EECON1,WR	;書き込み開始
		btfsc	EECON1,WR	;書き込み 終了か?
		goto	$-1		;No

		incf	EEADR,F		;記録アドレスの更新
		bcf	STATUS,RP0	;バンク0

		incf	FSR,F		;間接アドレスの更新
		movlw	bcd_xx + 1
		subwf	FSR,W
		btfss	STATUS,Z	;読み出しアドレス 終了か?
		goto	eep02		;No
		goto	eep04

		; EEPROM データの読み出し

eep03		bsf	STATUS,RP0	;バンク1
		bsf	EECON1,RD	;読み出し制御 = ON
		movf	EEDATA,W	;データの読み出し

		incf	EEADR,F		;記録アドレスの更新
		bcf	STATUS,RP0	;バンク0

		movwf	INDF		;BCD カウンタデータへ書き込み

		incf	FSR,F		;間接アドレスの更新
		movlw	bcd_xx + 1
		subwf	FSR,W
		btfss	STATUS,Z	;書き込みアドレス 終了か?
		goto	eep03		;No

		clrf	dsp_point	;表示位置ポインタの設定
		call	time_display	;LCD への "DD HH:MM:SS:XX" 表示
		movlw	" "		;ブリンク位置を表示範囲以外へ
		call	lcd_data	;LCD へデータを１文字出力
		clrf	dsp_point	;表示位置ポインタの設定

eep04		bcf	LCD,_END	;EEP MODE 表示 LED 消灯
		call	wait_1sec	;チャタリングを吸収
		return

;==========================================================================
;		→(RIGHT) 右スイッチの処理
;==========================================================================

right_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swR		;入力(RIGHT →)スイッチ = ON か？
		goto	rigsw02		;No

		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 150ms

		movlw	3
		subwf	dsp_point,W
		btfss	STATUS,Z	;dsp_point = 3 か？
		goto	rigsw01		;No

		movf	bcd_hh,W	;時 BCD カウンタ
		sublw	h'24' - 1	;h'24' - 1 - W
		btfsc	STATUS,C	;W < h'24' か？
		goto	rigsw01		;Yes

		call	buzzer_bu	;"ブッ" ブザー音出力
		goto	rigsw02		;Error

rigsw01		incf	dsp_point,F	;ブリンク位置ポインタ +1
		movlw	disp_tbl_end - disp_tbl - 1
		subwf	dsp_point,W
		btfss	STATUS,Z	;(dsp_point = テーブルデータ数) か？
		goto	rigsw02		;No

		clrf	dsp_point	;ブリンク位置ポインタの初期設定

rigsw02		return

;==========================================================================
;		↑(UPPER) 上スイッチの処理
;==========================================================================

upper_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swU		;入力(UPPER ↑)スイッチ = ON か？
		goto	uppsw07		;No

		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 150ms

		rrf	dsp_point,W
		andlw	h'07'		;インデックス値
		addlw	bcd_dd		;+ BCD カウンタの先頭番地
		movwf	FSR		;間接アドレスの先頭番地の設定

		btfsc	dsp_point,0	;奇数 か？
		goto	uppsw05		;Yes

		; 上位４ビットの処理

		movlw	h'10'
		addwf	INDF,F		;上位４ビット = インクリメント
		movlw	h'f0'
		andwf	INDF,W
		movwf	work

		movlw	2
		subwf	dsp_point,W
		btfss	STATUS,Z	;dsp_point = 2 か？
		goto	uppsw01		;No

		movlw	h'20'		;dsp_point = 2 の場合
		goto	uppsw03

uppsw01		btfss	dsp_point,2	;dsp_point = 4 or 6 か？
		goto	uppsw02		;No

		movlw	h'50'		;dsp_point = 4 or 6 の場合
		goto	uppsw03

uppsw02		movlw	h'90'		;dsp_point = 0 or 8 の場合

uppsw03		subwf	work,W		;work - W
		btfss	STATUS,C	;work < W か？
		goto	uppsw04		;Yes
		btfsc	STATUS,Z	;work = W か？
		goto	uppsw04		;Yes

		movlw	h'0f'
		andwf	INDF,F		;上位４ビット = h'0x'

uppsw04		swapf	INDF,W
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力
		goto	uppsw07

		; 下位４ビットの処理

uppsw05		incf	INDF,F		;下位４ビット = インクリメント
		movlw	h'0f'
		andwf	INDF,W
		sublw	h'09'		;h'09' - W
		btfsc	STATUS,C	;W =< h'09' か？
		goto	uppsw06		;Yes

		movlw	h'f0'
		andwf	INDF,F		;下位４ビット = h'x0'

uppsw06		movf	INDF,W
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力

uppsw07		return

;==========================================================================
;		↓(LOWER) 下スイッチの処理
;==========================================================================

lower_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swLO	;入力(LOWER ↓)スイッチ = ON か？
		goto	lowsw09		;No

		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 150ms

		rrf	dsp_point,W
		andlw	h'07'		;インデックス値
		addlw	bcd_dd		;+ BCD カウンタの先頭番地
		movwf	FSR		;間接アドレスの先頭番地の設定

		btfsc	dsp_point,0	;奇数 か？
		goto	lowsw06		;Yes

		; 上位４ビットの処理

		movlw	h'f0'
		andwf	INDF,W
		btfsc	STATUS,Z	;W = 0 か？
		goto	lowsw01		;Yes

		movlw	h'10'
		subwf	INDF,F		;上位４ビット = デクリメント
		goto	lowsw05

lowsw01		movlw	2
		subwf	dsp_point,W
		btfss	STATUS,Z	;dsp_point = 2 か？
		goto	lowsw02		;No

		movlw	h'20'		;dsp_point = 2 の場合
		goto	lowsw04

lowsw02		btfss	dsp_point,2	;dsp_point = 4 or 6 か？
		goto	lowsw03		;No

		movlw	h'50'		;dsp_point = 4 or 6 の場合
		goto	lowsw04

lowsw03		movlw	h'90'		;dsp_point = 0 or 8 の場合

lowsw04		addwf	INDF,F		;上位４ビット = h'2x' or h'5x' or h'9x'

lowsw05		swapf	INDF,W
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力
		goto	lowsw09

		; 下位４ビットの処理

lowsw06		movlw	h'0f'
		andwf	INDF,W
		btfsc	STATUS,Z	;W = 0 か？
		goto	lowsw07		;Yes

		decf	INDF,F		;下位４ビット = デクリメント
		goto	lowsw08

lowsw07		movlw	h'09'
		addwf	INDF,F		;下位４ビット = h'x9'

lowsw08		movf	INDF,W
		andlw	h'0f'
		iorlw	h'30'
		call	lcd_data	;LCD へデータを１文字出力

lowsw09		return

;==========================================================================
;		LCD 制御サブルーチン
;==========================================================================

		; LCD へコマンドを出力
lcd_cmd
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		goto	lcd01

		; LCD へデータを出力
lcd_data
		bsf	LCD,_RS		;RS = 1  (データモードに設定)
		nop

lcd01		bcf	LCD,_RW		;R/W = 0 (書き込みモードに設定)
		call	lcd_out		;上位４ビットを転送

		swapf	lcdtmp,W	;一時保存データの上位下位入れ替え
		call	lcd_out		;下位４ビットを転送

		call	lcd_busy	;LCD ビジーチェック
		return

		; ４ビット一回の送出
lcd_out
		movwf	lcdtmp		;コマンド／データを一時保存
		movlw	h'0f'		;下位４ビットの
		andwf	LCD,F		;コントロールポートの内容を残し
		movlw	h'f0'		;上位４ビットデータ
		andwf	lcdtmp,W	;を取り出して
		iorwf	LCD,F		;コントロールとＯＲ

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		nop			;E のパルス幅を220ns以上確保するため
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		return

		; LCD ビジーチェック
lcd_busy
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを入力ポート
		iorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		nop
		bsf	LCD,_RW		;R/W = 1 (読み込みモードに設定)

lcd_busy01	bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（上位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
;		andlw	h'f0'		;上位４ビット
		movwf	lcdtmp		;読み込みデータを一時保存
;		swapf	lcdtmp,F	;下位４ビットに移動

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（下位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
;		andlw	h'f0'		;上位４ビット
;		iorwf	lcdtmp,F	;上位４ビット + 下位４ビット
;		swapf	lcdtmp,F	;上位４ビットと下位４ビットを入れ替え
		btfsc	lcdtmp,_BF	;ビジーフラグのチェック (読み込みデータの７ビット目)
		goto	lcd_busy01	;_BF=0 になるまでループ

		bcf	LCD,_RW		;R/W = 0  (書き込みモードに設定)
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを出力ポートに戻す
		xorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		return

		; LCD 初期設定
lcd_init
		bcf	LCD,_RW		;R/W = 0 (書き込みモードに設定)
		nop
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		nop
		bcf	LCD,_E		;E = 0   (動作起動信号の設定)

		movlw	15
		call	wait_xxms	;wait 15ms （15ms以上を確保）
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		movlw	5
		call	wait_xxms	;wait 5ms （4.1ms以上を確保）
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定) 
		call	lcd_out		;上位４ビットを転送

		call	wait_100us
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		call	wait_100us
		movlw	b'00100000'	;ファンクションセット(4bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		call	wait_100us	;ここから 4bitモード
		movlw	b'00101000'	;ファンクションセット
		call	lcd_cmd		;DL=0: 4bit, N=1: 2行, F=0: 5x7ドット

		movlw	b'00001000'	;表示オン／オフコントロール
		call	lcd_cmd		;D=0: 表示オフ, C=0: カーソル非表示, B=0: 非ブリンク

		movlw	b'00000001'	;表示クリア
		call	lcd_cmd		;

		movlw	b'00000110'	;エントリーモードセット 
		call	lcd_cmd		;I/D=1: アドレスを+1しカーソルは右移動，S=0: 非シフト
		return

		; LCD からデータを入力

;<使用例>	movlw	h'80'		;読み出す DDRAM のアドレスをセット
;		call	lcd_cmd		;LCD へコマンドを出力
;		  :
;		call	lcd_data_rd	;LCD からデータを入力

lcd_data_rd
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを入力ポート
		iorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		bsf	LCD,_RS		;RS = 1  (データモードに設定)
		nop
		bsf	LCD,_RW		;R/W = 1 (読み込みモードに設定)

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（上位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		andlw	h'f0'		;上位４ビット
		movwf	lcdtmp		;読み込みデータを一時保存
		swapf	lcdtmp,F	;下位４ビットに移動

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（下位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		andlw	h'f0'		;上位４ビット
		iorwf	lcdtmp,F	;上位４ビット + 下位４ビット
		swapf	lcdtmp,F	;上位４ビットと下位４ビットを入れ替え

		bcf	LCD,_RW		;R/W = 0  (書き込みモードに設定)
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを出力ポートに戻す
		xorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0

		call	wait_100us
		movf	lcdtmp,W	;読み出しデータを W に移動
		return

		; LCD １行メッセージ表示

;<使用例>	movlw	h'80'		;表示位置の DDRAM のアドレスをセット
;		call	lcd_cmd		;LCD へコマンドを出力
;		movlw	high st_msg	;メッセージデータの先頭アドレスの high アドレス
;		movwf	addr_high	;
;		movlw	low st_msg	;メッセージデータの先頭アドレスの low アドレス
;		movwf	addr_low	;
;		call	lcd_disp	;メッセージデータ１行表示
;		  :
;st_msg		dt	"   StopW",0,"atch    ",0

lcd_disp
		call	tbl_read	;テーブルデータの読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新
		addlw	0
		btfsc	STATUS,Z	;h'00' か？
		return			;yes

		call	lcd_data	;LCD へデータを１文字出力
		goto	lcd_disp

		; テーブルデータの１文字読み出し
tbl_read
		movf	addr_high,W	;読み出すデータの high アドレス
		movwf	PCLATH
		movf	addr_low,W	;読み出すデータの low アドレス
		movwf	PCL

;==========================================================================
;		ブザー音出力ルーチン
;==========================================================================

		; "ブッ" ブザー音出力
buzzer_bu
		movlw	buh
		movwf	const_high	;音階用分周定数 high を設定
		movlw	bul
		movwf	const_low	;音階用分周定数 low を設定
		movlw	bulcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ピッ" ブザー音出力
buzzer_pi
		movlw	pih
		movwf	const_high	;音階用分周定数 high を設定
		movlw	pil
		movwf	const_low	;音階用分周定数 low を設定
		movlw	pilcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ポッ" ブザー音出力
buzzer_po
		movlw	poh
		movwf	const_high	;音階用分周定数 high を設定
		movlw	pol
		movwf	const_low	;音階用分周定数 low を設定
		movlw	polcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ピポッ" ブザー音出力
buzzer_pipo
		call	buzzer_pi	;"ピッ" ブザー音出力
		movlw	30
		call	wait_xxms
		call	buzzer_po	;"ポッ" ブザー音出力
		return

		; "ポッポッポッポッ" ブザー音出力
buzzer_po4
		movlw	4
		movwf	wt4cnt
po4		call	buzzer_po	;"ポッ" ブザー音出力
		movlw	30
		call	wait_xxms
		decfsz	wt4cnt,F
		goto	po4
		return

		; ブザー音出力コントロール
buzzer_control
		bsf	beepflg,0	;ビープ音フラグセット

		bsf	STATUS,RP0	;バンク 1
		bsf	PIE1,TMR1IE	;タイマー１割り込みを許可
		bcf	STATUS,RP0	;バンク 0

		call	wait_xxms	;入力 W: 音長（ループカウンタ）

		bsf	STATUS,RP0	;バンク 1
		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク 0

		bcf	beepflg,0	;ビープ音フラグリセット
		bcf	LCD,_END	;END 表示 LED 消灯
		return

;==========================================================================
;		ウェイト・ルーチン (20 MHz)
;==========================================================================

		; 100μ秒 ウェイトルーチン
wait_100us
		movlw	99		;1
		movwf	wt1cnt		;1
wait01		goto	$+1		;2
		decfsz	wt1cnt,F	;1,2
		goto	wait01		;2,0	1+1+(2+1+2)*98+(2+2+0)=496
;		goto	$+1		;2
		return			;2	496+2=498
					;       498/20MHz*4 = 99.6 μS = 100 μS = 0.1 mS

		; 1m 秒 ウェイトルーチン
wait_1ms
		movlw	10		;1
		movwf	wt2cnt		;1
wait02		call	wait_100us	;2	2+498=500
		decfsz	wt2cnt,F	;1,2
		goto	wait02		;2,0	1+1+(500+1+2)*9+(500+2+0)=5031
		return			;2	5031+2=5033
					;       5033/20MHz*4 = 1.0066 mS = 1 mS

		; 100m 秒 ウェイトルーチン
wait_100ms
		movlw	100

		; xx m 秒 ウェイトルーチン
wait_xxms
		movwf	wt3cnt		;1
wait03		call	wait_1ms	;2	2+5033=5035
		decfsz	wt3cnt,F	;1,2
		goto	wait03		;2,0	1+(5035+1+2)*(xx-1)+(5035+2+0)=5038*(xx)
		return			;2	5038*(xx)+2
					;

		; 500m 秒 ウェイトルーチン
wait_500ms
		movlw	5
		goto	wait04

		; 1 秒 ウェイトルーチン
wait_1sec
		movlw	10
wait04		movwf	wt4cnt

wait05		call	wait_100ms
		decfsz	wt4cnt,F
		goto	wait05
		return

;==========================================================================
;		割り込み処理
;==========================================================================

interrupt
		; レジスタの保存

		movwf	w_save		;W レジスタの保存
		swapf	STATUS,W
		clrf	STATUS
		movwf	s_save		;STATUS レジスタの保存
		movf	PCLATH,W
		movwf	p_save		;PCLATH レジスタの保存
		clrf	PCLATH
		movf	FSR,W
		movwf	f_save		;FSR レジスタの保存

		bcf	STATUS,RP0	;バンク 0
		bcf	STATUS,RP1
		btfss	PIR1,TMR1IF	;タイマ１オーバフロー か？
;		goto	init		;No. Reset(Illegal interrupt)
		goto	int02

		; タイマー１割り込み処理

		bcf	PIR1,TMR1IF	;タイマ１オーバフロー解除

		btfsc	beepflg,0	;ビープ音フラグセット か？
		goto	int01		;Yes

		movlw	basic_high	;
		movwf	TMR1H		;TMR1H に設定
		movlw	basic_low	;
		movwf	TMR1L		;TMR1L に設定

		btfss	SW,_swS		;SELECT スイッチ = STOPWATCH = ON('L') か？
		call	xxssmmhhdd_inc	;Yes, 日時分秒秒以下 BCD カウンタのインクリメント
		btfsc	SW,_swS		;SELECT スイッチ = TIMER = OFF('H') か？
		call	xxssmmhhdd_dec	;Yes, 日時分秒秒以下 BCD カウンタのデクリメント

		btfss	updtflg,1	;タイムアウトフラグ(タイマー処理で使用) = ON か？
		bsf	updtflg,0	;No, 更新フラグをセット
		goto	int02

int01		movf	const_high,W	;音階用分周定数 high を
		movwf	TMR1H		;TMR1H に設定
		movf	const_low,W	;音階用分周定数 low を
		movwf	TMR1L		;TMR1L に設定

		movlw	1 << _BZ	;ブザー音出力, 対象ビットをセット
		xorwf	LCD,F		;出力をビット反転

		; 割り込み処理の終了

int02		movf	f_save,W
		movwf	FSR		;FSR レジスタの復帰
		movf	p_save,W
		movwf	PCLATH		;PCLATH レジスタの復帰
		swapf	s_save,W
		movwf	STATUS		;STATUS レジスタの復帰
		swapf	w_save,F
		swapf	w_save,W	;W レジスタの復帰

		retfie			;割り込みからの復帰

;==========================================================================

		;      dspdigit2: bit7: 予備
		;		  bit6: 予備
		;		  bit5: 予備
		;		  bit4: 予備
		;		  bit3: 予備
		;		  bit2: 予備
		;		  bit1: "DH" 桁の指定
		;		  bit0: "DL" 桁の指定

		;	dspdigit: bit7: "HH" 桁の指定
		;		  bit6: "HL" 桁の指定
		;		  bit5: "MH" 桁の指定
		;		  bit4: "ML" 桁の指定
		;		  bit3: "SH" 桁の指定
		;		  bit2: "SL" 桁の指定
		;		  bit1: "XH" 桁の指定
		;		  bit0:  桁上がり指定

		; 日、時、分、秒、秒以下 BCD カウンタのインクリメント

xxssmmhhdd_inc
		clrf	dspdigit	;表示桁指定フラグの初期設定
		clrf	dspdigit2	;表示桁指定フラグの初期設定
		movlw	bcd_xx		;秒以下 BCD カウンタの番地
		movwf	FSR		;間接アドレスの先頭番地の設定
		call	inc_bcd		;秒以下 bcd_xx BCDインクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,1	;表示桁指定フラグ = "XH" 桁の指定
		movlw	h'a0'
		subwf	INDF,W
		btfss	STATUS,C	;bcd_xx >= h'a0' か？
		return			;No

		bsf	dspdigit,2	;表示桁指定フラグ = "SL" 桁の指定
		clrf	INDF		;bcd_xx = h'00'
		decf	FSR,F		;間接アドレスの更新
		call	inc_bcd		;秒 bcd_ss BCDインクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,3	;表示桁指定フラグ = "SH" 桁の指定
		movlw	h'60'
		subwf	INDF,W
		btfss	STATUS,C	;bcd_ss >= h'60' か？
		return			;No

		bsf	dspdigit,4	;表示桁指定フラグ = "ML" 桁の指定
		clrf	INDF		;bcd_ss = h'00'
		decf	FSR,F		;間接アドレスの更新
		call	inc_bcd		;分 bcd_mm BCDインクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,5	;表示桁指定フラグ = "MH" 桁の指定
		movlw	h'60'
		subwf	INDF,W
		btfss	STATUS,C	;bcd_mm >= h'60' か？
		return			;No

		bsf	dspdigit,6	;表示桁指定フラグ = "HL" 桁の指定
		clrf	INDF		;bcd_mm = h'00'
		decf	FSR,F		;間接アドレスの更新
		call	inc_bcd		;時 bcd_hh BCDインクリメント

;; (Ver. 1.04)	"HH"→"DL"の桁上がり時に誤表示されるのを修正
;;		"HL" 桁の更新時はすべて "HH" 桁も指定する
;;		btfsc	dspdigit,0	;桁上がり指定 = 1 か？	;;この行をコメント行にする

		bsf	dspdigit,7	;Yes, 表示桁指定フラグ = "HH" 桁の指定
		movlw	h'24'
		subwf	INDF,W
		btfss	STATUS,C	;bcd_hh >= h'24' か？
		return			;No

		bsf	dspdigit2,0	;表示桁指定フラグ = "DL" 桁の指定
		clrf	INDF		;bcd_hh = h'00'
		decf	FSR,F		;間接アドレスの更新
		call	inc_bcd		;日 bcd_dd BCDインクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit2,1	;表示桁指定フラグ = "DH" 桁の指定
		movlw	h'a0'
		subwf	INDF,W
		btfss	STATUS,C	;bcd_dd >= h'a0' か？
		return			;No

		clrf	INDF		;bcd_dd = h'00'
		return		

		; BCD インクリメント
inc_bcd
		bcf	dspdigit,0	;表示桁指定フラグ (桁上がり指定 = 0)
		incf	INDF,F		;+1 更新
		movf	INDF,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0a'
		btfss	STATUS,Z	;下位4ビット = h'0a' = 10 か？
		return			;No

		bsf	dspdigit,0	;表示桁指定フラグ (桁上がり指定 = 1)
		movlw	h'06'
		addwf	INDF,F		;下位4ビット = 0, 上位4ビット = +1
		return

;==========================================================================

		; 日、時、分、秒、秒以下 BCD カウンタのデクリメント

xxssmmhhdd_dec
		clrf	dspdigit	;表示桁指定フラグの初期設定
		clrf	dspdigit2	;表示桁指定フラグの初期設定
		movlw	bcd_xx		;秒以下 BCD カウンタの番地
		movwf	FSR		;間接アドレスの先頭番地の設定
		call	dec_bcd		;秒以下 bcd_xx BCDデクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,1	;表示桁指定フラグ = "XH" 桁の指定
		movf	INDF,W
		andlw	h'f0'		;上位4ビット
		sublw	h'f0'
		btfss	STATUS,Z	;上位4ビット = h'f0' か？
		return			;No

		movlw	h'99'
		movwf	INDF		;bcd_xx = h'99'
		bsf	dspdigit,2	;表示桁指定フラグ = "SL" 桁の指定
		decf	FSR,F		;間接アドレスの更新
		call	dec_bcd		;秒 bcd_ss BCDデクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,3	;表示桁指定フラグ = "SH" 桁の指定
		movf	INDF,W
		andlw	h'f0'		;上位4ビット
		sublw	h'f0'
		btfss	STATUS,Z	;上位4ビット = h'f0' か？
		return			;No

		movlw	h'59'
		movwf	INDF		;bcd_ss = h'59'
		bsf	dspdigit,4	;表示桁指定フラグ = "ML" 桁の指定
		decf	FSR,F		;間接アドレスの更新
		call	dec_bcd		;分 bcd_mm BCDデクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,5	;表示桁指定フラグ = "MH" 桁の指定
		movf	INDF,W
		andlw	h'f0'		;上位4ビット
		sublw	h'f0'
		btfss	STATUS,Z	;上位4ビット = h'f0' か？
		return			;No

		movlw	h'59'
		movwf	INDF		;bcd_mm = h'59'
		bsf	dspdigit,6	;表示桁指定フラグ = "HL" 桁の指定
		decf	FSR,F		;間接アドレスの更新
		call	dec_bcd		;時 bcd_hh BCDデクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit,7	;表示桁指定フラグ = "HH" 桁の指定
		movf	INDF,W
		andlw	h'f0'		;上位4ビット
		sublw	h'f0'
		btfss	STATUS,Z	;上位4ビット = h'f0' か？
		return			;No

		movlw	h'23'
		movwf	INDF		;bcd_hh = h'23'
		bsf	dspdigit2,0	;表示桁指定フラグ = "DL" 桁の指定
		decf	FSR,F		;間接アドレスの更新
		call	dec_bcd		;日 bcd_dd BCDデクリメント
		btfss	dspdigit,0	;桁上がり指定 = 1 か？
		return			;No

		bsf	dspdigit2,1	;表示桁指定フラグ = "DH" 桁の指定
		movf	INDF,W
		andlw	h'f0'		;上位4ビット
		sublw	h'f0'
		btfss	STATUS,Z	;上位4ビット = h'f0' か？
		return			;No

;		movlw	h'99'
;		movwf	INDF		;bcd_dd = h'99'
		bsf	updtflg,1	;タイムアウトフラグをセット
		return

		; BCD デクリメント
dec_bcd
		bcf	dspdigit,0	;表示桁指定フラグ (桁上がり指定 = 0)
		decf	INDF,F		;-1 更新
		movf	INDF,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0f'
		btfss	STATUS,Z	;下位4ビット = h'0f' か？
		return			;No

		bsf	dspdigit,0	;表示桁指定フラグ (桁上がり指定 = 1)
		movlw	h'06'
		subwf	INDF,F		;下位4ビット = 9, (上位4ビット = -1)
		return

;==========================================================================
;		EEPROM エリア
;==========================================================================

		org	h'2100'

eep_st		de	"Copyright (C) 2010-2017 by M.Yamamoto"

		de	h'ff'

eep_size	equ	$ - eep_st	;EEPROM データサイズ

;		de	h'ff'		;タイマー設定値の記録位置

		de	h'00',h'00',h'00',h'00',h'00'

;==========================================================================

		end			;プログラムの終了
