;***** StaticRamChecker.asm ***********************************************
;
;	簡易 S-RAM チェッカー
;
;	Copyright (C) 2010-2018   by M.Yamamoto. All rights reserved.
;
;     ( coding:  Ver. 0.00   2010/05/29  by M.Yamamoto )
;	coding:  Ver. 1.00   2010/07/01  初期バージョン
;	update:  Ver. 1.01   2010/07/17  スタートメッセージの変更
;	bugfix:  Ver. 1.02   2010/07/26  128KでのADDRESS更新を修正
;	update:  Ver. 1.03   2010/08/01  SRAMタイプの事前チェックの追加
;	update:  Ver. 1.04   2010/08/15  スタートメッセージの変更
;	bugfix:  Ver. 1.05   2018/06/19  データバスでのデータ衝突を修正
;	update:  Ver. 1.06   2018/06/21  チェック時間短縮の小改善の試み
;	update:  Ver. 1.07   2018/07/05  全チェックパタン実行の機能追加
;	update:  Ver. 1.07a  2018/07/26  コメント追加
;
;******************************************************* PicAsm 0222 ******

;	Device: PIC16F877A	Clock: 20MHz (セラロック)

#ifdef comment

 <機能概要>

・本装置は、今となっては既にレガシーなデバイスとなってしまった、８ビット幅のスタティックＲＡＭ
　（種類：２Ｋバイト、８Ｋバイト、３２Ｋバイト、６４Ｋバイト、１２８Ｋバイト）のメモリチェック
　を行なうのを目的とする。
・本装置は、電源スイッチをオンすると、"ピポッ" と起動ブザー音を出力後、液晶（ＬＣＤ）にスタート
　メッセージとして、次の文字列が約３秒間表示される。また同時に、BUSY(黄)、OK(緑)、NG(赤)の各 
　LED を、約１.５秒間細かく交互に点滅させて、点灯チェックも行う。
		"StaticRamChecker"
		"   ( 8 bit )    "
・その後、次のメッセージに切り替わって約１.５秒間表示され、その後には無表示が約１.５秒間続く。
		"    ver.x.xx    "
		"  by m.yamamoto "
・やがて無表示の後、次のような SRAM タイプの選択メッセージが表示され、初期値として 2K が選択さ
　れて、その直前の空白 " " の位置がブリンク表示されている。また同時に、"ピポッ" とブザー音を出
　力してユーザに選択の注意を喚起する。
		"Type?_  2K    8K"
		" 32K   64K  128K"
・これはユーザからのスイッチの入力待ちの状態を表し、←（LEFT）／ →（RIGHT）スイッチの操作によ
　って、自由に SRAM タイプの選択を行なうことができる。すなわちこのスイッチ操作によって "ポッ" 
　というブザー音とともにブリンク位置が移動し、今ブリンクしている直後の SRAM タイプが選択されて
　いることになる。
・ SRAM タイプを選択したなら、次に ENTER スイッチを押下することによりその選択が決定され、次のチ
　ェックのスタート促進メッセージが表示される。この時にもユーザの注意を喚起するため、"ピポッ" と
　ブザー音を出力する。
		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
		"                "
・そしてその後、ENTER スイッチが押下されればそのまま SRAM チェックがスタートすることになるが、
　もしここで何らかの理由により SRAM タイプの選択を変更したい場合には、BREAK スイッチを押下する
　ことによってチェックスタートされることなく、再び SRAM タイプの選択メッセージの表示に戻ること
　ができる。
・そのまま ENTER スイッチが押下されると、いよいよ SRAM チェックがスタートし "ピポッ" と開始ブザ
　ー音とともに、まず次のようなチェック進行メッセージが表示される。
		"<xxK>    Er:0000"
		"A:     W:   R:  "
・ここで機能の追加を行なった。機能の追加以前では、例え選択された SRAM タイプと実際にセットされ
　た SRAM が異なっていても、メモリチェックがスタートされてしまっていた。この場合に実際にはどん
　な影響が起こるのか良く分からないが、極端な場合にはＩＣ自体にもかなりのダメージを与えることも
　想像される。
・そこでメモリチェックがスタートされてしまう直前に、両者のタイプの整合性をチェックするように機
　能を追加した。整合性チェックがＯＫの場合のみ初めて、上記のようなチェック進行メッセージが表示
　されてチェックがスタートされる。
・整合性チェックがＮＧの場合には、次のようなタイプミスマッチエラー・メッセージが表示されるとと
　もに、結果 NG(赤LED) が点灯して同時に "ブッブー" というブザー音を出力して、整合性にエラーがあ
　ったことをユーザに知らせる。
	      ( "<xxK>   Start?_ " )
		"Type Mismatch !!"
・エラーを確認後、ENTER スイッチを押下することによって結果 NG(赤LED) を消灯させ、再び次のスター
　ト促進メッセージの表示に戻る。そこで、正しい SRAM タイプのＩＣをセットし直すか、またはこのス
　タート促進メッセージの表示で BREAK スイッチを押下することによって、再度 SRAM タイプの選択メッ
　セージの表示に戻って、SRAM タイプの選択からやり直すことになる。
		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
		"                "
・ただし、何らかの理由によりこの追加機能がひょっとして邪魔な場面があるかもしれない。そのための
　考慮として、ENTER スイッチを押下しながら POWER スイッチをＯＮした場合には、整合性チェックは一
　切機能しない。
・一方、メモリチェックがスタートされると上記のチェック進行メッセージが表示され、A: はアドレスを、
　W: は書き込みデータを、R: は読み出しデータをそれぞれ表し、":" の後にその内容が表示されてチェ
　ックの進行にしたがって刻々と変化をして行く。これらはすべて１６進数で表示され、通常は A:xxxx、
　W:xx、R:xx の形式で表示されるが、128K タイプの SRAM に限ってはそのアドレスは Axxxxx と表示さ
　れる。これはアドレスが 17 ビットあり１６進数４桁では表示できないためである。
・また、Er: はそのときまでに起こったエラー数を表示し、１６進数４桁表示であるが最大数を超えた場
　合にはオーバーフローして、また "0" からカウントをし直す。（１６進数４桁で表示し切れないような
　ものは、あきらかに異常な SRAM でありそのエラーの絶対数には、あまり意味を成さないためである）
・ただし、これらのチェック進行メッセージの内容表示がされるのは、LCD PASS スイッチ（SW6: DIP ス
　イッチの内の左端）が OFF に設定されている場合であり、ON に設定されている場合にはその内容表示
　はされない。これは液晶（ＬＣＤ）に表示するのに多くの時間を要し、メモリ容量の大きな SRAM では
　極端に時間がかかってしまうために、LCD PASS スイッチを設けたものである。ただし、エラー数表示に
　関しては LCD PASS スイッチの ON／OFF に係わらず、エラーがあった場合には常に更新表示される。
・また、SRAM をチェックするのに４つの方法が用意されており、それぞれ SELECT 1, 0 スイッチ（SW5: 
　DIP スイッチの内の真中、SW4: 右端）の設定で、自由に選択が可能である。
・この SRAM のチェックの進行中にエラーが多発したような場合で、もうこれ以上チェックを続行させて
　も無駄と判断した場合には、BREAK スイッチを押下することによって、いつでもチェックを中断し終了
　させることも可能である。ただし、エラーが起こってなくても BREAK スイッチを押下すれば、やはりチ
　ェックは中断終了してしまうのでそのスイッチの扱いには十分注意を要する。
・一方、次のチェックのスタート促進メッセージが表示されているときに、PAUSE (←（LEFT）スイッチと
　兼用) スイッチを押しながら ENTER スイッチを押下した場合には、エラー発生時にポーズ動作を行なう。
　すなわち、エラーが発生した場合には、その時点での A: アドレス、W: 書き込みデータ、R:読み出しデ
　ータの内容、および Er: エラー数が表示された状態で、一時的にチェックの進行が中断される。このと
　き、結果 NG(赤LED) が点灯するとともに "ブー" というブザー音も出力してエラー表示を行ない、ポー
　ズ状態に入ったことをユーザに知らせる。
		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
		"                "
・したがって、そのときの液晶（ＬＣＤ）に表示されている内容を確認した後、CONTINUE (→（RIGHT）ス
　イッチと兼用) スイッチを押下すると、結果 NG(赤LED) が消灯してこのポーズ状態から抜けチェックが
　続行される。この CONTINUE スイッチで続行しても、再度エラーが発生すれば再びポーズ状態に移行す
　ることになる。また、続行を中断したい場合には BREAK スイッチを押下すれば、やはりチェックは中断
　し終了処理に移行する。
・上記のように４つのチェック方法の相違によって、チェックから終了処理に至るまでの過程は違うもの
　の、やがてプログラミングされた予定の処理に終了を迎えた場合、または上記のように BREAK スイッチ
　によって強制的に中断終了させた場合に、終了処理に移行する。
・終了処理では、まず SRAM チェックの総合結果を LED の表示とブザー音の出力でユーザに知らせる。エ
　ラーがなく正常に終了した場合（ BREAK 終了も含む）には、結果 OK(緑LED) が点灯して同時に "ポッ
　ポッポッポッ" というブザー音を出力して正常終了をユーザに知らせる。また、エラーが１件以上あっ
　て終了した場合には、結果 NG(赤LED) が点灯して同時に "ブッブー" というブザー音を出力してエラー
　終了をユーザに知らせる。
・これでとりあえず１つの SRAM のチェックが終了したことになるが、続いて他の同タイプの SRAM のチ
　ェックを行ないたい場合には、ここで ENTER スイッチを押下すれば、再び以下のスタート促進メッセー
　ジが表示されるとともに、"ピポッ" とブザー音を出力してユーザの注意を喚起する。したがって、他の
　SRAM に交換して新たにチェックを行なう。
		"<xxK>   Start?_ "		; xxK 位置に選択された RAM タイプが入る
		"                "
・また、他のタイプの SRAM のチェックを行ないたい場合には、上記のスタート促進メッセージが表示さ
　れているときに BREAK スイッチを押下すれば、再び SRAM タイプの選択メッセージの表示に戻ることが
　できる。

