;***** PerpetualCalendar.asm **********************************************
;
;	グラフィック液晶表示 万年カレンダー
;
;	Copyright (C) 2014-2019   by M.Yamamoto. All rights reserved.
;
;     ( coding:  Ver. 0.00   2014/09/24  by M.Yamamoto )
;	coding:  Ver. 1.00   2014/11/07  初期バージョン打ち切り (未完成)
;	update:  Ver. 1.10   2014/11/23  PIC16F873A から PIC16F886 に変更
;	update:  Ver. 1.20   2014/12/19  LARGE モード画面の追加
;	update:  Ver. 1.21   2014/12/27  スイッチの操作性の改善
;	bugfix:  Ver. 1.30   2019/04/20  am/pm表示の不具合、他を修正
;
;******************************************************* PicAsm 0228 ******

;	Device: PIC16F886	Clock: 12.8MHz (クリスタルモジュール)

; Ver. 1.10
; ---------
; これまでいくつか同種のプログラムを作成してきた経験上で、今回のプログラムでも当初 CPU
; に、プログラムメモリのサイズが４Ｋワードの、 PIC16F873A を使用して開発を進めてきた。

; しかし、現在なお開発中で未完成にもかかわらず下記のように、従来のプログラムの２倍以上
; にもなって、残りのメモリが数百ワードとなってしまった。

; 今後もまだ機能アップを考えているので、とうてい４Ｋワード内に収まるはずもない。そこで
; この際、倍のサイズの８Ｋワードの CPU に変更することにした。

; PIC16F876 または PIC16F876A にしようかとも思ったが、最近入手したこれらの改良品である
; PIC16F886 を思い出し、初めてであるがこれを使ってみることにした。 

; (プログラム名)				(使用CPU)	(メモリサイズ)	(使用サイズ)

; MatrixLED_Clock	Ver. 2.30		PIC16F876	8,192		1,717
; Matrix57LED_Clock	Ver. 2.30		PIC16F873A	4,096		1,807
; NixieTubeClockII	Ver. 2.30		PIC16F873A	4,096		1,493
; PerpetualCalendar	Ver. 1.00 (未完成)	PIC16F873A	4,096		3,655

; ちなみに、本プログラムが大きくなった要因は、第一にグラフィック液晶に送るための文字フ
; ォントテーブルのサイズ (960 ワード) を含むことと、第二にグラフィック液晶を初めて使用
; することもあって、デモ表示のためのプログラミングに少々凝ってしまい、350 ワードほどを
; 費やしたこと、第三にこれは上記のどのプログラム内にも同じものであるが、サウンド・サブ
; ルーチン (430 ワードほど) を含むことなどがあげられる。

; Ver. 1.20
; ---------
; 画面表示をするのに従来の NORMAL モードに比べて、縦横２倍（面積４倍）のサイズで表示す
; る LARGE モードを追加した。

; LARGE モード関連のサブルーチンは、プログラムメモリ Page2 に収納して開発したが、それ
; でも LARGE モードの追加に伴って、Page0 の残りサイズが殆んど無くなって数ワードとなっ
; てしまったため、全体のソースを見直して、デモ関連のサブルーチンが残っていたのを Page1 
; に移した。

; これによって、現在、Page0 の残りサイズを 50ワード弱ほど確保できているので、今後の小
; さな変更には支障ないものと思われるが、その規模によっては一考が必要である。

;   (ページ)　(残りサイズ)	(主なプログラム)

;     Page0	     47		メイン, NORMALモード関連のサブルーチン, G_LCD.sub
;     Page1	    230		Font5x7.tbl, Sound.sub, デモ関連のサブルーチン
;     Page2	  1,064		LARGEモード関連のサブルーチン, LARGE用文字フォント
;     Page3	  2,048		(空き)

; 前バージョンから引き継いでいたバグ（NORMAL モードのカレンダー表示をしているときに、
; UP スイッチまたは DOWN スイッチを押すことによって、現在画面表示されている年月表示と
; カレンダー表示を、月ごとに前進、または後退させることができるが、このとき UP スイッチ
; または DOWN スイッチを連続的に何度も押していると、時々であるが画面が固まってしまって
; 時分秒の表示が止まり、スイッチ入力もまったく受け付けなくなってしまう事象）を修正した。
; 原因はスタックのオーバーフローであった。（詳細はホームページ上で報告）

; Ver. 1.21
; ---------
; LIGHT スイッチで、グラフィック液晶の LEDを ON→OFF または OFF→ON させたいのに、自分
; の意志とは違って、ON→OFF→ON または OFF→ON→OFF となってしまうときが時々ある。

; スイッチ入力の読み込み(sw_input)サブルーチン内では、250ms のウエイトを持たせてその間
; は、次のスイッチ入力を受け付けないようにしてあるが、それでも上記のようなことが時々起
; きるため、LIGHT スイッチの処理(light_switch)内にも 500ms のウエイトを置いた。すなわ
; ち 0.75秒経過しないと次のスイッチ入力を受け付けない。

; また SET モードのとき、NORMAL モードまたは LARGE モードに再び戻るため、最後の"秒"の
; 更新の後に SET スイッチを押したときに、やはり LIGHT スイッチのときと同じように、
; SET→NORMAL→LARGEモード または SET→LARGE→NORMALモードとなってしまうことが時々ある。

; そこでこれを回避するため、SET モードから戻る時に限り、フラグとカウンタを設けて約３秒
; 間は、新たな SET モード切り替えを受け付けないように変更した。

; また、MODE / SET スイッチで、NORMAL モードと LARGE モードを相互に切り替えたときの、
; 新モードの画面表示をさせるのに、MODE / SET スイッチの処理(set_switch)内で行っていた
; のを、メインルーチンで行うように改めた。

; その他 Page0 の残りエリアの確保のため、カレンダーデータのバックアップ (EEPROMへ書き
; 込み)(eeprom_write)を Page2 に移動した。

; Ver. 1.30
; ---------
; 下記<機能と使用法>の中で、１２時間(12H)表示と２４時間(24H)表示の対応において、↑位置
; に示す am/pmの表示が妥当でなかった不具合を修正した。下側に示すのが正解であり、修正前
; は作者の認識違いで、左↑位置のamと右↑位置のpmがそれぞれ逆に表示をしていた。

; 詳細は、ホームページ "７セグメントＬＥＤ表示時計" の "１２時間表示の扱いについて" の
; 項（http://xyama.sakura.ne.jp/hp/Clock7LED.html#12-hour）を参照のこと。

; 他に、Ver.1.20からVer.1.21へ更新したときに、デグレを起こしていたのを修正。LARGE モー
; ドにおいて、SIGNAL スイッチの押下時に、"Signal On" または "Signal Off" のメッセージ
; が表示されなくなってしまったのを、表示するように修正をした。

; 以下、デグレとは関係ないが、

; グラフィック液晶画面のバックライト用 LED の照明点灯の制御について、本機の起動直後は
; LED の点灯をデフォルトとしており、その後どのスイッチも操作しない状態が１５分以上続く
; と、自動的にバックライト用 LED を消灯させている。

; そして、再び点灯させるためには必ず LIGHT スイッチの操作が必要だったのを、どのスイッチ
; が操作されても点灯をするように修正をした。

; LIGHT スイッチの本来の機能である、OFF → ON または ON → OFF の押すごとに点灯と消灯を
; 交互に繰り返す、トグル動作については従来と変更はない。

; また、NORMAL モードにおいて、UP スイッチまたは DOWN スイッチの操作で、年月表示とカレ
; ンダー表示を、月ごとに前進、または後退をさせて表示することができる機能を持たせてある。

; そして、その表示中にも SET スイッチによって LARGE モードに切り替え、または SET モード
; への移行ができたが、しかし、これらの振る舞いは少々不都合なため、このときには SET スイ
; ッチの操作は無視をして、LARGE モードへの切り替え、または SET モードへの移行ができない
; ように修正をした。

; あくまでも、SET スイッチによる LARGE モードへの切り替え、または SET モードへの移行は、
; 年月表示とカレンダー表示が現在（本日）を表示している場合のみを可能と変更をした。

;--------------------------------------------------------------------------

#ifdef comment

 <機能と使用法>

　プログラム中のこの文章説明だけでは、その機能等を理解するのが少々難しいと思われるため、
　次のホームページ上で、多くの写真を加えた説明を用意したので、そちらをご覧いただきたい。

	ＵＲＬ： http://xyama.sakura.ne.jp/hp/PerpetualCalendar.html#usage

・本機の電源を投入すると、"ピポッ" と開始ブザー音を出力後、プログラムのタイトル、および
　バージョン番号などの表示とともに、グラフィック液晶のデモ表示が数秒間行われる。

			Perpetual Calendar
			   Version x.xx
			   by m.yamamoto

・グラフィック液晶のデモ表示が終了すると、本機の時計機能が開始され、液晶画面は時間表示
　とともにカレンダー表示に切り替わる。このとき表示される画面を、NORMAL モードと言う。

・初めて電源を投入するとカレンダーおよび時間は、"2014/11/01"、"00:00:00" と、本機をプ
　ログラミングしたときの設定値を表示するため、次の手順で現在の年月日、時分秒に設定し直
　す必要がある。

・なお、本機には操作するための押しボタンスイッチが６個あり、以下にその使用法を順に説明
　して行く。
　・ MODE / SET スイッチ
　・ UP スイッチ
　・ DOWN スイッチ
　・ ZERO / BACK スイッチ
　・ SIGNAL スイッチ
　・ LIGHT スイッチ

・設定手順の説明をする前に、Ver. 1.20 にて機能アップをしたので、そちらを先に少々触れる。

・上記のように、デモ表示の後 NORMAL モードに移行して、画面は通常の７曜カレンダー表示を
　するが、この状態のときに MODE / SET スイッチを押すと、画面は大きな文字が表示されるよ
　うになり、この状態を LARGE モードと言う。当然ながら文字が大きくなったため、７曜カレン
　ダー表示はできない。

・NORMAL モードと LARGE モードは、MODE スイッチを押すごとに交互にそのモードを切り替える
　ことができる。このように MODE スイッチをチョンと押して、NORMAL モードと LARGE モード
　を切り替えるのではなく、次のように長押しをすることにより、年月日、時分秒を希望値に設
　定変更することができるモードとなる。

・話を戻して設定手順は まず、MODE スイッチを数秒間押し続けると、画面右下のメッセージエ
　リアに "SET MODE" と反転表示されて、NORMAL モード、または LARGE モードから SET モード
　に切り替わったことを示し、年月日および時分秒の表示は更新が停止する。

・なお、このとき LARGE モードから SET モードに切り替わった場合には、メッセージエリアの
　確保のため、２行目（曜日、am/pm）の表示と３行目（時分秒）の表示が、以降 SET モードの
　間中は上部位置に移動して表示される。

・そこで MODE スイッチを放すと、メッセージは "Year Hi ?" に変わり、左上の年月 "xxxx/xx" 
　表示エリアの先頭２桁が反転表示されて、年の上位２桁の変更が可能となる。

・もし変更が必要であれば、UP スイッチを押すごとに現在値より１づつ増加し、また DOWN ス
　イッチを押すごとに１づつ減少するので、適宜希望する値に変更する。

・年の上位２桁の変更が済んだら、再び MODE / SET スイッチを押すとメッセージは "Year Lo ?" 
　に変わり、左上の年月 "xxxx/xx" 表示エリアの 年の下位２桁が反転表示され、年の下位２桁
　の変更が可能となる。

・同様に変更が必要であれば、UP スイッチまたは DOWN スイッチを押すことによって、適宜希
　望する値に変更する。

・以降、同様に SET スイッチを押すごとに、月 → 日 → 24H/12H → 時 → 分 → 秒 と設定
　項目を変更することができるので、変更が必要であればその該当項目の選択時に、UP スイッ
　チまたは DOWN スイッチを押すことによって、適宜希望する値に変更する。

・また、このときのメッセージエリアには、それぞれ "Month ?"、"Today ?"、"24H/12H ?"、
　"Hour ?"、"Minute ?"、"Second ?" と反転表示され、NORMAL モードでは１行目の該当項目
　の月、24H/12H、時、分、秒も反転表示されて選択項目を表す。LARGE モードにおいても位置
　は異なっているが、該当する項目が同様に反転表示される。

・選択項目の日 "xx" については、NORMAL モードでは７曜カレンダー内で該当日（本日）が反
　転点滅で表示されるので、同様に UP スイッチまたは DOWN スイッチによって、その位置を
　移動変更することにより選択をする。また、LARGE モードにおいては１行目の右端２桁が反
　転表示され、他の項目と同様に UP スイッチまたは DOWN スイッチを押すことによって、適
　宜希望する値に変更する。

・この SET スイッチによって項目を選択中に、誤って希望する項目を通り過ぎてしまったよう
　な場合には、BACK スイッチを押すごとにひとつづつ前の項目に戻ることができる。

・最後の秒の項目選択時に更に SET スイッチを押すと、SET モードから NORMAL モード、また
　は LARGE モードに再び切り替わり、今まで変更してきた設定値で年月日、時分秒の更新表示
　が再開される。

・SET モードでの選択項目の推移をまとめると次図のようになる。

　                              BACK            BACK  BACK  BACK       BACK  BACK  BACK
　            MODE               ←              ←    ←    ←         ←    ←    ←
　            /SET              SET             SET   SET   SET        SET   SET   SET   SET
　NORMALモード ─→ 年(上位２桁) → 年(下位２桁) → 月 → 日 → 24H/12H → 時 → 分 → 秒 ─→ NORMALモード
　(LARGEモード)          │                                                            ↑     (LARGEモード)
　                   BACK└──────────────────────────────┘

・ここで項目 24H/12H について補足をしておくと、これは時表示を 24時間表示にするか 12時
　間表示にするか、どちらかを選択することで、UP スイッチまたは DOWN スイッチのどちらか
　を押すことによって、交互に切り替えることができる。

・24H を選択した場合は、次項目に移った時に "24H/12H" 表示エリアには何も表示されないが、
　12H を選択した場合は、次項目に移った時に "am" または "pm" が、そのときの時 "xx" の設
　定値によって変更表示される。

・次に、１２時間表示と２４時間表示の対応を示す。なお、１２時間表示の場合だけ 時 "xx" 
　の先頭の１桁目は、ゼロサプレスを行なって表示をする。

　　　(24H)  00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23　┐            ;;
　　　(12H)  12  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11  │(←修正前)  ;;
　　　　　　 pm am am am am am am am am am am am am pm pm pm pm pm pm pm pm pm pm pm　┘            ;;
											            ;;Ver. 1.30 にて修正
　　　(24H)  00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23　┐            ;;
　　　(12H)  12  1  2  3  4  5  6  7  8  9 10 11 12  1  2  3  4  5  6  7  8  9 10 11  │(←修正後)  ;;
　　　       am am am am am am am am am am am am pm pm pm pm pm pm pm pm pm pm pm pm　┘            ;;
　　　       ↑                                  ↑

・以上のように、SET モードで年月日の設定変更を行うと、その値のバックアップがとられて次
　回（同一日であれば）に電源の投入をし直した時には、 その設定値で年月日、時分、および 
　00秒からスタートする。 また、年月日の設定変更を行なった場合ばかりでなく、 毎日日付が
　更新された時点でも、やはり同様に年月日、時分のバックアップがとられるため、次回に電源
　の投入をし直したときには、 そのバックアップ値で年月日、時分、および 00秒からスタート
　する。

・ZERO／BACK スイッチは、SET モードでは上記のように BACK スイッチとして機能するが、そ
　れ以外の NORMAL モード、および LARGE モードでは毎正時プラス・マイナス５分以内に押さ
　れると、00分00秒に設定するための ZERO スイッチとして機能する。

・また、NORMAL モードにおいての UP スイッチまたは DOWN スイッチの振る舞いは、それぞれ
　の項目の設定値を変更するのではなく、現在画面表示されている年月表示とカレンダー表示を、
　月ごとに前進、または後退させて表示する。なお、時分秒の時刻については、当然ながら現在
　時刻をきざみ続ける。

・このときメッセージエリアには、"←Down Up→" が表示され、かつ、"←Down" または "Up→" 
　のどちらかが反転表示されて、本日の年月日（現在位置）からどちらの方向に偏っているかを
　表している。本日の年月日にもどると、これらのメッセージは消えて７曜カレンダー内の該当
　日（本日）が反点表示される。

・なお、この "←Down Up→" が表示されているときには、SET スイッチの操作をしても無視され
　て、LARGE モードへの切り替え、または SET モードへの移行はできない。

・LARGE モードにおいては７曜カレンダー表示されることがないため、 UP スイッチまたは DOWN 
　スイッチを押しても、画面は何の変化もなく無視される。

・SIGNAL スイッチは、押すごとにメッセージエリアに "Signal On" と "Signal Off" を交互に
　数秒間表示し、毎時の時報音出力をブザーから鳴らすか止めるかを設定する。なお、電源を投
　入直後は "Signal On" の状態に設定されている。

・また、LARGE モードにおいては SET モードに切り替わったときと同様、メッセージエリアの
　確保のために２行目と３行目が上部位置に移動して表示される。

・LIGHT スイッチは、グラフィック液晶画面のバックライト用 LED の照明点灯を制御するもの
　で、押すごとに消灯と点灯を 交互に繰り返す。 また、どのスイッチも操作しない状態が１５
　分以上続くと、省エネのため自動的にバックライト用 LED は消灯する。

・なお、バックライト用 LED が消灯しているとき、どれかのスイッチが操作されると、再び点灯
　をする。

#endif

;--------------------------------------------------------------------------

;	PIC16F886 のピンと用途

;	  (1) MCLR: マスター・クリア入力	(28) RB7: G_LCD DB7 データバス入出力
;	  (2) RA0:  G_LCD /RES 信号出力		(27) RB6: G_LCD DB6 データバス入出力
;	  (3) RA1:  G_LCD R/W 信号出力		(26) RB5: G_LCD DB5 データバス入出力
;	  (4) RA2:  G_LCD E   信号出力		(25) RB4: G_LCD DB4 データバス入出力
;	  (5) RA3:  G_LCD CS1 信号出力		(24) RB3: G_LCD DB3 データバス入出力
;	  (6) RA4:  G_LCD CS2 信号出力		(23) RB2: G_LCD DB2 データバス入出力
;	  (7) RA5:  G_LCD D/I 信号出力		(22) RB1: G_LCD DB1 データバス入出力
;	  (8) VSS:  電源 GND			(21) RB0: G_LCD DB0 データバス入出力
;	  (9) OSC1: オシレータ水晶入力		(20) VDD: 電源 +5V DC
;	 (10) OSC2: オシレータ水晶入力		(19) VSS: 電源 GND
;	 (11) RC0:  SW0(MODE/SET) スイッチ入力 	(18) RC7: (ヨビ)
;	 (12) RC1:  SW1(UP) スイッチ入力 	(17) RC6: LEDコントロール出力
;	 (13) RC2:  SW2(DOWN) スイッチ入力 	(16) RC5: SW5(LIGHT) スイッチ入力
;	 (14) RC3:  SW3(ZERO/BACK) スイッチ入力 (15) RC4: SW4(SIGNAL) スイッチ入力／Bz出力

;==========================================================================

	list		p=pic16f886		;デバイス情報
	include		p16f886.inc		;インクルードファイル
	errorlevel	-302			;Eliminate bank warning

;==========================================================================
;		コンフィギュレーションの設定
;==========================================================================
 
;	__config _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF	;PIC16F873A, PIC16F876A のとき

	__config _CONFIG1, _HS_OSC & _WDT_OFF & _PWRTE_ON & _MCLRE_ON & _IESO_OFF & _FCMEN_OFF & _LVP_OFF
	__config _CONFIG2, _WRT_OFF

;==========================================================================
;		変数、定数の定義とレジスタ割付
;==========================================================================

		radix	dec

#define 	ver_no	"1.30"          ;バージョン番号: 1.30

;#define		sub_Glcd_Read
;#define		sub_Glcd_ReadStatus
;#define		sub_Glcd_ReadData
;#define		sub_Glcd_Pixel
;#define		sub_Glcd_Line
;#define		sub_Glcd_DispChr0
#define		sub_Glcd_DispChr
#define		sub_font_write
#define		sub_Glcd_DispStr
;#define		sub_Glcd_Image
;#define		sub_Glcd_Scroll
;#define		sub_Glcd_ScrollText

GL_INST		equ	PORTA		;G_LCD 制御用ポート
GL_T_INST	equ	TRISA		;G_LCD 制御用ポートの入出力切り替え
GL_DATA		equ	PORTB		;G_LCD データバス用ポート
GL_T_DATA	equ	TRISB		;G_LCD データバス用ポートの入出力切り替え

