;***** ElectOrgel.asm *****************************************************
;
;	電子オルゴール (Electronic Orgel)
;
;	Copyright (C) 2005-13   by M.Yamamoto. All rights reserved.
;
;     ( coding:  Ver. 0.00   2005/02/18  by M.Yamamoto )
;	coding:  Ver. 1.00   2005/02/26  初期バージョン
;	update:  Ver. 1.10   2005/02/27  プログラム部と曲データ部を分離
;	update:  Ver. 1.11   2005/02/27  ハードウェア変更に伴う変更
;	bugfix:  Ver. 1.12   2005/02/28  曲データの先頭アドレスの計算法
;	update:  Ver. 1.20   2006/07/05  曲データの読み出し方法の改善
;	bugfix:  Ver. 1.21   2013/08/24  曲データの読み出し方法の再改善
;
;***************************************************** PicAsm 0187-1 ******

;	Device: PIC16F648A	Clock: 20MHz (セラロック)

;	PIC16F648A のピンと用途

;	 (1) RA2: 予備				(18) RA1: スピーカ音声出力
;	 (2) RA3: START/STOP スイッチ入力	(17) RA0: LED 出力
;	 (3) RA4: 予備				(16) OSC1: オシレータ水晶入力
;	 (4) MCLR: リセット入力			(15) OSC2: オシレータ水晶入力
;	 (5) VSS: 電源 GND			(14) VDD: 電源 +5V DC
;	 (6) RB0: BCD 1 位スイッチ 0 入力	(13) RB7: BCD 10 位スイッチ 4 入力
;	 (7) RB1: BCD 1 位スイッチ 1 入力	(12) RB6: BCD 10 位スイッチ 2 入力
;	 (8) RB2: BCD 1 位スイッチ 2 入力	(11) RB5: BCD 10 位スイッチ 1 入力
;	 (9) RB3: BCD 1 位スイッチ 4 入力	(10) RB4: BCD 10 位スイッチ 0 入力

;	BCD スイッチの指定

;	00 ～ xx:     指定番号の曲データを再生
;	xx + 1 ～ 97: 曲データなしエラー
;	97:           エラー番号として使用
;	98:           全音階の再生テスト
;	99:           全曲データの再生

;==========================================================================

	list		p=pic16f648a	;デバイス情報
	include		p16f648a.inc	;インクルードファイル
	errorlevel	-302		;Eliminate bank warning

	__config _CP_OFF & DATA_CP_OFF & _LVP_OFF & _BOREN_OFF & _MCLRE_ON & _PWRTE_ON & _WDT_OFF & _HS_OSC

;==========================================================================
;	ラベル定義
;==========================================================================

#define _new_hardware

		radix	dec

ledout		equ	0		;RA0: LED 表示
speaker		equ	1		;RA1: スピーカ
startsw		equ	3		;RA3: Start スイッチ
rb4		equ	4		;一位の桁スイッチ
rb5		equ	5		;十位の桁スイッチ

Do		equ	28		;ド
Do_		equ	29		;ド＃
Re		equ	30		;レ
Re_		equ	31		;レ＃
Mi		equ	32		;ミ
Fa		equ	33		;ファ
Fa_		equ	34		;ファ＃
So		equ	35		;ソ
So_		equ	36		;ソ＃
Ra		equ	37		;ラ
Ra_		equ	38		;ラ＃
Si		equ	39		;シ

Half		equ	1		;半音
Oct1		equ	12		;1 オクターブ
Oct2		equ	24		;2 オクターブ
Oct3		equ	36		;3 オクターブ
Oct4		equ	48		;4 オクターブ
Oct5		equ	60		;5 オクターブ

Nn		equ	h'80'		;休止符
Xx		equ	h'c0'		;テンポ
Rep		equ	h'c1'		;繰り返し