機能追加											;;(Ver.1.07 で追加)
・チェックのスタート促進メッセージが表示されているときに、CONTINUE (→（RIGHT）スイッチと兼用) 
　スイッチを押しながら ENTER スイッチ を押下した場合 には、SELECT 1, 0 スイッチ（SW5: DIP スイ
　ッチの内の真中、SW4: 右端）の 指定にかかわらず、４つあるチェックパタンが (1) b'00'、(2) b'01'、
　(3) b'10'、(4) b'11' の順に、すべてを自動的に実行する。
・ただし、１つのチェックパタンが終了すると、その１つごとの総合的なチェック結果を表示し、ユーザ
　ー確認のために進行はそこで一時停止するので、 次のチェックパタンに移行するためにはユーザーの
　介入を要する。 すなわち、CONTINUE (→（RIGHT）スイッチ) スイッチ を押下することで次のチェッ
　クパタンに移行する。また、このとき何らかの理由により、次のチェックパタンに移行したくないとき
　には BREAK スイッチ を押下することで、自動実行を中止してスタート促進メッセージの表示に戻るこ
　とができいる。
・なお、チェック進行メッセージの表示中には、SELECT 1, 0 スイッチを見ればわかるので、今まではど
　のチェックパタンを実行しているのか LCD に表示がなかったが、全チェックパタンの自動実行の場合
　には（通常の動作の場合も含めて）、その区別を 1 ～ 4 の番号で LCD に表示するように改めた。
		"<xxK,x>  Er:0000"		; xxK 位置に選択された RAM タイプ、
		"A:     W:   R:  "		; ,x の位置にチェックパタン番号が入る
・ここでまとめておくと、チェックのスタート促進メッセージが表示されているときには、次の３つのキ
　ー操作方法がある。
　　　ENTER スイッチ					..........　通常の動作
　　　PAUSE (←（LEFT）) スイッチ ＋ ENTER スイッチ	..........　エラー発生時にポーズ動作
　　　CONTINUE (→（RIGHT）) スイッチ ＋ ENTER スイッチ ..........　全チェックパタンの自動実行

#endif

;==========================================================================

;	PIC16F877A のピンと用途

;	 (1) MCLR:マスター・クリア入力		(40) RB7: アドレス,データ D7 入出力
;	 (2) RA0: ENTER スイッチ入力		(39) RB6: アドレス,データ D6 入出力
;	 (3) RA1: LEFT← / PAUSE スイッチ入力　	(38) RB5: アドレス,データ D5 入出力
;	 (4) RA2: RIGHT→ / CONTI スイッチ入力	(37) RB4: アドレス,データ D4 入出力
;	 (5) RA3: BREAK スイッチ入力		(36) RB3: アドレス,データ D3 入出力
;	 (6) RA4: SELECT_0 スイッチ入力		(35) RB2: アドレス,データ D2 入出力
;	 (7) RA5: SELECT_1 スイッチ入力		(34) RB1: アドレス,データ D1 入出力
;　	 (8) RE0: ブザー音出力			(33) RB0: アドレス,データ D0 入出力
;	 (9) RE1: OK LED 出力			(32) VDD: 電源 +5V DC
;	(10) RE2: NG LED 出力			(31) VSS: 電源 GND
;	(11) VDD: 電源 +5V DC			(30) RD7: LCD DB7 信号 入出力制御
;	(12) VSS: 電源 GND			(29) RD6: LCD DB6 信号 入出力制御
;	(13) OSC1:オシレータ水晶入力		(28) RD5: LCD DB5 信号 入出力制御
;	(14) OSC2:オシレータ水晶入力		(27) RD4: LCD DB4 信号 入出力制御
;	(15) RC0: A16: 拡張アドレス 出力	(26) RC7: 74HC541(入力データ)-(INV) /G1,/G2出力
;	(16) RC1: 74HC574(出力データ)  CK出力	(25) RC6: 74HC273(コントロール)-(INV)  /CLR出力
;	(17) RC2: 74HC574(上位アドレス)CK出力	(24) RC5: 74HC273(コントロール) CK出力
;	(18) RC3: 74HC574(下位アドレス)CK出力	(23) RC4: 74HC574(出力データ)  /OE出力
;	(19) RD0: LCD E   信号 出力制御		(22) RD3: PASS  スイッチ入力
;	(20) RD1: LCD R/W 信号 出力制御		(21) RD2: LCD RS 信号 出力制御

;==========================================================================

	list		p=pic16f877a	;デバイス情報
	include		p16f877a.inc	;インクルードファイル
	errorlevel	-302		;Eliminate bank warning

	__config	_CP_OFF & _LVP_OFF & _BODEN_OFF & _PWRTE_ON & _WDT_OFF & _HS_OSC

;==========================================================================
;		変数の定義とレジスタ割付け
;==========================================================================

#define 	ver_no	"1.07"
#define		_bug_fixes		;(Ver.1.05 で追加)( 2018/06/19 )

;#define		_ddram_read		;LCD DDRAM 読み込みを使う場合
;#define		_table_conv		;テーブル変換を使用する場合

		radix	dec

SW		equ	PORTA		;各スイッチ入力ポート
TRIS_SW		equ	TRISA		;各スイッチ入力ポートの入出力切り替え
SRAM		equ	PORTB		;SRAM アドレスデータ用ポート
TRIS_RAM	equ	TRISB		;SRAM 用ポートの入出力切り替え
CONT		equ	PORTC		;コントロール用ポート
TRIS_CNT	equ	TRISC		;コントロール用ポートの入出力切り替え
LCD		equ	PORTD		;LCD 制御用ポート
TRIS_LCD	equ	TRISD		;LCD 制御用ポートの入出力切り替え
LED		equ	PORTE		;LED 制御用ポート
TRIS_LED	equ	TRISE		;LED 制御用ポートの入出力切り替え

_swE		equ	0		;ENTER スイッチ
_swL		equ	1		;LEFT  ← スイッチ
_swR		equ	2		;RIGHT → スイッチ
_swB		equ	3		;BREAK スイッチ
_sw0		equ	4		;SELECT_0 スイッチ
_sw1		equ	5		;SELECT_1 スイッチ
_swP		equ	3		;PASS  スイッチ (LCD)

ramOEb		equ	1		;SRAM /OE: アウトプットイネーブルのビット位置	;;(Ver.1.06 で追加)( 2018/06/21 )
ramWEb		equ	2		;SRAM /WE: ライトイネーブルのビット位置		;;
ramCS		equ	h'01'		;SRAM /CS: チップセレクト
ramOE		equ	h'02'		;SRAM /OE: アウトプットイネーブル
ramWE		equ	h'04'		;SRAM /WE: ライトイネーブル
ramCS2		equ	h'08'		;SRAM CS2: チップセレクト2
Vcc24		equ	h'20'		;SRAM Vcc = 24pin
Vcc28		equ	h'40'		;SRAM Vcc = 28pin
Vcc32		equ	h'80'		;SRAM Vcc = 32pin

PC0		equ	0		;A16: 拡張アドレス 16 ビット目
PC1		equ	1		;74HC574(出力データ)  フリップフロップ用 CK
PC2		equ	2		;74HC574(上位アドレス)フリップフロップ用 CK
PC3		equ	3		;74HC574(下位アドレス)フリップフロップ用 CK
PC4		equ	4		;74HC574(出力データ)-(INV) フリップフロップ用/OE
PC5		equ	5		;74HC273(コントロール)フリップフロップ用 CK
PC6		equ	6		;74HC273(コントロール)フリップフロップ用CLR
PC7		equ	7		;74HC541(入力データ)-(INV) バスバッファ用/G1,/G2

_E		equ	0		;LCD E:   動作起動信号
_RW		equ	1		;LCD R/W: 読み出し／書き込み選択信号
_RS		equ	2		;LCD RS:  レジスタ選択信号

_BF		equ	7		;LCD ビジーフラグ

_OK		equ	1		;結果 OK(緑LED)
_NG		equ	2		;結果 NG(赤LED)

buh		equ	high (65536 - 9555)	;ド (261.63 Hz)
bul		equ	low  (65536 - 9555)	;
pih		equ	high (65536 - 6377)	;ソ (392.00 Hz)
pil		equ	low  (65536 - 6377)	;
poh		equ	high (65536 - 4777)	;ド (523.26 Hz)
pol		equ	low  (65536 - 4777)	;

buulcnt		equ	250		;音長
bulcnt		equ	70		;音長
pilcnt		equ	70		;音長
polcnt		equ	70		;音長

		cblock  h'20'
lcdtmp					;LCD への入出力データの一時保存
ledcnt					;LED 点灯チェック用ループカウンタ
ramtyp					;選択 SRAM タイプ
rt_save					;選択 SRAM タイプの保存用
chkcnt					;整合性用ループカウンタ
sel_sw					;SELECT_0,1 スイッチの内容(正論理に変換後)

ddram_ad				;DDRAM のアドレスを保存
ddram_wk				;DDRAM のアドレスを保存
ram_idx					;文字列の保存エリアのインデックス
ram_type	;(00)			;選択 SRAM タイプ文字列の保存エリア
		;(01)
		;(02)
		;(03)
		endc

		cblock  ram_type + 4
addr_high				;読み出すデータの high アドレス
addr_low				;読み出すデータの low アドレス

const_high				;音階用分周定数 high の保存
const_low				;音階用分周定数 low の保存

wt1cnt					;ウェイト用ループカウンタ
wt2cnt					;ウェイト用ループカウンタ
wt3cnt					;ウェイト用ループカウンタ
wt4cnt					;ウェイト用ループカウンタ

ram_addr_e				;SRAM の ext アドレス
ram_addr_h				;SRAM の high アドレス
ram_addr_l				;SRAM の low アドレス
ram_data_i				;SRAM の 入力(読み出し)データ
ram_data_o				;SRAM の 出力(書き込み)データ
ram_data_w				;SRAM の 出力(書き込み)データ
ram_cont				;SRAM の コントロール出力
ram_err_h				;エラー数の high 値
ram_err_l				;エラー数の low  値
error_flg				;エラーフラグ
pause_flg				;ポーズフラグ
conti_flg				;コンティニューフラグ				;;(Ver.1.07 で追加)
break_flg				;ブレイクフラグ
adend_flg				;更新終了フラグ
pass_flg				;LCD 非表示フラグ
typchk_flg				;SRAM タイプ整合性チェックフラグ