_G_RES		equ	0		;G_LCD /RES: L:リセット信号
_G_RW		equ	1		;G_LCD R/W:  H:読み出し／L:書き込み信号
_G_E		equ	2		;G_LCD E:    H→L:イネーブル信号
_G_CS1		equ	3		;G_LCD CS1:  H:チップセレクト信号 IC1
_G_CS2		equ	4		;G_LCD CS2:  H:チップセレクト信号 IC2
_G_DI		equ	5		;G_LCD D/I:  H:データ／L:インストラクション

sec1cnt		equ	d'3125'		;1秒 / (1/(12.8M/4) * 4(プリスケーラ値) * 256) = 3125
speaker		equ	4		;RC4: スピーカ

f_do		equ	d'262'		;ド	261.63Hz
f_do_		equ	d'277'		;ド＃	277.18Hz
f_re		equ	d'294'		;レ	293.66Hz
f_re_		equ	d'311'		;レ＃	311.13Hz
f_mi		equ	d'330'		;ミ	329.63Hz
f_fa		equ	d'349'		;ファ	349.23Hz
f_fa_		equ	d'370'		;ファ＃	369.99Hz
f_so		equ	d'392'		;ソ	392.00Hz
f_so_		equ	d'415'		;ソ＃	415.30Hz
f_ra		equ	d'440'		;ラ	440.00Hz
f_ra_		equ	d'466'		;ラ＃	466.16Hz
f_si		equ	d'494'		;シ	493.88Hz

f_doh		equ	d'523'		;ド	523.26Hz
f_doh_		equ	d'554'		;ド＃	554.36Hz
f_reh		equ	d'587'		;レ	587.32Hz
f_reh_		equ	d'622'		;レ＃	622.26Hz
f_mih		equ	d'659'		;ミ	659.26Hz
f_fah		equ	d'698'		;ファ	698.46Hz
f_fah_		equ	d'740'		;ファ＃	739.98Hz
f_soh		equ	d'784'		;ソ	784.00Hz
f_soh_		equ	d'831'		;ソ＃	830.60Hz
f_rah		equ	d'880'		;ラ	880.00Hz
f_rah_		equ	d'932'		;ラ＃	932.32Hz
f_sih		equ	d'988'		;シ	987.76Hz

f_do2		equ	d'1047'		;ド	1046.52Hz
f_do2_		equ	d'1109'		;ド＃	1108.72Hz
f_re2		equ	d'1175'		;レ	1174.64Hz
f_re2_		equ	d'1245'		;レ＃	1244.52Hz
f_mi2		equ	d'1319'		;ミ	1318.52Hz
f_fa2		equ	d'1397'		;ファ	1396.92Hz
f_fa2_		equ	d'1480'		;ファ＃	1479.96Hz
f_so2		equ	d'1568'		;ソ	1568.00Hz
f_so2_		equ	d'1661'		;ソ＃	1661.20Hz
f_ra2		equ	d'1760'		;ラ	1760.00Hz
f_ra2_		equ	d'1865'		;ラ＃	1864.64Hz
f_si2		equ	d'1976'		;シ	1975.52Hz

		cblock  h'20'
bcd_yh					;年(上位2桁) BCD カウンタ
bcd_yl					;年(下位2桁) BCD カウンタ
bcd_nn					;月 BCD カウンタ
bcd_dd					;日 BCD カウンタ
bcd_hh					;時 BCD カウンタ
bcd_mm					;分 BCD カウンタ
bcd_ss					;秒 BCD カウンタ
temp_yh					;退避用 年(上位2桁) BCD カウンタ
temp_yl					;退避用 年(下位2桁) BCD カウンタ
temp_nn					;退避用 月 BCD カウンタ
temp_dd					;退避用 日 BCD カウンタ
temp_hh					;仮の 時 BCD カウンタ
updtflg					;更新フラグ: bit0:時分秒更新済, 1:年月日更新要求, 3:EEPROM制御, 4:時分秒更新禁止
cnt_high				;１秒カウンタ high
cnt_low					;１秒カウンタ low
led_high				;LED 制御カウンタ high
led_low					;LED 制御カウンタ low	
timeflg					;時間表示フラグ  bit0=0:24H/1:12H, bit1=0:am/1:pm
blinkflg				;0.5,1秒表示反点滅タイミング
swstate					;スイッチの1:ON／0:OFF状態, bit0:SET, 1:UP, 2:DOWN, 3;ZERO/BACK, 4:SIGNAL, 5:LIGHT
sigflg					;時報音出力フラグ, bit0-2:カウンタ, 4:カウント許可, 5:予報音, 6:正報音, 7:出力許可
set_cnt					;SETモードカウンタ
saveflg					;bcd_xx → temp_xx へ退避中表示フラグ
modeflg					;モードフラグ  bit0=0:NORMALモード/1:LARGEモード, bit1=1:SETモード, bit2:main制御フラグ
					;              bit4-6:切り替え許可ダウンカウンタ, bit7=0:許可/1:禁止 ... (Ver.1.21で追加)
cur_yh					;年(上位2桁)(変) BCD カウンタ
cur_yl					;年(下位2桁)(変) BCD カウンタ
cur_nn					;月(変) BCD カウンタ
cur_dd					;日(変) BCD カウンタ
cur_week				;週位置カウンタ（曜日 0～6）
end_day					;各月の終了日（日数 28～31)
xxx_yh					; (改良)
uru_flag				;0:平年 / 1:閏年
sel_flag				;選択フラグ（bit7:年(上位)/6:年(下位)/5:月/4:カレンダ/3:(24H/am/pm)/2:時/1:分/0:秒）

wtcnt1					;ウェイト用ループカウンタ
wtcnt2					;ウェイト用ループカウンタ
lpcnt					;ループカウンタ
work1					;ワーク
work2					;ワーク

port_x					;5:PORTA, 6:PORTB, 7:PORTC, 8:PORTD, 9:PORTE
port_bit				;0:bit0,  1:bit1,  2:bit2,  3:bit3,  4:bit4,  5:bit5,  6:bit6,  7:bit7
freq_lo					;low  周波数(Hz)
freq_hi					;high
time_lo					;low  時間(ms)
time_hi					;high

wr_chip					;G_LCD 書き込み対象チップ: 1:左側選択 / 2:右側選択
wr_data					;G_LCD 書き込みデータ

gl_temp					;G_LCD への入出力データの一時保存
gl_temp1				;データの一時保存
gl_temp2				;データの一時保存
gl_chip					;1:左側選択 / 2:右側選択 / 3:左側と右側選択
gl_diflg				;0:インストラクション / 1:データ
gl_cnt1					;ループカウンタ1
gl_cnt2					;ループカウンタ2
gl_x					;X座標
gl_y					;Y座標
gl_on					;ドット 0:消灯 / 1:点灯
gl_tbl_h				;文字フォントデータ high アドレス
gl_tbl_l				;文字フォントデータ low  アドレス
addr_high				;文字列データ high アドレス
addr_low				;文字列データ low  アドレス
		endc

		cblock	h'60'
sound00					;
sound01					;ポートアドレス (5:PORTA, 6:PORTB, 7:PORTC, 8:PORTD, 9:PORTE)
sound02					;Sound出力ポートの bit 位置 (反転値)
sound03					;Sound出力ポートの bit 位置
sound04					;
sound05					;
sound06					;
sound07					;
sound08					;
sound09					;
sound0a					;
sound0b					;
sound0c					;

f_save					;FSR レジスタの退避用
		endc

		cblock	h'70'
sound70					;
sound71					;
sound72					;
sound73					;
sound74					;
sound75					;
sound76					;
sound77					;
sound78					;
sound79					;
sound7a					;
sound7b					;
sound7c					;

w_save					;W レジスタの退避用
s_save					;STATUS レジスタの退避用
p_save					;PCLATH レジスタの退避用
		endc

;==========================================================================
;		マクロ命令定義
;==========================================================================

;		Sound_Play_M マクロ

Sound_Play_M	macro	@frq,@tim
		movlw	low  @frq	;出力周波数(Hz)
		movwf	freq_lo
		movlw	high @frq
		movwf	freq_hi
		movlw	low  @tim	;出力時間(ms)
		movwf	time_lo
		movlw	high @tim
		movwf	time_hi
		call	sub_Sound_Play	;*(注) サウンドを鳴らす
		endm

;*(注). マクロの本体が少々大きくなってきたので、サブルーチン化した。

;==========================================================================
;		プログラム開始
;==========================================================================

		org	0		;リセットベクタ
		goto	init
		org	4		;割り込みベクタ
;		goto	interrupt

;==========================================================================
;		割り込み処理
;==========================================================================

interrupt
		; レジスタの保存

		movwf	w_save		;W レジスタの保存
		swapf	STATUS,W
		movwf	s_save		;STATUS レジスタの保存
		movf	PCLATH,W
		movwf	p_save		;PCLATH レジスタの保存
		movf	FSR,W
		movwf	f_save		;FSR レジスタの保存
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定

		btfsc	INTCON,T0IF	;タイマ０オーバフロー か？
		goto	t0int01		;Yes
		goto	int_end		;No

		; タイマー０割り込み

t0int01		bcf	INTCON,T0IF	;タイマ０オーバフロー解除

		incfsz	cnt_low,F	;１秒カウンタ cnt_low = +1 更新
		goto	$+2
		incf	cnt_high,F

		; 0.5秒 チェック	;1秒 / (1/(12.8M/4) * 4(プリスケーラ値) * 256) / 2 = 3125 / 2 = 1562

		movlw	low (sec1cnt / 2) ;low (h'0C35'/2 = h'061A' = d'3125'/2 = d'1562') = h'1A'
		subwf	cnt_low,W
		btfss	STATUS,Z	;１秒カウンタ cnt_low = h'1A' か？
		goto	t0int02		;No

		movlw	high (sec1cnt / 2) ;high (h'0C35'/2 = h'061A' = d'3125'/2 = d'1562') = h'06'
		subwf	cnt_high,W
		btfss	STATUS,C	;１秒カウンタ cnt_high >= h'06' か？
		goto	t0int02		;No

		movlw	b'00000010'
		xorwf	blinkflg,F	;0.5秒表示反点滅タイミング-1
		bsf	blinkflg,2	;0.5秒表示反点滅タイミング-2

		; 1秒 チェック		;1秒 / (1/(12.8M/4) * 4(プリスケーラ値) * 256) = 3125

t0int02		movlw	low sec1cnt	;low (h'0C35' = d'3125') = h'35'
		subwf	cnt_low,W
		btfss	STATUS,Z	;１秒カウンタ cnt_low = h'35' か？
		goto	int_end		;No

		movlw	high sec1cnt	;high (h'0C35' = d'3125') = h'0c'
		subwf	cnt_high,W
		btfss	STATUS,C	;１秒カウンタ cnt_high >= h'0c' か？
		goto	int_end		;No

		movlw	b'00000011'
		xorwf	blinkflg,F	;0.5秒表示反点滅タイミング-1, 1秒表示反点滅タイミング
		bsf	blinkflg,2	;0.5秒表示反点滅タイミング-2

		clrf	cnt_high	;１秒カウンタの初期設定
		clrf	cnt_low

		incfsz	led_low,F	;LED制御カウンタ +1 更新
		goto	$+2
		incf	led_high,F	;	

		btfsc	updtflg,4	;時分秒更新禁止フラグ = クリア か？
		goto	int_end		;No

	;;	call	bcd_ssmmhh_inc	;;時分秒 BCD カウンタのインクリメント
		goto	bcd_ssmmhh_inc	;;(Ver.1.20にて変更)

t0int03		call	time_signal	;時報音出力コントロール

		; 割り込み処理の終了

int_end		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			;割り込みからの復帰	

;--------------------------------------------------------------------------
;		時報音出力コントロール
;--------------------------------------------------------------------------

