こちらのレベル3で一応MIDI再生できるようになったVS1053bのSPI駆動をS1で試してみます。
レベル3ではDISKBASICから1セクタずつデータを取りだしてバッファせずに演奏していたので、セクタを読んでいる間数秒の演奏停止がありました。
マーク5の64KB拡張メモリをバッファにして一気にVS1053bにデータを転送しようとチャレンジしましたが今のところうまくいっていません。(なんだか難しい・・・^^;;;)
そこで大容量メモリを積んでいるS1で試してみることにしました。
結果、マーク5の64KB拡張メモリよりもシンプルにバッファを実装できました(^^)
VS1053bのMIDI演奏機能なのでSMF0のMIDIファイルしか対応していませんがS1でMIDIを演奏できる満足感は高いです。
但し、セクタ読出しは相変わらずDISKBASICのシーケンシャルファイルリードを使っているので65KB程度のMIDIデータを全てメモリに格納するのに約15分かかるポンコツローダーです(^^;;;
遅いけどDISKBASICの世界なので2D,2HDの区別く使用できます。
でも、この遅さは改善したい・・・・
ハードの取付
レベル3用のPIAカード MP-1895は56ピンエッジコネクタなので端を1ピン側に寄せて取り付けます。![]()
VS1052bカードはレベル3の時と同じ中華製のモジュールを使いました。
DREQのタイミングを見るのに中華製の簡易ロジアナも取り付けてます(^^)
![]()
メモリーはKR2-A改造の512KBです
ハードは以上の構成で実験しています(^^)
■ソフト編
拡張メモリへのデータ転送部分は SAMさんの CP/Mローダーを参考にしています。
PIAのSPIドライバはold68funさんのPIA-SPI変換やPIA-I2C変換を参考にしています。
VS1053bのドライバはレベル3の時に作ったものを改良しています。
DRQタイムアウトのリトライ処理を追加して演奏が止まりにくくなりました(^^;;;
使用したアセンブラはいつものシステムロード製SASMアセンブラです。
機械語部分の全リストを貼ります
一応、期待した動作はしているようですがもっと良い改造法や改善した方がいい点などありましたらご指摘下さい。
▼DISKBASIC用MIDIローダ
100 CLEAR,&H5FFF: WIDTH40 110 FLBUF = &H6000: BUFLEN = 256 120 ' ================================================================ 130 ' FILE -> EXTENDED MEMORY -> VS1053 PLAYER for MB-S1 L1 V0.3.0 140 ' VSPLAYER ENTRY: $6300 INIT $6304 BUF_INIT 150 ' $6307 BUF_WRITE $630A BUF_DONE $630D PLAY_ALL 160 ' ================================================================ 170 LOADM "VSPLAYER": EXEC &H6300 'VS1053 Init 180 LOADM "EXTMEM" 'Load EXTMEM_COPY($B000) 190 EXEC &H6304 'BUF_INIT 200 NSEC = 0: NBYTES = 0 210 OPEN "I", #1, "MUSIC1.BIN" 220 PRINT "VS1003/VS1053 MIDI Player (L1 V3)" 230 PRINT "FD READ SECT -> EXT-MEMORY Buffering..." 240 ' 250 IF EOF(1) THEN 390 260 CNT = 0 270 IF EOF(1) THEN 330 280 POKE FLBUF + CNT, ASC(INPUT$(1, #1)) 290 CNT = CNT + 1 300 IF CNT < BUFLEN THEN 270 310 ' 320 '--- Buffer->Extended Memory Write 330 EXEC &H6307 'BUF_WRITE 340 NSEC = NSEC + 1: NBYTES = NBYTES + CNT 350 PRINT NSEC; 360 GOTO 250 370 ' 380 '--- BUFFERING END --- 390 CLOSE #1 400 EXEC &H630A 'BUF_DONE 410 PRINT "": PRINT "LOADED SECTORS=";NSEC;" BYTES=";NBYTES 420 IF PEEK(&H611A) = 1 THEN PRINT "WARNING: EXT-MEMORY FULL (MAX 448KB)" 430 PRINT "PLAYING..." 440 EXEC &H630D 'PLAY_ALL 450 PRINT "DATA SEND COMPLETE..." 460 END
一度拡張メモリにロードしたMIDIデータはRUN 430で何度も演奏できます(^^)
▼拡張メモリ用ドライバ
こちらのメモリテストプログラムで物理ページ$01, $02, $09ページにアクセスするとハングアップするのでそこは使用せずに$10~$7Fページのみ使うのがよさそうです。
それでも約450KB以上あるのでMIDIのバッファとしては十分です(^^)
Page 1 (26-10-13 22:46:49) EXTMEM.asm
1: ;EXTMEM.ASM
2: PAGE 999
3: ; ==========================================================================================
4: ; EXTMEM_COPY MB-S1 拡張メモリ ブロックコピー L1 Ver0.30
5: ;
6: ; S1の拡張メモリ(物理ページ$00-$7F、1ページ=4KB、最大512KB)と、通常MEM
7: ; (64KB論理空間)の間で、任意バイト数をコピーする。 JSR $B000 で実行
8: ; パラメータをセットしJSR $B000 で使う。
9: ;
10: ; 呼び出しインターフェース (固定番地へPOKE(STA)してから JSR $B000
11: ; EXTC_DIR $B004 (1byte): 0=通常MEM->拡張MEM,1=拡張MEM->通常MEM
12: ; EXTC_NADR $B005 (2byte): 通常メモリ側アドレス(上位Byteが先)
13: ; EXTC_XPAGE $B007 (1byte): 拡張メモリ側 物理ページ番号(0-127, $00-$7F)
14: ; EXTC_XOFS $B008 (2byte): 拡張メモリ側 ページ内オフセット(0-4095)
15: ; EXTC_LEN $B00A (2byte): 転送バイト数(0なら何もしない)
16: ; 戻ると、NADR・XPAGE/XOFSは転送した分だけ進み、LENは0
17: ; 位置を設定し直さずに続けて呼べる(256Byteずつ連続した領域へ書く)
18: ; ==========================================================================================
19:
20: B000' ORG $B000
21: B000' 7E B00E JMP EXTMEM_COPY
22: B003' 03 FCB $03 ;バージョン3
23:
24: ; ---- 呼び出しインターフェース(ワークエリア) ----
25: B004' 00 EXTC_DIR: FCB 0 ;1byte 0=通常→拡張 / 1=拡張→通常
26: B005' 0000 EXTC_NADR: FDB 0 ;2byte 通常メモリ側アドレス
27: B007' 00 EXTC_XPAGE: FCB 0 ;1byte 拡張メモリ側 物理ページ番号
28: B008' 0000 EXTC_XOFS: FDB 0 ;2byte 拡張メモリ側 ページ内オフセット
29: B00A' 0000 EXTC_LEN: FDB 0 ;2byte 転送バイト数
30: B00C' 0000 ECP_CHUNK: FDB 0 ;転送するバイト数(作業用)
31:
32: B00E' 0009 WIN_PAGE_POS EQU $09 ;自系列(F)側の窓ページ位置
33: B00E' 9000 WIN_BASE EQU $9000 ;WIN_PAGE_POS*$1000
34: B00E' 1000 PAGE_SIZE EQU $1000 ;拡張メモリ1ページのバイト数(4KB)=窓の大きさ
35: B00E' 00F0 SERIES_F_NIB EQU $F0 ;MMSTPGのACCB上位ニブル: 系列F
36: B00E' 0040 SYS_MMSTPG_SER EQU $40 ;SWI2のサービス: 系列0(メモリ管理)のMMSTPG
37: B00E' 0009 SYS_MMSTPG_RT EQU 9 ;SWI2のルーチン番号: MMSTPG(ページ位置へ物理ページ)
38: B00E' 0050 CC_MASK_IF EQU %01010000 ;CC: F(FIRQ禁止)とI(IRQ禁止)のビット
39: B00E' 00AF CC_CLR_IF EQU %10101111 ;割込み許可
40:
41: ; ---------------------------------------------------------------
42: ; EXTMEM_COPY本体
43: ; ---------------------------------------------------------------
44: B00E' EXTMEM_COPY: ;本体メモリ⇔拡張メモリ のデータコピー
45: B00E' FC B00A ECP_LOOP: LDD EXTC_LEN
46: B011' 10 27 0089 LBEQ ECP_DONE ;残りバイト数=0で終了
47:
48: B015' 1A 50 ORCC #CC_MASK_IF ;割込み禁止(窓切替~転送の間)
49:
50: B017' B6 B007 LDA EXTC_XPAGE ;ACCA=物理ページ番号
51: B01A' C6 F9 LDB #SERIES_F_NIB+WIN_PAGE_POS ;ACCB=系列F PAGE位置WIN_PAGE_POS
52: B01C' 10 3F SWI2
53: B01E' 40 09 FCB SYS_MMSTPG_SER,SYS_MMSTPG_RT ;MMSTPG(系列0,ルーチン9)
54:
55: B020' 8E 9000 LDX #WIN_BASE
56: B023' FC B008 LDD EXTC_XOFS
57: B026' 30 8B LEAX D,X ;X=窓内の実アドレス
58:
59: B028' CC 1000 LDD #PAGE_SIZE
60: B02B' B3 B008 SUBD EXTC_XOFS ;D=このページで転送できる残りByte数
61: B02E' FD B00C STD ECP_CHUNK
62:
63: B031' FC B00A LDD EXTC_LEN
64: B034' 10 B3 B00C CMPD ECP_CHUNK
65: B038' 23 03 BLS ECP_SETLEN
66: B03A' FC B00C LDD ECP_CHUNK
67: B03D' ECP_SETLEN:
68: B03D' FD B00C STD ECP_CHUNK
69:
70: B040' 10 BE B005 LDY EXTC_NADR ;Y=通常メモリ側アドレス
71:
72: B044' B6 B004 LDA EXTC_DIR
73: B047' 26 16 BNE ECP_X2N
74:
75: B049' ECP_N2X: ;通常メモリ→拡張メモリ
76: B049' FC B00C LDD ECP_CHUNK
77: B04C' 27 25 BEQ ECP_ADV
78: B04E' FE B00C LDU ECP_CHUNK ;U=転送バイト数(カウンタ専用
79: B051' ECP_N2X_LP:
80: B051' A6 A0 LDA ,Y+
81: B053' A7 80 STA ,X+
82: B055' 33 5F LEAU -1,U ;LEAUはフラグを変えないので、次のCMPUでゼロ判定
83: B057' 11 83 0000 CMPU #0
84: B05B' 26 F4 BNE ECP_N2X_LP
85: B05D' 20 14 BRA ECP_ADV
86:
87: B05F' ECP_X2N: ;拡張メモリ→通常メモリ
88: B05F' FC B00C LDD ECP_CHUNK
89: B062' 27 0F BEQ ECP_ADV
90: B064' FE B00C LDU ECP_CHUNK
91: B067' ECP_X2N_LP:
92: B067' A6 80 LDA ,X+
93: B069' A7 A0 STA ,Y+
94: B06B' 33 5F LEAU -1,U
95: B06D' 11 83 0000 CMPU #0
96: B071' 26 F4 BNE ECP_X2N_LP
97:
98: B073' ECP_ADV:
99: B073' 1C AF ANDCC #CC_CLR_IF ;割込み許可
100:
101: B075' FC B005 LDD EXTC_NADR
102: B078' F3 B00C ADDD ECP_CHUNK
103: B07B' FD B005 STD EXTC_NADR ;通常MEM側アドレスをCHUNK分進める
104:
105: B07E' FC B008 LDD EXTC_XOFS
106: B081' F3 B00C ADDD ECP_CHUNK
107: B084' 10 83 1000 CMPD #PAGE_SIZE
108: B088' 26 05 BNE ECP_NOCARRY ;ページ内にまだ残りがある
109: B08A' 4F CLRA ;ページ終わり->次のページ先頭
110: B08B' 5F CLRB
111: B08C' 7C B007 INC EXTC_XPAGE
112: B08F' ECP_NOCARRY:
113: B08F' FD B008 STD EXTC_XOFS
114:
115: B092' FC B00A LDD EXTC_LEN
116: B095' B3 B00C SUBD ECP_CHUNK
117: B098' FD B00A STD EXTC_LEN ;残りByte数を減らす
118:
119: B09B' 16 FF70 LBRA ECP_LOOP ;次CHUNKへ(LENが0で終了)
120:
121: B09E' 39 ECP_DONE: RTS
122:
123: END
0 errors.
▼PIA-SPI用MIDIプレーヤ (SPIビットバンキング)
Page 1 (26-10-13 22:47:42) VSPLAYER.asm
1: ; VSPLAYER.ASM (MB-S1 L1)
2: PAGE 999
3: ;===============================================================
4: ; VS1053b AUDIO LSI MIDI Player -- MB-S1 L1 (拡張メモリ経由の単体版)
5: ; Version : 0.3.0 (L1)
6: ;
7: ; VS1053bにSDIでデータを送ってMIDIデータを演奏
8:
9: ; メモリマップ
10: ; $6000-$60FF SECT_BUF 256Byte (BASICがPOKEするセクタバッファ)
11: ; $6100-$6103 SPI作業 / $6110-$611C VS1053・拡張メモリの作業(下の表)
12: ; $6300- プログラム $B000- EXTMEM_COPY(EXTMEM.ASM)
13: ;
14: ; 作業領域 ($6110 = VS_WORK_TOP からの位置)
15: ; +0 BUF_RDY VSPLAYER(初期化)の結果 0=OK 1=TIMEOUT
16: ; +4 SEND_SDI_CNT VS1053_SEND_SDIの残りブロック数(32Byte単位)
17: ; +5 SEND_SDI_PTR 同、送信ポインタ(2Byte。+5/+6)
18: ; +7 EXT_END_PAGE 書込み終端の物理ページ (BUF_DONEが設定)
19: ; +8 EXT_END_OFS 書込み終端のページ内オフセット(2Byte。+8/+9)
20: ; +10 EXT_OVERFLOW 1=拡張メモリ満杯でBUF_WRITEが書込みを打切った
21: ; +11 SEND_TOUT_CNT DREQタイムアウトの累計(診断用)
22: ; +12 SEND_RETRY 現在の256Byteブロックでの連続リトライ回数
23: ;
24: ; データバッファ: 物理ページ$10-$7F(112ページ=448KB分確保)
25: ;===============================================================
26:
27: ;---------------------------------------------------------------
28: ; MB-S1の定数
29: ;---------------------------------------------------------------
30: 0000' FF60 PIA_ADDR EQU $FF60 ; MP-1895 PIA(MC6821) PortA/B
31: 0000' FF60 PIA_PA_DATA EQU PIA_ADDR ; PortAデータ(DDRアクセス時はDDRA)
32: 0000' FF61 PIA_PA_CTRL EQU PIA_ADDR+1
33: 0000' FF62 PIA_PB_DATA EQU PIA_ADDR+2
34: 0000' FF63 PIA_PB_CTRL EQU PIA_ADDR+3
35: 0000' 0004 PIA_CR_NORMAL EQU %00000100 ; コントロール/データレジスタ(0=DDR)
36: 0000' 00FF PIA_DIR_OUT EQU $FF ; DDR 全ビット出力
37:
38: 0000' 6000 COMMON_WORK_TOP EQU $6000 ; SECTBUF
39: 0000' 6000 SECT_BUF EQU COMMON_WORK_TOP
40: 0000' 0100 SECT_SIZE EQU 256
41: 0000' 6100 SPI_WORK_TOP EQU $6100
42: 0000' 6110 VS_WORK_TOP EQU $6110
43: 0000' 6300 PROGRAM_TOP EQU $6300
44:
45: 0000' 0119 DLY_1MS_CNT EQU 281 ; DELAY_1MS
46: 0000' 000A DLY_10MS_TIMES EQU 10 ; DELAY_10MS
47:
48: ;---------------------------------------------------------------
49: ; 拡張メモリ(EXTMEM.ASM)の呼び出しインターフェース
50: ;---------------------------------------------------------------
51: 0000' B000 EXTMEM_COPY EQU $B000 ; JSRで呼ぶ
52: 0000' B004 EXTC_DIR EQU $B004 ; 1Byte 0=通常->拡張 / 1=拡張->通常
53: 0000' B005 EXTC_NADR EQU $B005 ; 2Byte 通常メモリ側アドレス
54: 0000' B007 EXTC_XPAGE EQU $B007 ; 1Byte 拡張メモリ側 物理ページ(転送後はインクリ)
55: 0000' B008 EXTC_XOFS EQU $B008 ; 2Byte ページ内OFFSET
56: 0000' B00A EXTC_LEN EQU $B00A ; 2Byte 転送Byte数
57: 0000' 0000 XDIR_TO_EXT EQU 0
58: 0000' 0001 XDIR_FROM_EXT EQU 1
59:
60: 0000' 0010 EXT_BUF_START_PAGE EQU $10 ; BUF開始 物理PAGE
61: 0000' 0000 EXT_BUF_START_OFS EQU $0000
62: 0000' 007F EXT_BUF_END_PAGE EQU $7F ; BUF最終 PAGE
63:
64: ;---------------------------------------------------------------
65: ; 作業領域
66: ;---------------------------------------------------------------
67: 0000' 6100 SPI_PORTA EQU SPI_WORK_TOP ; PortAの出力イメージ
68: 0000' 6101 SPI_TEMP EQU SPI_WORK_TOP+1 ; 3Byte +0=レジスタ番号 +1=データMSB +2=データLSB
69: 0000' 6110 BUF_RDY EQU VS_WORK_TOP ; 初期化の結果
70: 0000' 6114 SEND_SDI_CNT EQU VS_WORK_TOP+4
71: 0000' 6115 SEND_SDI_PTR EQU VS_WORK_TOP+5
72: 0000' 6117 EXT_END_PAGE EQU VS_WORK_TOP+7
73: 0000' 6118 EXT_END_OFS EQU VS_WORK_TOP+8
74: 0000' 611A EXT_OVERFLOW EQU VS_WORK_TOP+10
75: 0000' 611B SEND_TOUT_CNT EQU VS_WORK_TOP+11
76: 0000' 611C SEND_RETRY EQU VS_WORK_TOP+12
77: 0000' 00C8 SEND_RETRY_MAX EQU 200 ; RETRY MAX
78: 0000' 0001 FLAG_ON EQU 1
79:
80: ;---------------------------------------------------------------
81: ; VS1053b / SPIの定数
82: ;---------------------------------------------------------------
83: 0000' 0000 VS_OK EQU 0
84: 0000' 0001 VS_TIMEOUT EQU 1
85: 0000' C350 VS_DREQ_TIMEOUT EQU 50000 ; DREQ待ちのループ回数(約0.45秒。1周18サイクル)
86: 0000' 9800 VS_CLOCK_INIT EQU $9800 ; SCI_CLOCKF 3.5倍
87: 0000' 2020 VS_VOL_INIT EQU $2020 ; SCI_VOL L=32 R=32
88: 0000' 0800 VS_MODE_INIT EQU $0800 ; SCI_MODE SDI NewMode
89: 0000' 0000 SCI_MODE_REG EQU 0
90: 0000' 0003 SCI_CLOCKF_REG EQU 3
91: 0000' 000B SCI_VOL_REG EQU 11
92: 0000' 0002 SCI_WRITE_CMD EQU $02 ; SCI書込みコマンド
93: 0000' 0008 SEND256_CNT EQU 8 ; 256Byte=32Bytex8Block
94: 0000' 0020 SEND32_SIZE EQU 32
95:
96: 0000' 0001 SPI_MOSI_BIT EQU %00000001 ; PortA bit0
97: 0000' 0002 SPI_SCK_BIT EQU %00000010 ; bit1
98: 0000' 0004 SPI_CS0_BIT EQU %00000100 ; bit2 XCS (SCI選択)
99: 0000' 0008 SPI_CS1_BIT EQU %00001000 ; bit3 XDCS(SDI選択)
100: 0000' 0020 SPI_RESET_BIT EQU %00100000 ; bit5 RESET
101: 0000' 0002 SPI_DREQ_IBIT EQU %00000010 ; PortB bit1 DREQ
102: 0000' 00FE CLR_MOSI_MASK EQU %11111110 ; NOT(MOSI) 各ビットのクリア用マスク(2進数で明示)
103: 0000' 00FD CLR_SCK_MASK EQU %11111101
104: 0000' 00FB CLR_CS0_MASK EQU %11111011
105: 0000' 00F7 CLR_CS1_MASK EQU %11110111
106: 0000' 00DF CLR_RESET_MASK EQU %11011111
107: 0000' 003C SPI_IDLE EQU $3C ; 待機状態 XCS=H XDCS=H RESET=H MOSI=L SCK=L (%00111100)
108: 0000' 0028 SPI_BASE_SCI EQU $28 ; SCI通信中のベース値 RESET=H XDCS=H XCS=L (%00101000)
109: 0000' 0008 SPI_BITS EQU 8
110: 0000' 0080 SPI_MSB EQU %10000000 ; 送信データの最上位ビット
111:
112: ;===============================================================
113: ; ENTRY
114: ;===============================================================
115: 6300' ORG PROGRAM_TOP
116: 6300' 7E 6310 ENTRY: JMP VSPLAYER ; $6300 VS1053初期化
117: 6303' 01 FCB $01 ; $6303 バージョン
118: 6304' 7E 631B JMP BUF_INIT ; $6304
119: 6307' 7E 632D JMP BUF_WRITE ; $6307
120: 630A' 7E 634D JMP BUF_DONE ; $630A
121: 630D' 7E 635A JMP PLAY_ALL ; $630D
122:
123: ;------------------------------------------------------------
124: ; VSPLAYER
125: ; 機能: VS1053bを初期化する(BASICの EXEC &H6300 から)
126: ; 処理内容: VS1053_INITを呼び、結果を BUF_RDY($6110) へ書く
127: ; 引数: なし
128: ; 戻り値: $6110 = 0(OK) / 1(TIMEOUT)
129: ; 破壊レジスタ: Aのみ(他は保存してBASICへ戻る)
130: ;------------------------------------------------------------
131: 6310' 34 75 VSPLAYER: PSHS B,X,Y,U,CC ; Aレジスタ以外を退避
132: 6312' BD 63BF JSR VS1053_INIT ; Aに戻り値が入る
133: 6315' B7 6110 STA BUF_RDY ; $6110 に書き込み
134: 6318' 35 75 PULS CC,U,Y,X,B ; Aレジスタ以外を復元
135: 631A' 39 RTS
136:
137: ;------------------------------------------------------------
138: ; BUF_INIT
139: ; 機能: 拡張メモリの書込み位置を先頭($10ページ:0)に初期化し、
140: ; 満杯フラグと失敗回数の累計を0クリア
141: ; 引数: なし 戻り値: なし
142: ; 破壊レジスタ: A,B,CC
143: ;------------------------------------------------------------
144: 631B' 86 10 BUF_INIT: LDA #EXT_BUF_START_PAGE
145: 631D' B7 B007 STA EXTC_XPAGE
146: 6320' CC 0000 LDD #EXT_BUF_START_OFS
147: 6323' FD B008 STD EXTC_XOFS
148: 6326' 7F 611A CLR EXT_OVERFLOW
149: 6329' 7F 611B CLR SEND_TOUT_CNT
150: 632C' 39 RTS
151:
152: ;------------------------------------------------------------
153: ; BUF_WRITE
154: ; 機能: SECT_BUF(256Byte)を、拡張メモリの現在位置へ書き込む
155: ; 引数: SECT_BUFに256Byte 戻り値: なし(満杯でEXT_OVERFLOW=1)
156: ; 破壊レジスタ: A,B,X,Y,U,CC
157: ;------------------------------------------------------------
158: 632D' B6 B007 BUF_WRITE: LDA EXTC_XPAGE
159: 6330' 81 7F CMPA #EXT_BUF_END_PAGE
160: 6332' 23 06 BLS BW_OK ; $7F以下->書ける
161: 6334' 86 01 LDA #FLAG_ON ; 満杯は書込まずFLAG ON
162: 6336' B7 611A STA EXT_OVERFLOW
163: 6339' 39 RTS
164: 633A' 7F B004 BW_OK: CLR EXTC_DIR ; 0 = 通常->拡張
165: 633D' CC 6000 LDD #SECT_BUF
166: 6340' FD B005 STD EXTC_NADR
167: 6343' CC 0100 LDD #SECT_SIZE
168: 6346' FD B00A STD EXTC_LEN
169: 6349' BD B000 JSR EXTMEM_COPY
170: 634C' 39 RTS
171:
172: ;------------------------------------------------------------
173: ; BUF_DONE
174: ; 機能: ファイル読込み完了後に現在の書込位置を「終端」として記録
175: ; PLAY_ALLはここで止まる
176: ; 引数: なし 戻り値: なし 破壊レジスタ: A,B,CC
177: ;------------------------------------------------------------
178: 634D' B6 B007 BUF_DONE: LDA EXTC_XPAGE
179: 6350' B7 6117 STA EXT_END_PAGE
180: 6353' FC B008 LDD EXTC_XOFS
181: 6356' FD 6118 STD EXT_END_OFS
182: 6359' 39 RTS
183:
184: ;------------------------------------------------------------
185: ; PLAY_ALL
186: ; 機能: 拡張メモリの先頭から終端まで、256Byteずつ VS1053b へ連続送信
187: ; 引数: BUF_INIT -> BUF_WRITE -> BUF_DONE 戻り値: なし
188: ; 破壊レジスタ: A,B,X,Y,U,CC
189: ;------------------------------------------------------------
190: 635A' 86 10 PLAY_ALL: LDA #EXT_BUF_START_PAGE
191: 635C' B7 B007 STA EXTC_XPAGE
192: 635F' CC 0000 LDD #EXT_BUF_START_OFS
193: 6362' FD B008 STD EXTC_XOFS
194: 6365' B6 B007 PA_LOOP: LDA EXTC_XPAGE
195: 6368' B1 6117 CMPA EXT_END_PAGE
196: 636B' 26 09 BNE PA_CONT ; PAGEが違う(NOT EOF)
197: 636D' FC B008 LDD EXTC_XOFS
198: 6370' 10 B3 6118 CMPD EXT_END_OFS
199: 6374' 27 1F BEQ PA_DONE ; ページもオフセットも一致 -> 送信完了
200: 6376' 86 01 PA_CONT: LDA #XDIR_FROM_EXT ; 拡張->通常(SECT_BUF)
201: 6378' B7 B004 STA EXTC_DIR
202: 637B' CC 6000 LDD #SECT_BUF
203: 637E' FD B005 STD EXTC_NADR
204: 6381' CC 0100 LDD #SECT_SIZE
205: 6384' FD B00A STD EXTC_LEN
206: 6387' BD B000 JSR EXTMEM_COPY ; EXTC_XPAGE/XOFSは自動で進む
207: 638A' BD 6396 JSR SEND_SDI
208: 638D' 81 00 CMPA #VS_OK
209: 638F' 10 26 0002 LBNE PA_DONE ; 送信失敗:
210: 6393' 20 D0 BRA PA_LOOP
211: 6395' 39 PA_DONE: RTS
212:
213: ;--------------------------------------------------------------------------
214: ; SEND_SDI
215: ; 機能: SECT_BUF(256Byte=32Byte x 8ブロック)を VS1053b へ送る。(DREQ H/S)
216: ; タイムアウトで同じブロックから再送
217: ; 引数: なし(送信元はSECT_BUF固定) 戻り値: A = VS_OK / VS_TIMEOUT
218: ; 破壊レジスタ: Aのみ(B,X,Y,U,CCは保存)
219: ;---------------------------------------------------------------------------
220: 6396' 34 75 SEND_SDI: PSHS B,X,Y,U,CC ; Aレジスタ以外を退避
221: 6398' 8E 6000 LDX #SECT_BUF ; 送信元固定
222: 639B' C6 08 LDB #SEND256_CNT ; ブロック数固定(8)
223: 639D' 7F 611C CLR SEND_RETRY
224: 63A0' BD 6443 SS_TRY: JSR VS1053_SEND_SDI ; A = VS_OK / VS_TIMEOUT (タイムアウト時は途中の状態が残る)
225: 63A3' 81 00 CMPA #VS_OK
226: 63A5' 27 15 BEQ SS_OUT ; 全ブロック送れた
227: 63A7' 7C 611B INC SEND_TOUT_CNT ; 診断用の累計
228: 63AA' 7C 611C INC SEND_RETRY
229: 63AD' B6 611C LDA SEND_RETRY
230: 63B0' 81 C8 CMPA #SEND_RETRY_MAX
231: 63B2' 24 08 BCC SS_OUT ; 失敗が続いた: 諦めて失敗を返す
232: 63B4' BE 6115 LDX SEND_SDI_PTR ; 止まったブロックから再開
233: 63B7' F6 6114 LDB SEND_SDI_CNT
234: 63BA' 20 E4 BRA SS_TRY
235: 63BC' 35 75 SS_OUT: PULS CC,U,Y,X,B ; A=結果
236: 63BE' 39 RTS
237:
238: ;------------------------------------------------------------
239: ; VS1053_INIT
240: ; 機能: VS1053bを使用可能な状態へ初期化する
241: ; 処理内容:
242: ; 引数: なし 戻り値: A = VS_OK / VS_TIMEOUT
243: ; 破壊レジスタ: A,B,X,CC
244: ;------------------------------------------------------------
245: 63BF' BD 646B VS1053_INIT: JSR PIA_SETUP
246: 63C2' BD 63F6 JSR VS1053_RESET
247: 63C5' BD 6406 JSR VS1053_WAIT_DREQ
248: 63C8' 81 00 CMPA #VS_OK
249: 63CA' 26 27 BNE VI_TIMEOUT
250: 63CC' 86 00 LDA #SCI_MODE_REG
251: 63CE' 8E 0800 LDX #VS_MODE_INIT
252: 63D1' BD 641A JSR VS1053_WRITE_REG
253: 63D4' 81 00 CMPA #VS_OK
254: 63D6' 26 1B BNE VI_TIMEOUT
255: 63D8' 86 03 LDA #SCI_CLOCKF_REG
256: 63DA' 8E 9800 LDX #VS_CLOCK_INIT
257: 63DD' BD 641A JSR VS1053_WRITE_REG
258: 63E0' 81 00 CMPA #VS_OK
259: 63E2' 26 0F BNE VI_TIMEOUT
260: 63E4' 86 0B LDA #SCI_VOL_REG
261: 63E6' 8E 2020 LDX #VS_VOL_INIT
262: 63E9' BD 641A JSR VS1053_WRITE_REG
263: 63EC' 81 00 CMPA #VS_OK
264: 63EE' 26 03 BNE VI_TIMEOUT
265: 63F0' 86 00 LDA #VS_OK
266: 63F2' 39 RTS
267: 63F3' 86 01 VI_TIMEOUT: LDA #VS_TIMEOUT
268: 63F5' 39 RTS
269:
270: ;------------------------------------------------------------
271: ; VS1053_RESET
272: ; 機能: VS1053bをハードウェアリセットする
273: ; SPI信号を待機状態→RESETを1ms Lowにして解除→起動のため10ms待つ
274: ; 引数/戻り値: なし 破壊レジスタ: A,CC (DELAYは全レジスタを保存)
275: ;------------------------------------------------------------
276: 63F6' BD 6485 VS1053_RESET: JSR SPI_INIT
277: 63F9' BD 64AA JSR SPI_RESET_LOW
278: 63FC' BD 64EB JSR DELAY_1MS
279: 63FF' BD 64B1 JSR SPI_RESET_HIGH
280: 6402' BD 64F7 JSR DELAY_10MS
281: 6405' 39 RTS
282:
283: ;------------------------------------------------------------
284: ; VS1053_WAIT_DREQ
285: ; 機能: DREQ(PortB bit1)がHighになるまで待つ
286: ; VS_DREQ_TIMEOUT回(約0.45秒)でHighにならないとタイムアウト
287: ; 引数: なし 戻り値: A = VS_OK / VS_TIMEOUT
288: ; 破壊レジスタ: A,X,CC
289: ;------------------------------------------------------------
290: 6406' 8E C350 VS1053_WAIT_DREQ: LDX #VS_DREQ_TIMEOUT
291: 6409' B6 FF62 VW_LOOP: LDA PIA_PB_DATA
292: 640C' 85 02 BITA #SPI_DREQ_IBIT ; DREQ
293: 640E' 26 07 BNE VW_READY ; High->受信可能
294: 6410' 30 1F LEAX -1,X
295: 6412' 26 F5 BNE VW_LOOP
296: 6414' 86 01 LDA #VS_TIMEOUT
297: 6416' 39 RTS
298: 6417' 86 00 VW_READY: LDA #VS_OK
299: 6419' 39 RTS
300:
301: ;------------------------------------------------------------
302: ; VS1053_WRITE_REG
303: ; 機能: SCIレジスタへ16bitを書き込む
304: ; 処理内容: XCS=L -> 書込みコマンド($02) -> レジスタ番号 -> データMSB -> データLSB -> XCS=H -> DREQ待ち
305: ; 引数: A = レジスタ番号 X = 書込みデータ(MSB:上位Byte)
306: ; 戻り値: A = VS_OK / VS_TIMEOUT (最後のDREQ待ち結果)
307: ; 破壊レジスタ: A,B,X,CC
308: ;------------------------------------------------------------
309: 641A' B7 6101 VS1053_WRITE_REG: STA SPI_TEMP ; レジスタ番号
310: 641D' BF 6102 STX SPI_TEMP+1 ; データ MSB/LSB
311: 6420' BD 648E JSR SPI_XCS_LOW
312: 6423' 86 28 LDA #SPI_BASE_SCI ; 以降のSPI_SEND_BYTEのベース値
313: 6425' C6 02 LDB #SCI_WRITE_CMD
314: 6427' BD 64BD JSR SPI_SEND_BYTE
315: 642A' F6 6101 LDB SPI_TEMP
316: 642D' BD 64BD JSR SPI_SEND_BYTE
317: 6430' F6 6102 LDB SPI_TEMP+1
318: 6433' BD 64BD JSR SPI_SEND_BYTE
319: 6436' F6 6103 LDB SPI_TEMP+2
320: 6439' BD 64BD JSR SPI_SEND_BYTE
321: 643C' BD 6495 JSR SPI_XCS_HIGH ; 通信確定
322: 643F' BD 6406 JSR VS1053_WAIT_DREQ ; 書込み処理完了待ち
323: 6442' 39 RTS
324:
325: ;------------------------------------------------------------
326: ; VS1053_SEND_SDI
327: ; 機能: 32Byte単位でDREQを確認しながら、指定ブロック数をSDIで送る
328: ; 引数: X = 送信データ先頭 B = ブロック数(32Byte単位。256Byteなら8)
329: ; 戻り値: A = VS_OK / VS_TIMEOUT (TIMEOUTしたらSEND_SDI_PTR/CNTが止まった位置)
330: ; 破壊レジスタ: A,B,X,Y,CC
331: ;------------------------------------------------------------
332: 6443' F7 6114 VS1053_SEND_SDI: STB SEND_SDI_CNT
333: 6446' BF 6115 STX SEND_SDI_PTR
334: 6449' BD 6406 VD_LOOP: JSR VS1053_WAIT_DREQ
335: 644C' 81 00 CMPA #VS_OK
336: 644E' 26 1A BNE VD_EXIT ;TIMEOUT->失敗を返す
337: 6450' BD 649C JSR SPI_XDCS_LOW
338: 6453' BE 6115 LDX SEND_SDI_PTR
339: 6456' 10 8E 0020 LDY #SEND32_SIZE
340: 645A' BD 64E1 JSR SPI_SEND_BLOCK
341: 645D' BF 6115 STX SEND_SDI_PTR
342: 6460' BD 64A3 JSR SPI_XDCS_HIGH
343: 6463' 7A 6114 DEC SEND_SDI_CNT
344: 6466' 26 E1 BNE VD_LOOP
345: 6468' 86 00 LDA #VS_OK
346: 646A' 39 VD_EXIT: RTS
347:
348:
349: ;------------------------------------------------------------
350: ; PIA_SETUP
351: ; 機能: PIAを初期化する(PortA=全ビット出力、PortB=全ビット入力)
352: ; 引数/戻り値: なし 破壊レジスタ: A,CC
353: ;------------------------------------------------------------
354: 646B' 7F FF61 PIA_SETUP: CLR PIA_PA_CTRL ; DDRAを選択
355: 646E' 7F FF63 CLR PIA_PB_CTRL ; DDRBを選択
356: 6471' 86 FF LDA #PIA_DIR_OUT
357: 6473' B7 FF60 STA PIA_PA_DATA ; DDRA=$FF(出力)
358: 6476' 7F FF62 CLR PIA_PB_DATA ; DDRB=$00(入力)
359: 6479' 86 04 LDA #PIA_CR_NORMAL
360: 647B' B7 FF61 STA PIA_PA_CTRL ; PortAをDDRへ
361: 647E' B7 FF63 STA PIA_PB_CTRL ; PortBをDDRへ
362: 6481' 7F FF60 CLR PIA_PA_DATA ; PortA出力=0
363: 6484' 39 RTS
364:
365: ;------------------------------------------------------------
366: ; SPI_INIT
367: ; 機能: SPI信号を待機状態($3C)にする。 XCS=H XDCS=H RESET=H MOSI=L SCK=L
368: ; 引数/戻り値: なし 破壊レジスタ: A,CC
369: ;------------------------------------------------------------
370: 6485' 86 3C SPI_INIT: LDA #SPI_IDLE
371: 6487' B7 6100 STA SPI_PORTA ; PortA管理イメージを初期化
372: 648A' B7 FF60 STA PIA_PA_DATA ; PIAへ出力
373: 648D' 39 RTS
374:
375: ;------------------------------------------------------------
376: ; SPI_XCS_LOW / SPI_XCS_HIGH / SPI_XDCS_LOW / SPI_XDCS_HIGH / SPI_RESET_LOW / SPI_RESET_HIGH
377: ; 機能: イメージ(SPI_PORTA)の該当ビットだけ変えて、PortAへ出力する
378: ; 戻り値: A = 出力した値(SPI_XCS_LOW / SPI_XDCS_LOW の戻りが、SPI_SEND_BYTEのベース値になる)
379: ; 破壊レジスタ: A,CC
380: ;------------------------------------------------------------
381: 648E' B6 6100 SPI_XCS_LOW: LDA SPI_PORTA
382: 6491' 84 FB ANDA #CLR_CS0_MASK ; XCS=Low
383: 6493' 20 21 BRA SPI_PUT
384: 6495' B6 6100 SPI_XCS_HIGH: LDA SPI_PORTA
385: 6498' 8A 04 ORA #SPI_CS0_BIT ; XCS=High
386: 649A' 20 1A BRA SPI_PUT
387: 649C' B6 6100 SPI_XDCS_LOW: LDA SPI_PORTA
388: 649F' 84 F7 ANDA #CLR_CS1_MASK ; XDCS=Low
389: 64A1' 20 13 BRA SPI_PUT
390: 64A3' B6 6100 SPI_XDCS_HIGH: LDA SPI_PORTA
391: 64A6' 8A 08 ORA #SPI_CS1_BIT ; XDCS=High
392: 64A8' 20 0C BRA SPI_PUT
393: 64AA' B6 6100 SPI_RESET_LOW: LDA SPI_PORTA
394: 64AD' 84 DF ANDA #CLR_RESET_MASK ; RESET=Low
395: 64AF' 20 05 BRA SPI_PUT
396: 64B1' B6 6100 SPI_RESET_HIGH: LDA SPI_PORTA
397: 64B4' 8A 20 ORA #SPI_RESET_BIT ; RESET=High
398: 64B6' B7 6100 SPI_PUT: STA SPI_PORTA ; イメージ更新
399: 64B9' B7 FF60 STA PIA_PA_DATA ; PIAへ出力
400: 64BC' 39 RTS
401:
402: ;------------------------------------------------------------
403: ; SPI_SEND_BYTE
404: ; 機能: 1Byteを MSB first で送る
405: ; 引数: B = 送信データ A = ベース値(RESET=H 選択中のCS=L 解除中のCS=H の状態 SCI通信中は$28)
406: ; 戻り値: なし(Aは保存、Bは壊れる) 破壊レジスタ: B,CC
407: ;------------------------------------------------------------
408: 64BD' 34 12 SPI_SEND_BYTE: PSHS A,X
409: 64BF' 8E 0008 LDX #SPI_BITS ; ビットカウンタ
410: 64C2' C5 80 SB_LOOP: BITB #$80 ; 送信データのBit7 (MSB)
411: 64C4' 27 04 BEQ SB_LOW
412: 64C6' 8A 01 ORA #SPI_MOSI_BIT ; MOSI = 1
413: 64C8' 20 02 BRA SB_OUT
414: 64CA' 84 FE SB_LOW: ANDA #CLR_MOSI_MASK ; MOSI = 0
415: 64CC' B7 FF60 SB_OUT: STA PIA_PA_DATA ; SCK=Lのままデータを確定
416: 64CF' 8A 02 ORA #SPI_SCK_BIT
417: 64D1' B7 FF60 STA PIA_PA_DATA ; SCK = High (立ち上がりで送信)
418: 64D4' 12 NOP ; パルス幅の確保
419: 64D5' 84 FD ANDA #CLR_SCK_MASK
420: 64D7' B7 FF60 STA PIA_PA_DATA ; SCK = Low (立ち下がり)
421: 64DA' 58 LSLB ; 次のbitをBit7へ
422: 64DB' 30 1F LEAX -1,X
423: 64DD' 26 E3 BNE SB_LOOP
424: 64DF' 35 92 PULS A,X,PC ; 復元して復帰
425:
426: ;------------------------------------------------------------
427: ; SPI_SEND_BLOCK
428: ; 機能: Byte列を SPI_SEND_BYTE で連続送信する
429: ; 引数: X = 送信データ先頭 Y = Byte数(1以上) A = ベース値
430: ; 戻り値: X = 最後に送ったByteの次
431: ; 破壊レジスタ: B,X,Y,CC (Aは保存)
432: ;------------------------------------------------------------
433: 64E1' E6 80 SPI_SEND_BLOCK: LDB ,X+
434: 64E3' BD 64BD JSR SPI_SEND_BYTE
435: 64E6' 31 3F LEAY -1,Y
436: 64E8' 26 F7 BNE SPI_SEND_BLOCK
437: 64EA' 39 RTS
438:
439: ;------------------------------------------------------------
440: ; DELAY_1MS / DELAY_10MS
441: ; 機能: 約1ms / 約10ms 待つ (全レジスタ保存)
442: ;------------------------------------------------------------
443: 64EB' 34 77 DELAY_1MS: PSHS A,B,X,Y,U,CC
444: 64ED' 8E 0119 LDX #DLY_1MS_CNT
445: 64F0' 30 1F DL1_LOOP: LEAX -1,X
446: 64F2' 26 FC BNE DL1_LOOP
447: 64F4' 35 77 PULS CC,U,Y,X,B,A
448: 64F6' 39 RTS
449:
450: 64F7' 34 77 DELAY_10MS: PSHS A,B,X,Y,U,CC
451: 64F9' C6 0A LDB #DLY_10MS_TIMES ; 1msを10回
452: 64FB' 8E 0119 DL10_OUTER: LDX #DLY_1MS_CNT
453: 64FE' 30 1F DL10_INNER: LEAX -1,X
454: 6500' 26 FC BNE DL10_INNER
455: 6502' 5A DECB
456: 6503' 26 F6 BNE DL10_OUTER
457: 6505' 35 77 PULS CC,U,Y,X,B,A
458: 6507' 39 RTS
459:
460: 6508' 4C 31 20 56 31 2E FCC "L1 V1.0.0"
461: 30 2E 30
462: END
0 errors.
HEXファイルです
EXTMEM :20B000007EB00E0300000000000000000000FCB00A102700891A50B6B007C6F9103F40094D :20B020008E9000FCB008308BCC1000B3B008FDB00CFCB00A10B3B00C2303FCB00CFDB00CB7 :20B0400010BEB005B6B0042616FCB00C2725FEB00CA6A0A780335F1183000026F42014FC2C :20B06000B00C270FFEB00CA680A7A0335F1183000026F41CAFFCB005F3B00CFDB005FCB0EE :1FB0800008F3B00C1083100026054F5F7CB007FDB008FCB00AB3B00CFDB00A16FF7039FC :00000001FF VSPLAYER :206300007E6310017E631B7E632D7E634D7E635A3475BD63BFB761103575398610B7B00781 :20632000CC0000FDB0087F611A7F611B39B6B007817F23068601B7611A397FB004CC6000C7 :20634000FDB005CC0100FDB00ABDB00039B6B007B76117FCB008FD6118398610B7B007CC92 :206360000000FDB008B6B007B161172609FCB00810B36118271F8601B7B004CC6000FDB0A2 :2063800005CC0100FDB00ABDB000BD639681001026000220D03934758E6000C6087F611C0E :2063A000BD6443810027157C611B7C611CB6611C81C82408BE6115F6611420E4357539BDE0 :2063C000646BBD63F6BD64068100262786008E0800BD641A8100261B86038E9800BD641AE0 :2063E0008100260F860B8E2020BD641A81002603860039860139BD6485BD64AABD64EBBDEA :2064000064B1BD64F7398EC350B6FF6285022607301F26F5860139860039B76101BF610286 :20642000BD648E8628C602BD64BDF66101BD64BDF66102BD64BDF66103BD64BDBD6495BD41 :20644000640639F76114BF6115BD64068100261ABD649CBE6115108E0020BD64E1BF61152A :20646000BD64A37A611426E18600397FFF617FFF6386FFB7FF607FFF628604B7FF61B7FF11 :20648000637FFF6039863CB76100B7FF6039B6610084FB2021B661008A04201AB661008408 :2064A000F72013B661008A08200CB6610084DF2005B661008A20B76100B7FF603934128E42 :2064C0000008C58027048A01200284FEB7FF608A02B7FF601284FDB7FF6058301F26E335CF :2064E00092E680BD64BD313F26F73934778E0119301F26FC3577393477C60A8E0119301FE5 :1165000026FC5A26F63577394C312056312E302E302D :00000001FF
VS1053bのMIDIデコーダを使用しているのでMIDIデータのパースは不要です。
DREQを見ながらSPIでデータをそのままVS1053に送るだけで演奏できるので便利ですね、、、
今のところローダがポンコツでロードに数分かかりますが、S1でのMIDI演奏楽しいです(^^)
皆さんもお試しください。
そんなS1でのSMF0 MIDI演奏の記録・・・