max_addr_h				;SRAM アドレス MAX値の high
max_addr_l				;SRAM アドレス MAX値の low

rd1cnt					;SRAM 種類別テーブルの読み出し用ループカウンタ
rd2cnt					;SRAM 種類別テーブルの読み出し用ループカウンタ

cnvtmp					;変換データの一時保存
hextmp					;変換データの一時保存
		endc

		cblock	h'70'
w_save					;W レジスタの保存用（割り込み処理で使用）
s_save					;STATUS レジスタの保存用（割り込み処理で使用）
		endc

;==========================================================================
;		マクロ命令定義
;==========================================================================

;		LCD メッセージデータ１／２行表示マクロ

;		@x=1: １行表示, @x=2: ２行表示

Disp_Lcd	macro	@com,@msg,@x
		movlw	@com
		call	lcd_cmd		;LCD へコマンドを出力
		movlw	high @msg	;メッセージデータの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low @msg	;メッセージデータの先頭アドレスの low アドレス
		movwf	addr_low	;
		call	lcd_disp	;メッセージデータ１行目表示
	#if 	@x == 1
	#else
		movlw	b'11000000'	;２行目先頭にアドレスセット
		call	lcd_cmd		;LCD へコマンドを出力
		call	lcd_disp	;メッセージデータ２行目表示
	#endif
		endm

;		Flip-Flop ／ Buffer 設定マクロ

;		@x=0: W レジスタの内容, @x=1: リテラル, @x=2: F レジスタの内容

Flip_Flop_Set	macro	@dat,@clk,@x
	#if	@x == 0
	#else
	  #if	@x == 1
		movlw	@dat		;書き込みデータ
	  #else
		movf	@dat,W		;書き込みデータ
	  #endif
	#endif
		movwf	SRAM		;PIC のアドレス／データ／コントロール用ポートに出力
		bsf	CONT,@clk	;bitx=1: Flip-Flop CK
		nop
		bcf	CONT,@clk	;bitx=0
		endm

;==========================================================================
;		プログラム開始
;==========================================================================

		org	0		;リセットベクタ
		goto	init
		org	4		;割り込みベクタ
		goto	interrupt

;==========================================================================
;		初期化処理
;==========================================================================

		; PIC16F877A 初期設定
init
		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0
		clrf	ADCON0		;ADCON0 の設定, A/D 未使用

;		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		movlw	h'06'		;ポートA, E を ディジタルモード
		movwf	ADCON1		;ADCON1 の設定

		movlw	b'00111111'	;RA5-0: 入力
		movwf	TRIS_SW		;設定
		clrf	TRIS_RAM	;RB7-0: 出力 の設定
		clrf	TRIS_CNT	;RC7-0: 出力 の設定
		movlw	b'00001000'	;RD3: 入力, RD7-4,2-0: 出力
		movwf	TRIS_LCD	;設定
		clrf	TRIS_LED	;RE2-0: 出力 の設定

		movlw	h'80'		;プルアップ抵抗を使用しない
		movwf	OPTION_REG	;OPTION_REG の設定

		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止

;		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0
		movlw	b'00000001'	;bit7-6: 未使用
					;bit5-4=00: プリスケーラのスケール値 1:1
					;bit3=0: 専用の発振器を使う場合に指定
					;bit2=0: 外部入力クロック指定時に有効
					;bit1=0: 内部クロックを使う
					;bit0=1: タイマー１を動作
		movwf	T1CON		;T1CON に設定

		clrf	SRAM		;アドレスデータ用ポート
		movlw	b'01000000'	;bit6=1: 74HC273 /CLR
		movwf	CONT		;コントロール用ポート
		bcf	CONT,PC6	;bit6=0
		clrf	LCD		;LCD 制御用ポート
		clrf	LED		;LED, 圧電ブザー 制御用ポート

		clrf	typchk_flg	;SRAM タイプ整合性チェックフラグの初期設定
		btfss	SW,_swE		;ENTER スイッチ = ON か？
		bsf	typchk_flg,0	;Yes, 整合性チェックをパス

		; SC1602BS-B(LCD) 初期設定, スタートメッセージの表示

		call	lcd_init	;LCD の初期設定

		Disp_Lcd	b'00001100',start_msg,2	;表示ON

;			 0123456789ABCDEF

;			"StaticRamChecker",0
;			"   ( 8 bit )    ",0

		; ブザー音出力チェック

		bsf	INTCON,PEIE	;PEIE 周辺機器割り込みを許可
		bsf	INTCON,GIE	;GIE 全割り込み許可

		call	buzzer_pipo	;"ピポッ" ブザー音出力

		; BUSY(黄), OK(緑), NG(赤) LED 点灯／消灯チェック

		movlw	5
		movwf	ledcnt		;ループカウンタ

ledck		Flip_Flop_Set	Vcc32,PC5,1	;74HC273(コントロール) CK  → BUSY(黄LED) 点灯
		call	wait_100ms	;100m 秒 ウェイト
		bsf	CONT,PC6	;bit6=1: 74HC273(コントロール) CLR → BUSY(黄LED) 消灯
		nop
		bcf	CONT,PC6	;bit6=0

		bsf	LED,_OK		;結果 OK(緑LED) 点灯
		call	wait_100ms	;100m 秒 ウェイト
		bcf	LED,_OK		;結果 OK(緑LED) 消灯

		bsf	LED,_NG		;結果 NG(赤LED) 点灯
		call	wait_100ms	;100m 秒 ウェイト
		bcf	LED,_NG		;結果 NG(赤LED) 消灯

		decfsz	ledcnt,F	;ループカウンタ - 1 = 0 か？
		goto	ledck		;No

		call	wait_1500ms	;1.5 秒 ウェイトルーチン

		Disp_Lcd	b'00000001',start_msg2,2	;表示クリア

;			 0123456789ABCDEF

;			"    ver.x.xx    ",0
;			"  by m.yamamoto ",0

		call	wait_1500ms	;1.5 秒 ウェイトルーチン

		movlw	h'01'		;表示クリア
		call	lcd_cmd		;LCD へコマンドを出力

		call	wait_1500ms	;1.5 秒 ウェイトルーチン

;		btfsc	SW,_swE		;ENTER スイッチ = ON か？
;		goto	$ - 1		;No

;==========================================================================
;		メイン・ルーチン
;==========================================================================

main
		call	wait_500ms	;チャタリングを吸収

		; SRAM タイプ選択メッセージの表示

		Disp_Lcd	b'00000001',type_msg,2	;表示クリア

;			 0123456789ABCDEF

;			"Type?_  2K    8K",0
;			" 32K   64K  128K",0

		; SRAM タイプの選択 (LCD ブリンク位置決め)

		call	buzzer_pipo	;"ピポッ" ブザー音出力
		call	wait_500ms
		clrf	ramtyp		;選択 SRAM タイプの初期設定

		movlw	b'00001101'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=1: ブリンク

main01		movf	ramtyp,W	;選択 SRAM タイプを W へロード
		call	blink_tbl_read	;ブリンク位置テーブル読み込み
		movwf	ddram_ad	;DDRAM のアドレスを保存
		iorlw	h'80'		;DDRAM のアドレス(ブリンク位置)をセット
		call	lcd_cmd		;LCD へコマンドを出力

		btfss	SW,_swE		;ENTER スイッチ = ON か？
		goto	main02		;Yes

		btfss	SW,_swL		;←(LEFT)スイッチ = ON か？
		call	left_switch	;Yes

		btfss	SW,_swR		;→(RIGHT)スイッチ = ON か？
		call	right_switch	;Yes
		goto	main01

main02		call	wait_500ms	;ENTER スイッチのチャタリングを吸収

#ifdef		_ddram_read		;( 選択文字列を LCD DDRAM から取得する場合 )

		; 選択 SRAM タイプ文字列の取得

		movf	ramtyp,W	;選択 SRAM タイプを W へロード
		call	blink_tbl_read	;ブリンク位置テーブル読み込み
		addlw	1		;取得文字列の位置を +1
		iorlw	h'80'		;DDRAM のアドレスをセット
		call	lcd_cmd		;LCD へコマンドを出力

		clrf	ram_idx		;文字列の保存エリアのインデックス = 0 を設定

main03		movlw	ram_type	;保存エリアの先頭アドレス
		addwf	ram_idx,W	;保存エリアのインデックス値 + 保存エリアの先頭アドレス
		movwf	FSR		;FSR に設定

		call	lcd_data_rd	;LCD からデータを入力
		movwf	INDF		;読み出しデータを保存エリアに書き込む
		incf	ram_idx,F	;保存エリアのインデックスの更新

		sublw	"K"
		btfss	STATUS,Z	;(読み出しデータ = "K") か？
		goto	main03		;No

		; 選択 SRAM タイプの表示

main0x		movlw	b'00000001'	;表示クリア
		call	lcd_cmd		;LCD へコマンドを出力

		movlw	"<"
		call	lcd_data	;LCD へデータを１文字出力

		clrf	ram_idx		;文字列の保存エリアのインデックス = 0 を設定

main04		movlw	ram_type	;保存エリアの先頭アドレス
		addwf	ram_idx,W	;保存エリアのインデックス値 + 保存エリアの先頭アドレス
		movwf	FSR		;FSR に設定

		movf	INDF,W		;保存エリアから読み出す
		call	lcd_data	;LCD へデータを１文字出力

		movf	INDF,W		;もう一度保存エリアから読み出す
		incf	ram_idx,F	;保存エリアのインデックスの更新
		sublw	"K"
		btfss	STATUS,Z	;(INDF) = "K" か？
		goto	main04		;No

#else					;( 選択文字列をメッセージテーブルから取得する場合 )

main0x		movlw	b'00000001'	;表示クリア
		call	lcd_cmd		;LCD へコマンドを出力

		movlw	"<"
		call	lcd_data	;LCD へデータを１文字出力

		movlw	high type_msg	;メッセージデータの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low type_msg	;メッセージデータの先頭アドレスの low アドレス
		movwf	addr_low	;

		movf	ddram_ad,W	;DDRAM のアドレスを
		movwf	ddram_wk	;ワークへ

		btfss	ddram_wk,6	;ブリンク位置 ddram_wk >= h'40' か？
		goto	main03		;No

		movlw	b'10111111'	;
		andwf	ddram_wk,F	;ddram_wk - h'40'

		movlw	high type_msg2	;メッセージデータの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low type_msg2	;メッセージデータの先頭アドレスの low アドレス
		movwf	addr_low	;