;  NHKの時報は、1000ミリ秒以上の無音、予報音3回、正報音1回、1000ミリ秒以上の無音という構成になっている。 
;  予報音は、一定音量の440Hzの正弦波を100ミリ秒発振させ、その後900ミリ秒の無音を置く。
;  これを1セットとして、正時の3秒前から3回繰り返している。
;  正報音は、880Hzの正弦波を発振させ、1000ミリ秒間一定の音量に保ち、次の2000ミリ秒で減衰させている。
;  出典: フリー百科事典『ウィキペディア（Wikipedia）』 ( http://ja.wikipedia.org/wiki/%E6%99%82%E5%A0%B1 )

;出力:		sigflg: 時報音出力フラグ ( bit0-bit3:カウンタ, bit4:カウント許可, bit5:予報音, bit6:正報音, bit7:出力許可 )
;		                                                                     *            *
time_signal
		btfss	sigflg,7	;時報音出力許可 か？
		goto	ts102		;No

		movlw	h'59'
		subwf	bcd_mm,W	;分 BCD カウンタ
		btfss	STATUS,Z	;bcd_mm = h'59' か？
		goto	ts101		;No

		movlw	h'57'
		subwf	bcd_ss,W	;秒 BCD カウンタ
		btfss	STATUS,C	;bcd_ss >= h'57' か？
		goto	ts101		;No

		; "プッ"		;予報音 (440Hz)
;		Sound_Play_M	f_rah, d'100'	; "プッ"
		bsf	sigflg,5	;予報音フラグのセット
		goto	ts102

ts101		movf	bcd_ss,W
		iorwf	bcd_mm,W
		btfss	STATUS,Z	;bcd_ss = bcd_mm = h'00' か？
		goto	ts102		;No

		; "ポッ～～ン"		;正報音 (880Hz)
;		Sound_Play_M	f_ra2, d'1000'	; "ポッ～～ン"
		bsf	sigflg,6	;正報音フラグのセット

ts102		return

;==========================================================================
;		初期化処理
;==========================================================================

init
		bcf	STATUS,RP0	;バンク 0
		clrf	PORTA
		clrf	PORTB
		clrf	PORTC
		clrf	ADCON0		;ADCON0 の設定, A/D 未使用

		bsf	STATUS,RP0	;バンク 1
		movlw	h'06'		;ポートA を すべてディジタルモード
		movwf	ADCON1		;ADCON1 の設定
		movlw	b'00000000'	;RA5-0: 出力
		movwf	TRISA
		movlw	b'00000000'	;RB7-0: 出力
		movwf	TRISB
		movlw	b'10111111'	;RC6: 出力, RC7,5-0: 入力
		movwf	TRISC
;		bsf	TRISC,speaker	;;音を出す直前まで入力ポートにしておく（雑音対策）
		movlw	b'11010001'	;PBPU=1: プルアップ抵抗を使用しない
					;INTEDG=1: RB0/INTピンの立ち上がりで割り込み
					;T0SE=1: RA4/T0CKIピンの立ち下がりでカウントアップ
					;PS=001: プリスケーラのスケール値 1:4
		movwf	OPTION_REG

		bsf	STATUS,RP1	;;バンク 3  ** PIC16F886 のとき必要 **
		clrf	ANSEL		;;
		clrf	ANSELH		;;
		bcf	STATUS,RP1	;;バンク 1

		bcf	STATUS,RP0	;バンク 0
		movlw	h'20'		;GIE=0: 全割り込み禁止, PEIE=0: 周辺機器割り込み禁止,
					;T0IE=1: タイマー(TMR0)オーバーフロー割り込み許可
		movwf	INTCON

		call	Glcd_Init	;グラフィック LCD の初期設定

		movlw	PORTC		;7:PORTC
		movwf	port_x
		movlw	speaker		;7:bit7
		movwf	port_bit

		bsf	PCLATH,3	;Page 1
		call	Sound_Init	;サウンドの初期化
		bcf	PCLATH,3	;Page 0
		clrf	sigflg		;時報音出力フラグのクリア
		bsf	sigflg,7	;時報音出力許可

		movlw	h'40'
		movwf	PORTC		;グラフィック液晶の LED = 点灯

		; EEPROM データ（カレンダーデータのバックアップ）の読み出し
		;( bcd_yh, bcd_yl, bcd_nn, bcd_dd, bcd_hh, bcd_mm, timeflg )

		movlw	bcd_yh		;bcd_yh のアドレス
		movwf	FSR

		movlw	6		;bcd_yh ～ bcd_mm
		movwf	lpcnt		;ループカウンタを設定

		bsf	STATUS,RP1	;バンク 2
		movlw	eep_size	;EEPROM 格納先頭アドレス
		movwf	EEADR		;EEPROM の記録アドレスを設定

ini01		bsf	STATUS,RP1	;バンク 2
		bsf	STATUS,RP0	;バンク 3
		bsf	EECON1,RD	;読み出し制御 = ON
		bcf	STATUS,RP0	;バンク 2
		movf	EEDATA,W	;データの読み出し
		incf	EEADR,F		;EEPROM アドレス +1 更新

		bcf	STATUS,RP1	;バンク 0
		movf	lpcnt,F
		btfsc	STATUS,Z	;終了 か？
		goto	ini02		;Yes

		movwf	INDF		;bcd_yh ～ bcd_mm を設定
		incf	FSR,F		;間接アドレス +1 更新
		decf	lpcnt,F		;ループカウンタ - 1
		goto	ini01		;No

ini02		movwf	timeflg		;timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

		clrf	bcd_ss		;時 BCD カウンタの初期設定 (00秒)
		clrf	cnt_high	;１秒カウンタの初期設定
		clrf	cnt_low
		clrf	updtflg		;更新フラグの初期設定
		bsf	INTCON,GIE	;全割り込み禁止解除

;==========================================================================
;		メイン処理への前準備
;==========================================================================

		; プログラム名と Ver番号の表示

		call	buzzer_pipo	;"ピポッ" ブザー音出力

		movlw	high prog_title	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low prog_title	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;
		goto	pre01

prog_title	dt	"Perpetual Calendar",0
		dt	"Version ",ver_no,0
		dt	"by m.yamamoto",0

pre01		movlw	1
		movwf	gl_x		;X座標
		movlw	1
		movwf	gl_y		;Y座標
		call	Glcd_DispStr	;１行目の表示

		movlw	4
		movwf	gl_x		;X座標
		movlw	3
		movwf	gl_y		;Y座標
		call	Glcd_DispStr	;２行目の表示

		movlw	4
		movwf	gl_x		;X座標
		movlw	6
		movwf	gl_y		;Y座標
		call	Glcd_DispStr	;３行目の表示

		; 縁枠のデモ表示

		call	edge_frame_on	;上下左右縁枠の表示
		movlw	2
		call	wait_xs		;2 秒間のウエイト

		call	edge_frame_off	;上下左右縁枠の消去
		call	wait_1s		;1 秒間のウエイト

		bsf	PCLATH,3	;Page 1
		call	demo_display	;デモの表示
		bcf	PCLATH,3	;Page 0
		call	wait_1s		;1 秒間のウエイト

		call	edge_frame_on	;上下左右縁枠の表示
		call	wait_1s		;1 秒間のウエイト

		call	edge_frame_off	;上下左右縁枠の消去
		call	wait_1s		;1 秒間のウエイト

		call	edge_frame_on	;上下左右縁枠の表示
		call	wait_1s		;1 秒間のウエイト

		call	edge_frame_off	;上下左右縁枠の消去
		call	wait_1s		;1 秒間のウエイト

		call	edge_frame_on	;上下左右縁枠の表示
		movlw	3
		call	wait_xs		;3 秒間のウエイト

		; カレンダー表示の準備

		call	glcd_all_clear	;全画面消去

		movlw	2
		call	wait_xs		;2 秒間のウエイト

		clrf	bcd_ss		;秒 BCD カウンタの初期設定
		clrf	cnt_high	;１秒カウンタの初期設定
		clrf	cnt_low
		clrf	updtflg
		bsf	updtflg,0	;更新フラグの初期設定
		clrf	sel_flag	;選択フラグの初期設定
		clrf	swstate		;スイッチのON／OFF状態の初期設定
		clrf	saveflg		;bcd_xx → temp_xx へ退避中表示フラグの初期設定
		clrf	modeflg		;モードフラグ(bit0=0:NORMALモード)の初期設定
		goto	main

;--------------------------------------------------------------------------

;		サウンドを鳴らす (Sound_Play_M マクロの本体)

sub_Sound_Play
		bsf	STATUS,RP0	;バンク 1
		bcf	TRISC,speaker	;音出しの直前に出力ポートにする（雑音対策）
		bcf	STATUS,RP0	;バンク 0

		bsf	PCLATH,3	;Page 1
		call	Sound_Play	;サウンドを鳴らす
		bcf	PCLATH,3	;Page 0
		bsf	PORTC,speaker	;*(注1)
		movlw	3		;*(注2)
		call	wait_x1ms	;ウエイト

		bsf	STATUS,RP0	;バンク 1
		bsf	TRISC,speaker	;再び入力ポートにしておく（雑音対策）
		bcf	STATUS,RP0	;バンク 0
		return

; *(注1). "H" を出力しておかないと、次に入力ポートに設定したときに、"L" を検出して
;         スイッチが ON 状態と誤解釈をしてしまう。
; *(注2). また、このウエイトも必ず必要で、無いと同状態となる。値的にはどれほどが
;         妥当かわからないが、とりあえず 3ms とした。（1ms でもＯＫだった）

;--------------------------------------------------------------------------

;		"ピポッ" ブザー音出力

buzzer_pipo
		Sound_Play_M	f_soh, d'100'	;"ピッ" ブザー音出力
		movlw	d'30'
		call	wait_x1ms
		Sound_Play_M	f_do2, d'100'	;"ポッ" ブザー音出力
		return

;--------------------------------------------------------------------------

;		1 秒 ウェイトルーチン

wait_1s
		movlw	1

;		秒単位 ウェイトルーチン

;入力:		W: 秒数

wait_xs
		movwf	lpcnt		;W 秒間のウエイト
		clrf	bcd_ss

wts01		movf	lpcnt,W		;秒単位のウエイト
		subwf	bcd_ss,W
		btfss	STATUS,C	;秒 BCD カウンタ >= lpcnt(秒数) か？
		goto	wts01		;No

		return

;--------------------------------------------------------------------------

;		上下左右縁枠の表示

edge_frame_on
		movlw	1
		movwf	gl_on		;0:縁枠の消去 / 1:縁枠の表示
		bsf	PCLATH,3	;Page 1
		call	edge_frame	;上下左右縁枠の表示
		bcf	PCLATH,3	;Page 0
		return

;		上下左右縁枠の消去

edge_frame_off
		clrf	gl_on		;0:縁枠の消去 / 1:縁枠の表示
		bsf	PCLATH,3	;Page 1
		call	edge_frame	;上下左右縁枠の消去
		bcf	PCLATH,3	;Page 0
		return

;		全画面消去

glcd_all_clear
		movlw	3
		movwf	gl_chip		;3: 左側と右側を選択
		clrw
		call	Glcd_Clear	;画面消去
		return

;==========================================================================
;		メイン・ルーチン
;==========================================================================

;modeflg: モードフラグ ( bit0=0:NORMALモード/1:LARGEモード, bit1=1:SETモード, bit2:main制御フラグ 
;			 bit4-6:切り替え許可ダウンカウンタ, bit7=0:許可/1:禁止 )	 ... (Ver.1.21で追加)
;updtflg: 更新フラグ   ( bit0:時分秒更新済 / bit1:年月日更新要求 / bit3:EEPROM制御 / bit4:時分秒更新禁止 )
;swstate: スイッチの 1:ON／0:OFF状態  ( bit0:SET, 1:UP, 2:DOWN, 3;ZERO/BACK, 4:SIGNAL, 5:LIGHT )

main
		bcf	modeflg,2	;main制御フラグのクリア(SIGNALスイッチ処理)
	;;	call	glcd_all_clear	;全画面消去			;;(Ver.1.30で削除、set_switch 内で行う、Ver.1.21のデグレを修正)
		call	week_display	;曜日タイトルの表示
		call	yyyymm_display	;年月 (yyyy/mm) の表示

main01		call	calendar_display ;カレンダーの表示

main02		btfss	updtflg,0	;時分秒更新済フラグ = ON か？
		goto	main04		;No

		call	time_display	;時分秒 (hh:mm:ss) の表示
		call	ampm_display	;(  /am/pm) の表示
		bcf	updtflg,0	;時分秒更新済フラグのクリア

		; 時報音の出力制御

;		btfss	sigflg,7	;時報音出力許可 か？
;		goto	main04		;No

		btfss	sigflg,5	;時報音出力フラグ = 予報音か？
		goto	main03		;No

		Sound_Play_M	f_rah, d'100'	; "プッ"
		bcf	sigflg,5	;予報音フラグのクリア
		goto	main04

main03		btfss	sigflg,6	;時報音出力フラグ = 正報音か？
		goto	main04		;No

		Sound_Play_M	f_ra2, d'1000'	; "ポッ～～ン"
		bcf	sigflg,6	;正報音フラグのクリア

		; カレンダーデータのバックアップ

main04		btfss	updtflg,3	;EEPROM制御フラグ = ON か？
		goto	main05		;No

		bsf	PCLATH,4	;Page 2	 ... (Ver.1.21で Page 2 へ移動)
		call	eeprom_write	;No. カレンダーデータのバックアップ (EEPROMへ書き込み)
		bcf	PCLATH,4	;Page 0

		; グラフィック液晶の LED制御

main05		movlw	low (60 * 15)	;low (d'900' = h'384') = h'84'
		subwf	led_low,W
		btfss	STATUS,Z	;LED制御カウンタ led_low = h'84' か？
		goto	main06		;No

		movlw	high (60 * 15)	;high (d'900' = h'384') = h'03'
		subwf	led_high,W
		btfss	STATUS,Z	;LED制御カウンタ led_high = h'03' か？
		goto	main06		;No

		bcf	PORTC,6		;グラフィック液晶の LED = 滅灯

		; 年月日の更新

main06		btfss	updtflg,1	;年月日更新要求フラグ = ON か？
		goto	main07		;No

		bcf	updtflg,1	;年月日更新要求フラグのクリア
		bsf	updtflg,3	;EEPROM制御要求フラグのセット

		call	bcd_dd_inc	;日 BCD カウンタのインクリメント
		movlw	h'01'
		subwf	bcd_dd,W
		btfss	STATUS,Z	;日 BCD カウンタ = h'01' か？
		goto	main01		;No

		call	bcd_nn_inc	;月 BCD カウンタのインクリメント
		movlw	h'01'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'01' か？
		goto	main		;No

		call	bcd_yl_inc	;年(下位2桁) BCD カウンタのインクリメント
		movf	bcd_yl,W
		btfss	STATUS,Z	;年(下位2桁) BCD カウンタ = h'00' か？
		goto	main		;No

		call	bcd_yh_inc	;年(上位2桁) BCD カウンタのインクリメント
		goto	main

		; スイッチの ON／OFF 状態フラグのチェック

main07		call	sw_input	;スイッチ入力の読み込み

		call	change_count	;NORMAL / LARGE モード切り替え
					; = 禁止中の処理		;(Ver.1.21で追加)
		btfsc	swstate,0	;MODE / SETスイッチ = OFF か？
	;;	call	set_switch	;No. MODE / SETスイッチの処理	;; LARGEモードのとき、スタックがオーバ
		goto	set_switch	;				;; ーフローするのため、call が使えない
main08									;; goto で飛び goto で戻る (1/5)
		btfsc	swstate,1	;UPスイッチ = OFF か？
	;;	call	up_switch	;No. UPスイッチの処理
		goto	up_switch
main09
		btfsc	swstate,2	;DOWNスイッチ = OFF か？
	;;	call	down_switch	;No. DOWNスイッチの処理
		goto	down_switch
main10
		btfsc	swstate,3	;ZEROスイッチ = OFF か？
		call	zero_switch	;No. ZEROスイッチの処理

		btfsc	swstate,4	;SIGNALスイッチ = OFF か？
		call	signal_switch	;No. SIGNALスイッチの処理

		btfsc	swstate,5	;LIGHTスイッチ = OFF か？
		call	light_switch	;No. LIGHTスイッチの処理

		call	disp_count	;SIGNALメッセージ表示時間のカウントとメッセージエリアのクリア

		btfss	modeflg,2	;main制御フラグ = ON か？
		goto	main02		;No
		goto	main		;Yes

;--------------------------------------------------------------------------

;		スイッチ入力の読み込み

;出力:		swstate: スイッチの1:ON／0:OFF状態, ( bit0:SET, 1:UP, 2:DOWN, 3;ZERO/BACK, 4:SIGNAL, 5:LIGHT )

sw_input
		movf	PORTC,W		;一度に各スイッチ入力を読み込み
		andlw	h'bf'		;スイッチ入力だけの
		xorlw	h'bf'		;反転値を取り出して
		movwf	swstate		;保存する
		btfss	STATUS,Z	;すべてのスイッチ = OFF か？
		goto	swin01		;No

		clrf	set_cnt		;SETモードカウンタのクリア
		goto	swin02

swin01		clrf	led_high	;LED制御カウンタのクリア
		clrf	led_low		;

		btfss	swstate,5	;LIGHTスイッチ = ON か？		;;(Ver.1.30 で追加)
		bsf	PORTC,6		;No. グラフィック液晶の LED = 点灯	;;

		movlw	d'250'
		call	wait_x1ms	;チャタリング吸収

swin02		return

;--------------------------------------------------------------------------

;		NORMAL / LARGE モード切り替え = 禁止中の処理 ... (Ver.1.21で追加)

change_count
		btfss	modeflg,7	;モード切り替え = 禁止 か？
		goto	chg01		;No. 許可中

		btfss	blinkflg,2	;0.5秒表示反点滅タイミング-2 = ON か？
		goto	chg01		;No

		bcf	blinkflg,2	;0.5秒表示反点滅タイミング-2 のクリア
	;	swapf	modeflg,F	;カウンタ部分を下位4bitに移動
	;	decf	modeflg,F	;切り替え許可ダウンカウンタ -1 更新
	;	movlw	h'07'
	;	andwf	modeflg,W	;ダウンカウンタを取り出す
	;	swapf	modeflg,F	;元に戻す
		movlw	h'10'
		subwf	modeflg,F	;切り替え許可ダウンカウンタ - h'10' 更新
		movlw	h'70'
		andwf	modeflg,W	;ダウンカウンタを取り出す
		btfss	STATUS,Z	;ダウンカウンタ = 0 (3～3.5秒経過) か？
		goto	chg01		;No

		bcf	modeflg,7	;bit7: モード切り替え = 許可 にセット

chg01		return

;==========================================================================
;		MODE / SET スイッチの処理
;==========================================================================

;選択フラグ sel_flag:（ bit7:年(上位) / 6:年(下位) / 5:月 / 4:日 / 3:24H/12H / 2:時 / 1:分 / 0:秒 ）
;モードフラグ modeflg:  bit0=0:NORMALモード/1:LARGEモード, bit1=1:SETモード, bit2:main制御フラグ
;			bit4-6:切り替え許可ダウンカウンタ, bit7=0:許可/1:禁止 ... (Ver.1.21で追加)

set_switch
		btfsc	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグのセット か？	;;(Ver.1.30 で追加)
		goto	set42		;Yes							;;

		btfss	PORTC,0		;SETスイッチ = OFF か？
		goto	set01		;No

		; NORMALモード / LARGEモード の切り替えの判定

		movlw	d'100'
		call	wait_x1ms	;ウエイト

		btfsc	modeflg,7	;モード切り替え = 許可  か？
		goto	set42		;No. 禁止中

		movlw	h'01'
		xorwf	modeflg,F	;bit0: 0:NORMALモード / 1:LARGEモード の切り替え
		goto	set41

		; SETモードに移行するかどうかの判定

set01		btfss	blinkflg,2	;0.5秒表示反点滅タイミング-2 = ON か？
		goto	set42		;No

		bcf	blinkflg,2	;0.5秒表示反点滅タイミング-2 のクリア
		incf	set_cnt,F	;SETモードカウンタの更新
		movlw	7
		subwf	set_cnt,W
		btfss	STATUS,Z	;SETモードカウンタ = 7 (3～3.5秒経過) か？
		goto	set42		;No

	;;	bcf	INTCON,GIE	;全割り込み禁止
		bsf	updtflg,4	;時分秒更新禁止フラグのセット

		clrf	set_cnt		;SETモードカウンタのクリア
		bsf	modeflg,1	;SETモードにセット
		btfss	modeflg,0	;1:LARGEモード か？
		goto	set02		;No. 0:NORMALモード

		call	glcd_all_clear	;全画面消去		;LARGEモードのとき
		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダー（日と曜日）の表示
		call	ampm_display	;24H / 12H の表示

set02		call	time_display	;時分秒 (hh:mm:ss) の表示
		call	setmode_display	;SETモードメッセージの表示

		btfss	PORTC,0		;SETスイッチ = OFF か？
		goto	$ - 1		;No

		movlw	d'100'
		call	wait_x1ms	;ウエイト

		btfss	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグ = セット か？
		goto	set03		;No

		call	date_return	;年(上位2桁), 年(下位2桁), 月, 日 BCD カウンタ の復帰
		goto	set04

set03		call	date_save	;年(上位2桁), 年(下位2桁), 月, 日 BCD カウンタ の退避
		bcf	saveflg,0	;SET処理内では不要なので退避中表示フラグをクリアしておく

		; 年(上位)の変更処理

set04		clrf	sel_flag
		bsf	sel_flag,7	;選択フラグ = 7: 年(上位)
		call	inquiry_display	;質問メッセージの表示

set05		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダーの表示更新

set06		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set36		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set09		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set07		;No

		call	bcd_yh_inc	;年(上位2桁) BCD カウンタのインクリメント
		goto	set08

set07		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set06		;No

		call	bcd_yh_dec	;年(上位2桁) BCD カウンタのデクリメント

set08		movf	bcd_yh,W
		iorwf	bcd_yl,W
		btfss	STATUS,Z	;年(4桁) BCD カウンタ = '0000' か？
		goto	set05		;No

		movlw	h'01'
		movwf	bcd_yl		;(0000) → 0001
		goto	set05

		; 年(下位)の変更処理

set09		clrf	sel_flag
		bsf	sel_flag,6	;選択フラグ = 6: 年(下位)
		call	inquiry_display	;質問メッセージの表示

set10		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダーの表示更新

set11		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set04		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set14		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set12		;No

		call	bcd_yl_inc	;年(下位2桁) BCD カウンタのインクリメント
		goto	set13

set12		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set11		;No

		call	bcd_yl_dec	;年(下位2桁) BCD カウンタのデクリメント

set13		movf	bcd_yh,W
		iorwf	bcd_yl,W
		btfss	STATUS,Z	;年(4桁) BCD カウンタ = '0000' か？
		goto	set10		;No

		movlw	h'01'
		movwf	bcd_yl		;(0000) → 0001
		goto	set10

		; 月の変更処理

set14		clrf	sel_flag
		bsf	sel_flag,5	;選択フラグ = 5: 月
		call	inquiry_display	;質問メッセージの表示

set15		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダーの表示更新

set16		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set09		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set19		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set17		;No

		call	bcd_nn_inc	;月 BCD カウンタのインクリメント
		goto	set18

set17		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set16		;No

		call	bcd_nn_dec	;月 BCD カウンタのデクリメント

set18		call	month_days	;各月の日数計算
		subwf	bcd_dd,W
		btfss	STATUS,C	;日 BCD カウンタ < 各月の最終日 か？
		goto	set15		;Yes

		btfsc	STATUS,Z	;日 BCD カウンタ = 各月の最終日 か？
		goto	set15		;Yes

		movlw	h'01'
		movwf	bcd_dd		;日 BCD カウンタ = h'01' 設定
		goto	set15

		; 日の変更処理

set19		clrf	sel_flag
		call	yyyymm_display	;年月 (yyyy/mm) の再表示 (SET時対策)
		call	ampm_display	;( /am/pm) の再表示 (BACK時対策)

		bsf	sel_flag,4	;選択フラグ = 4: 日
		call	inquiry_display	;質問メッセージの表示

set20		call	calendar_display ;カレンダーの表示

set21		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set14		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set24		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set22		;No

		call	bcd_dd_inc	;日 BCD カウンタのインクリメント
		goto	set20

set22		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set23		;No

		call	bcd_dd_dec	;日 BCD カウンタのデクリメント
		goto	set20

set23		btfss	blinkflg,2	;0.5秒表示反点滅タイミング-2 = ON か？
		goto	set21		;No

		bcf	blinkflg,2	;0.5秒表示反点滅タイミング-2 クリア
		goto	set20		;Yes

		; 24H / 12H の変更処理
;		timeflg(時間表示フラグ):  bit0 = 0:24H / 1:12H

set24		clrf	sel_flag
		call	calendar_display ;カレンダーの再表示 (SET対策)

		bsf	sel_flag,3	;選択フラグ = 3: 24H/12H
		call	inquiry_display	;質問メッセージの表示

set25		call	ampm_display	;24H / 12H の表示
		call	time_display	;時分秒 (hh:mm:ss) の表示

set26		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set19		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set28		;No

		btfsc	swstate,1	;UPスイッチ = OFF か？
		goto	set27		;No

		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set26		;No

set27		movlw	h'01'
		xorwf	timeflg,F	;timeflg: 時間表示フラグの更新
		goto	set25

		; 時の変更処理

set28		clrf	sel_flag
		bsf	sel_flag,2	;選択フラグ = 2: 時
		call	inquiry_display	;質問メッセージの表示

set29		call	time_display	;時分秒 (hh:mm:ss) の表示
		call	ampm_display	;( /am/pm) の表示

set30		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set24		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set32		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set31		;No

		call	bcd_hh_inc	;時 BCD カウンタのインクリメント
		goto	set29

set31		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set30		;No

		call	bcd_hh_dec	;時 BCD カウンタのデクリメント
		goto	set29

		; 分の変更処理

set32		clrf	sel_flag
		bsf	sel_flag,1	;選択フラグ = 1: 分
		call	inquiry_display	;質問メッセージの表示

set33		call	time_display	;時分秒 (hh:mm:ss) の表示

set34		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set28		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set36		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set35		;No

		call	bcd_mm_inc	;分 BCD カウンタのインクリメント
		goto	set33

set35		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set34		;No

		call	bcd_mm_dec	;分 BCD カウンタのデクリメント
		goto	set33

		; 秒の変更処理

set36		clrf	sel_flag
		call	yyyymm_display	;年月 (yyyy/mm) の再表示 (BACK時対策)

		bsf	sel_flag,0	;選択フラグ = 0: 秒
		call	inquiry_display	;質問メッセージの表示

set37		call	time_display	;時分秒 (hh:mm:ss) の表示

set38		call	sw_input	;スイッチ入力の読み込み
		btfsc	swstate,3	;BACKスイッチ = OFF か？
		goto	set32		;No

		btfsc	swstate,0	;SETスイッチ = OFF か？
		goto	set40		;No

		btfss	swstate,1	;UPスイッチ = ON か？
		goto	set39		;No

		call	bcd_ss_inc	;秒 BCD カウンタのインクリメント
		goto	set37

set39		btfss	swstate,2	;DOWNスイッチ = ON か？
		goto	set38		;No

		call	bcd_ss_dec	;秒 BCD カウンタのデクリメント
		goto	set37

		; 年(上位2桁, 下位2桁), 月, 日, 時の 変更有無の判定

set40		call	date_check	;変更有無チェック
		btfss	STATUS,Z	;変更無し か？
		bsf	updtflg,3	;No. EEPROM制御要求フラグのセット

		clrf	sel_flag	;選択フラグをクリア
		bsf	updtflg,0	;時分秒更新済フラグのセット（無条件）
		clrf	cnt_high	;１秒カウンタの初期設定
		clrf	cnt_low
		bcf	modeflg,1	;SETモードをクリア

	;;	bsf	INTCON,GIE	;全割り込み禁止解除
		bcf	updtflg,4	;時分秒更新禁止フラグのクリア

		movlw	h'f0'		;				;(Ver.1.21で追加)
		iorwf	modeflg,F	;bit7 = 1: モード切り替えフラグ = 禁止, bit6-4 = 7: ダウンカウンタ のセット

		btfsc	modeflg,0	;0:NORMALモード か？
		goto	set41		;No

		call	inquiry_display	;質問メッセージエリアのクリア
		goto	set42

		; 新モードの画面表示

set41		call	glcd_all_clear	;全画面消去			;;(Ver.1.30で残すように変更、Ver.1.21のデグレを修正)

	;	call	glcd_all_clear	;全画面消去			;(Ver.1.21で変更)
	;	call	week_display	;曜日タイトルの表示		;
	;	call	yyyymm_display	;年月 (yyyy/mm) の表示		;
	;	call	calendar_display ;カレンダー（日と曜日）の表示	; これらの call命令は
	;	call	ampm_display	;(  /am/pm) の表示		; main ルーチンで行う
	;	call	time_display	;時分秒 (hh:mm:ss) の表示	;
		bsf	modeflg,2	;main制御フラグのセット		;
		bsf	updtflg,0	;時分秒更新済フラグのセット	;

set42	;;	return
		goto	main08		;; 戻る (1/5)

;--------------------------------------------------------------------------

;		SETモードメッセージの表示

setmode_display
		movlw	10
		movwf	gl_x		;X座標 = 10
		movlw	7 + h'c0'	;h'c0': 反転表示と1 Line ずらし指示
		movwf	gl_y		;Y座標 = 7

		movlw	high setmode_msg ;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low setmode_msg	 ;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示

		bcf	gl_y,7		;反転表示指示解除
		return

setmode_msg	dt	" SET MODE ",0

;==========================================================================
;		UP スイッチの処理
;==========================================================================

up_switch
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	up02		;No. 1:LARGEモード

		btfss	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグのセット か？
		call	date_save	;No

		call	bcd_nn_inc	;月 BCD カウンタのインクリメント
		movlw	h'01'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'01' か？
		goto	up01		;No

		call	bcd_yyyy_inc	;年(4桁) BCD カウンタのインクリメント

up01		call	date_check	;退避チェック
		call	down_up_display	;DOWN/UP スイッチ操作中メッセージの表示
		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダーの表示

up02	;;	return
		goto	main09		;; 戻る

;==========================================================================
;		DOWN スイッチの処理
;==========================================================================

down_switch
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	down02		;No. 1:LARGEモード

		btfss	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグのセット か？
		call	date_save	;No

		call	bcd_nn_dec	;月 BCD カウンタのデクリメント
		movlw	h'12'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'12' か？
		goto	down01		;No

		call	bcd_yyyy_dec	;年(4桁) BCD カウンタのデクリメント

down01		call	date_check	;退避チェック
		call	down_up_display	;DOWN/UP スイッチ操作中メッセージの表示
		call	yyyymm_display	;年月 (yyyy/mm) の表示
		call	calendar_display ;カレンダーの表示

down02	;;	return
		goto	main10		;; 戻る

;--------------------------------------------------------------------------

;		年(上位2桁), 年(下位2桁), 月, 日 BCD カウンタ の退避

date_save
		movf	bcd_yh,W	;年(上位2桁) BCD カウンタ
		movwf	temp_yh		;退避用 年(上位2桁) BCD カウンタ
		movf	bcd_yl,W	;年(下位2桁) BCD カウンタ
		movwf	temp_yl		;退避用 年(下位2桁) BCD カウンタ
		movf	bcd_nn,W	;月 BCD カウンタ
		movwf	temp_nn		;退避用 月 BCD カウンタ
		movf	bcd_dd,W	;日 BCD カウンタ
		movwf	temp_dd		;退避用 日 BCD カウンタ
		bsf	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグのセット
		return

;--------------------------------------------------------------------------

;		年(上位2桁), 年(下位2桁), 月, 日 BCD カウンタ の復帰

date_return
		movf	temp_yh,W	;退避用 年(上位2桁) BCD カウンタ
		movwf	bcd_yh		;年(上位2桁) BCD カウンタ
		movf	temp_yl,W	;退避用 年(下位2桁) BCD カウンタ
		movwf	bcd_yl		;年(下位2桁) BCD カウンタ
		movf	temp_nn,W	;退避用 月 BCD カウンタ
		movwf	bcd_nn		;月 BCD カウンタ
		movf	temp_dd,W	;退避用 日 BCD カウンタ
		movwf	bcd_dd		;日 BCD カウンタ
		bcf	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグのクリア
		return

;--------------------------------------------------------------------------

;		年(上位2桁), 年(下位2桁), 月, 日 BCD カウンタ の退避チェック

date_check
		movf	temp_yh,W	;退避用 年(上位2桁) BCD カウンタ
		subwf	bcd_yh,W
		btfss	STATUS,C	;年(上位2桁) BCD カウンタ >= 退避用 か？
		goto	dtck01		;No. <

		btfss	STATUS,Z	;年(上位2桁) BCD カウンタ = 退避用 か？
		goto	dtck02		;No. >

		movf	temp_yl,W	;退避用 年(下位2桁) BCD カウンタ
		subwf	bcd_yl,W
		btfss	STATUS,C	;年(下位2桁) BCD カウンタ >= 退避用 か？
		goto	dtck01		;No. <

		btfss	STATUS,Z	;年(下位2桁) BCD カウンタ = 退避用 か？
		goto	dtck02		;No. >

		movf	temp_nn,W	;退避用 月 BCD カウンタ
		subwf	bcd_nn,W
		btfss	STATUS,C	;月 BCD カウンタ >= 退避用 か？
		goto	dtck01		;No. <

		btfss	STATUS,Z	;月 BCD カウンタ = 退避用 か？
		goto	dtck02		;No. >

		movf	temp_dd,W	;退避用 日 BCD カウンタ
		subwf	bcd_dd,W
		btfss	STATUS,C	;日 BCD カウンタ >= 退避用 か？
		goto	dtck01		;No. <

		btfss	STATUS,Z	;日 BCD カウンタ = 退避用 か？
		goto	dtck02		;No. >

		clrf	saveflg		;bcd_xx → temp_xx へ退避中表示フラグのクリア
		goto	dtck03

dtck01		bcf	saveflg,1	;temp_xx > bcd_xx フラグのクリア
		goto	dtck03

dtck02		bsf	saveflg,1	;temp_xx > bcd_xx フラグのセット

dtck03		return

;--------------------------------------------------------------------------

;		DOWN/UP スイッチの 操作中メッセージの表示

down_up_display
		;メッセージエリアのクリア
		movlw	2
		movwf	gl_chip		;2: 右側選択
		movlw	7
		movwf	gl_y
		call	Glcd_SetPage	;Page Address の設定
		movlw	5
		call	Glcd_SetColumn	;開始 Column Address = 5 設定
		movlw	55
		movwf	gl_cnt2		;出力数 = 55

du01		clrw
		call	Glcd_WriteData	;
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	du01		;No

		movf	saveflg,W
		btfsc	STATUS,Z	;bcd_xx → temp_xx へ退避中表示フラグ = セット か？
		goto	du04		;No

		;メッセージの表示
		btfsc	saveflg,1	;bcd_xx < temp_xx か？
		goto	du02		;No

		movlw	5
		call	Glcd_SetColumn	;Column Address = 5 設定
		movlw	h'fe'
		call	Glcd_WriteData	;h'fe'
		bsf	gl_y,7		;反転表示指示

du02		movlw	11
		movwf	gl_x		;X座標 = 11
		bsf	gl_y,6		;1 Line ずらし指示

		movlw	high down_up_msg ;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low down_up_msg	 ;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示
		bcf	gl_y,7		;反転表示指示解除

		btfss	saveflg,1	;bcd_xx > temp_xx か？
		goto	du03		;No

		movlw	41
		call	Glcd_SetColumn	;Column Address = 41 設定
		movlw	h'fe'
		call	Glcd_WriteData	;h'fe'
		bsf	gl_y,7		;反転表示指示

du03		movlw	17
		movwf	gl_x		;X座標 = 17
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示
		bcf	gl_y,7		;反転表示指示解除

du04		return

down_up_msg	dt	h'7f',"Down",0
			; ←
		dt	"Up",h'7e',0
			;      →

;==========================================================================
;		ZERO スイッチの処理
;==========================================================================

zero_switch
		movlw	h'06'
		subwf	bcd_mm,W
		btfss	STATUS,C	;分 BCD カウンタ >= h'06' か？
		goto	zero01		;No

		movlw	h'55'
		subwf	bcd_mm,W
		btfss	STATUS,C	;分 BCD カウンタ >= h'55' か？
		goto	zero03		;No

	;	bcf	INTCON,GIE	;全割り込み禁止
		bsf	updtflg,4	;時分秒更新禁止フラグのセット
		call	bcd_hh_inc	;時 BCD カウンタのインクリメント
		movf	bcd_hh,W
		btfsc	STATUS,Z	;時 BCD カウンタ <> h'00' か？
		bsf	updtflg,1	;No. 年月日更新要求フラグのセット
		goto	zero02

zero01	;	bcf	INTCON,GIE	;全割り込み禁止
		bsf	updtflg,4	;時分秒更新禁止フラグのセット

zero02		bsf	updtflg,0	;時分秒更新済フラグのセット
		clrf	bcd_mm		;分 BCD カウンタのクリア
		clrf	bcd_ss		;秒 BCD カウンタのクリア
		clrf	cnt_high	;１秒カウンタの初期設定
		clrf	cnt_low

	;	bsf	INTCON,GIE	;全割り込み禁止解除
		bcf	updtflg,4	;時分秒更新禁止フラグのクリア

zero03		return

;==========================================================================
;		SIGNAL スイッチの処理
;==========================================================================

;入出力:	sigflg: 時報音出力フラグ ( bit0-bit3:カウンタ, bit4:カウント許可, bit5:予報音, bit6:正報音, bit7:出力許可 )
;		                                                  *                                            *
signal_switch
		btfsc	sigflg,4	;メッセージ表示時間のカウント許可中 か？
		goto	sig02		;Yes

		movlw	b'10000000'
		xorwf	sigflg,F	;時報音出力許可フラグの更新

		btfss	modeflg,0	;1:LARGEモード か？
		goto	sig01		;No. 0:NORMALモード

		call	glcd_all_clear	;全画面消去
		bsf	modeflg,1	;仮にSETモードにセット...表示位置を上にずらす
		bsf	modeflg,2	;main制御フラグのセット
		bsf	updtflg,0	;時分秒更新済フラグのセット

sig01		bsf	sel_flag,0	;選択フラグ = ダミーセット
		call	signal_display	;SIGNAL スイッチの ON／OFF メッセージの表示
 		clrf	sel_flag	;ダミークリア
		bsf	sigflg,4	;メッセージ表示時間のカウント許可

sig02		return

;--------------------------------------------------------------------------

;		メッセージ表示時間のカウントとメッセージエリアのクリア

disp_count
		btfss	sigflg,4	;メッセージ表示時間のカウント許可 か？
		goto	dcnt02		;No

		btfss	blinkflg,2	;0.5秒表示反点滅タイミング-2 = ON か？
		goto	dcnt02		;No

		bcf	blinkflg,2	;0.5秒表示反点滅タイミング-2 のクリア
		incf	sigflg,F	;メッセージ表示時間のカウント
		movlw	h'0f'
		andwf	sigflg,W	;カウンタを取り出す
		sublw	h'0f'
		btfss	STATUS,Z	;メッセージ表示時間 = 3秒 ～ 3.5秒 か？
		goto	dcnt02		;No

		movlw	h'e0'
		andwf	sigflg,F	;カウンタのクリア

		btfss	modeflg,0	;1:LARGEモード か？
		goto	dcnt01		;No. 0:NORMALモード

		call	glcd_all_clear	;全画面消去
		bcf	modeflg,1	;仮のSETモードをリセット...表示位置を元に戻す
		bsf	modeflg,2	;main制御フラグのセット
		bsf	updtflg,0	;時分秒更新済フラグのセット
		goto	dcnt02		;No

dcnt01		clrf	sel_flag	;クリア処理
		call	signal_display	;メッセージエリアのクリア

dcnt02		return

;--------------------------------------------------------------------------

;		SIGNAL スイッチの ON／OFF メッセージの表示

signal_display
		;メッセージエリアの白黒反転
sigm0x		call	area_reverse

		movlw	52
		call	Glcd_SetColumn	;開始 Column Address = 58 設定
		movlw	6
		movwf	gl_cnt2		;出力数 = 6

		movf	sel_flag,W
		btfss	STATUS,Z	;クリア処理 か？
		movlw	h'fe'		;No. 白黒反転

sigm01		call	Glcd_WriteData	;
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	sigm01		;No

		movf	sel_flag,W
		btfsc	STATUS,Z	;クリア処理 か？
		goto	sigm04		;Yes

		;メッセージの表示
		btfss	sigflg,7	;出力許可 か？
		goto	sigm02		;No

		movlw	high signal_msg	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low signal_msg	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;
		goto	sigm03

sigm02		movlw	high (signal_msg + 10)	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low (signal_msg + 10)	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;

sigm03		movlw	9
		movwf	gl_x		;X座標 = 9
		movlw	7 + h'c0'	;h'c0': 反転表示と1 Line ずらし指示
		movwf	gl_y		;Y座標 = 7
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示

sigm04		return

signal_msg 	dt	"Signal On",0	;sigflg bit7 = 1
 		dt	"Signal Off",0	;sigflg bit7 = 0

;==========================================================================
;		LIGHT スイッチの処理
;==========================================================================

light_switch
		movlw	h'40'
		xorwf	PORTC,F		;グラフィック液晶の LEDコントロール

		movlw	d'250'						;(Ver.1.21で追加)
		call	wait_x1ms	;ウエイト			;
		movlw	d'250'						;
		call	wait_x1ms	;ウエイト			;
		return

;==========================================================================
;		各種サブルーチン
;==========================================================================

;--------------------------------------------------------------------------
;		曜日タイトル の表示
;--------------------------------------------------------------------------

week_display
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	weekt01		;No. 1:LARGEモード

		movlw	high week_title	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low week_title	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;

		movlw	0
		movwf	gl_x		;X座標
		movlw	1 + h'40'	;h'40': 1 Line ずらし指示
		movwf	gl_y		;Y座標
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示

weekt01		return

week_title	dt	"Su Mo Tu We Th Fr Sa",0

;--------------------------------------------------------------------------
;		年月 (yyyy/mm) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit7:年(上位) / 6:年(下位) / 5:月 ）

yyyymm_display
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	yym05		;No. 1:LARGEモード

		;年月 (yyyy/mm) 表示エリアの h'00'クリア
		movlw	1
		movwf	gl_chip		;1: 左側選択
		clrw
		call	Glcd_SetPage	;Page Address = 0 設定
		movlw	3
		call	Glcd_SetColumn	;Column Address = 3 設定
		movlw	43
		movwf	gl_cnt2		;出力数 = 43 設定

yym01		clrw
		call	Glcd_WriteData	;フィルデータ = h'00'
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	yym01		;No

		;年 (上位2桁 yy) の表示
		clrf	gl_x		;X座標 = 0
		clrf	gl_y		;Y座標 = 0
		btfss	sel_flag,7	;選択フラグ = bit7: 年(上位2桁) か？
		goto	yym02		;No

		movlw	3
		call	Glcd_SetColumn	;Column Address = 3 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;反転表示指示

yym02		swapf	bcd_yh,W	;年(上位2桁) BCD カウンタ 上位4ビット
		call	number_disp

		incf	gl_x,F
		movf	bcd_yh,W	;年(上位2桁) BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除

		;年 (下位2桁 yy/) の表示
		incf	gl_x,F
		btfss	sel_flag,6	;選択フラグ = bit6: 年(下位2桁) か？
		goto	yym03		;No

		movlw	15
		call	Glcd_SetColumn	;Column Address = 15 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;反転表示指示

yym03		swapf	bcd_yl,W	;年(下位2桁) BCD カウンタ 上位4ビット
		call	number_disp

		incf	gl_x,F
		movf	bcd_yl,W	;年(下位2桁) BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a'/'
		call	Glcd_DispChr

		;月 (mm) の表示
		incf	gl_x,F
		btfss	sel_flag,5	;選択フラグ = bit5: 月 か？
		goto	yym04		;No

		movlw	33
		call	Glcd_SetColumn	;Column Address = 33 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;反転表示指示

yym04		swapf	bcd_nn,W	;月 BCD カウンタ 上位4ビット
		call	number_disp

		incf	gl_x,F
		movf	bcd_nn,W	;月 BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除
		return

;		; LARGEモード時の表示

yym05		bsf	PCLATH,4	;Page 2
	;;	call	yyyymm_display_lg		;; スタックに余裕を持たせるため
		goto	yyyymm_display_lg		;; ここでも call の使用はやめて
yym06							;; goto で飛び goto で戻る (2/5)
		return

;--------------------------------------------------------------------------

;		BCD から数字へ変換表示

number_disp
		andlw	h'0f'
		iorlw	h'30'
		call	Glcd_DispChr
		return

;--------------------------------------------------------------------------
;		24H / 12H (  /am/pm) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit3=1: 24H/12H, 0: (  /am/pm) ）
;		timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

ampm_display
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	ampm06		;No. 1:LARGEモード

		;24H / 12H (  /am/pm) 表示エリアの h'00'クリア
		movlw	1
		movwf	gl_chip		;1: 左側選択
		clrw
		call	Glcd_SetPage	;Page Address = 0 設定
		movlw	51
		call	Glcd_SetColumn	;Column Address = 51 設定
		movlw	13
		movwf	gl_cnt2		;出力数 = 13 設定

ampm01		clrw
		call	Glcd_WriteData	;フィルデータ = h'00'
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	ampm01		;No

		movlw	10
		movwf	gl_x		;X座標 = 10
		clrf	gl_y		;Y座標 = 0
		movlw	a' '
		call	Glcd_DispChr

		btfsc	sel_flag,3	;選択フラグ <> bit3: 24H / 12H か？
		goto	ampm02		;No

		;(  /am/pm) の表示
		movlw	9
		movwf	gl_x		;X座標 = 9

		movlw	a'a'
		btfsc	timeflg,1	;bit1=0: am か？
		movlw	a'p'		;No
		btfss	timeflg,0	;bit0=1: 12H か？
		movlw	a' '		;No
		call	Glcd_DispChr

		incf	gl_x,F
		movlw	a'm'
		btfss	timeflg,0	;bit0=1: 12H か？
		movlw	a' '		;No
		call	Glcd_DispChr
		goto	ampm05

		;24H / 12H の表示
ampm02		movlw	1
		movwf	gl_chip		;1: 左側選択
		clrw
		call	Glcd_SetPage	;Page Address = 0 設定
		movlw	51
		call	Glcd_SetColumn	;Column Address = 51 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'

		movlw	8
		movwf	gl_x		;X座標 = 8
		clrf	gl_y		;Y座標 = 0
		bsf	gl_y,7		;反転表示指示

		btfsc	timeflg,0	;bit0=0: 24H か？
		goto	ampm03		;No

		movlw	high h24_12_msg	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low h24_12_msg	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;
		goto	ampm04

ampm03		movlw	high (h24_12_msg + 4)	;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low (h24_12_msg + 4)	;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;

ampm04		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示
		bcf	gl_y,7		;反転表示指示解除

ampm05		return

h24_12_msg 	dt	"24H",0		;timeflg: bit0=0
 		dt	"12H",0		;timeflg: bit0=1

;		; LARGEモード時の表示

ampm06		bsf	PCLATH,4	;Page 2
	;;	call	ampm_display_lg			;; スタックに余裕を持たせるため
		goto	ampm_display_lg			;; ここでも call の使用はやめて
ampm07							;; goto で飛び goto で戻る (3/5)
		return

;--------------------------------------------------------------------------
;		時分秒 (hh:mm:ss) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit2:時 / 1:分 / 0:秒 ）
;		timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

time_display
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	tim07		;No. 1:LARGEモード

		;時分秒 (hh:mm:ss) 表示エリアの h'00'クリア
		movlw	2
		movwf	gl_chip		;2: 右側選択
		clrw
		call	Glcd_SetPage	;Page Address = 0 設定
		movlw	11
		call	Glcd_SetColumn	;Column Address = 11 設定
		movlw	49
		movwf	gl_cnt2		;出力数 = 49 設定

tim01		clrw
		call	Glcd_WriteData	;フィルデータ = h'00'
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	tim01		;No

		;時 (hh:) の表示
		movlw	12
		movwf	gl_x		;X座標 = 12
		clrf	gl_y		;Y座標 = 0

		btfss	sel_flag,2	;選択フラグ = bit2: 時 か？
		goto	tim02		;No

		movlw	11
		call	Glcd_SetColumn	;Column Address = 11 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;反転表示指示

tim02		swapf	bcd_hh,W	;No. 時 BCD カウンタ 上位4ビット
		btfss	timeflg,0	;時間表示フラグ = 12H か？
		goto	tim03		;No. 24H

		call	cnv_24to12	;24時間表示を12時間表示に変換
		swapf	temp_hh,W	;仮の 時 BCD カウンタ 上位4ビット
		andlw	h'0f'
		btfss	STATUS,Z	;上位4ビット = 0 か？
		goto	tim03		;No

		movlw	a' '
		call	Glcd_DispChr	;ゼロサプレス
		goto	tim04

tim03		call	number_disp

tim04		incf	gl_x,F
		movf	temp_hh,W	;仮の 時 BCD カウンタ 下位4ビット
		btfss	timeflg,0	;時間表示フラグ = 12H か？
		movf	bcd_hh,W	;No. 時 BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a':'
		call	Glcd_DispChr

		;分 (mm:) の表示
		incf	gl_x,F
		btfss	sel_flag,1	;選択フラグ = bit1: 分 か？
		goto	tim05		;No

		movlw	29
		call	Glcd_SetColumn	;Column Address = 29 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;反転表示指示

tim05		swapf	bcd_mm,W	;分 BCD カウンタ 上位4ビット
		call	number_disp

		incf	gl_x,F
		movf	bcd_mm,W	;分 BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a':'
		call	Glcd_DispChr

		;秒 (ss) の表示
		incf	gl_x,F
		btfss	sel_flag,0	;選択フラグ = bit0: 秒 か？
		goto	tim06		;No

		movlw	47
		call	Glcd_SetColumn	;Column Address = 47 設定
		movlw	h'7f'
		call	Glcd_WriteData	;h'7f'
		bsf	gl_y,7		;Yes. 反転表示指示

tim06		swapf	bcd_ss,W	;秒 BCD カウンタ 上位4ビット
		call	number_disp

		incf	gl_x,F
		movf	bcd_ss,W	;秒 BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除
		return

;		; LARGEモード時の表示

tim07		bsf	PCLATH,4	;Page 2
	;;	call	time_display_lg			;; スタックに余裕を持たせるため
		goto	time_display_lg			;; ここでも call の使用はやめて
tim08							;; goto で飛び goto で戻る (4/5)
		return

;--------------------------------------------------------------------------

;		24時間表示を12時間表示に変換

;(24H) 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 
;(12H) 12 01 02 03 04 05 06 07 08 09 10 11 12 01 02 03 04 05 06 07 08 09 10 11
;      am am am am am am am am am am am am pm pm pm pm pm pm pm pm pm pm pm pm		;;Ver. 1.30 にて修正
;                                          -----------------------------------
;     +12                                 -12
;    ( 12 ef f0 f1 f2 f3 f4 f5 f6 f7 fe ff 00 01 02 03 04 05 06 07 0e 0f 10 11 )

cnv_24to12
		bcf	timeflg,1	;bit1=0: am に設定

		movf	bcd_hh,W	;時 BCD カウンタ
		movwf	temp_hh		;仮の 時 BCD カウンタ

		movf	temp_hh,W
		btfss	STATUS,Z	;仮の 時 BCD カウンタ = h'00' か？
		goto	cnv01		;No

	;;	movlw	h'24'								;;
	;;	movwf	temp_hh		;仮の 時 BCD カウンタ temp_hh = h'24'		;;
	;;										;;Ver. 1.30 にて修正
		movlw	h'12'								;;
		movwf	temp_hh		;仮の 時 BCD カウンタ temp_hh = h'12'		;;
		goto	cnv03								;;

cnv01		movlw	h'12'
		subwf	temp_hh,W
	;;	btfsc	STATUS,Z	;仮の時 BCD カウンタ <> h'12' か？		;;
	;;	goto	cnv03		;No						;;
	;;										;;
	;;	btfss	STATUS,C	;仮の時 BCD カウンタ > h'12' か？		;;
	;;	goto	cnv03		;No						;;
											;;Ver. 1.30 にて修正
		btfss	STATUS,C	;仮の時 BCD カウンタ < h'12' か？		;;
		goto	cnv03		;Yes. (am)					;;
											;;
		btfsc	STATUS,Z	;仮の時 BCD カウンタ = h'12' か？		;;
		goto	cnv02		;Yes. (pm)					;;

		movwf	temp_hh		;仮の時 BCD カウンタ temp_hh = temp_hh - 12
		movlw	h'0e'
		subwf	temp_hh,W
		btfss	STATUS,C	;仮の時 BCD カウンタ >= h'0e' か？
		goto	cnv02		;No

		movlw	h'10'
		subwf	temp_hh,W
		btfsc	STATUS,C	;仮の時 BCD カウンタ < h'10' か？
		goto	cnv02		;No

		movlw	h'06'
		subwf	temp_hh,F	;補正

cnv02		bsf	timeflg,1	;bit1=1: pm に設定

cnv03		return

;--------------------------------------------------------------------------
;		カレンダーの表示
;--------------------------------------------------------------------------

calendar_display
		btfsc	modeflg,0	;0:NORMALモード か？
		goto	calen10		;No. 1:LARGEモード

		;カレンダー表示エリアの h'00'クリア
		movlw	3
		movwf	gl_chip		;3: 左側と右側選択
		movlw	2
		movwf	gl_y		;Page Address = 2 初期設定

calen01		movf	gl_y,W
		call	Glcd_SetPage	;Page Address の設定
		clrw
		call	Glcd_SetColumn	;Column Address の設定
		movlw	64
		movwf	gl_cnt2		;出力数 = 64 設定

calen02		clrw
		call	Glcd_WriteData	;フィルデータ = h'00'
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	calen02		;No

		incf	gl_y,F		;Page Address +1 更新
		movlw	7
		subwf	gl_y,W
		btfss	STATUS,Z	;Page Address = 7 か？
		goto	calen01		;No

		movlw	1
		movwf	gl_chip		;1: 左側選択
		movf	gl_y,W
		call	Glcd_SetPage	;Page Address の設定
		clrw
		call	Glcd_SetColumn	;Column Address の設定
		movlw	51
		movwf	gl_cnt2		;出力数 = 51 設定

calen03		clrw
		call	Glcd_WriteData	;フィルデータ = h'00'
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	calen03		;No

		;カレンダー (一ヶ月分) の表示
		call	first_week	;該当月の先頭曜日の取得
		call	month_days	;各月の日数計算
		movwf	end_day		;各月の終了日（日数 28～31)
		movlw	h'02' + h'40'	;h'40': 1 Line ずらし指示
		movwf	gl_y		;Y座標の初期設定 = 2
		movlw	h'01'
		movwf	cur_dd		;日(変) BCD カウンタの初期設定