L1		equ	64		;1/1   64 x 1 x tempo = 64 mS x tempo
L2		equ	32		;1/2   32 x 1 x tempo = 32 mS x tempo
L4		equ	16		;1/4   16 x 1 x tempo = 16 mS x tempo
L8		equ	8		;1/8	8 x 1 x tempo =  8 mS x tempo
L16		equ	4		;1/16	4 x 1 x tempo =  4 mS x tempo
L32		equ	2		;1/32	2 x 1 x tempo =  2 mS x tempo
Lx		equ	1		;	1 x 1 x tempo =  1 mS x tempo

		cblock	h'20'
bcd10sw					;BCD 十位の桁スイッチの格納用
bcd01sw					;BCD 一位の桁スイッチの格納用
const_high				;音階用分周定数 high の保存
const_low				;音階用分周定数 low の保存
scale					;音階コードの保存
length					;音長の保存
tempo					;テンポ指定
repeat					;繰り返し指定
lcount1					;ループカウンタ
lcount2					;ループカウンタ
lcount3					;ループカウンタ
lcount4					;ループカウンタ
lcount5					;ループカウンタ
naddr_high				;曲データの先頭アドレスの high アドレス
naddr_low				;曲データの先頭アドレスの low アドレス
addr_high				;読み出す曲データの high アドレス
addr_low				;読み出す曲データの low アドレス
rep_addr_high				;繰り返し曲データの high アドレス
rep_addr_low				;繰り返し曲データの low アドレス
work					;ワーク
		endc

w_save		equ	h'70'		;W レジスタの退避用
s_save		equ	h'71'		;STATUS レジスタの退避用

;==========================================================================
;	プログラム開始
;==========================================================================

		org	0		;リセットベクタ
		goto	start
		org	4		;割り込みベクタ
		goto	interrupt

;==========================================================================
;	音階用分周定数を取得
;==========================================================================