;			 0123456789ABCDEF

;type_msg		"Type?_  2K    8K",0
;type_msg2		" 32K   64K  128K",0

main03		incf	ddram_wk,F	;ブリンク位置 +1

main04		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		decfsz	ddram_wk,F
		goto	main04

main05		call	tbl_read	;テーブルデータの読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		call	lcd_data	;LCD へデータを１文字出力

		call	tbl_read	;もう一度テーブルデータの読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		sublw	"K"		;データの読み出しは
		btfss	STATUS,Z	;"K" か？
		goto	main05		;No
#endif

		movlw	">"
		call	lcd_data	;LCD へデータを１文字出力

		; チェックスタート促進メッセージの表示

		movlw	b'00001101'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=1: ブリンク

		Disp_Lcd	b'10001000',ckst_msg,1	;DDRAM = '08' アドレスセット

;			 0123456789ABCDEF

;		0x	 <xxK>  "Start?_",0

		call	buzzer_pipo	;"ピポッ" ブザー音出力
		call	wait_500ms

main06		movf	SW,W		;各スイッチ入力ポートの読み出し			;;(Ver.1.07 で変更)
		andlw	b'00001111'	;4つのスイッチを取り出し			;;
		xorlw	b'00001111'	;正論理に変換して				;;
		movwf	sel_sw		;保存						;;
											;;
		btfsc	sel_sw,_swB	;BREAK スイッチ = ON か？			;;
		goto	main		;Yes						;;
											;;
		btfss	sel_sw,_swE	;ENTER スイッチ = ON か？			;;
		goto	main06		;No						;;
											;;
		clrf	pause_flg	;ポーズフラグのクリア				;;
		clrf	conti_flg	;コンティニューフラグのクリア			;;
											;;
		call	buzzer_pipo	;"ピポッ" ブザー音出力				;;
		btfss	sel_sw,_swL	;PAUSE(LEFT←) スイッチ = ON か？		;;
		goto	main07		;No						;;
											;;
		bsf	pause_flg,0	;ポーズフラグのセット				;;
		goto	main08								;;
											;;
main07		btfss	sel_sw,_swR	;CONTI(RIGHT→) スイッチ = ON か？		;;
		goto	main08		;No						;;
											;;
		bsf	conti_flg,0	;コンティニューフラグのセット			;;
		clrf	sel_sw		;チェックパタンの初期設定			;;
											;;
main08		btfsc	typchk_flg,0	;整合性チェックをパス か？			;;
		goto	chk_start	;Yes, SRAM チェック開始
		goto	type_chk	;No,  SRAM タイプの事前整合性チェック

;==========================================================================

		; ブリンク位置テーブル読み込み
blink_tbl_read
		addlw	low blink_tbl	;テーブルデータの先頭アドレスの low アドレス
		movwf	addr_low	;
		movlw	high blink_tbl	;テーブルデータの先頭アドレスの high アドレス
		btfsc	STATUS,C	;オーバーフローした場合は
		addlw	1
		movwf	addr_high	;

		call	tbl_read
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		return

		; ブリンク位置テーブル
blink_tbl
		;	0     1     2     3     4
		dt	h'07',h'0d',h'40',h'46',h'4b'
blink_tbl_end

;			 0123456789ABCDEF

;			"Type?_  2K    8K",0
;			" 32K   64K  128K",0

;==========================================================================
;		SRAM タイプの事前整合性チェック
;==========================================================================

#ifdef comment

		整合性チェック方法の概要

		for Ram = 128K, 64K, 32K, 8K, 2K
			if Ram < Type
				exit for
			endif
			ADDRESS = max
			W_DATA = 'ff'
			(write)
			(read)
			if R_DATA <> '00' then
				if Ram <> 2K
					(A11 bit check)
					select case Ram
						case 128K
							(A16 bit check)
						case 64K
							(A15 bit check)
						case 32K
							(A13 bit check)
						case else
							exit for
					endselect
					if R_DATA <> '00' then
						exit for
					endif
				else
					exit for
				endif
			endif
		next
		if Ram >= 2K then
			if Ram = Type
				OK
			else
				NG
			endif
		else
			NG
		endif

#endif

;==========================================================================

type_chk
		movf	ramtyp,W
		movwf	rt_save		;選択 SRAM タイプの保存

		movlw	5
		movwf	chkcnt		;ループカウンタの初期設定

typck01		decf	chkcnt,W
		movwf	ramtyp		;仮の SRAM タイプを設定

		movf	rt_save,W
		subwf	ramtyp,W	;ramtyp - W(rt_save)
		btfss	STATUS,C	;ramtyp < W(rt_save) か？
		goto	typck06		;Yes, Error

		movf	ramtyp,W
		call	ram_tbl_read	;ram_cont, max_addr_h, max_addr_l へ設定

		call	vcc_ram_init	;電源(DC+5V)供給と初期設定

		; SRAM アドレス(xxxx) の出力制御

		movf	max_addr_h,W
		movwf	ram_addr_h	;SRAM の high アドレスの設定
		movf	max_addr_l,W
		movwf	ram_addr_l	;SRAM の low アドレスの設定
		movlw	h'01'
		movwf	ram_addr_e	;SRAM の ext アドレスの設定

		call	addr01		;SRAM アドレスの出力制御

		; SRAM 書き込みデータ(xx) の出力制御

		movlw	h'ff'
		movwf	ram_data_o	;SRAM 書き込みデータの設定

		call	wdata01		;SRAM 書き込みデータの制御

		; SRAM 読み出しデータ(xx) の入力制御

		movlw	h'01'
		movwf	pass_flg	;LCD 非表示フラグをセット

		call	rdata_lcd_ram	;SRAM 読み出しデータの制御

		; 整合性チェックの判定

		movf	ram_data_i,F	;SRAM の 入力データ
		btfsc	STATUS,Z	;どれかのビット = ON か？
		goto	typck04		;No

		; (仮の SRAM タイプ = 2K byte の場合)
		movlw	0
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfsc	STATUS,Z	;ramtyp = 0 (2K byte SRAM) か？
		goto	typck05		;Yes

		; (仮の SRAM タイプ = 2K byte 以外の場合)
		movlw	b'00001000'	;A11 ビット
		xorwf	ram_addr_h,F	;SRAM の high アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		clrf	ram_data_o	;SRAM 書き込みデータの設定
		call	wdata01		;SRAM 書き込みデータの制御

		movlw	b'00001000'	;A11 ビット
		iorwf	ram_addr_h,F	;SRAM の high アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		movlw	h'01'
		movwf	pass_flg	;LCD 非表示フラグをセット
		call	rdata_lcd_ram	;SRAM 読み出しデータの制御

		movf	ram_data_i,F	;SRAM の 入力データ
		btfsc	STATUS,Z	;どれかのビット = ON か？
		goto	typck04		;No

		movlw	4
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 4 (128K byte SRAM) か？
		goto	typck02		;No

		; (仮の SRAM タイプ = 128K byte の場合)
		clrf	ram_addr_e	;SRAM の ext アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		clrf	ram_data_o	;SRAM 書き込みデータの設定
		call	wdata01		;SRAM 書き込みデータの制御

		movlw	h'01'
		movwf	ram_addr_e	;SRAM の ext アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		movlw	h'01'
		movwf	pass_flg	;LCD 非表示フラグをセット
		call	rdata_lcd_ram	;SRAM 読み出しデータの制御

		movf	ram_data_i,F	;SRAM の 入力データ
		btfsc	STATUS,Z	;どれかのビット = ON か？
		goto	typck04		;No
		goto	typck05		;Yes

typck02		movlw	3
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 3 (64K byte SRAM) か？
		goto	typck03		;No

		; (仮の SRAM タイプ = 64K byte の場合)
		movlw	b'10000000'	;A15 ビット
		xorwf	ram_addr_h,F	;SRAM の high アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		clrf	ram_data_o	;SRAM 書き込みデータの設定
		call	wdata01		;SRAM 書き込みデータの制御

		movlw	b'10000000'	;A15 ビット
		iorwf	ram_addr_h,F	;SRAM の high アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		movlw	h'01'
		movwf	pass_flg	;LCD 非表示フラグをセット
		call	rdata_lcd_ram	;SRAM 読み出しデータの制御

		movf	ram_data_i,F	;SRAM の 入力データ
		btfsc	STATUS,Z	;どれかのビット = ON か？
		goto	typck04		;No
		goto	typck05		;Yes

typck03		movlw	2
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 2 (32K byte SRAM) か？
		goto	typck05		;No

		; (仮の SRAM タイプ = 32K byte の場合)
		movlw	b'00100000'	;A13 ビット
		xorwf	ram_addr_h,F	;SRAM の high アドレスの設定
		call	addr01		;SRAM アドレスの出力制御

		movlw	h'ff'
		movwf	ram_data_o	;SRAM 書き込みデータの設定
		call	wdata01		;SRAM 書き込みデータの制御

		movlw	h'01'
		movwf	pass_flg	;LCD 非表示フラグをセット
		call	rdata_lcd_ram	;SRAM 読み出しデータの制御

		movf	ram_data_i,F	;SRAM の 入力データ
		btfss	STATUS,Z	;どれかのビット = ON か？
		goto	typck05		;Yes

typck04		decfsz	chkcnt,F	;終了 か？
		goto	typck01		;No
		goto	typck06

		; 良否の判定

typck05		movf	rt_save,W
		subwf	ramtyp,W	;ramtyp - W(rt_save)
		bcf	error_flg,0	;エラーフラグの初期設定
		btfss	STATUS,Z	;ramtyp = W(rt_save) か？

typck06		bsf	error_flg,0	;No, エラーフラグの設定

		movf	rt_save,W
		movwf	ramtyp		;選択 SRAM タイプの復帰

		btfss	error_flg,0	;エラー か？
		goto	chk_start	;No

		; 整合性チェックエラー

		bsf	CONT,PC6	;bit6=1: 74HC273 /CLR
		nop
		bcf	CONT,PC6	;bit6=0

		Disp_Lcd	b'11000000',mis_msg,1	;DDRAM = '40' アドレスセット