calen04		movf	cur_week,W
		movwf	gl_x		;3倍する
		addwf	gl_x,F		; Su Mo Tu We Th Fr Sa
		addwf	gl_x,F		; 00 03 06 09 12 15 18
		btfsc	saveflg,0	;bcd_xx → temp_xx へ退避中表示フラグ = クリア か？
		goto	calen06		;No

		movf	bcd_dd,W
		subwf	cur_dd,W
		btfss	STATUS,Z	;cur_dd = bcd_dd か？
		goto	calen06		;No

		movlw	a' '
		call	Glcd_DispChr	;ダミー出力
		decf	gl_temp1,W
		call	Glcd_SetColumn	;Column (横位置) を指定
		btfss	sel_flag,4	;選択フラグ = 4: 日 か？
		goto	calen05		;No

		btfss	blinkflg,1	;0.5秒表示反点滅タイミング-1 = OFF か？
		goto	calen06		;No

calen05		movlw	h'fe'
		call	Glcd_WriteData	;h'fe'
		bsf	gl_y,7		;反転表示指示

calen06		swapf	cur_dd,W	;日(変) BCD カウンタ 上位4ビット
		andlw	h'0f'
		btfss	STATUS,Z	;上位4ビット = 0 か？
		goto	calen07		;No

		movlw	a' '
		call	Glcd_DispChr	;ゼロサプレス
		goto	calen08