get_scale	movwf	work
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定
		movf	work,W

		addwf	PCL,F			;PC = PC + W

		retlw	high (65536 - 45454)	;01: ラ
		retlw	low  (65536 - 45454)
		retlw	high (65536 - 42903)	;02: ラ＃
		retlw	low  (65536 - 42903)
		retlw	high (65536 - 40495)	;03: シ
		retlw	low  (65536 - 40495)

		retlw	high (65536 - 38222)	;04: ド
		retlw	low  (65536 - 38222)
		retlw	high (65536 - 36077)	;05: ド＃
		retlw	low  (65536 - 36077)
		retlw	high (65536 - 34053)	;06: レ
		retlw	low  (65536 - 34053)
		retlw	high (65536 - 32141)	;07: レ＃
		retlw	low  (65536 - 32141)
		retlw	high (65536 - 30337)	;08: ミ
		retlw	low  (65536 - 30337)
		retlw	high (65536 - 28634)	;09: ファ
		retlw	low  (65536 - 28634)
		retlw	high (65536 - 27028)	;10: ファ＃
		retlw	low  (65536 - 27028)
		retlw	high (65536 - 25510)	;11: ソ
		retlw	low  (65536 - 25510)
		retlw	high (65536 - 24079)	;12: ソ＃
		retlw	low  (65536 - 24079)
		retlw	high (65536 - 22727)	;13: ラ
		retlw	low  (65536 - 22727)
		retlw	high (65536 - 21452)	;14: ラ＃
		retlw	low  (65536 - 21452)
		retlw	high (65536 - 20248)	;15: シ
		retlw	low  (65536 - 20248)

		retlw	high (65536 - 19111)	;16: ド
		retlw	low  (65536 - 19111)
		retlw	high (65536 - 18039)	;17: ド＃
		retlw	low  (65536 - 18039)
		retlw	high (65536 - 17026)	;18: レ
		retlw	low  (65536 - 17026)
		retlw	high (65536 - 16070)	;19: レ＃
		retlw	low  (65536 - 16070)
		retlw	high (65536 - 15168)	;20: ミ
		retlw	low  (65536 - 15168)
		retlw	high (65536 - 14317)	;21: ファ
		retlw	low  (65536 - 14317)
		retlw	high (65536 - 13514)	;22: ファ＃
		retlw	low  (65536 - 13514)
		retlw	high (65536 - 12755)	;23: ソ
		retlw	low  (65536 - 12755)
		retlw	high (65536 - 12039)	;24: ソ＃
		retlw	low  (65536 - 12039)
		retlw	high (65536 - 11363)	;25: ラ
		retlw	low  (65536 - 11363)
		retlw	high (65536 - 10726)	;26: ラ＃
		retlw	low  (65536 - 10726)
		retlw	high (65536 - 10124)	;27: シ
		retlw	low  (65536 - 10124)

		retlw	high (65536 - 9555)	;28: ド		( 261.63 Hz )
		retlw	low  (65536 - 9555)
		retlw	high (65536 - 9019)	;29: ド＃	( 277.18 Hz )
		retlw	low  (65536 - 9019)
		retlw	high (65536 - 8513)	;30: レ		( 293.66 Hz )
		retlw	low  (65536 - 8513)
		retlw	high (65536 - 8035)	;31: レ＃	( 311.13 Hz )
		retlw	low  (65536 - 8035)
		retlw	high (65536 - 7584)	;32: ミ		( 329.63 Hz )
		retlw	low  (65536 - 7584)
		retlw	high (65536 - 7158)	;33: ファ	( 349.23 Hz )
		retlw	low  (65536 - 7158)
		retlw	high (65536 - 6757)	;34: ファ＃	( 369.99 Hz )
		retlw	low  (65536 - 6757)
		retlw	high (65536 - 6377)	;35: ソ		( 392.00 Hz )
		retlw	low  (65536 - 6377)
		retlw	high (65536 - 6019)	;36: ソ＃	( 415.30 Hz )
		retlw	low  (65536 - 6019)
		retlw	high (65536 - 5682)	;37: ラ		( 440.00 Hz )
		retlw	low  (65536 - 5682)
		retlw	high (65536 - 5363)	;38: ラ＃	( 466.16 Hz )
		retlw	low  (65536 - 5363)
		retlw	high (65536 - 5062)	;39: シ		( 493.88 Hz )
		retlw	low  (65536 - 5062)

		retlw	high (65536 - 4777)	;40: ド
		retlw	low  (65536 - 4777)
		retlw	high (65536 - 4509)	;41: ド＃
		retlw	low  (65536 - 4509)
		retlw	high (65536 - 4256)	;42: レ
		retlw	low  (65536 - 4256)
		retlw	high (65536 - 4017)	;43: レ＃
		retlw	low  (65536 - 4017)
		retlw	high (65536 - 3792)	;44: ミ
		retlw	low  (65536 - 3792)
		retlw	high (65536 - 3579)	;45: ファ
		retlw	low  (65536 - 3579)
		retlw	high (65536 - 3378)	;46: ファ＃
		retlw	low  (65536 - 3378)
		retlw	high (65536 - 3189)	;47: ソ
		retlw	low  (65536 - 3189)
		retlw	high (65536 - 3010)	;48: ソ＃
		retlw	low  (65536 - 3010)
		retlw	high (65536 - 2841)	;49: ラ
		retlw	low  (65536 - 2841)
		retlw	high (65536 - 2681)	;50: ラ＃
		retlw	low  (65536 - 2681)
		retlw	high (65536 - 2531)	;51: シ
		retlw	low  (65536 - 2531)

		retlw	high (65536 - 2389)	;52: ド
		retlw	low  (65536 - 2389)
		retlw	high (65536 - 2255)	;53: ド＃
		retlw	low  (65536 - 2255)
		retlw	high (65536 - 2128)	;54: レ
		retlw	low  (65536 - 2128)
		retlw	high (65536 - 2009)	;55: レ＃
		retlw	low  (65536 - 2009)
		retlw	high (65536 - 1896)	;56: ミ
		retlw	low  (65536 - 1896)
		retlw	high (65536 - 1789)	;57: ファ
		retlw	low  (65536 - 1789)
		retlw	high (65536 - 1689)	;58: ファ＃
		retlw	low  (65536 - 1689)
		retlw	high (65536 - 1594)	;59: ソ
		retlw	low  (65536 - 1594)
		retlw	high (65536 - 1505)	;60: ソ＃
		retlw	low  (65536 - 1505)
		retlw	high (65536 - 1420)	;61: ラ
		retlw	low  (65536 - 1420)
		retlw	high (65536 - 1340)	;62: ラ＃
		retlw	low  (65536 - 1340)
		retlw	high (65536 - 1265)	;63: シ
		retlw	low  (65536 - 1265)

		retlw	high (65536 - 1194)	;64: ド
		retlw	low  (65536 - 1194)
		retlw	high (65536 - 1127)	;65: ド＃
		retlw	low  (65536 - 1127)
		retlw	high (65536 - 1064)	;66: レ
		retlw	low  (65536 - 1064)
		retlw	high (65536 - 1004)	;67: レ＃
		retlw	low  (65536 - 1004)
		retlw	high (65536 - 948)	;68: ミ
		retlw	low  (65536 - 948)
		retlw	high (65536 - 895)	;69: ファ
		retlw	low  (65536 - 895)
		retlw	high (65536 - 844)	;70: ファ＃
		retlw	low  (65536 - 844)
		retlw	high (65536 - 797)	;71: ソ
		retlw	low  (65536 - 797)
		retlw	high (65536 - 752)	;72: ソ＃
		retlw	low  (65536 - 752)
		retlw	high (65536 - 710)	;73: ラ
		retlw	low  (65536 - 710)
		retlw	high (65536 - 670)	;74: ラ＃
		retlw	low  (65536 - 670)
		retlw	high (65536 - 632)	;75: シ
		retlw	low  (65536 - 632)

		retlw	high (65536 - 597)	;76: ド
		retlw	low  (65536 - 597)
		retlw	high (65536 - 563)	;77: ド＃
		retlw	low  (65536 - 563)
		retlw	high (65536 - 532)	;78: レ
		retlw	low  (65536 - 532)
		retlw	high (65536 - 502)	;79: レ＃
		retlw	low  (65536 - 502)
		retlw	high (65536 - 474)	;80: ミ
		retlw	low  (65536 - 474)
		retlw	high (65536 - 447)	;81: ファ
		retlw	low  (65536 - 447)
		retlw	high (65536 - 422)	;82: ファ＃
		retlw	low  (65536 - 422)
		retlw	high (65536 - 398)	;83: ソ
		retlw	low  (65536 - 398)
		retlw	high (65536 - 376)	;84: ソ＃
		retlw	low  (65536 - 376)
		retlw	high (65536 - 355)	;85: ラ
		retlw	low  (65536 - 355)
		retlw	high (65536 - 335)	;86: ラ＃
		retlw	low  (65536 - 335)
		retlw	high (65536 - 316)	;87: シ
		retlw	low  (65536 - 316)

		retlw	high (65536 - 298)	;88: ド
		retlw	low  (65536 - 298)