;			 0123456789ABCDEF

;		0x    ( "<xxK>   Start?_ ",0 )
;		4x	"Type Mismatch !!",0	;タイプミスマッチエラー・メッセージ

		bsf	LED,_NG		;結果 NG(赤LED)
		call	buzzer_bubuu	;"ブッブー" ブザー音出力

		btfsc	SW,_swE		;ENTER スイッチ = ON か？
		goto	$ - 1		;No

		clrf	LED		;LED, 圧電ブザー 制御用ポート
		goto	main0x

;==========================================================================
;		SRAM チェック開始
;==========================================================================

#ifdef comment

		SELECT_1,0 スイッチの内容別 チェックパタンの概要

	(1) sel_sw = b'00' の場合

		for ADDRESS = 0 to max
			for W_DATA = 0 to 'ff'
				(write)
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next

	(2) sel_sw = b'01' の場合

		for W_DATA = 0 to 'ff'
			for ADDRESS = 0 to max
				(write)
			next
			for ADDRESS = 0 to max
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next

	(3) sel_sw = b'10' の場合

		for wk = 0 to 'ff'
			W_DATA = wk
			for ADDRESS = 0 to max
				(write)
				W_DATA = W_DATA + 1
			next
			W_DATA = wk
			for ADDRESS = 0 to max
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
				W_DATA = W_DATA + 1
			next
		next

	(4) sel_sw = b'11' の場合

		for ADDRESS = 0 to max
			for W_DATA = '01','02','04','08','10','20','40','80','00','ff','55','aa'
				(write)
				(read)
				if R_DATA = W_DATA then
					OK
				else
					NG
				endif
			next
		next

#endif

;==========================================================================

chk_start
		; SRAM チェック進行メッセージ(固定文字部分)の表示

		movlw	b'00001100'	;表示オン／オフコントロール
		call	lcd_cmd		;D=1: 表示オン, C=0: カーソル非表示, B=0: 非ブリンク

		Disp_Lcd	b'10001000',check_msg,2	;DDRAM = '08' アドレスセット

;			 0123456789ABCDEF

;		0x	        " Er:0000",0
;		4x	"A:     W:   R:  ",0

		; SRAM 種類別 Vcc pin, アドレス MAX テーブルの読み出し

		call	ram_tbl_read	;ram_cont, max_addr_h, max_addr_l へ設定

		; SRAM Vcc pin 電源(DC+5V)供給と初期設定

		call	vcc_ram_init	;電源(DC+5V)供給と初期設定

		clrf	pass_flg	;LCD 非表示フラグ = OFF				;;(Ver.1.07 で変更)
		btfss	LCD,_swP	;PASS スイッチ = ON か？			;;
		bsf	pass_flg,0	;Yes, LCD 非表示フラグ = ON			;;
											;;
		clrf	ram_err_h	;エラー数の high 値の初期設定			;;
		clrf	ram_err_l	;エラー数の low  値の初期設定			;;
		clrf	error_flg	;エラーフラグの初期設定				;;
											;;
		btfsc	conti_flg,0	;コンティニューフラグ = ON か？			;;
		goto	chk00		;Yes						;;
											;;
		swapf	SW,W		;上下入れ替えて各スイッチ入力ポートの読み出し	;;
		andlw	b'00000011'	;SELECT_0,1 スイッチを取り出し			;;
		xorlw	b'00000011'	;正論理に変換して				;;
		movwf	sel_sw		;保存						;;
											;;
chk00		call	sel_sw_lcd	;チェックパタンの LCD 表示			;;

	;;;;;;; チェックパタン '00' の場合

		movf	sel_sw,W
		btfss	STATUS,Z	;sel_sw = b'00' か？
		goto	chk03		;No

		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

chk01		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		clrf	ram_data_o	;SRAM の 出力データの初期設定

chk02		call	wdata_lcd_ram	;SRAM 書き込みデータ(xx) の LCD 制御と SRAM への 出力制御

		call	rdata_lcd_ram	;SRAM 読み出しデータ(xx) の SRAM への 入力制御と LCD 制御

		call	err_lcd_pause	;エラー時の LCD 制御と ポーズ動作
		btfsc	break_flg,0	;ブレイクフラグ = ON か？
		goto	chk20		;Yes

		btfss	SW,_swB		;BREAK スイッチ = ON か？
		goto	chk20		;Yes

		incfsz	ram_data_o,F	;SRAM の 出力データの更新
		goto	chk02

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfsc	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk01		;No
		goto	chk20

	;;;;;;; チェックパタン '01' の場合

chk03		movlw	1
		subwf	sel_sw,W
		btfss	STATUS,Z	;sel_sw = b'01' か？
		goto	chk07		;No

		clrf	ram_data_o	;SRAM の 出力データの初期設定

chk04		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

chk05		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		call	wdata_lcd_ram	;SRAM 書き込みデータ(xx) の LCD 制御と SRAM への 出力制御

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfsc	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk05		;No

		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

chk06		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		call	rdata_lcd_ram	;SRAM 読み出しデータ(xx) の SRAM への 入力制御と LCD 制御

		call	err_lcd_pause	;エラー時の LCD 制御と ポーズ動作
		btfsc	break_flg,0	;ブレイクフラグ = ON か？
		goto	chk20		;Yes

		btfss	SW,_swB		;BREAK スイッチ = ON か？
		goto	chk20		;Yes

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfsc	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk06		;No

		incfsz	ram_data_o,F	;SRAM の 出力データの更新
		goto	chk04
		goto	chk20

	;;;;;;; チェックパタン '10' の場合

chk07		movlw	2
		subwf	sel_sw,W
		btfss	STATUS,Z	;sel_sw = b'10' か？
		goto	chk13		;No

		clrf	ram_data_w	;SRAM の 出力データの初期設定

chk08		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

		movf	ram_data_w,W
		movwf	ram_data_o

chk09		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		call	wdata_lcd_ram	;SRAM 書き込みデータ(xx) の LCD 制御と SRAM への 出力制御

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfss	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk10		;Yes

		incf	ram_data_o,F	;SRAM の 出力データの更新
		goto	chk09

chk10		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

		movf	ram_data_w,W
		movwf	ram_data_o

chk11		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		call	rdata_lcd_ram	;SRAM 読み出しデータ(xx) の SRAM への 入力制御と LCD 制御

		call	err_lcd_pause	;エラー時の LCD 制御と ポーズ動作
		btfsc	break_flg,0	;ブレイクフラグ = ON か？
		goto	chk20		;Yes

		btfss	SW,_swB		;BREAK スイッチ = ON か？
		goto	chk20		;Yes

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfss	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk12		;Yes

		incf	ram_data_o,F	;SRAM の 出力データの更新
		goto	chk11

chk12		incfsz	ram_data_w,F	;SRAM の 出力データの更新
		goto	chk08
		goto	chk20

	;;;;;;; チェックパタン '11' の場合

ptn_tbl		dt	h'01',h'02',h'04',h'08',h'10',h'20',h'40',h'80'
		dt	h'00',h'ff',h'55',h'aa'

chk13		clrf	ram_addr_h	;SRAM の high アドレスの初期設定	
		clrf	ram_addr_l	;SRAM の low  アドレスの初期設定
		clrf	ram_addr_e	;SRAM の ext  アドレスの初期設定 (128K byte SRAM 用)

chk14		call	addr_lcd_ram	;SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

		movlw	high ptn_tbl	;パタンテーブルの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low ptn_tbl	;パタンテーブルの先頭アドレスの low アドレス
		movwf	addr_low	;

chk15		call	tbl_read	;テーブルデータの読み出し

		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		movwf	ram_data_o	;SRAM の 出力データの設定

		call	wdata_lcd_ram	;SRAM 書き込みデータ(xx) の LCD 制御と SRAM への 出力制御

		call	rdata_lcd_ram	;SRAM 読み出しデータ(xx) の SRAM への 入力制御と LCD 制御

		call	err_lcd_pause	;エラー時の LCD 制御と ポーズ動作
		btfsc	break_flg,0	;ブレイクフラグ = ON か？
		goto	chk20		;Yes

		btfss	SW,_swB		;BREAK スイッチ = ON か？
		goto	chk20		;Yes

		movlw	h'aa'
		subwf	ram_data_o,W
		btfss	STATUS,Z	;SRAM の 出力データ = 終了'aa' か？
		goto	chk15		;No

		call	ram_addr_inc	;SRAM の アドレスの更新
		movf	adend_flg,F
		btfsc	STATUS,Z	;更新終了フラグ = ON か？
		goto	chk14		;No

	;;;;;;; SRAM チェックの総合結果 (LED の表示とブザー音出力)

chk20		movf	error_flg,F	
		btfsc	STATUS,Z	;エラー数 = 0 か？
		goto	chk21		;Yes

		bsf	LED,_NG		;結果 NG(赤LED)
		call	buzzer_bubuu	;"ブッブー" ブザー音出力
		goto	chk22

chk21		bsf	LED,_OK		;結果 OK(緑LED)
		call	buzzer_po4	;"ポッポッポッポッ" ブザー音出力

chk22		bsf	CONT,PC6	;bit6=1: 74HC273 /CLR
		nop
		bcf	CONT,PC6	;bit6=0

		btfsc	conti_flg,0	;コンティニューフラグ = ON か？			;;(Ver.1.07 で追加)
		goto	chk24		;Yes						;;

		btfsc	SW,_swE		;ENTER スイッチ = ON か？
		goto	$ - 1		;No

chk23		clrf	LED		;LED, 圧電ブザー 制御用ポート			;;(Ver.1.07 で変更)
		goto	main0x

chk24		btfss	SW,_swB		;BREAK スイッチ = ON か？			;;(Ver.1.07 で追加)
		goto	chk23		;Yes						;;
											;;
		btfsc	SW,_swR		;CONTI(RIGHT→) スイッチ = ON か？		;;
		goto	chk24		;No						;;
											;;
		clrf	LED		;LED, 圧電ブザー 制御用ポート			;;
		incf	sel_sw,F	;チェックパタンの更新				;;
		movlw	4								;;
		subwf	sel_sw,W							;;
		btfss	STATUS,Z	;sel_sw = 4 か？				;;
		goto	chk_start	;No						;;
		goto	main0x								;;