calen07		call	number_disp

calen08		incf	gl_x,F
		movf	cur_dd,W	;日(変) BCD カウンタ 下位4ビット
		call	number_disp
		bcf	gl_y,7		;反転表示指示解除
		movf	end_day,W
		subwf	cur_dd,W
		btfsc	STATUS,C	;cur_dd < end_dd か？
		goto	calen09		;No

		movlw	cur_dd		;日(変) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;日(変) BCDインクリメント
		incf	cur_week,F	;週位置の更新
		movlw	7
		subwf	cur_week,W
		btfss	STATUS,C	;週位置 >= 7 か？
		goto	calen04		;No

		clrf	cur_week	;週位置の初期設定
		incf	gl_y,F		;Y座標の更新
		goto	calen04		;No

calen09		return

;		; LARGEモード時の表示

calen10		bsf	PCLATH,4	;Page 2
	;;	call	calendar_display_lg		;; スタックに余裕を持たせるため
		goto	calendar_display_lg		;; ここでも call の使用はやめて
calen11							;; goto で飛び goto で戻る (5/5)
		return

;--------------------------------------------------------------------------

;		該当月の先頭曜日の取得

;入力:		bcd_yh: 年(上位2桁) BCD カウンタ, bcd_yl: 年(下位2桁) BCD カウンタ, bcd_nn: 月 BCD カウンタ

;出力:		cur_week: ( 0:日, 1:月, 2:火, 3:水, 4:木, 5:金, 6:土 )

;	(参考)	2014/01 02 03 04 05 06 07 08 09 10 11 12
;		      3  6  6  2  4  0  2  5  1  3  6  1

first_week
		movlw	h'01'
		movwf	cur_yl		;西暦元年 = '0001' とする
		clrf	cur_yh		;

		movlw	h'01'
		movwf	cur_week	;初期設定 (西暦元年1月1日 = 月曜日 とする)

		movf	bcd_yh,W	;++++++++++ (改良) ... 400年後毎の同月同日は同じ曜日
		call	bcd2_to_binary	;バイナリ変換
		movwf	xxx_yh		;
					;
fweek0x		movlw	4		;
		subwf	xxx_yh,W	;
		btfss	STATUS,C	;xxx_yh >= 4 か？
		goto	fweek01		;No
					;
		btfss	STATUS,Z	;xxx_yh = 4 か？
		goto	fweek0y		;No
					;
		movf	bcd_yl,W	;
		btfsc	STATUS,Z	;bcd_yl <> 0 か？
		goto	fweek01		;No
					;
fweek0y		movlw	4		;
		subwf	xxx_yh,F	;
		goto	fweek0x		;++++++++++

		;年の計算
fweek01		movf	bcd_yl,W
		subwf	cur_yl,W
		btfss	STATUS,Z	;cur_yl = bcd_yl か？
		goto	fweek02		;No

	;	movf	bcd_yh,W
		movf	xxx_yh,W	; (改良)
		subwf	cur_yh,W
		btfsc	STATUS,Z	;cur_yh <> xxx_yh か？
		goto	fweek03		;No

fweek02		movlw	365 % 7		;365 % 7 = 365 - 7 * 52 = 1
		addwf	cur_week,F
		call	uruu_check	;平年／閏年の判定
		btfsc	uru_flag,0	;平年 か？
		incf	cur_week,F	;No. 閏年

		movlw	7
		subwf	cur_week,W
		btfsc	STATUS,C	;cur_week < 7 か？
		movwf	cur_week	;No

		movlw	cur_yl		;年(下位2桁)(変) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

		movlw	h'a0'
		subwf	cur_yl,W
		btfss	STATUS,Z	;年(下位2桁)(変) BCD カウンタ = h'a0' か？
		goto	fweek01		;No

		clrf	cur_yl		;年(下位2桁)(変) BCD カウンタ = h'00' 設定

		movlw	cur_yh		;年(上位2桁)(変) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

;		movlw	h'a0'
;		subwf	cur_yh,W
;		btfss	STATUS,Z	;年(上位2桁)(変) BCD カウンタ = h'a0' か？
;		goto	fweek01		;No

;		clrf	cur_yh		;年(上位2桁)(変) BCD カウンタ = h'00' 設定
;		movlw	h'01'
;		movwf	cur_yl		;9999 → (0000) → 0001
		goto	fweek01

		;月の計算
fweek03		movlw	h'01'
		movwf	cur_nn		;月(変) BCD カウンタ

fweek04		movf	bcd_nn,W
		subwf	cur_nn,W
		btfsc	STATUS,Z	;cur_nn <> bcd_nn か？
		goto	fweek06		;No

		movf	cur_nn,W
		call	bcd2_to_binary	;BCD (2桁) からバイナリ変換
		movwf	work1		;退避
		call	month_day2	;月データのテーブル読み出し
		addwf	cur_week,F
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定

		movlw	h'02'
		subwf	cur_nn,W
		btfss	STATUS,Z	;cur_nn = 2 か？
		goto	fweek05		;No

		call	uruu_check	;平年／閏年の判定
		btfsc	uru_flag,0	;平年 か？
		incf	cur_week,F	;No. 閏年

fweek05		movlw	7
		subwf	cur_week,W
		btfsc	STATUS,C	;cur_week < 7 か？
		movwf	cur_week	;No

		movlw	cur_nn		;月(変) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント
		goto	fweek04

fweek06		return

;--------------------------------------------------------------------------

;		月データのテーブル読み出し

month_day2
		movlw	high day_tbl	;月データの high アドレス
		movwf	PCLATH
		decf	work1,W
		addlw	low day_tbl	;月データの low アドレス
		movwf	PCL

day_tbl		retlw	31 % 7		; 1:  31 % 7 = 3
		retlw	28 % 7		; 2:  28 % 7 = 0
		retlw	31 % 7		; 3:  31 % 7 = 3
		retlw	30 % 7		; 4:  30 % 7 = 2
		retlw	31 % 7		; 5:  31 % 7 = 3
		retlw	30 % 7		; 6:  30 % 7 = 2
		retlw	31 % 7		; 7:  31 % 7 = 3
		retlw	31 % 7		; 8:  31 % 7 = 3
		retlw	30 % 7		; 9:  30 % 7 = 2
		retlw	31 % 7		;10:  31 % 7 = 3
		retlw	30 % 7		;11:  30 % 7 = 2
;		retlw	31 % 7		;12:  31 % 7 = 3  (使用しない)

;--------------------------------------------------------------------------

;		平年／閏年の判定

uruu_check
		clrf	uru_flag	;平年に設定

		movf	cur_yl,W	;年(下位2桁)(変) BCD カウンタ
		call	bcd2_to_binary	;BCD (2桁) からバイナリ変換
		andlw	h'03'		;下位2ビット
		btfss	STATUS,Z	;下位2ビット = b'00' か？
		goto	uru02		;No. 平年 ... 4で割れない

		movf	cur_yl,W
		btfss	STATUS,Z	;年(下位2桁)(変) BCD カウンタ = h'00' か？
		goto	uru01		;No. 閏年 ... 100で割れない

		movf	cur_yh,W	;年(上位2桁)(変) BCD カウンタ
		call	bcd2_to_binary	;BCD (2桁) からバイナリ変換
		andlw	h'03'		;下位2ビット
		btfss	STATUS,Z	;下位2ビット = b'00' か？
		goto	uru02		;No. 平年 ... 400で割れない

uru01		bsf	uru_flag,0	;閏年に設定

uru02		return

;--------------------------------------------------------------------------
;		質問メッセージの表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit7:年(上位) / 6:年(下位)  / 5:月 / 4:日 / 3:24H/12H / 2:時 / 1:分 / 0:秒 ）

inquiry_display
		;メッセージエリアの白黒反転
		call	area_reverse
		movf	sel_flag,W
		btfsc	STATUS,Z	;クリア処理のみ か？
		goto	inq04		;Yes

		;メッセージの表示
		movlw	high inquiry_msg ;文字列データの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low inquiry_msg	 ;文字列データの先頭アドレスの low アドレス
		movwf	addr_low	;

		movf	sel_flag,W	;選択フラグ, メッセージの選択
		movwf	work2

inq01		rlf	work2,F
		btfsc	STATUS,C	;終了 か？
		goto	inq03		;Yes

inq02		call	str_read	;文字列データの読み出し
		movwf	gl_temp		;一時退避

		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		movf	gl_temp,W
		btfss	STATUS,Z	;文字列の終了(h'00') か？
		goto	inq02		;No
		goto	inq01		;Yes

inq03		movlw	10
		movwf	gl_x		;X座標 = 10
		movlw	7 + h'c0'	;h'c0': 反転表示と1 Line ずらし指示
		movwf	gl_y		;Y座標 = 7
		call	Glcd_DispStr	;キャラクタ (横:6 x 縦:8) 文字列の表示

inq04		return

inquiry_msg 	dt	"Year Hi ?",0	;sel_flag = bit7
		dt	"Year Lo ?",0	;sel_flag = bit6
		dt	"Month ? ",0	;sel_flag = bit5
		dt	"Today ?",0	;sel_flag = bit4
		dt	"24H/12H ?",0	;sel_flag = bit3
		dt	"Hour ?",0	;sel_flag = bit2
		dt	"Minute ?",0	;sel_flag = bit1
		dt	"Second ?",0	;sel_flag = bit0

;--------------------------------------------------------------------------

		;メッセージエリアの白黒反転

area_reverse
		movlw	3
		movwf	gl_chip		;3: 左側と右側選択
		movlw	7
		call	Glcd_SetPage	;Page Address 設定

		decf	gl_chip,F	;2: 右側選択
		clrw
		call	Glcd_SetColumn	;開始 Column Address = 0 設定
		movlw	60	;59
		movwf	gl_cnt2		;出力数 = 60	;59

		movf	sel_flag,W
		btfss	STATUS,Z	;クリア処理 か？
		movlw	h'fe'		;No. 白黒反転

arev01		call	Glcd_WriteData	;
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	arev01		;No

		decf	gl_chip,F	;1: 左側選択
		movlw	58
		call	Glcd_SetColumn	;開始 Column Address = 58 設定
		movlw	6
		movwf	gl_cnt2		;出力数 = 6

		movf	sel_flag,W
		btfss	STATUS,Z	;クリア処理 か？
		movlw	h'fe'		;No. 白黒反転

arev02		call	Glcd_WriteData	;
		decfsz	gl_cnt2,F	;出力数 - 1 = 0 か？
		goto	arev02		;No

		return

;==========================================================================

;--------------------------------------------------------------------------
;		日 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_dd_inc
		call	month_days	;各月の日数計算
		subwf	bcd_dd,W
		btfss	STATUS,Z	;日 BCD カウンタ = 各月の最終日 か？
		goto	ddinc01		;No

		movlw	h'01'
		movwf	bcd_dd		;日 BCD カウンタ = h'01' 設定
		goto	ddinc02

ddinc01		movlw	bcd_dd		;日 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

ddinc02		return

;--------------------------------------------------------------------------

;		各月の日数計算

month_days
		movlw	h'02'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'02' か？
		goto	mday02		;No

		movf	bcd_yl,W	;年(下位2桁) BCD カウンタ
		movwf	cur_yl
		movf	bcd_yh,W	;年(上位2桁) BCD カウンタ
		movwf	cur_yh
		call	uruu_check	;平年／閏年の判定
		btfss	uru_flag,0	;閏年 か？
		goto	mday01		;No

		movlw	h'29'		;閏年 2月
		goto	mday04

mday01		movlw	h'28'		;平年 2月
		goto	mday04

mday02		movlw	h'04'
		subwf	bcd_nn,W
		btfsc	STATUS,Z	;月 BCD カウンタ <> h'04' か？
		goto	mday03		;No

		movlw	h'06'
		subwf	bcd_nn,W
		btfsc	STATUS,Z	;月 BCD カウンタ <> h'06' か？
		goto	mday03		;No

		movlw	h'09'
		subwf	bcd_nn,W
		btfsc	STATUS,Z	;月 BCD カウンタ <> h'09' か？
		goto	mday03		;No

		movlw	h'11'
		subwf	bcd_nn,W
		btfsc	STATUS,Z	;月 BCD カウンタ <> h'11' か？
		goto	mday03		;No

		movlw	h'31'		;h'01', h'03', h'05', h'07', h'08', h'10', h'12'
		goto	mday04

mday03		movlw	h'30'		;h'04', h'06', h'09', h'11'

mday04		return

;--------------------------------------------------------------------------

;		BCD (2桁) からバイナリ変換

bcd2_to_binary
		movwf	work2		;退避
		swapf	work2,W		;上位4ビット(10位)を BCD からバイナリ変換
		andlw	h'0f'
		movwf	work1
		bcf	STATUS,C
		rlf	work1,F		;2倍
		rlf	work1,F		;4倍
		addwf	work1,F		;5倍
		rlf	work1,F		;10倍

		movf	work2,W		;下位4ビット(単位)
		andlw	h'0f'
		addwf	work1,W		;10位 + 単位 = W レジスタ
		return

;--------------------------------------------------------------------------
;		月 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_nn_inc
		movlw	bcd_nn		;月 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

		movlw	h'13'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'13' か？
		goto	nninc01		;No

		movlw	h'01'
		movwf	bcd_nn		;月 BCD カウンタ = h'01' 設定

nninc01		return