;==========================================================================
;	初期化処理
;==========================================================================

start
		bcf	STATUS,RP1
		bcf	STATUS,RP0	;バンク0 を選択
		clrf	PORTA		;
		movlw	b'00000111'	;RA3-0 を Digital I/O
		movwf	CMCON		;CMCON の設定

		bsf	STATUS,RP0	;バンク1 を選択
		movlw	b'11100'	;RA4-2: 入力, RA1-0: 出力
		movwf	TRISA		;ポートA の I/0 設定
#ifndef _new_hardware
		movlw	b'11001111'	;RB7-6,3-0: 入力, RB5-4: 出力
#else
		movlw	b'11111111'	;RB7-0: 入力
#endif
		movwf	TRISB		;ポートB の I/0 設定

		movlw	b'01000000'	;bit7:0 プルアップ抵抗を使用
					;bit6:1 割り込みパルスの立ち上がりで割り込み
					;bit5:0 タイマに内部クロックを使用
					;bit4:0 立ち上がりでカウントアップ
					;bit3:0 タイマにプリスケーラを使用
					;bit2-0:000 2分周
		movwf	OPTION_REG	;OPTION_REG の設定

		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止

		bcf	STATUS,RP0	;バンク0 を選択
		movlw	b'00000001'	;bit7-6: 未使用
					;bit5-4:00 プリスケーラのスケール値 1:1
					;bit3:0 専用の発振器を使う場合に指定
					;bit2:0 外部入力クロック指定時に有効
					;bit1:0 内部クロックを使う
					;bit0:1 タイマー１を動作
		movwf	T1CON		;T1CON の設定

		clrf	PORTA		;初期値（全ビット０）を設定
		clrf	PORTB		;初期値（全ビット０）を設定
		bcf	INTCON,T0IE	;タイマー０割り込みを禁止
		bsf	INTCON,PEIE	;周辺機器割り込みを許可
		bsf	INTCON,GIE	;全割り込み制御を許可