;==========================================================================

;==========================================================================

	;;;;;;; SRAM Vcc pin 電源(DC+5V)供給、初期設定

vcc_ram_init
		movlw	ramOE |	ramWE	;初期値 /OE=1,/WE=1,/CS=0 にする
		iorwf	ram_cont,F	;Vxx と合成

		movlw	3
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,C	;ramtyp >= 3 (64K or 128K byte SRAM) か？
		goto	vcc01		;No

		movlw	ramCS2		;(64K or 128K byte SRAM) の場合は CS2 を 'H' にしておく
		iorwf	ram_cont,F

vcc01		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		movf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 0 (2K byte SRAM) か？
		goto	vcc02		;No
					;(2K byte SRAM) の場合は /WE(A11) を 'H' にしておく
		Flip_Flop_Set	b'00001000',PC2,1	;bit2: 74HC574(上位アドレス) CK
		goto	vcc03

vcc02		sublw	1
		btfss	STATUS,Z	;ramtyp = 1 (8K byte SRAM) か？
		goto	vcc03		;No
					;(8K byte SRAM) の場合は CS2(A13) を 'H' にしておく
		Flip_Flop_Set	b'00100000',PC2,1	;bit2: 74HC574(上位アドレス) CK

vcc03		return

	;;;;;;; チェックパタン番号の LCD 表示						;;(Ver.1.07 で追加)
											;;
sel_sw_lcd										;;
		movlw	2								;;
		subwf	ramtyp,W	;選択 SRAM タイプ				;;
		movlw	h'03'								;;
		btfss	STATUS,C	;ramtyp < 2 (2K or 8K byte SRAM) か？		;;
		goto	selsw01		;Yes						;;
											;;
		movlw	4								;;
		subwf	ramtyp,W	;選択 SRAM タイプ				;;
		movlw	h'04'								;;
		btfss	STATUS,C	;ramtyp < 4 (32K or 64K byte SRAM) か？		;;
		goto	selsw01		;Yes						;;
											;;
		movlw	h'05'		;ramtyp = 4 (128K byte SRAM)			;;
											;;
selsw01		iorlw	b'10000000'	;DDRAM アドレスセット				;;
		call	lcd_cmd		;LCD へコマンドを出力				;;
											;;
		movlw	','								;;
		call	lcd_data	;LCD へデータを１文字出力			;;
											;;
		movlw	h'31'								;;
		addwf	sel_sw,W	;チェックパタン番号				;;
		call	lcd_data	;LCD へデータを１文字出力			;;
											;;
		movlw	'>'								;;
		call	lcd_data	;LCD へデータを１文字出力			;;
		return									;;

	;;;;;;; SRAM アドレス(xxxx) の LCD 制御と SRAM への 出力制御

addr_lcd_ram
		; SRAM アドレス(xxxx) の LCD 表示

		movf	pass_flg,F
		btfss	STATUS,Z	;LCD 非表示フラグ = ON か？
		goto	addr01		;Yes

		movlw	b'11000010'	;DDRAM = '42' アドレスセット
		call	lcd_cmd		;LCD へコマンドを出力
		movf	ram_addr_h,W	;SRAM の high アドレス
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示
		movf	ram_addr_l,W	;SRAM の low アドレス
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示

		movlw	4
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 4 (128K byte SRAM) か？
		goto	addr01		;No

		movlw	b'11000001'	;DDRAM = '41' アドレスセット
		call	lcd_cmd		;LCD へコマンドを出力

		movlw	h'0f'
		andwf	ram_addr_e,W	;SRAM の ext  アドレス (A16: 拡張アドレス 16 ビット目)
		call	hex_conv	;下位４ビットの変換
		call	lcd_data	;LCD へデータを１文字出力

		; SRAM アドレス(xxxx) の 出力設定

addr01		movf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 0 (2K byte SRAM) か？
		goto	addr02		;No
					;(2K byte SRAM) の場合は
		movlw	b'00001000'	;SRAM /WE を 'H' にしておく
		goto	addr03

addr02		sublw	1
		movlw	b'00000000'	;2K,8K byte SRAM 以外
		btfss	STATUS,Z	;ramtyp = 1 (8K byte SRAM) か？
		goto	addr03		;No
					;(8K byte SRAM) の場合は CS2(A13) を 'H' にしておく
		movlw	b'00100000'	;SRAM CS2 を 'H' にしておく

addr03		iorwf	ram_addr_h,W	;SRAM の high アドレス
		Flip_Flop_Set		  ,PC2,0	;bit2: 74HC574(上位アドレス) CK

		Flip_Flop_Set	ram_addr_l,PC3,2	;bit3: 74HC574(下位アドレス) CK

		movlw	4
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 4 (128K byte SRAM) か？
		goto	addr04		;No

		bcf	CONT,PC0	;bit0=0
		movf	ram_addr_e,W	;SRAM の ext アドレス (A16: 拡張アドレス 16 ビット目)
		btfss	STATUS,Z
		bsf	CONT,PC0	;bit0=1

addr04		return

	;;;;;;; SRAM 書き込みデータ(xx) の LCD 制御と SRAM への 出力制御

wdata_lcd_ram
		; SRAM 書き込みデータ(xx) の LCD 表示

		movf	pass_flg,F
		btfss	STATUS,Z	;LCD 非表示フラグ = ON か？
		goto	wdata01		;Yes

		movlw	b'11001001'	;DDRAM = '49' アドレスセット
		call	lcd_cmd		;LCD へコマンドを出力
		movf	ram_data_o,W	;SRAM の 出力データ
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示

		; SRAM 書き込みデータ(xx) の 出力設定

wdata01		Flip_Flop_Set	ram_data_o,PC1,2	;bit1: 74HC574(データ出力) CK
	
		; SRAM /WE の送出 (2K byte SRAM の場合)

		movf	ramtyp,F	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 0 (2K byte SRAM) か？
		goto	wdata02		;No

		movf	ram_addr_h,W	;SRAM の high アドレス
		andlw	h'07'		;SRAM /WE=0 にする
		Flip_Flop_Set		  ,PC2,0	;bit2: 74HC574(上位アドレス) CK
	
		movf	ram_addr_h,W	;SRAM の high アドレス
		iorlw	h'08'		;SRAM 再び /WE=1 にする
		Flip_Flop_Set		  ,PC2,0	;bit2: 74HC574(上位アドレス) CK
		goto	wdata03

		; SRAM /WE の送出 (2K byte SRAM 以外の場合)

wdata02	;;	movlw	ramWE									;;(Ver.1.06 で変更)
	;;	xorlw	h'ff'									;;
	;;	andwf	ram_cont,F	;SRAM /WE だけを 'L' にする				;;
		bcf	ram_cont,ramWEb								;;
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

	;;	movlw	ramWE									;;(Ver.1.06 で変更)
	;;	iorwf	ram_cont,F	;SRAM /WE を再び 'H' にする				;;
		bsf	ram_cont,ramWEb								;;
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

wdata03		return

	;;;;;;; SRAM 読み出しデータ(xx) の SRAM への 入力制御と LCD 制御

rdata_lcd_ram
		; SRAM 読み出しデータ(xx) の 入力設定

#ifdef		_bug_fixes		;(Ver.1.05 で変更)( 2018/06/19 修正 ... ハードウエアの修正も必要 )

		;; SRAM のモード設定

		;;(CE2)	/CE /OE /WE	Mode		I/O
		;; (H)	 L   H   H	Output disable	High Z
		;; (H)	 L   L   H	Read		D out
		;; (H)	 L   x   L	Write		D in

		bsf	CONT,PC4	;74HC574(データ出力) /OE 無効 (High Z)

	;;	movlw	ramOE									;;(Ver.1.06 で変更)
	;;	xorlw	h'ff'									;;
	;;	andwf	ram_cont,F	;SRAM /OE だけを 'L' にする (SRAM を Read モードにする)	;;
		bcf	ram_cont,ramOEb								;;
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		movlw	b'11111111'
		movwf	TRIS_RAM	;RB7-0: 入力 の設定
;		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		bsf	CONT,PC7	;74HC541(データ入力) /G1,/G2 有効 (PC7:インバータ出力)
		movf	SRAM,W		;SRAM データの読み出し
		movwf	ram_data_i	;SRAM の 入力データ
		bcf	CONT,PC7	;74HC541(データ入力) /G1,/G2 無効 (High Z)

;		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		clrf	TRIS_RAM	;RB7-0: 出力 の設定
;		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

	;;	movlw	ramOE									;;(Ver.1.06 で変更)
	;;	iorwf	ram_cont,F	;SRAM /OE を再び 'H' にする (SRAM を Write モードにする);;
		bsf	ram_cont,ramOEb								;;
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		bcf	CONT,PC4	;74HC574(データ出力) /OE 有効

#else					;( 修正前のリスト )

		movlw	ramOE
		xorlw	h'ff'
		andwf	ram_cont,F	;SRAM /OE だけを 'L' にする
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK

		bsf	CONT,PC4	;74HC541(データ入力) /G1,/G2 有効, 74HC574(データ出力) /OE 無効

		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		movlw	b'11111111'
		movwf	TRIS_RAM	;RB7-0: 入力 の設定
;		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		movf	SRAM,W		;SRAM データの読み出し
		movwf	ram_data_i	;SRAM の 入力データ

;		bcf	STATUS,RP1	;バンク 1
		bsf	STATUS,RP0
		clrf	TRIS_RAM	;RB7-0: 出力 の設定
;		bcf	STATUS,RP1	;バンク 0
		bcf	STATUS,RP0

		bcf	CONT,PC4	;74HC541(データ入力) /G1,/G2 無効, 74HC574(データ出力) /OE 有効

		movlw	ramOE
		iorwf	ram_cont,F	;SRAM /OE を再び 'H' にする (SRAM を Write モードにする)
		Flip_Flop_Set	ram_cont,  PC5,2	;bit5: 74HC273(コントロール) CK
#endif

		; SRAM 読み出しデータ(xx) の LCD 表示

		movf	pass_flg,F
		btfss	STATUS,Z	;LCD 非表示フラグ = ON か？
		goto	rdata01		;Yes

		movlw	b'11001110'	;DDRAM = '4E' アドレスセット
		call	lcd_cmd		;LCD へコマンドを出力
		movf	ram_data_i,W	;SRAM の 入力データ
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示