;--------------------------------------------------------------------------
;		年(4桁) BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_yyyy_inc
		call	bcd_yl_inc	;年(下位2桁) BCD カウンタのインクリメント
		btfss	STATUS,C	;年(下位2桁) BCD カウンタ >= 'a0' か？
		goto	yyinc01		;No

		call	bcd_yh_inc	;年(上位2桁) BCD カウンタのインクリメント
		btfss	STATUS,C	;年(上位2桁) BCD カウンタ >= 'a0' か？
		goto	yyinc01		;No

		movlw	h'01'
		movwf	bcd_yl		;9999 → (0000) → 0001

yyinc01		return

;--------------------------------------------------------------------------
;		年(下位2桁) BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_yl_inc
		movlw	bcd_yl		;年(下位2桁) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

		movlw	h'a0'
		subwf	bcd_yl,W
		btfss	STATUS,Z	;年(下位2桁) BCD カウンタ = 'a0' か？
		goto	ylinc01		;No

		clrf	bcd_yl		;年(下位2桁) BCD カウンタ = h'00' 設定

ylinc01		return

;--------------------------------------------------------------------------
;		年(上位2桁) BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_yh_inc
		movlw	bcd_yh		;年(上位2桁) BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCD インクリメント

		movlw	h'a0'
		subwf	bcd_yh,W
		btfss	STATUS,Z	;年(上位2桁) BCD カウンタ = 'a0' か？
		goto	yhinc02		;No

		clrf	bcd_yh		;年(上位2桁) BCD カウンタ = h'00' 設定

yhinc02		return

;--------------------------------------------------------------------------
;		日 BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_dd_dec
		decf	bcd_dd,F	;日 BCD カウンタ -1 更新
		btfss	STATUS,Z	;日 BCD カウンタ = h'00' か？
		goto	dddec01		;No

		call	month_days	;各月の日数計算
		movwf	bcd_dd		;日 BCD カウンタ 設定
		goto	dddec02

dddec01		movf	bcd_dd,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0f'
		btfss	STATUS,Z	;下位4ビット = h'0f' か？
		goto	dddec02		;No

		movlw	h'06'
		subwf	bcd_dd,F	;日 BCD カウンタ 更新

dddec02		return

;--------------------------------------------------------------------------
;		月 BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_nn_dec
		decf	bcd_nn,F	;月 BCD カウンタ -1 更新
		btfss	STATUS,Z	;月 BCD カウンタ = h'00' か？
		goto	nndec01		;No

		movlw	h'12'
		goto	nndec02

nndec01		movlw	h'0f'
		subwf	bcd_nn,W
		btfss	STATUS,Z	;月 BCD カウンタ = h'0f' か？
		goto	nndec03		;No

		movlw	h'09'

nndec02		movwf	bcd_nn		;月 BCD カウンタの設定

nndec03		return

;--------------------------------------------------------------------------
;		年(4桁) BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_yyyy_dec
		call	bcd_yl_dec	;年(下位2桁) BCD カウンタのデクリメント
		movf	bcd_yl,W
		btfsc	STATUS,Z	;年(下位2桁) BCD カウンタ <> '00' か？
		goto	yydec01		;No
		
		movlw	h'99'
		subwf	bcd_yl,W
		btfss	STATUS,Z	;年(下位2桁) BCD カウンタ = '99' か？
		goto	yydec02		;No

		call	bcd_yh_dec	;年(上位2桁) BCD カウンタのデクリメント
		goto	yydec02

yydec01		movf	bcd_yh,W
		btfss	STATUS,Z	;年(上位2桁) BCD カウンタ = '00' か？
		goto	yydec02		;No

		movlw	h'99'
		movwf	bcd_yh
		movwf	bcd_yl		;0001 → (0000) → 9999

yydec02		return

;--------------------------------------------------------------------------
;		年(下位2桁) BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_yl_dec
		decf	bcd_yl,F	;年(下位2桁) BCD カウンタ -1 更新
		incf	bcd_yl,W
		btfss	STATUS,Z	;年(下位2桁) BCD カウンタ = h'ff' か？
		goto	yldec01		;No

		movlw	h'66'
		subwf	bcd_yl,F	;年(下位2桁) BCD カウンタ 更新
		goto	yldec02

yldec01		movf	bcd_yl,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0f'
		btfss	STATUS,Z	;下位4ビット = h'0f' か？
		goto	yldec02		;No

		movlw	h'06'
		subwf	bcd_yl,F	;年(下位2桁) BCD カウンタ 更新

yldec02		return

;--------------------------------------------------------------------------
;		年(上位2桁) BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_yh_dec
		decf	bcd_yh,F	;年(上位2桁) BCD カウンタ -1 更新
		incf	bcd_yh,W
		btfss	STATUS,Z	;年(上位2桁) BCD カウンタ = h'ff' か？
		goto	yhdec01		;No

		movlw	h'66'
		subwf	bcd_yh,F	;年(上位2桁) BCD カウンタ 更新
		goto	yhdec02

yhdec01		movf	bcd_yh,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0f'
		btfss	STATUS,Z	;下位4ビット = h'0f' か？
		goto	yhdec02		;No

		movlw	h'06'
		subwf	bcd_yh,F	;年(上位2桁) BCD カウンタ 更新

yhdec02		return	

;--------------------------------------------------------------------------
;		時分秒 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

;	Ver.1.20にて変更: サブルーチンを止め gotoで飛んできてgotoで戻る
;			またcall bcd_ss_inc,bcd_mm_inc,bcd_hh_incを使用しない

bcd_ssmmhh_inc
	;;	call	bcd_ss_inc	;秒 BCD カウンタのインクリメント
		movlw	bcd_ss		;秒 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'60'
		subwf	bcd_ss,W
		btfss	STATUS,C	;秒 BCD カウンタ >= h'60' か？
		goto	smhinc01	;No

		clrf	bcd_ss		;秒 BCD カウンタのクリア

	;;	call	bcd_mm_inc	;分 BCD カウンタのインクリメント
		movlw	bcd_mm		;分 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'60'
		subwf	bcd_mm,W
		btfss	STATUS,C	;分 BCD カウンタ >= h'60' か？
		goto	smhinc01	;No

		clrf	bcd_mm		;分 BCD カウンタのクリア

	;;	call	bcd_hh_inc	;時 BCD カウンタのインクリメント
		movlw	bcd_hh		;時 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'24'
		subwf	bcd_hh,W
		btfss	STATUS,C	;時 BCD カウンタ >= h'24' か？
		goto	smhinc01	;No

		clrf	bcd_hh		;時 BCD カウンタのクリア

		bsf	updtflg,1	;年月日更新要求フラグのセット

smhinc01	bsf	updtflg,0	;時分秒更新済フラグのセット
	;;	return
		goto	t0int03		;割り込みルーチンに戻る

;--------------------------------------------------------------------------
;		秒 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_ss_inc
		movlw	bcd_ss		;秒 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'60'
		subwf	bcd_ss,W
		btfsc	STATUS,C	;秒 BCD カウンタ < h'60' か？
		clrf	bcd_ss		;No. 秒 BCD カウンタのクリア
		return

;--------------------------------------------------------------------------
;		分 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_mm_inc
		movlw	bcd_mm		;分 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'60'
		subwf	bcd_mm,W
		btfsc	STATUS,C	;分 BCD カウンタ < h'60' か？
		clrf	bcd_mm		;No. 分 BCD カウンタのクリア
		return

;--------------------------------------------------------------------------
;		時 BCD カウンタのインクリメント
;--------------------------------------------------------------------------

bcd_hh_inc
		movlw	bcd_hh		;時 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	inc_bcd		;BCDインクリメント
		movlw	h'24'
		subwf	bcd_hh,W
		btfsc	STATUS,C	;時 BCD カウンタ < h'24' か？
		clrf	bcd_hh		;No. 時 BCD カウンタのクリア
		return

;--------------------------------------------------------------------------
;		秒 BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_ss_dec
		movlw	bcd_ss		;秒 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	dec_bcd		;BCDデクリメント
		movlw	h'f9'		;h'00' - h'01' - h'06'
		subwf	bcd_ss,W
		btfss	STATUS,Z	;秒 BCD カウンタ = h'f9' か？
		goto	ssdec01		;No

		movlw	h'59'
		movwf	bcd_ss		;秒 BCD カウンタ = h'59' 設定

ssdec01		return

;--------------------------------------------------------------------------
;		分 BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_mm_dec
		movlw	bcd_mm		;分 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	dec_bcd		;BCDデクリメント
		movlw	h'f9'		;h'00' - h'01' - h'06'
		subwf	bcd_mm,W
		btfss	STATUS,Z	;分 BCD カウンタ = h'f9' か？
		goto	mmdec01		;No

		movlw	h'59'
		movwf	bcd_mm		;分 BCD カウンタ = h'59' 設定

mmdec01		return

;--------------------------------------------------------------------------
;		時 BCD カウンタのデクリメント
;--------------------------------------------------------------------------

bcd_hh_dec
		movlw	bcd_hh		;時 BCD カウンタの番地
		movwf	FSR		;間接アドレスに設定
		call	dec_bcd		;BCDデクリメント
		movlw	h'f9'		;h'00' - h'01' - h'06'
		subwf	bcd_hh,W
		btfss	STATUS,Z	;時 BCD カウンタ = h'f9' か？
		goto	hhdec01		;No

		movlw	h'23'
		movwf	bcd_hh		;時 BCD カウンタ = h'23' 設定

hhdec01		return

;--------------------------------------------------------------------------

;		BCD インクリメント

inc_bcd
		incf	INDF,F		;BCD カウンタ +1 更新
		movf	INDF,W
		andlw	h'0f'		;下位4ビット
		sublw	h'0a'
		btfss	STATUS,Z	;下位4ビット = d'10' か？
		return			;No

		movlw	h'06'
		addwf	INDF,F		;下位4ビット = 0, 上位4ビット = +1
		return

;--------------------------------------------------------------------------

;		BCD デクリメント

dec_bcd
		movf	INDF,W
		andlw	h'0f'		;下位4ビット
		btfsc	STATUS,Z	;下位4ビット <> h'00' か？
		goto	dec01		;No

		decf	INDF,F		;-1 更新
		return

dec01		decf	INDF,F		;-1 更新
		movlw	h'06'
		subwf	INDF,F		;下位4ビット = 9
		return

;==========================================================================
;		ウェイト・ルーチン (12.8 MHz)
;==========================================================================

;		50μ秒 ウェイトルーチン   (使用しない)

wait_50us
		movlw	d'52'		;1
		goto	wt01		;2
					;Total	161/12.8MHz*4 = 50.3125 μS

;		100μ秒 ウェイトルーチン  (使用しない)

wait_100us
		movlw	d'105'		;1
wt01		movwf	wtcnt1		;1

wt02		decfsz	wtcnt1,F	;1,2
		goto	wt02		;2,0	1+1+(1+2)*104+(2+0)=316

		return			;2	316+2=318
					;Total	318/12.8MHz*4 = 99.375 μS

;		1x m秒 ウェイトルーチン

wait_x1ms
		movwf	wtcnt1		;1

wt03		movlw	h'00'		;1
		movwf	wtcnt2		;1

wt04		nop			;1
		nop			;1
		nop			;1
		nop			;1
		nop			;1
		nop			;1
		nop			;1
		nop			;1
		nop			;1
		decfsz	wtcnt2,F	;1,2
		goto	wt04		;2,0	1+1+(1*9+1+2)*256-1=3073

		decfsz	wtcnt1,F	;1,2
		goto	wt03		;2,0	1+(wtcnt1)*(3073+1+2)-1=(wtcnt1)*3076

		return			;2	(wtcnt1)*3076+2
					;Total	((wtcnt1)*3076+2)/12.8MHz*4 = 961.875 μS (wtcnt1=1)

;==========================================================================
;		サブルーチンファイルのインクルード
;==========================================================================

		include		C:\Data\Project\PIC\_sub\G_LCD.sub

		org	h'800'		;Page1

		include		C:\Data\Project\PIC\_sub\Font5x7.tbl

sys_clk		equ	d'12800'	;システムクロック(KHz)を指定
		include		C:\Data\Project\PIC\_sub\Sound.sub

;==========================================================================
;		グラフィック LCD の 上下左右縁枠のデモ表示
;==========================================================================

demo_display
		call	demo1_display
		call	demo2_display
		call	demo3_display
		call	demo4_display
		return

;--------------------------------------------------------------------------
;			　　　(1)
;			　　　→→
;		デモ-1	 (2)↓　　↓(4)
;			　　　→→
;			　　　(3)
;--------------------------------------------------------------------------

demo1_display
;		左上→右上方向と 左上→左下方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	lpcnt		;ループカウンタの初期設定

demo101		movlw	1
		movwf	wr_chip		;対象チップ(上縁線用) = 1: 左側選択
		clrf	gl_y		;Y座標(左縁線用)の初期設定

demo102		clrf	gl_x		;X座標(上縁線用)の初期設定

demo103		movlw	h'01'
		movwf	wr_data		;WriteData(左縁線用)の初期設定

demo104		call	upper_left_right ;(1) 上縁線(左→右)の表示
		btfss	gl_x,0		;gl_x % 2 = 1 か？
		goto	demo105		;No

		call	left_upper_lower ;(2) 左縁線(上→下)の表示

demo105		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		movlw	h'0f'
		andwf	gl_x,W
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo104		;No

		incf	gl_y,F		;Y座標の更新
		btfss	gl_x,6		;gl_x = 64 か？
		goto	demo103		;No

		incf	wr_chip,F	;対象チップの更新
		movlw	h'3'
		subwf	wr_chip,W
		btfss	STATUS,Z	;対象チップ = 3: 終了 か？
		goto	demo102		;No

;		左下→右下方向と 右上→右下方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	1
		movwf	wr_chip		;対象チップ(下縁線用) = 1: 左側選択
		clrf	gl_y		;Y座標(右縁線用)の初期設定

demo106		clrf	gl_x		;X座標(下縁線用)の初期設定

demo107		movlw	h'01'
		movwf	wr_data		;WriteData(右縁線用)の初期設定

demo108		call	lower_left_right  ;(3) 下縁線(左→右)の表示
		btfss	gl_x,0		;gl_x % 2 = 1 か？
		goto	demo109		;No

		call	right_upper_lower ;(4) 右縁線(上→下)の表示

demo109		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		movlw	h'0f'
		andwf	gl_x,W
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo108		;No

		incf	gl_y,F		;Y座標の更新
		btfss	gl_x,6		;gl_x = 64 か？
		goto	demo107		;No

		incf	wr_chip,F	;対象チップの更新
		movlw	h'3'
		subwf	wr_chip,W
		btfss	STATUS,Z	;対象チップ = 3: 終了 か？
		goto	demo106		;No

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	demo101		;No

		return

;--------------------------------------------------------------------------
;			　　　 (1)
;			　　　←←
;		デモ-2	 (4)↓　　↓(2)
;			　　　←←
;			　　　 (3)
;--------------------------------------------------------------------------

demo2_display
;		右上→左上方向と 右上→右下方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	lpcnt		;ループカウンタの初期設定

demo201		movlw	2
		movwf	wr_chip		;対象チップ(上縁線用) = 2: 右側選択
		clrf	gl_y		;Y座標(右縁線用)の初期設定

demo202		movlw	63
		movwf	gl_x		;X座標(上縁線用)の初期設定

demo203		movlw	h'01'
		movwf	wr_data		;WriteData(右縁線用)の初期設定

demo204		call	upper_right_left  ;(1) 上縁線(右→左)の表示
		btfsc	gl_x,0		;gl_x % 2 = 0 か？
		goto	demo205		;No

		call	right_upper_lower ;(2) 右縁線(上→下)の表示

demo205		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		incf	gl_x,W
		andlw	h'0f'
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo204		;No

		incf	gl_y,F		;Y座標の更新
		incfsz	gl_x,W		;gl_x + 1 = 0 か？
		goto	demo203		;No

		decfsz	wr_chip,F	;対象チップ - 1 = 0: 終了 か？
		goto	demo202		;No

;		右下→左下方向と 左上→左下方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	wr_chip		;対象チップ(下縁線用) = 2: 右側選択
		clrf	gl_y		;Y座標(左縁線用)の初期設定

demo206		movlw	63
		movwf	gl_x		;X座標(下縁線用)の初期設定

demo207		movlw	h'01'
		movwf	wr_data		;WriteData(左縁線用)の初期設定

demo208		call	lower_right_left ;(3) 下縁線(右→左)の表示
		btfsc	gl_x,0		;gl_x % 2 = 0 か？
		goto	demo209		;No

		call	left_upper_lower ;(4) 左縁線(上→下)の表示

demo209		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		incf	gl_x,W
		andlw	h'0f'
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo208		;No

		incf	gl_y,F		;Y座標の更新
		incfsz	gl_x,W		;gl_x + 1 = 0 か？
		goto	demo207		;No

		decfsz	wr_chip,F	;対象チップ - 1 = 0: 終了 か？
		goto	demo206		;No

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	demo201		;No

		return

;--------------------------------------------------------------------------
;			　　　 (3)
;			　　　←←
;		デモ-3	 (4)↑　　↑(2)
;			　　　←←
;			　　　 (1)
;--------------------------------------------------------------------------

demo3_display
;		右下→左下方向と 右下→右上方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	lpcnt		;ループカウンタの初期設定

demo301		movlw	2
		movwf	wr_chip		;対象チップ(下縁線用) = 2: 右側選択
		movlw	7
		movwf	gl_y		;Y座標(右縁線用)の初期設定

demo302		movlw	63
		movwf	gl_x		;X座標(下縁線用)の初期設定

demo303		movlw	h'80'
		movwf	wr_data		;WriteData(右縁線用)の初期設定

demo304		call	lower_right_left  ;(1) 下縁線(右→左)の表示
		btfsc	gl_x,0		;gl_x % 2 = 0 か？
		goto	demo305		;No

		call	right_lower_upper ;(2) 右縁線(下→上)の表示

demo305		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		incf	gl_x,W
		andlw	h'0f'
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo304		;No

		decf	gl_y,F		;Y座標の更新
		incfsz	gl_x,W		;gl_x + 1 = 0 か？
		goto	demo303		;No

		decfsz	wr_chip,F	;対象チップ - 1 = 0: 終了 か？
		goto	demo302		;No

;		右上→左上方向と 左下→左上方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	wr_chip		;対象チップ(上縁線用) = 2: 右側選択
		movlw	7
		movwf	gl_y		;Y座標(左縁線用)の初期設定

demo306		movlw	63
		movwf	gl_x		;X座標(上縁線用)の初期設定

demo307		movlw	h'80'
		movwf	wr_data		;WriteData(左縁線用)の初期設定

demo308		call	upper_right_left ;(3) 上縁線(右→左)の表示
		btfsc	gl_x,0		;gl_x % 2 = 0 か？
		goto	demo309		;No

		call	left_lower_upper ;(4) 左縁線(下→上)の表示

demo309		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		incf	gl_x,W
		andlw	h'0f'
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo308		;No

		decf	gl_y,F		;Y座標の更新
		incfsz	gl_x,W		;gl_x + 1 = 0 か？
		goto	demo307		;No

		decfsz	wr_chip,F	;対象チップ - 1 = 0: 終了 か？
		goto	demo306		;No

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	demo301		;No

		return

;--------------------------------------------------------------------------
;			　　　(3)
;			　　　→→
;		デモ-4	 (2)↑　　↑(4)
;			　　　→→
;			　　　(1)
;--------------------------------------------------------------------------

demo4_display
;		左下→右下方向と 左下→左上方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	2
		movwf	lpcnt		;ループカウンタの初期設定

demo401		movlw	1
		movwf	wr_chip		;対象チップ(下縁線用) = 1: 左側選択
		movlw	7
		movwf	gl_y		;Y座標(左縁線用)の初期設定

demo402		clrf	gl_x		;X座標(下縁線用)の初期設定

demo403		movlw	h'80'
		movwf	wr_data		;WriteData(左縁線用)の初期設定

demo404		call	lower_left_right ;(1) 下縁線(左→右)の表示
		btfss	gl_x,0		;gl_x % 2 = 1 か？
		goto	demo405		;No

		call	left_lower_upper ;(2) 左縁線(下→上)の表示

demo405		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		movlw	h'0f'
		andwf	gl_x,W
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo404		;No

		decf	gl_y,F		;Y座標の更新
		btfss	gl_x,6		;gl_x = 64 か？
		goto	demo403		;No

		incf	wr_chip,F	;対象チップの更新
		movlw	h'3'
		subwf	wr_chip,W
		btfss	STATUS,Z	;対象チップ = 3: 終了 か？
		goto	demo402		;No

;		左上→右上方向と 右下→右上方向に ドット増(lpcnt=2)／減(lpcnt=1)移行

		movlw	1
		movwf	wr_chip		;対象チップ(上縁線用) = 1: 左側選択
		movlw	7
		movwf	gl_y		;Y座標(右縁線用)の初期設定