;==========================================================================
;	メイン・ルーチン
;==========================================================================

stand_by
		; Start スイッチのチェック

		btfsc	PORTA,startsw	;Start スイッチ = ON か？
		goto	stand_by	;No.

		; BCD スイッチの読み取り

#ifndef _new_hardware
		bsf	PORTB,rb5	;10: 十位の桁スイッチの指定
		bcf	PORTB,rb4
		call	wait_1ms	;1m 秒のウエイト
		movf	PORTB,W		;十位の桁スイッチ（BCD-SW1）読み込み
		xorlw	h'ff'		;0/1 ビット反転
		andlw	h'0f'		;下 4 ビットの取り出し
		movwf	bcd10sw		;十位の格納

		bcf	PORTB,rb5	;01: 一位の桁スイッチの指定
		bsf	PORTB,rb4
		call	wait_1ms	;1m 秒のウエイト
		movf	PORTB,W		;一位の桁スイッチ（BCD-SW2）読み込み
		xorlw	h'ff'		;0/1 ビット反転
		andlw	h'0f'		;下 4 ビットの取り出し
		movwf	bcd01sw		;一位の格納
#else
		movf	PORTB,W		;十位の桁スイッチ（BCD-SW1）読み込み
		xorlw	h'ff'		;0/1 ビット反転
		andlw	h'f0'		;上 4 ビットの取り出し
		movwf	bcd10sw	
		swapf	bcd10sw,F	;十位の格納

		movf	PORTB,W		;一位の桁スイッチ（BCD-SW2）読み込み
		xorlw	h'ff'		;0/1 ビット反転
		andlw	h'0f'		;下 4 ビットの取り出し
		movwf	bcd01sw		;一位の格納
#endif

		; 設定された BCD スイッチ値の変換

		bcf	STATUS,C	;一位 + 10 * 十位 の計算
		rlf	bcd10sw,W
		addwf	bcd01sw,F	;一位 + 2 * 十位
		rlf	bcd10sw,F
		rlf	bcd10sw,F
		rlf	bcd10sw,W
		addwf	bcd01sw,F	;(一位 + 2 * 十位) + (8 * 十位)

		; 全音階の再生テスト

		movlw	98
		subwf	bcd01sw,W
		btfss	STATUS,Z	;BCD スイッチ値 = 98 か?
		goto	stb01		;No

		call	test_scale	;全音階の再生テスト
		movlw	high stand_by	;;
		movwf	PCLATH		;;
		goto	stand_by

		; 全曲データの再生

stb01		movlw	99
		subwf	bcd01sw,W
		btfss	STATUS,Z	;BCD スイッチ値 = 99 か?
		goto	stb02		;No

		call	all_play_back	;全曲データの再生
		movlw	high stand_by	;;
		movwf	PCLATH		;;
		goto	stand_by

		; 指定曲データの再生

stb02		movlw	(name_table_end - name_table) >> 1
		subwf	bcd01sw,W
		btfsc	STATUS,C	;BCD スイッチ値 < (曲番号 + 1) か?
		goto	stb03		;No

		call	play_back	;該当曲データの再生
		movlw	high stand_by	;;
		movwf	PCLATH		;;
		goto	stand_by

		; BCD スイッチの指定エラー

stb03		call	bcdsw_error	;指定エラー
		movlw	high stand_by	;;
		movwf	PCLATH		;;
		goto	stand_by

;==========================================================================
;	全音階の再生テスト（BCD スイッチ = 98 指定）
;==========================================================================