rdata01		return

	;;;;;;; エラー時の LCD 制御と ポーズ動作

err_lcd_pause
		clrf	break_flg	;ブレイクフラグのクリア

		; エラー数の LCD 表示

		movf	ram_data_i,W	;SRAM の 入力データ
		subwf	ram_data_o,W
		btfsc	STATUS,Z	;等しい か？
		goto	pause03		;Yes

		incf	ram_err_l,F	;エラー数の low  値の更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	ram_err_h,F	;エラー数の high 値の更新
		bsf	error_flg,0	;エラーフラグの設定	

		movlw	b'10001100'	;DDRAM = '0C' アドレスセット
		call	lcd_cmd		;LCD へコマンドを出力
		movf	ram_err_h,W	;エラー数の high 値
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示
		movf	ram_err_l,W	;エラー数の low  値
		call	lcd_hex_out	;１バイト変換 (BIN → HEX 文字) ２文字 LCD 表示

		; ポーズ動作をする場合

		movf	pause_flg,F
		btfsc	STATUS,Z	;ポーズフラグ = ON か？
		goto	pause03		;No

		bsf	LED,_NG		;結果 NG(赤LED) 点灯
		call	buzzer_buu	;"ブー" ブザー音出力

pause01		btfsc	SW,_swB		;BREAK スイッチ = ON か？
		goto	pause02		;No

		bsf	break_flg,0	;ブレイクフラグのセット
		goto	pause03

pause02		btfsc	SW,_swR		;CONTI(RIGHT→) スイッチ = ON か？
		goto	pause01		;No

		bcf	LED,_NG		;結果 NG(赤LED) 消灯
		call	wait_500ms	;CONTI スイッチのチャタリングを吸収

pause03		return

	;;;;;;; SRAM の アドレスの更新

ram_addr_inc
		clrf	adend_flg	;更新終了フラグのクリア

		movf	max_addr_l,W	;SRAM アドレス MAX値の low
		subwf	ram_addr_l,W	;SRAM の low アドレス
		btfss	STATUS,Z	;等しい か？
		goto	adinc01		;No

		movf	max_addr_h,W	;SRAM アドレス MAX値の high
		subwf	ram_addr_h,W	;SRAM の high アドレス
		btfsc	STATUS,Z	;等しい か？
		goto	adinc02		;Yes

adinc01		incf	ram_addr_l,F	;SRAM の low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	ram_addr_h,F	;SRAM の high アドレスの更新
		goto	adinc04

adinc02		movlw	4
		subwf	ramtyp,W	;選択 SRAM タイプ
		btfss	STATUS,Z	;ramtyp = 4 (128K byte SRAM) か？
		goto	adinc03		;No

		movf	ram_addr_e,F	;SRAM の ext アドレス (A16: 拡張アドレス 16 ビット目)
		btfss	STATUS,Z	;ram_addr_e = 0 か？
		goto	adinc03		;No

		incf	ram_addr_e,F	;SRAM の ext アドレスの更新
		clrf	ram_addr_h	;SRAM の high アドレス
		clrf	ram_addr_l	;SRAM の low アドレス
		goto	adinc04

adinc03		bsf	adend_flg,0	;更新終了フラグのセット

adinc04		return

;==========================================================================

		; １バイト変換 (BIN → HEX 文字) ２文字 LCD 出力
lcd_hex_out
		movwf	cnvtmp		;変換データの一時保存
		swapf	cnvtmp,W
		andlw	h'0f'
		call	hex_conv	;上位４ビットの変換
		call	lcd_data	;LCD へデータを１文字出力

		movlw	h'0f'
		andwf	cnvtmp,W
		call	hex_conv	;下位４ビットの変換
		call	lcd_data	;LCD へデータを１文字出力
		return

		; ４ビット変換 (BIN → HEX 文字)
hex_conv

#ifndef		_table_conv		;( テーブル変換を使用しない場合 )

		movwf	hextmp
		sublw	h'0a'
		btfsc	STATUS,Z	;
		goto	cnv01		;W = h'0a' 

		btfss	STATUS,C	;
		goto	cnv01		;W > h'0a' 

		movlw	h'30'		;0 ～ 9
		goto	cnv02

cnv01		movlw	h'40' - 9	;A ～ F

cnv02		addwf	hextmp,W
		return

#else					;( テーブル変換を使用する場合 )

		addwf	PCL,F
		dt	"0","1","2","3","4","5","6","7"
		dt	"8","9","A","B","C","D","E","F"
#endif

;==========================================================================
;		LCD（ SC1602BS-B の場合 ）表示用 各種メッセージ等
;==========================================================================

		; スタートメッセージ

start_msg	dt	"StaticRamChecker",0
		;	 0123456789ABCDEF
		dt	"   ( 8 bit )    ",0

start_msg2
		dt	"    ver.",ver_no,"    ",0
		dt	"  by m.yamamoto ",0

		; SRAM タイプ選択メッセージ

type_msg	dt	"Type?_  2K    8K",0
		;	 0123456789ABCDEF
type_msg2	dt	" 32K   64K  128K",0

		; SRAM チェックスタート促進メッセージ

ckst_msg	dt	        "Start?_",0
		;	 0123456789ABCDEF

		; タイプミスマッチエラー・メッセージ

mis_msg		dt	"Type Mismatch !!",0

		; SRAM チェック進行メッセージ

check_msg	dt	        " Er:0000",0
		;	 0123456789ABCDEF
		dt	"A:     W:   R:  ",0

;		dt	"<128K>   Er:xxxx",0
;		dt	"A:xxxx W:xx R:xx",0

;==========================================================================
;		←(LEFT) 左スイッチの処理
;==========================================================================

left_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swL		;入力(LEFT ←)スイッチ = ON か？
		goto	lefsw01		;No

		call	buzzer_po	;"ポッ" ブザー音出力
		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 100ms

		decf	ramtyp,F	;選択 SRAM タイプ -1
		incf	ramtyp,W
		btfss	STATUS,Z	;(ramtyp < 0) か？
		goto	lefsw01		;No

		movlw	blink_tbl_end - blink_tbl - 1
		movwf	ramtyp		;選択 SRAM タイプの初期設定

lefsw01		return

;==========================================================================
;		→(RIGHT) 右スイッチの処理
;==========================================================================

right_switch
		movlw	30		;チャッタリング吸収1
		call	wait_xxms	;wait 30ms
		btfsc	SW,_swR		;入力(RIGHT →)スイッチ = ON か？
		goto	rigsw01		;No

		call	buzzer_po	;"ポッ" ブザー音出力
		movlw	150		;チャッタリング吸収2
		call	wait_xxms	;wait 100ms

		incf	ramtyp,F	;選択 SRAM タイプ +1
		movlw	blink_tbl_end - blink_tbl
		subwf	ramtyp,W
		btfss	STATUS,Z	;(ramtyp = テーブルデータ数) か？
		goto	rigsw01		;No

		clrf	ramtyp		;選択 SRAM タイプの初期設定

rigsw01		return

;==========================================================================
;		SRAM 種類別 Vcc pin, アドレス MAX テーブルの読み出し
;==========================================================================

ram_tbl_read
		movlw	high ram_tbl	;テーブルデータの先頭アドレスの high アドレス
		movwf	addr_high	;
		movlw	low ram_tbl	;テーブルデータの先頭アドレスの low アドレス
		movwf	addr_low	;

		movf	ramtyp,W	;選択 SRAM タイプ値を
		movwf	rd1cnt		;rd1cnt にセット

tblrd01		movf	rd1cnt,F
		btfsc	STATUS,Z	;rd1cnt = 0 か？
		goto	tblrd03		;Yes

		movlw	3
		movwf	rd2cnt		;rd2cnt = 3 をセット

tblrd02		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		decfsz	rd2cnt,F	;rd2cnt - 1 = 0 か？
		goto	tblrd02		;No

		decf	rd1cnt,F	;rd1cnt - 1
		goto	tblrd01

tblrd03		call	tbl_read	;テーブルデータの１文字読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		movwf	ram_cont	;;SRAM の コントロールバッファへ設定
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		call	tbl_read	;テーブルデータの１文字読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		movwf	max_addr_h	;;SRAM アドレス MAX値の high へ設定
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新

		call	tbl_read	;テーブルデータの１文字読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		movwf	max_addr_l	;;SRAM アドレス MAX値の low へ設定
		return

		; SRAM 種類別 Vcc pin, アドレス MAX テーブル
ram_tbl
		dt	Vcc24, h'07',h'ff'	;0:   2K byte SRAM
		dt	Vcc28, h'1f',h'ff'	;1:   8K byte SRAM
		dt	Vcc28, h'7f',h'ff'	;2:  32K byte SRAM
		dt	Vcc32, h'ff',h'ff'	;3:  64K byte SRAM
		dt	Vcc32, h'ff',h'ff'	;4: 128K byte SRAM, h'1ffff'

;==========================================================================
;		LCD 制御サブルーチン
;==========================================================================

		; LCD へコマンドを出力
lcd_cmd
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		goto	lcd01

		; LCD へデータを出力
lcd_data
		bsf	LCD,_RS		;RS = 1  (データモードに設定)
		nop

lcd01		bcf	LCD,_RW		;R/W = 0 (書き込みモードに設定)
		call	lcd_out		;上位４ビットを転送

		swapf	lcdtmp,W	;一時保存データの上位下位入れ替え
		call	lcd_out		;下位４ビットを転送

		call	lcd_busy	;LCD ビジーチェック
		return

		; ４ビット一回の送出
lcd_out
		movwf	lcdtmp		;コマンド／データを一時保存
		movlw	h'0f'		;下位４ビットの
		andwf	LCD,F		;コントロールポートの内容を残し
		movlw	h'f0'		;上位４ビットデータ
		andwf	lcdtmp,W	;を取り出して
		iorwf	LCD,F		;コントロールとＯＲ

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		nop			;E のパルス幅を220ns以上確保するため
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		return

		; LCD ビジーチェック
lcd_busy
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを入力ポート
		iorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		nop
		bsf	LCD,_RW		;R/W = 1 (読み込みモードに設定)