demo406		clrf	gl_x		;X座標(上縁線用)の初期設定

demo407		movlw	h'80'
		movwf	wr_data		;WriteData(右縁線用)の初期設定

demo408		call	upper_left_right  ;(3) 上縁線(左→右)の表示
		btfss	gl_x,0		;gl_x % 2 = 1 か？
		goto	demo409		;No

		call	right_lower_upper ;(4) 右縁線(下→上)の表示

demo409		call	xwait_xxms	;ウェイト

		;繰り返しチェック
		movlw	h'0f'
		andwf	gl_x,W
		btfss	STATUS,Z	;gl_x % 16 = 0 か？
		goto	demo408		;No

		decf	gl_y,F		;Y座標の更新
		btfss	gl_x,6		;gl_x = 64 か？
		goto	demo407		;No

		incf	wr_chip,F	;対象チップの更新
		movlw	h'3'
		subwf	wr_chip,W
		btfss	STATUS,Z	;対象チップ = 3: 終了 か？
		goto	demo406		;No

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	demo401		;No

		return

;--------------------------------------------------------------------------

;		上縁線(左→右)の表示

upper_left_right
		movf	wr_chip,W
		movwf	gl_chip		;チップ選択 (1: 左側 / 2: 右側) (可変)
		movf	gl_x,W
		btfss	STATUS,Z	;gl_x = 0 か？
		goto	ulr01		;No

		btfss	wr_chip,1	;wr_chip = 2: 右側 か？
		goto	ulr03		;No. (gl_x = 0) & (wr_chip = 1)
		goto	ulr02

ulr01		movlw	63
		subwf	gl_x,W
		btfss	STATUS,Z	;gl_x = 63 か？
		goto	ulr02		;No

		btfss	wr_chip,0	;wr_chip = 1: 左側 か？
		goto	ulr03		;No. (gl_x = 63) & (wr_chip = 2)

ulr02		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標 = 0～63 (可変)
		clrw
		call	xGlcd_SetPage	;Y座標 = 0 (固定)
		movlw	h'01'		;WriteData = h'01'
		btfss	lpcnt,1		;lpcnt = 2 か？
		clrw			;No. WriteData = h'00'
		call	xGlcd_WriteData	;上縁線の書き込み

ulr03		incf	gl_x,F		;X座標の更新
		return

;--------------------------------------------------------------------------

;		上縁線(右→左)の表示

upper_right_left
		movf	wr_chip,W
		movwf	gl_chip		;チップ選択 (1: 左側 / 2: 右側) (可変)
		movlw	63
		subwf	gl_x,W
		btfss	STATUS,Z	;gl_x = 63 か？
		goto	url01		;No

		btfss	wr_chip,0	;wr_chip = 1: 左側 か？
		goto	url03		;No. (gl_x = 63) & (wr_chip = 2)
		goto	url02

url01		movf	gl_x,W
		btfss	STATUS,Z	;gl_x = 0 か？
		goto	url02		;No

		btfss	wr_chip,1	;wr_chip = 2: 右側 か？
		goto	url03		;No. (gl_x = 0) & (wr_chip = 1)

url02		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標 = 63～0 (可変)
		clrw
		call	xGlcd_SetPage	;Y座標 = 0 (固定)
		movlw	h'01'		;WriteData = h'01'
		btfss	lpcnt,1		;lpcnt = 2 か？
		clrw			;No. WriteData = h'00'
		call	xGlcd_WriteData	;上縁線の書き込み

url03		decf	gl_x,F		;X座標の更新
		return

;--------------------------------------------------------------------------

;		下縁線(左→右)の表示

lower_left_right
		movf	wr_chip,W
		movwf	gl_chip		;チップ選択 (1: 左側 / 2: 右側) (可変)
		movf	gl_x,W
		btfss	STATUS,Z	;gl_x = 0 か？
		goto	llr01		;No

		btfss	wr_chip,1	;wr_chip = 2: 右側 か？
		goto	llr03		;No. (gl_x = 0) & (wr_chip = 1)
		goto	llr02

llr01		movlw	63
		subwf	gl_x,W
		btfss	STATUS,Z	;gl_x = 63 か？
		goto	llr02		;No

		btfss	wr_chip,0	;wr_chip = 1: 左側 か？
		goto	llr03		;No. (gl_x = 63) & (wr_chip = 2)

llr02		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標 = 0～63 (可変)
		movlw	7
		call	xGlcd_SetPage	;Y座標 = 7 (固定)
		movlw	h'80'		;WriteData = h'80'
		btfss	lpcnt,1		;lpcnt = 2 か？
		clrw			;No. WriteData = h'00'
		call	xGlcd_WriteData	;上縁線の書き込み (固定)

llr03		incf	gl_x,F		;X座標の更新
		return

;--------------------------------------------------------------------------

;		下縁線(右→左)の表示

lower_right_left
		movf	wr_chip,W
		movwf	gl_chip		;チップ選択 (1: 左側 / 2: 右側) (可変)
		movlw	63
		subwf	gl_x,W
		btfss	STATUS,Z	;gl_x = 63 か？
		goto	lrl01		;No

		btfss	wr_chip,0	;wr_chip = 1: 左側 か？
		goto	lrl03		;No.  (gl_x = 63) & (wr_chip = 2)
		goto	lrl02

lrl01		movf	gl_x,W
		btfss	STATUS,Z	;gl_x = 0 か？
		goto	lrl02		;No

		btfss	wr_chip,1	;wr_chip = 2: 右側 か？
		goto	lrl03		;No. (gl_x = 0) & (wr_chip = 1)

lrl02		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標 = 63～0 (可変)
		movlw	7
		call	xGlcd_SetPage	;Y座標 = 7 (固定)
		movlw	h'80'		;WriteData = h'80'
		btfss	lpcnt,1		;lpcnt = 2 か？
		clrw			;No. WriteData = h'00'
		call	xGlcd_WriteData	;上縁線の書き込み (固定)

lrl03		decf	gl_x,F		;X座標の更新
		return

;--------------------------------------------------------------------------

;		左縁線(上→下)の表示

left_upper_lower
		movlw	1
		movwf	gl_chip		;対象チップ = 1: 左側選択 (固定)
		clrw
		call	xGlcd_SetColumn	;X座標 = 0 (固定)
		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標 = 0～7 (可変)
		movf	wr_data,W	;WriteData = h'01',h'03',h'07',h'0f',h'1f',h'3f',h'7f',h'ff'
		btfss	lpcnt,0		;lpcnt = 1 か？
		goto	lul01		;No

		xorlw	h'ff'		;反転値    = h'fe',h'fc',h'f8',h'f0',h'e0',h'c0',h'80',h'00'

lul01		call	xGlcd_WriteData	;左縁線の書き込み (可変)
		bsf	STATUS,C
		rlf	wr_data,F	;WriteDataの更新
		return

;--------------------------------------------------------------------------

;		左縁線(下→上)の表示

left_lower_upper
		movlw	1
		movwf	gl_chip		;対象チップ =1: 左側選択 (固定)
		clrw
		call	xGlcd_SetColumn	;X座標 = 0 (固定)
		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標 = 7～0 (可変)
		movf	wr_data,W	;WriteData = h'80',h'c0',h'e0',h'f0',h'f8',h'fc',h'fe',h'ff'
		btfss	lpcnt,0		;lpcnt = 1 か？
		goto	llu01		;No

		xorlw	h'ff'		;反転値    = h'7f',h'3f',h'1f',h'0f',h'07',h'03',h'01',h'00'

llu01		call	xGlcd_WriteData	;右縁線の書き込み (可変)
		bsf	STATUS,C
		rrf	wr_data,F	;WriteDataの更新
		return

;--------------------------------------------------------------------------

;		右縁線(上→下)の表示

right_upper_lower
		movlw	2
		movwf	gl_chip		;対象チップ = 2: 右側選択 (固定)
		movlw	63
		call	xGlcd_SetColumn	;X座標 = 63 (固定)
		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標 = 0～7 (可変)
		movf	wr_data,W	;WriteData = h'01',h'03',h'07',h'0f',h'1f',h'3f',h'7f',h'ff'
		btfss	lpcnt,0		;lpcnt = 1 か？
		goto	rul01		;No

		xorlw	h'ff'		;反転値    = h'fe',h'fc',h'f8',h'f0',h'e0',h'c0',h'80',h'00'

rul01		call	xGlcd_WriteData	;右縁線の書き込み (可変)
		bsf	STATUS,C
		rlf	wr_data,F	;WriteDataの更新
		return

;--------------------------------------------------------------------------

;		右縁線(下→上)の表示

right_lower_upper
		movlw	2
		movwf	gl_chip		;対象チップ = 2: 右側選択 (固定)
		movlw	63
		call	xGlcd_SetColumn	;X座標 = 63 (固定)
		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標 = 7～0 (可変)
		movf	wr_data,W	;WriteData = h'80',h'c0',h'e0',h'f0',h'f8',h'fc',h'fe',h'ff'
		btfss	lpcnt,0		;lpcnt = 1 か？
		goto	rlu01		;No

		xorlw	h'ff'		;反転値    = h'7f',h'3f',h'1f',h'0f',h'07',h'03',h'01',h'00'

rlu01		call	xGlcd_WriteData	;右縁線の書き込み (可変)
		bsf	STATUS,C
		rrf	wr_data,F	;WriteDataの更新
		return

;--------------------------------------------------------------------------
;		上下左右縁枠の表示と消去
;--------------------------------------------------------------------------

;入力:		gl_on:	0:縁枠の消去 / 1:縁枠の表示

edge_frame
		;上縁線 の表示(消去)
		movlw	3
		movwf	gl_chip		;3: 左側と右側選択
	
		clrw
		call	xGlcd_SetPage	;Y座標 = 0
		clrf	gl_x		;X座標の初期設定
		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標
		movlw	h'01'
		btfss	gl_on,0		;1:縁枠の表示 か？
		clrw			;No. 消去

frm01		call	xGlcd_WriteData	;h'01' (上縁線) 書き込み
		incf	gl_x,F		;X座標の更新
		btfss	gl_x,6		;X座標 = 64 終了か？
		goto	frm01		;No

		;下縁線 の表示(消去)
		movlw	7
		call	xGlcd_SetPage	;Y座標 = 7
		clrf	gl_x		;X座標の初期設定
		movf	gl_x,W
		call	xGlcd_SetColumn	;X座標
		movlw	h'80'
		btfss	gl_on,0		;1:縁枠の表示 か？
		clrw			;No. 消去

frm02		call	xGlcd_WriteData	;h'80' (下縁線) 書き込み
		incf	gl_x,F		;X座標の更新
		btfss	gl_x,6		;X座標 = 64 終了か？
		goto	frm02		;No

		;右縁線 の表示(消去)
		decf	gl_chip,F	;2: 右側選択
		clrf	gl_y		;Y座標の初期設定

frm03		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標
		movlw	63
		call	xGlcd_SetColumn	;X座標 = 63
		movlw	h'ff'
		btfss	gl_on,0		;1:縁枠の表示 か？
		clrw			;No. 消去
		call	xGlcd_WriteData	;h'ff' (右縁線) 書き込み

		incf	gl_y,F		;Y座標の更新
		btfss	gl_y,3		;Y座標 = 8 終了か？
		goto	frm03		;No

		;左縁線 の表示(消去)
		decf	gl_chip,F	;1: 左側選択
		clrf	gl_y		;Y座標の初期設定

frm04		movf	gl_y,W
		call	xGlcd_SetPage	;Y座標
		clrw
		call	xGlcd_SetColumn	;X座標 = 0
		movlw	h'ff'
		btfss	gl_on,0		;1:縁枠の表示 か？
		clrw			;No. 消去
		call	xGlcd_WriteData	;h'ff' (左縁線) 書き込み

		incf	gl_y,F		;Y座標の更新
		btfss	gl_y,3		;Y座標 = 8 終了か？
		goto	frm04		;No

		return

;--------------------------------------------------------------------------

xGlcd_SetColumn
		bcf	PCLATH,3	;Page 0
		call	Glcd_SetColumn	;G_LCD の Column (横位置) の指定
		bsf	PCLATH,3	;Page 1
		return

xGlcd_SetPage
		bcf	PCLATH,3	;Page 0
		call	Glcd_SetPage	;G_LCD の Page (縦位置) の指定
		bsf	PCLATH,3	;Page 1
		return

xGlcd_WriteData
		bcf	PCLATH,3	;Page 0
		call	Glcd_WriteData	;G_LCD へ データを出力
		bsf	PCLATH,3	;Page 1
		return

xwait_xxms
		movlw	10		;ミリ秒単位
		bcf	PCLATH,3	;Page 0
		call	wait_x1ms	;1x m秒 ウェイトルーチン
		bsf	PCLATH,3	;Page 1
		return

;==========================================================================
;		LARGE モード サブルーチン
;==========================================================================

		org	h'1000'		;Page2

;--------------------------------------------------------------------------
;		年月 (yyyy/mm) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit7:年(上位) / 6:年(下位) / 5:月 ）

yyyymm_display_lg

		;年 (上位2桁 yy) の表示
		clrf	gl_x		;X座標 = 0
		clrf	gl_y		;Y座標 = 0
		btfsc	sel_flag,7	;選択フラグ = bit7: 年(上位2桁) か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_yh,W	;年(上位2桁) BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_yh,W	;年(上位2桁) BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

		;年 (下位2桁 yy/) の表示
		incf	gl_x,F
		btfsc	sel_flag,6	;選択フラグ = bit6: 年(下位2桁) か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_yl,W	;年(下位2桁) BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_yl,W	;年(下位2桁) BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a'/'
		call	Glcd_DispChr_lg

		;月 (mm) の表示
		incf	gl_x,F
		btfsc	sel_flag,5	;選択フラグ = bit5: 月 か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_nn,W	;月 BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_nn,W	;月 BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

	;;	return
		bcf	PCLATH,4	;; Page 0
		goto	yym06		;; 戻る (2/5)

;--------------------------------------------------------------------------

;		BCD から数字へ変換表示

number_disp_lg
		andlw	h'0f'
		iorlw	h'30'
		call	Glcd_DispChr_lg
		return

;--------------------------------------------------------------------------
;		24H / 12H (  /am/pm) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit3=1: 24H/12H, 0: (  /am/pm) ）
;		timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

ampm_display_lg
		;24H / 12H (  /am/pm) 表示エリアの h'00'クリア
		movlw	6
		movwf	gl_x		;X座標 = 6
		movlw	3
		btfsc	modeflg,1	;SETモード か？
		movlw	2		;Yes
		movwf	gl_y		;Y座標 = 3 / 2

		call	space_clear	;３文字スペース（ゼロ）クリア
		incf	gl_x,F
		call	space_clear
		incf	gl_x,F
		call	space_clear

		movlw	6
		movwf	gl_x		;X座標 = 6

		btfsc	sel_flag,3	;選択フラグ <> bit3: 24H / 12H か？
		goto	ampmg03		;No

		;(  /am/pm) の表示
		btfss	timeflg,0	;bit0=1: 12H か？
		goto	ampmg04		;No

		btfsc	timeflg,1	;bit1=0: am か？
		goto	ampmg01		;No

		movlw	high font_small_a
		movwf	gl_tbl_h	;
		movlw	low font_small_a
		movwf	gl_tbl_l	;
		goto	ampmg02

ampmg01		movlw	high font_small_p
		movwf	gl_tbl_h	;
		movlw	low font_small_p
		movwf	gl_tbl_l	;

ampmg02		clrw
		call	Glcd_DispChr_lg
		incf	gl_x,F

		movlw	high font_small_m
		movwf	gl_tbl_h	;
		movlw	low font_small_m
		movwf	gl_tbl_l	;
		clrw
		call	Glcd_DispChr_lg
		goto	ampmg04

		;24H / 12H の表示
ampmg03		bsf	gl_y,7		;反転表示指示

		movlw	a'2'
		btfsc	timeflg,0	;bit0=0: 24H か？
		movlw	a'1'		;No
		call	Glcd_DispChr_lg
		incf	gl_x,F

		movlw	a'4'
		btfsc	timeflg,0	;bit0=0: 24H か？
		movlw	a'2'		;No
		call	Glcd_DispChr_lg
		incf	gl_x,F

		movlw	high font_large_h
		movwf	gl_tbl_h	;
		movlw	low font_large_h
		movwf	gl_tbl_l	;
		clrw
		call	Glcd_DispChr_lg
		bcf	gl_y,7		;反転表示指示解除

ampmg04	;;	return
		bcf	PCLATH,4	;; Page 0
		goto	ampm07		;; 戻る (3/5)

;--------------------------------------------------------------------------

;		１文字スペース（ゼロ）クリア

space_clear
		movlw	low font_space
		movwf	gl_tbl_l	;spaceフォントデータの先頭 low アドレス
		movlw	high font_space
		movwf	gl_tbl_h	;spaceフォントデータの先頭 high アドレス
		clrw
		call	Glcd_DispChr_lg
		return

;--------------------------------------------------------------------------
;		時分秒 (hh:mm:ss) の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit2:時 / 1:分 / 0:秒 ）
;		timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

time_display_lg
		;時 (hh:) の表示
		movlw	1
		movwf	gl_x		;X座標 = 1
		movlw	6
		btfsc	modeflg,1	;SETモード か？
		movlw	4		;Yes
		movwf	gl_y		;Y座標 = 6 / 4

		btfsc	sel_flag,2	;選択フラグ = bit2: 時 か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_hh,W	;No. 時 BCD カウンタ 上位4ビット
		btfss	timeflg,0	;時間表示フラグ = 12H か？
		goto	timg01		;No. 24H

		bcf	PCLATH,4	;Page 0
		call	cnv_24to12	;24時間表示を12時間表示に変換
		bsf	PCLATH,4	;Page 2
		swapf	temp_hh,W	;仮の 時 BCD カウンタ 上位4ビット
		andlw	h'0f'
		btfss	STATUS,Z	;上位4ビット = 0 か？
		goto	timg01		;No

		call	space_clear	;ゼロサプレス
		goto	timg02

timg01		call	number_disp_lg

timg02		incf	gl_x,F
		movf	temp_hh,W	;仮の 時 BCD カウンタ 下位4ビット
		btfss	timeflg,0	;時間表示フラグ = 12H か？
		movf	bcd_hh,W	;No. 時 BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a':'
		call	Glcd_DispChr_lg

		;分 (mm:) の表示
		incf	gl_x,F
		btfsc	sel_flag,1	;選択フラグ = bit1: 分 か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_mm,W	;分 BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_mm,W	;分 BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

		incf	gl_x,F
		movlw	a':'
		call	Glcd_DispChr_lg

		;秒 (ss) の表示
		incf	gl_x,F
		btfsc	sel_flag,0	;選択フラグ = bit0: 秒 か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_ss,W	;秒 BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_ss,W	;秒 BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

	;;	return
		bcf	PCLATH,4	;; Page 0
		goto	tim08		;; 戻る (4/5)

;--------------------------------------------------------------------------
;		カレンダー（日と曜日）の表示
;--------------------------------------------------------------------------

;入力:		sel_flag: 選択フラグ（ bit4:日 ）
;		timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

calendar_display_lg
		;日 (/dd) の表示
		movlw	7
		movwf	gl_x		;X座標 = 7
		clrf	gl_y		;Y座標 = 0

		movlw	a'/'
		call	Glcd_DispChr_lg

		incf	gl_x,F
		btfsc	sel_flag,4	;選択フラグ = 4: 日 か？
		bsf	gl_y,7		;Yes. 反転表示指示

		swapf	bcd_dd,W	;日 BCD カウンタ 上位4ビット
		call	number_disp_lg

		incf	gl_x,F
		movf	bcd_dd,W	;日 BCD カウンタ 下位4ビット
		call	number_disp_lg
		bcf	gl_y,7		;反転表示指示解除

		;曜日 (xxx) の表示
		movlw	2
		movwf	gl_x		;X座標 = 2
		movlw	3
		btfsc	modeflg,1	;SETモード か？
		movlw	2		;Yes
		movwf	gl_y		;Y座標 = 3 / 2

		bcf	PCLATH,4	;Page 0
		call	first_week	;該当月の先頭曜日の取得
		bsf	PCLATH,4	;Page 2

		movf	bcd_dd,W
		bcf	PCLATH,4	;Page 0
		call	bcd2_to_binary	;BCD (2桁) からバイナリ変換
		bsf	PCLATH,4	;Page 2

		addwf	cur_week,F
		decf	cur_week,F	;-1 しておく