test_scale
		call	led_control	;LED 点滅

		bsf	STATUS,RP0	;バンク1 を選択
		bsf	PIE1,TMR1IE	;タイマー１割り込みを許可
		bcf	STATUS,RP0	;バンク0 を選択

		movlw	1
		movwf	scale		;音階コードに初期値を設定

		; 音階の再生

tst01		movf	scale,W
		movwf	tempo		;tempo をワークとして使用
		decf	tempo,F		;音階コード -1
		bcf	STATUS,C
		rlf	tempo,W		;音階コードを 2 倍する
		call	get_scale	;音階用分周定数を取得
		movwf	const_high	;high に保存する

		bsf	STATUS,C
		rlf	tempo,W		;音階コードを 2 倍して +1 する
		call	get_scale	;音階用分周定数を取得
		movwf	const_low	;low に保存する

		movlw	50
		movwf	lcount5		;ループカウンタを設定

tst02		call	wait_10ms	;音長を 500ms で再生
		decfsz	lcount5,F	;ループ終了 か?
		goto	tst02		;No

		; 再生中断の監視と音階コードの更新

		btfss	PORTA,startsw	;Start スイッチ = ON か？
		goto	tst03		;Yes

		incf	scale,F		;音階コードの更新
		movf	scale,W
		sublw	88
		btfsc	STATUS,C	;音階コード終了 か?
		goto	tst01		;No

tst03		bsf	STATUS,RP0	;バンク1 を選択
		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク0 を選択

		call	led_control	;LED 点滅

		return

;==========================================================================
;	全曲データの再生（BCD スイッチ = 99 指定）
;==========================================================================

all_play_back
		clrf	bcd10sw		;再生曲番号の初期設定

all01		movf	bcd10sw,W
		movwf	bcd01sw		;再生曲番号を設定
		call	play_back

		btfsc	PORTA,startsw	;Start スイッチ = ON か？
		goto	all02		;No

		call	led_control	;LED 点滅
		goto	all03

all02		incf	bcd10sw,F	;再生曲番号の更新
		movlw	(name_table_end - name_table) >> 1
		subwf	bcd10sw,W
		btfss	STATUS,C	;BCD スイッチ値 >= (曲番号 + 1) か?
		goto	all01		;No

all03		return

;==========================================================================
;	BCD スイッチの指定エラー（BCD スイッチ = xx + 1 ～ 97 指定）
;==========================================================================

bcdsw_error
		movlw	97
		movwf	bcd01sw		;エラー番号の設定

		movlw	high error_data
		movwf	addr_high	;読み出す曲データのアドレス high に設定
		movlw	low error_data
		movwf	addr_low	;読み出す曲データのアドレス low に設定
		call	play_back

		return

		; エラーデータ

error_data	retlw	Xx		;テンポ
		retlw	20

		retlw	Rep		;繰り返し
		retlw	3

		retlw	Mi
		retlw	L16
		retlw	Si
		retlw	L16
		retlw	Nn
		retlw	L16

		retlw	0

;==========================================================================
;	指定番号（bcd01sw）に応じ 該当曲データを再生
;==========================================================================

play_back
		call	led_control	;LED 点滅

		movlw	1
		movwf	repeat		;繰り返し指定の初期設定

		; 各曲データの先頭アドレスの読み出し

		movlw	97		;エラー番号
		subwf	bcd01sw,W
		btfsc	STATUS,Z	;BCD スイッチ値 = 97 か?
		goto	ply01		;Yes

		bcf	STATUS,C	;(一位 + 10 * 十位) * 2 の計算
		rlf	bcd01sw,F	;0,2,4 ･･･ の偶数値

		movlw	high name_table	;曲データの先頭アドレステーブルの high アドレス
		movwf	naddr_high	;
		movlw	low name_table	;曲データの先頭アドレステーブルの low アドレス
		addwf	bcd01sw,W	;low + (一位 + 10 * 十位 - 1) * 2
		movwf	naddr_low	;
		btfsc	STATUS,C	;オーバーフローした場合は
		incf	naddr_high,F	;曲データの先頭アドレス high の更新
		call	ndt_read
		movwf	addr_high      ;;読み出す曲データのアドレス high を設定

		incf	naddr_low,F	;曲データの先頭アドレス low の更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	naddr_high,F	;曲データの先頭アドレス high の更新
		call	ndt_read
		movwf	addr_low       ;;読み出す曲データのアドレス low を設定

		; 曲データの読み出し