lcd_busy01	bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（上位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
;		andlw	h'f0'		;上位４ビット
		movwf	lcdtmp		;読み込みデータを一時保存
;		swapf	lcdtmp,F	;下位４ビットに移動

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（下位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
;		andlw	h'f0'		;上位４ビット
;		iorwf	lcdtmp,F	;上位４ビット + 下位４ビット
;		swapf	lcdtmp,F	;上位４ビットと下位４ビットを入れ替え
		btfsc	lcdtmp,_BF	;ビジーフラグのチェック (読み込みデータの７ビット目)
		goto	lcd_busy01	;_BF=0 になるまでループ

		bcf	LCD,_RW		;R/W = 0  (書き込みモードに設定)
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを出力ポートに戻す
		xorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		return

		; LCD 初期設定
lcd_init
		bcf	LCD,_RW		;R/W = 0 (書き込みモードに設定)
		nop
		bcf	LCD,_RS		;RS = 0  (コマンドモードに設定)
		nop
		bcf	LCD,_E		;E = 0   (動作起動信号の設定)

		movlw	15
		call	wait_xxms	;wait 15ms （15ms以上を確保）
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		movlw	5
		call	wait_xxms	;wait 5ms （4.1ms以上を確保）
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定) 
		call	lcd_out		;上位４ビットを転送

		call	wait_100us
		movlw	b'00110000'	;ファンクションセット(8bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		call	wait_100us
		movlw	b'00100000'	;ファンクションセット(4bitモードに設定)
		call	lcd_out		;上位４ビットを転送

		call	wait_100us	;ここから 4bitモード
		movlw	b'00101000'	;ファンクションセット
		call	lcd_cmd		;DL=0: 4bit, N=1: 2行, F=0: 5x7ドット

		movlw	b'00001000'	;表示オン／オフコントロール
		call	lcd_cmd		;D=0: 表示オフ, C=0: カーソル非表示, B=0: 非ブリンク

		movlw	b'00000001'	;表示クリア
		call	lcd_cmd		;

		movlw	b'00000110'	;エントリーモードセット 
		call	lcd_cmd		;I/D=1: アドレスを+1しカーソルは右移動，S=0: 非シフト
		return

		; LCD からデータを入力

;<使用例>	movlw	h'80'		;読み出す DDRAM のアドレスをセット
;		call	lcd_cmd		;LCD へコマンドを出力
;		  :
;		call	lcd_data_rd	;LCD からデータを入力

lcd_data_rd
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを入力ポート
		iorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0
		bsf	LCD,_RS		;RS = 1  (データモードに設定)
		nop
		bsf	LCD,_RW		;R/W = 1 (読み込みモードに設定)

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（上位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		andlw	h'f0'		;上位４ビット
		movwf	lcdtmp		;読み込みデータを一時保存
		swapf	lcdtmp,F	;下位４ビットに移動

		bsf	LCD,_E		;E = 1   (動作起動信号の設定：Hでストローブ)
		movf	LCD,W		;DDRAM からのデータ（下位４ビット）の読み出し
		bcf	LCD,_E		;E = 0   (動作起動信号の設定：Lに戻す)
		andlw	h'f0'		;上位４ビット
		iorwf	lcdtmp,F	;上位４ビット + 下位４ビット
		swapf	lcdtmp,F	;上位４ビットと下位４ビットを入れ替え

		bcf	LCD,_RW		;R/W = 0  (書き込みモードに設定)
		bsf	STATUS,RP0	;バンク 1
		movlw	b'11110000'	;上位４ビットを出力ポートに戻す
		xorwf	TRIS_LCD,F
		bcf	STATUS,RP0	;バンク 0

		call	wait_100us
		movf	lcdtmp,W	;読み出しデータを W に移動
		return

		; LCD １行メッセージ表示

;<使用例>	movlw	h'80'		;表示位置の DDRAM のアドレスをセット
;		call	lcd_cmd		;LCD へコマンドを出力
;		movlw	high st_msg	;メッセージデータの先頭アドレスの high アドレス
;		movwf	addr_high	;
;		movlw	low st_msg	;メッセージデータの先頭アドレスの low アドレス
;		movwf	addr_low	;
;		call	lcd_disp	;メッセージデータ１行表示
;		  :
;st_msg		dt	"StaticRamChecker",0

lcd_disp
		call	tbl_read	;テーブルデータの読み出し
		bcf	PCLATH,3	;ページ 0 に戻す
		bcf	PCLATH,4
		incf	addr_low,F	;読み出すデータの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;読み出すデータの high アドレスの更新
		addlw	0
		btfsc	STATUS,Z	;h'00' か？
		return			;yes

		call	lcd_data	;LCD へデータを１文字出力
		goto	lcd_disp

		; テーブルデータの１文字読み出し
tbl_read
		movf	addr_high,W	;読み出すデータの high アドレス
		movwf	PCLATH
		movf	addr_low,W	;読み出すデータの low アドレス
		movwf	PCL

;==========================================================================
;		ブザー音出力ルーチン
;==========================================================================

		; "ブー" ブザー音出力
buzzer_buu
		movlw	buh
		movwf	const_high	;音階用分周定数 high を設定
		movlw	bul
		movwf	const_low	;音階用分周定数 low を設定
		movlw	buulcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ブッ" ブザー音出力
buzzer_bu
		movlw	buh
		movwf	const_high	;音階用分周定数 high を設定
		movlw	bul
		movwf	const_low	;音階用分周定数 low を設定
		movlw	bulcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ピッ" ブザー音出力
buzzer_pi
		movlw	pih
		movwf	const_high	;音階用分周定数 high を設定
		movlw	pil
		movwf	const_low	;音階用分周定数 low を設定
		movlw	pilcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ポッ" ブザー音出力
buzzer_po
		movlw	poh
		movwf	const_high	;音階用分周定数 high を設定
		movlw	pol
		movwf	const_low	;音階用分周定数 low を設定
		movlw	polcnt		;音長（ループカウンタ）
		goto	buzzer_control

		; "ピポッ" ブザー音出力
buzzer_pipo
		call	buzzer_pi	;"ピッ" ブザー音出力
		movlw	30
		call	wait_xxms
		call	buzzer_po	;"ポッ" ブザー音出力
		return

		; "ポッポッポッポッ" ブザー音出力
buzzer_po4
		movlw	4
		movwf	wt4cnt
po4		call	buzzer_po	;"ポッ" ブザー音出力
		movlw	30
		call	wait_xxms
		decfsz	wt4cnt,F
		goto	po4
		return

		; "ブッブー" ブザー音出力
buzzer_bubuu
		call	buzzer_bu	;"ブッ" ブザー音出力
		movlw	70
		call	wait_xxms
		call	buzzer_buu	;"ブー" ブザー音出力
		return

		; ブザー音出力コントロール

buzzer_control
		bsf	STATUS,RP0	;バンク 1
		bsf	PIE1,TMR1IE	;タイマー１割り込みを許可
		bcf	STATUS,RP0	;バンク 0

		call	wait_xxms	;入力 W: 音長（ループカウンタ）

		bsf	STATUS,RP0	;バンク 1
		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク 0
		return

;==========================================================================
;		ウェイト・ルーチン (20 MHz)
;==========================================================================

		; 100μ秒 ウェイトルーチン
wait_100us
		movlw	99		;1
		movwf	wt1cnt		;1
wait01		goto	$+1		;2
		decfsz	wt1cnt,F	;1,2
		goto	wait01		;2,0	1+1+(2+1+2)*98+(2+2+0)=496
;		goto	$+1		;2
		return			;2	496+2=498
					;       498/20MHz*4 = 99.6 μS = 100 μS = 0.1 mS

		; 1m 秒 ウェイトルーチン
wait_1ms
		movlw	10		;1
		movwf	wt2cnt		;1
wait02		call	wait_100us	;2	2+498=500
		decfsz	wt2cnt,F	;1,2
		goto	wait02		;2,0	1+1+(500+1+2)*9+(500+2+0)=5031
		return			;2	5031+2=5033
					;       5033/20MHz*4 = 1.0066 mS = 1 mS

		; 100m 秒 ウェイトルーチン
wait_100ms
		movlw	100

		; xx m 秒 ウェイトルーチン
wait_xxms
		movwf	wt3cnt		;1
wait03		call	wait_1ms	;2	2+5033=5035
		decfsz	wt3cnt,F	;1,2
		goto	wait03		;2,0	1+(5035+1+2)*(xx-1)+(5035+2+0)=5038*(xx)
		return			;2	5038*(xx)+2
					;

		; 500m 秒 ウェイトルーチン
wait_500ms
		movlw	5
		goto	wait04

		; 1.5 秒 ウェイトルーチン
wait_1500ms
		movlw	15
wait04		movwf	wt4cnt

wait05		call	wait_100ms
		decfsz	wt4cnt,F
		goto	wait05
		return

;==========================================================================
;		タイマー割り込み処理
;==========================================================================

interrupt
		; レジスタの保存

		movwf	w_save		;W レジスタの保存
		movf	STATUS,W
		movwf	s_save		;STATUS レジスタの保存

		bcf	STATUS,RP0	;バンク 0
		bcf	STATUS,RP1
		btfss	PIR1,TMR1IF	;タイマ１オーバフロー か？
;		goto	init		;No. Reset(Illegal interrupt)
		goto	int01

		; タイマー１割り込み処理

		movf	const_high,W	;音階用分周定数 high を
		movwf	TMR1H		;TMR1H に設定
		movf	const_low,W	;音階用分周定数 low を
		movwf	TMR1L		;TMR1L に設定

		movlw	b'00000001'	;RE0: ブザー音出力, 対象ビットをセット
		xorwf	PORTE,F		;出力をビット反転

		bcf	PIR1,TMR1IF	;タイマ１オーバフロー解除

		; レジスタの復帰

int01		movf	s_save,W
		movwf	STATUS		;STATUS レジスタの復帰
		swapf	w_save,F
		swapf	w_save,W	;W レジスタの復帰

		retfie			;割り込みからの復帰

;==========================================================================
;		EEPROM エリア
;==========================================================================

		org	h'2100'

eep_st		de	"Copyright (C) 2010-2018 by M.Yamamoto"

;==========================================================================

		end			;プログラムの終了