caleng01	movlw	7
		subwf	cur_week,W
		btfss	STATUS,C	;cur_week >= 7 か？
		goto	caleng02	;No

		movwf	cur_week
		goto	caleng01

caleng02	movf	cur_week,W
		movwf	addr_low	;
		clrf	addr_high

		bcf	STATUS,C	;6倍する
		rlf	addr_low,F	;2倍
		movf	addr_low,W	;W に一時退避
		rlf	addr_low,F	;4倍
		addwf	addr_low,F	;6倍

		movlw	low week_string_tbl
		addwf	addr_low,F	;曜日文字列テーブルの先頭 low アドレス
		btfsc	STATUS,C	;オーバーフローした場合は
		incf	addr_high,F	;曜日文字列テーブルの先頭 high の更新

		movlw	high week_string_tbl
		addwf	addr_high,F	;曜日文字列テーブルの先頭 high アドレス

		movlw	3
		movwf	lpcnt		;ループカウンタ

caleng03	call	str_read_lg	;文字列から１文字読み出し
		movwf	gl_tbl_h	;
		incf	addr_low,F	;曜日文字列テーブルアドレス low の更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;曜日文字列テーブルアドレス high の更新

		call	str_read_lg	;文字列から１文字読み出し
		movwf	gl_tbl_l	;
		incf	addr_low,F	;曜日文字列テーブルアドレス low の更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;曜日文字列テーブルアドレス high の更新

		clrw			;文字コードによらないデータパタンの出力
		call	Glcd_DispChr_lg	;LCD へデータを１文字出力
		incf	gl_x,F		;X座標の更新

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	caleng03	;No

	;;	return
		bcf	PCLATH,4	;; Page 0
		goto	calen11		;; 戻る (5/5)

;		文字列から１文字読み出し
str_read_lg
		movf	addr_high,W	;読み出すデータの high アドレス
		movwf	PCLATH
		movf	addr_low,W	;読み出すデータの low アドレス
		movwf	PCL

;--------------------------------------------------------------------------

;		曜日文字列テーブル	0: Sun ～ 6: Sat

week_string_tbl
		retlw	high font_large_s	;0	;S
		retlw	low  font_large_s
		retlw	high font_small_u		;u
		retlw	low  font_small_u
		retlw	high font_small_n		;n
		retlw	low  font_small_n

		retlw	high font_large_m	;1	;M
		retlw	low  font_large_m
		retlw	high font_small_o		;o
		retlw	low  font_small_o
		retlw	high font_small_n		;n
		retlw	low  font_small_n

		retlw	high font_large_t	;2	;T
		retlw	low  font_large_t
		retlw	high font_small_u		;u
		retlw	low  font_small_u
		retlw	high font_small_e		;e
		retlw	low  font_small_e

		retlw	high font_large_w	;3	;W
		retlw	low  font_large_w
		retlw	high font_small_e		;e
		retlw	low  font_small_e
		retlw	high font_small_d		;d
		retlw	low  font_small_d

		retlw	high font_large_t	;4	;T
		retlw	low  font_large_t
		retlw	high font_small_h		;h
		retlw	low  font_small_h
		retlw	high font_small_u		;u
		retlw	low  font_small_u

		retlw	high font_large_f	;5	;F
		retlw	low  font_large_f
		retlw	high font_small_r		;r
		retlw	low  font_small_r
		retlw	high font_small_i		;i
		retlw	low  font_small_i

		retlw	high font_large_s	;6	;S
		retlw	low  font_large_s
		retlw	high font_small_a		;a
		retlw	low  font_small_a
		retlw	high font_small_t		;t
		retlw	low  font_small_t

;==========================================================================
;		キャラクタ文字 (横:12 x 縦:16) の表示
;		座標: (0,0) ～ (9,7)	1行 = 10文字表示
;==========================================================================

;入力:		W reg:  表示文字コード (h'00',h'2f'～h'3a')
;		gl_x: X座標 (0～9),	
;		gl_y: Y座標 (0～7) + bit7=1: 反転表示指示
;	      W reg = 0 のとき:
;		gl_tbl_h, gl_tbl_l: 任意文字フォントデータの先頭アドレス

Glcd_DispChr_lg
		movwf	gl_temp		;文字コードを退避

		clrf	gl_chip
		incf	gl_chip,F	;1: 左側選択

		movf	gl_x,W
		movwf	gl_temp1	;X座標

		movlw	5
		subwf	gl_temp1,W
		btfss	STATUS,C	;gl_temp1 >= 5 か？
		goto	gchrg01		;No

		movwf	gl_temp1	;gl_temp1 - 5
		incf	gl_chip,F	;2: 右側選択

gchrg01		bcf	STATUS,C	;X座標 * 12
		rlf	gl_temp1,F
		rlf	gl_temp1,F
		movf	gl_temp1,W
		rlf	gl_temp1,F
		addwf	gl_temp1,F	;Column (0,12,24,36,48)

		btfss	gl_chip,0	;1: 左側選択 か？
		goto	gchrg02		;No

		movlw	4
		addwf	gl_temp1,F	;Column (4,16,28,40,52)

gchrg02		movf	gl_y,W
		movwf	gl_temp2	;Y座標
		movf	gl_temp,W	;表示する文字コード
		btfsc	STATUS,Z	;gl_temp <> 0 か？
		goto	gchrg03		;No

;		1 文字フォントデータパタンの出力
;		入力:	W: 文字データ (h'2f'～h'3a')

		movwf	gl_tbl_l	;表示する文字コードを退避
		clrf	gl_tbl_h

		movlw	h'2f'		;h'2f'がテーブルの先頭位置
		subwf	gl_tbl_l,F

		bcf	STATUS,C	;20倍する
		rlf	gl_tbl_l,F	;2倍
		rlf	gl_tbl_l,F	;4倍
		movf	gl_tbl_l,W	;W に一時退避
		rlf	gl_tbl_l,F	;8倍
		rlf	gl_tbl_l,F	;16倍
		addwf	gl_tbl_l,F	;20倍 ... 一時退避した値を足す

		movlw	low font10x14_data_tbl
		addwf	gl_tbl_l,F	;文字フォントデータの先頭 low アドレス
		btfsc	STATUS,C	;オーバーフローした場合は
		incf	gl_tbl_h,F	;文字フォントデータアドレス high の更新

		movlw	high font10x14_data_tbl
		addwf	gl_tbl_h,F	;文字フォントデータの先頭 high アドレス

;		文字コードによらない 1 文字フォントデータパタンの出力
;		入力:	gl_tbl_h, gl_tbl_l: 任意文字フォントデータの先頭アドレス

gchrg03		movlw	2
		movwf	gl_cnt1		;ループカウンタ1 = 2 を設定

gchrg04		movf	gl_temp2,W	;Page (Y座標)
		andlw	h'7f'
		call	yGlcd_SetPage	;Page (縦位置) を指定
		movf	gl_temp1,W
		call	yGlcd_SetColumn	;Column (横位置) を指定

		movlw	10
		movwf	gl_cnt2		;ループカウンタ2 = 10 を設定

		clrw
		btfsc	gl_temp2,7	;反転表示指示 か？
		movlw	h'ff'		;Yes. ビット反転
		call	yGlcd_WriteData	;グラフィック LCD へ データを出力

gchrg05		call	table_read_lg	;文字フォントデータのテーブル読み出し
		movwf	gl_temp		;一時退避
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定

		btfss	gl_temp2,7	;反転表示指示 か？
		goto	gchrg06		;No

		movlw	h'ff'
		xorwf	gl_temp,F	;ビット反転

gchrg06		movf	gl_temp,W
		call	yGlcd_WriteData	;グラフィック LCD へ データを出力

		incf	gl_tbl_l,F	;文字フォントデータアドレス low の更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	gl_tbl_h,F	;文字フォントデータアドレス high の更新

		decfsz	gl_cnt2,F	;ループカウンタ2 - 1 = 0 か？
		goto	gchrg05		;No

		clrw
		btfsc	gl_temp2,7	;反転表示指示 か？
		movlw	h'ff'		;Yes. ビット反転
		call	yGlcd_WriteData	;グラフィック LCD へ データを出力

		incf	gl_temp2,F	;Page (Y座標)の更新
		decfsz	gl_cnt1,F	;ループカウンタ1 - 1 = 0 か？
		goto	gchrg04		;No

		return

;		文字フォントデータのテーブル読み出し

;入力:		gl_tbl_h: 文字フォントデータ high アドレス
;		gl_tbl_l: 文字フォントデータ low アドレス
;出力:		W: 文字フォントデータ

table_read_lg
		movf	gl_tbl_h,W	;文字フォントデータの high アドレス
		movwf	PCLATH
		movf	gl_tbl_l,W	;文字フォントデータの low アドレス
		movwf	PCL

;--------------------------------------------------------------------------

yGlcd_SetColumn
		bcf	PCLATH,4	;Page 0
		call	Glcd_SetColumn	;G_LCD の Column (横位置) の指定
		bsf	PCLATH,4	;Page 2
		return

yGlcd_SetPage
		bcf	PCLATH,4	;Page 0
		call	Glcd_SetPage	;G_LCD の Page (縦位置) の指定
		bsf	PCLATH,4	;Page 2
		return

yGlcd_WriteData
		bcf	PCLATH,4	;Page 0
		call	Glcd_WriteData	;G_LCD へ データを出力
		bsf	PCLATH,4	;Page 2
		return

;==========================================================================
;	文字フォント（10 x 14）データテーブル （グラフィック LCD 用）
;		h'2f'(/), h'30'(0) ～ h'39'(9), h'3a'(:) 
;==========================================================================

font10x14_data_tbl
		dt	h'00', h'00', h'00', h'00', h'80'	;/   h'2f'
		dt	h'c0', h'e0', h'70', h'38', h'18'
		dt	h'18', h'1c', h'0e', h'07', h'03'
		dt	h'01', h'00', h'00', h'00', h'00'

;		dt	h'f8', h'fc', h'0e', h'06', h'86'	;0   h'30'
;		dt	h'c6', h'e6', h'6e', h'fc', h'f8'
;		dt	h'1f', h'3f', h'76', h'67', h'63'
;		dt	h'61', h'60', h'70', h'3f', h'1f'

		dt	h'f8', h'fc', h'0e', h'06', h'06'	;0   h'30'
		dt	h'06', h'06', h'0e', h'fc', h'f8'
		dt	h'1f', h'3f', h'70', h'60', h'60'
		dt	h'60', h'60', h'70', h'3f', h'1f'

		dt	h'00', h'00', h'18', h'1c', h'fe'	;1   h'31'
		dt	h'fe', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'60', h'60', h'7f'
		dt	h'7f', h'60', h'60', h'00', h'00'

		dt	h'18', h'1c', h'0e', h'06', h'06'	;2   h'32'
		dt	h'06', h'86', h'ce', h'fc', h'78'
		dt	h'60', h'70', h'78', h'7c', h'6e'
		dt	h'67', h'63', h'61', h'60', h'60'

		dt	h'06', h'06', h'06', h'06', h'66'	;3   h'33'
		dt	h'f6', h'fe', h'9e', h'0e', h'06'
		dt	h'18', h'38', h'70', h'60', h'60'
		dt	h'60', h'61', h'73', h'3f', h'1e'

		dt	h'80', h'c0', h'e0', h'70', h'38'	;4   h'34'
		dt	h'1c', h'fe', h'fe', h'00', h'00'
		dt	h'07', h'07', h'06', h'06', h'06'
		dt	h'06', h'7f', h'7f', h'06', h'06'

		dt	h'7e', h'7e', h'66', h'66', h'66'	;5   h'35'
		dt	h'66', h'66', h'e6', h'c6', h'86'
		dt	h'18', h'38', h'70', h'60', h'60'
		dt	h'60', h'60', h'70', h'3f', h'1f'

		dt	h'e0', h'f0', h'b8', h'9c', h'8e'	;6   h'36'
		dt	h'86', h'86', h'86', h'00', h'00'
		dt	h'1f', h'3f', h'71', h'61', h'61'
		dt	h'61', h'61', h'73', h'3f', h'1e'

		dt	h'06', h'06', h'06', h'06', h'86'	;7   h'37'
		dt	h'c6', h'e6', h'76', h'3e', h'1e'
		dt	h'00', h'00', h'7e', h'7f', h'03'
		dt	h'01', h'00', h'00', h'00', h'00'

		dt	h'78', h'fc', h'ce', h'86', h'86'	;8   h'38'
		dt	h'86', h'86', h'ce', h'fc', h'78'
		dt	h'1e', h'3f', h'73', h'61', h'61'
		dt	h'61', h'61', h'73', h'3f', h'1e'

		dt	h'78', h'fc', h'ce', h'86', h'86'	;9   h'39'
		dt	h'86', h'86', h'8e', h'fc', h'f8'
		dt	h'00', h'00', h'61', h'61', h'61'
		dt	h'71', h'39', h'1d', h'0f', h'07'

		dt	h'00', h'00', h'00', h'70', h'70'	;:   h'3a'
		dt	h'70', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'00', h'1c', h'1c'
		dt	h'1c', h'00', h'00', h'00', h'00'

;--------------------------------------------------------------------------

font_space	dt	h'00', h'00', h'00', h'00', h'00'	;SP   h'20'
		dt	h'00', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'00', h'00', h'00'

font_large_f	dt	h'fe', h'fe', h'86', h'86', h'86'	;F   h'46'
		dt	h'86', h'86', h'86', h'06', h'06'
		dt	h'7f', h'7f', h'01', h'01', h'01'
		dt	h'01', h'01', h'01', h'00', h'00'

font_large_h	dt	h'fe', h'fe', h'80', h'80', h'80'	;H   h'48'
		dt	h'80', h'80', h'80', h'fe', h'fe'
		dt	h'7f', h'7f', h'01', h'01', h'01'
		dt	h'01', h'01', h'01', h'7f', h'7f'

font_large_m	dt	h'fe', h'fe', h'1c', h'78', h'e0'	;M   h'4d'
		dt	h'e0', h'78', h'1c', h'fe', h'fe'
		dt	h'7f', h'7f', h'00', h'00', h'01'
		dt	h'01', h'00', h'00', h'7f', h'7f'

font_large_s	dt	h'78', h'fc', h'ce', h'86', h'86'	;S   h'53'
		dt	h'86', h'86', h'86', h'0e', h'0c'
		dt	h'30', h'70', h'61', h'61', h'61'
		dt	h'61', h'61', h'73', h'3f', h'1e'

font_large_t	dt	h'06', h'06', h'06', h'06', h'fe'	;T   h'54'
		dt	h'fe', h'06', h'06', h'06', h'06'
		dt	h'00', h'00', h'00', h'00', h'7f'
		dt	h'7f', h'00', h'00', h'00', h'00'

font_large_w	dt	h'fe', h'fe', h'00', h'00', h'80'	;W   h'57'
		dt	h'80', h'00', h'00', h'fe', h'fe'
		dt	h'0f', h'1f', h'70', h'60', h'1f'
		dt	h'1f', h'60', h'70', h'1f', h'0f'

font_small_a	dt	h'00', h'40', h'60', h'60', h'60'	;a   h'61'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'18', h'3c', h'66', h'66', h'66'
		dt	h'66', h'66', h'36', h'7f', h'7f'

font_small_d	dt	h'80', h'c0', h'e0', h'60', h'60'	;d   h'64'
		dt	h'e0', h'c0', h'80', h'fe', h'fe'
		dt	h'1f', h'3f', h'70', h'60', h'60'
		dt	h'60', h'61', h'31', h'7f', h'7f'

font_small_e	dt	h'80', h'c0', h'e0', h'60', h'60'	;e   h'65'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'1f', h'3f', h'76', h'66', h'66'
		dt	h'66', h'66', h'66', h'27', h'03'

font_small_h	dt	h'fe', h'fe', h'80', h'c0', h'e0'	;h   h'68'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'7f', h'7f', h'01', h'01', h'00'
		dt	h'00', h'00', h'00', h'7f', h'7f'

font_small_i	dt	h'00', h'00', h'60', h'60', h'e6'	;i   h'69'
		dt	h'e6', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'60', h'60', h'7f'
		dt	h'7f', h'60', h'60', h'00', h'00'

font_small_m	dt	h'e0', h'e0', h'c0', h'60', h'c0'	;m   h'6d'
		dt	h'80', h'e0', h'60', h'c0', h'80'
		dt	h'7f', h'7f', h'00', h'00', h'07'
		dt	h'07', h'00', h'00', h'7f', h'7f'

font_small_n	dt	h'e0', h'e0', h'80', h'c0', h'e0'	;n   h'6e'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'7f', h'7f', h'03', h'01', h'00'
		dt	h'00', h'00', h'00', h'7f', h'7f'

font_small_o	dt	h'80', h'c0', h'e0', h'60', h'60'	;o   h'6f'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'1f', h'3f', h'70', h'60', h'60'
		dt	h'60', h'60', h'70', h'3f', h'1f'

font_small_p	dt	h'e0', h'e0', h'60', h'60', h'60'	;p   h'70'
		dt	h'60', h'60', h'60', h'c0', h'80'
		dt	h'7f', h'7f', h'06', h'06', h'06'
		dt	h'06', h'06', h'06', h'03', h'01'

font_small_r	dt	h'e0', h'e0', h'80', h'c0', h'e0'	;r   h'72'
		dt	h'60', h'60', h'e0', h'c0', h'80'
		dt	h'7f', h'7f', h'01', h'01', h'00'
		dt	h'00', h'00', h'00', h'01', h'01'

font_small_t	dt	h'60', h'60', h'fe', h'fe', h'60'	;t   h'74'
		dt	h'60', h'00', h'00', h'00', h'00'
		dt	h'00', h'00', h'1f', h'3f', h'70'
		dt	h'60', h'60', h'70', h'38', h'18'

font_small_u	dt	h'e0', h'e0', h'00', h'00', h'00'	;u   h'75'
		dt	h'00', h'00', h'00', h'e0', h'e0'
		dt	h'1f', h'3f', h'70', h'60', h'60'
		dt	h'70', h'38', h'18', h'7f', h'7f'

;==========================================================================
;		カレンダーデータのバックアップ (EEPROMへ書き込み)	     ... (Ver.1.21で移動)
;		( bcd_yh, bcd_yl, bcd_nn, bcd_dd, bcd_hh, bcd_mm, timeflg )
;==========================================================================

eeprom_write
		bcf	updtflg,3	;EEPROM制御要求フラグのクリア

		movlw	bcd_yh		;bcd_yy のアドレス
		movwf	FSR

		movlw	6		;bcd_yy ～ bcd_mm
		movwf	lpcnt		;ループカウンタを設定

		bsf	STATUS,RP1	;バンク 2
		movlw	eep_size	;EEPROM 格納先頭アドレス
		movwf	EEADR		;EEPROM の記録アドレスを設定
		bcf	STATUS,RP1	;バンク 0

eepw01		movf	INDF,W		;データの読み出し
		incf	FSR,F		;間接アドレス +1 更新

eepw02		bsf	STATUS,RP1	;バンク 2
		movwf	EEDATA		;書き込みデータを設定
		bsf	STATUS,RP0	;バンク 3
		bcf	EECON1,EEPGD	;データEEPROMメモリ
		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

		bcf	EECON1,WREN	;書き込みイネーブル = OFF
		bcf	STATUS,RP0	;バンク 2
		incf	EEADR,F		;EEPROM 格納アドレス +1 更新

		bcf	STATUS,RP1	;バンク 0
		movf	lpcnt,F
		btfsc	STATUS,Z	;終了 か？
		goto	eepw03		;Yes

		decfsz	lpcnt,F		;ループカウンタ - 1 = 0 か？
		goto	eepw01		;No

		movf	timeflg,W	;timeflg: 時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）
		goto	eepw02

eepw03		return

;==========================================================================
;		EEPROM エリア
;==========================================================================

		org	h'2100'

eep_st		de	"Copyright (C) 2014-2019 by M.Yamamoto"

		de	h'ff'

eep_size	equ	$ - eep_st	;EEPROM データサイズ

e_bcd_yh	de	h'20'		;年(上位2桁) BCD カウンタ
e_bcd_yl	de	h'14'		;年(下位2桁) BCD カウンタ
e_bcd_nn	de	h'11'		;月 BCD カウンタ
e_bcd_dd	de	h'01'		;日 BCD カウンタ
e_bcd_hh	de	h'00'		;時 BCD カウンタ
e_bcd_mm	de	h'00'		;分 BCD カウンタ
e_timeflg	de	h'00'		;時間表示フラグ（ bit0=0:24H / 1:12H,  bit1=0:am / 1:pm ）

;==========================================================================

		end			;プログラムの終了