ply01		call	kdt_read	;曲データ1 を読み出す
		movwf	scale	       ;;音階コードに保存

		movf	scale,W
		btfsc	STATUS,Z	;読み出しデータ 終了か?
		goto	ply07		;Yes

		call	kdt_read	;曲データ2 を読み出す
		movwf	length	       ;;音長に保存

		; 音階コードの分析

		movlw	Nn		;音階コードが (Nn) の時は休止符
		subwf	scale,W
		btfsc	STATUS,Z	;音階コード = (Nn) か？
		goto	ply04		;Yes

		movlw	Xx		;音階コードが (Xx) の時は テンポ指定
		subwf	scale,W
		btfss	STATUS,Z	;音階コード = (Xx) か？
		goto	ply02		;No

		movf	length,W	;テンポを取り出す
		movwf	tempo		;テンポ指定を設定
		goto	ply06

ply02		movlw	Rep		;音階コードが (Rep) の時は 繰り返し指定
		subwf	scale,W
		btfss	STATUS,Z	;音階コード = (Rep) か？
		goto	ply03		;No

		movf	addr_high,W
		movwf	rep_addr_high	;繰り返し曲データの high アドレスを保存
		movf	addr_low,W
		movwf	rep_addr_low	;繰り返し曲データの low アドレスを保存

		movf	length,W	;繰り返しを取り出す
		movwf	repeat		;繰り返し指定を設定
		goto	ply06

		; 音符, 休符の再生

ply03		decf	scale,F		;音階コード -1
		bcf	STATUS,C
		rlf	scale,W		;音階コードを 2 倍する
		call	get_scale	;音階用分周定数を取得
		movwf	const_high     ;;high に保存する
		bsf	STATUS,C
		rlf	scale,W		;音階コードを 2 倍して +1 する
		call	get_scale	;音階用分周定数を取得
		movwf	const_low      ;;low に保存する

		bsf	STATUS,RP0	;バンク1 を選択
		bsf	PIE1,TMR1IE	;タイマー１割り込みを許可
		bcf	STATUS,RP0	;バンク0 を選択

ply04		movf	tempo,W
		movwf	lcount5		;ループカウンタを設定

ply05		call	wait_1ms	;音長を (tempo * length) 倍で再生
		decfsz	lcount5,F	;ループ終了 か?
		goto	ply05		;No

		decfsz	length,F	;音長 = 0 か？
		goto	ply04		;No

		bsf	STATUS,RP0	;バンク1 を選択
		bcf	PIE1,TMR1IE	;タイマー１割り込みを禁止
		bcf	STATUS,RP0	;バンク0 を選択

		; 再生中断の監視と繰り返し処理

ply06		;movlw	1 << ledout	;対象ビットをセット
		;xorwf	PORTA,F		;LED 点滅（再生中表示）

		btfsc	PORTA,startsw	;Start スイッチ = ON か？
		goto	ply01		;No
		goto	ply09		;Yes

ply07		decfsz	repeat,F	;繰り返し終了 か?
		goto	ply08		;No
		goto	ply09		;Yes

ply08		movf	rep_addr_high,W
		movwf	addr_high	;繰り返し曲データの high アドレスを復帰
		movf	rep_addr_low,W
		movwf	addr_low	;繰り返し曲データの low アドレスを復帰
		goto	ply01		;No

		; 読み出し終了処理

ply09		call	led_control	;LED 点滅

		return

		; 曲データの先頭アドレスの読み出し

ndt_read
		call	ndt_read_0	;テーブルデータの読み出し
		movwf	work
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定
		movf	work,W
		return

ndt_read_0
		movf	naddr_high,W	;曲データの先頭アドレスの high アドレス
		movwf	PCLATH
		movf	naddr_low,W	;曲データの先頭アドレスの low アドレス
		movwf	PCL

		; 曲データの読み出し

kdt_read
		call	kdt_read_0	;テーブルデータの読み出し
		movwf	work
		movlw	high $		;この場所の high アドレスを
		movwf	PCLATH		;PCLATH に設定
		movf	work,W

		incf	addr_low,F	;曲データの low アドレスの更新
		btfsc	STATUS,Z	;オーバーフローした場合は
		incf	addr_high,F	;曲データの high アドレスの更新
		return

kdt_read_0
		movf	addr_high,W	;読み出す曲データの high アドレス
		movwf	PCLATH
		movf	addr_low,W	;読み出す曲データの low アドレス
		movwf	PCL

		; LED 点滅コントロール

led_control
		movlw	5
		movwf	lcount5

led01		bsf	PORTA,ledout	;LED 点灯
		call	wait_50ms	;50m 秒待機
		bcf	PORTA,ledout	;LED 消灯
		call	wait_50ms	;50m 秒待機
		decfsz	lcount5,F	;ループ終了か?
		goto	led01		;No

		return

;==========================================================================
;	ウェイト・ルーチン（ 20 MHz ）
;==========================================================================

		; 0.2m 秒 ウェイトルーチン

wait_200us
	       ;movlw	199		;	1+1+(2+1+2)*198+(2+2+0)+2=998
		movlw	198		;1
		movwf	lcount1		;1
wait01		goto	$+1		;2
		decfsz	lcount1,F	;1,2
		goto	wait01		;2,0	1+1+(2+1+2)*197+(2+2+0)=991
		return			;2	991+2=993
					;       993/20MHz*4 = 0.1986 mS = 0.2 mS

		; 1m 秒 ウェイトルーチン

wait_1ms
		movlw	5		;1
		movwf	lcount2		;1
wait02		call	wait_200us	;2	2+993=995
		goto	$+1		;2
		decfsz	lcount2,F	;1,2
		goto	wait02		;2,0	1+1+(995+2+1+2)*4+(995+2+2+0)=5001
		return			;2	5001+2=5003
					;       5003/20MHz*4 = 1.0006 mS = 1 mS

		; 10m 秒 ウェイトルーチン

wait_10ms
		movlw	50		;1
		movwf	lcount3		;1
wait03		call	wait_200us	;2	2+993=995
		goto	$+1		;2
		decfsz	lcount3,F	;1,2
		goto	wait03		;2,0	1+1+(995+2+1+2)*49+(995+2+2+0)=50001
		return			;2	50001+2=50003
					;       50003/20MHz*4 = 10.0006 mS = 10 mS

		; 50m 秒 ウェイトルーチン

wait_50ms
		movlw	5		;1
		movwf	lcount4		;1
wait04		call	wait_10ms	;2	2+50003=50005
		decfsz	lcount4,F	;1,2
		goto	wait04		;2,0	1+1+(50005+1+2)*4+(50005+2+0)=250041
		return			;2	250041+2=250043
					;       250043/20MHz*4 = 50.0086 mS = 50 mS

;==========================================================================
;	タイマー１割り込み処理
;==========================================================================

interrupt
		movwf	w_save		;W レジスタを退避
		swapf	STATUS,W
		movwf	s_save		;STATUS レジスタを退避

		clrf	STATUS

		movf	const_high,W	;音階用分周定数 high を
		movwf	TMR1H		;TMR1H に設定
		movf	const_low,W	;音階用分周定数 low を
		movwf	TMR1L		;TMR1L に設定

		movlw	1 << speaker	;対象ビットをセット
		xorwf	PORTA,F		;出力をビット反転

		bcf	PIR1,TMR1IF	;タイマ１オーバフロー解除

		swapf	s_save,W
		movwf	STATUS		;STATUS レジスタを復帰
		swapf	w_save,F
		swapf	w_save,W	;W レジスタを復帰

		retfie			;割り込み処理の終了

;==========================================================================

		include	OrgelData.inc	;曲データ部のインクルード

		end			;プログラムの終了
