こちらでSPIのビットバンキング実験をして駆動の方法を調査したVS1053bとVS1003bを
ベーシックマスタレベル3を使いMIDI(SMF0のみ対応)を再生してみました。
MP-1895は50ピンアンフェノールコネクタなので変換基板を作ってVS1053bのモジュールを接続できるようにします。
中華製の格安ロジアナも接続してSPIの信号も確認できるようにしておきます
レベル3用のPIAカード MP-1895です。
こちらは以前アメリカのeBayで購入したS1/10に付属していたカードです(^^)
ダイソーのお気に入りスピーカに接続してAF出力もOK(^^)
![]()
今回の実験で作ったソフトはこちら
PIA/SPI/VS1053ドライバー
; VSMIDI.ASM
;
INCLUDE "EQU.TXT"
;
ORG PROGRAM_TOP
; CPUクロック設定
CPU_CLOCK EQU 1 ; CPU CLOCK選択
IF CPU_CLOCK EQ 1
;@1MHz LEVEL3
DLY_1MS_CNT EQU 140
ELSE
;@2MHz MB-S1/FM-7
DLY_1MS_CNT EQU 281
ENDIF
PIA_CR_NORMAL EQU %00000100
PIA_DIR_OUT EQU $FF
; SPI Work Area
SPI_PORTA EQU SPI_WORK_TOP
SPI_TEMP EQU SPI_WORK_TOP+1
; SCI Register Number / Command
SCI_MODE_REG EQU 0
SCI_CLOCKF_REG EQU 3
SCI_VOL_REG EQU 11
SCI_WRITE_CMD EQU $02
; SPI PortA Bit Assignment
SPI_MOSI_BIT EQU %00000001 ; PA0(MOSI)
SPI_SCK_BIT EQU %00000010 ; PA1(SCK)
SPI_CS0_BIT EQU %00000100 ; PA2(XCS)
SPI_CS1_BIT EQU %00001000 ; PA3(XDCS)
SPI_AUX0_OBIT EQU %00100000 ; PA5(RESET)
SPI_AUX0_IBIT EQU %00000010 ; PB1(DREQ)
CLR_MOSI_MASK EQU %11111110 ; NOT(SPI_MOSI_BIT)
CLR_SCK_MASK EQU %11111101 ; NOT(SPI_SCK_BIT)
CLR_CS0_MASK EQU %11111011 ; NOT(SPI_CS0_BIT) XCSのみクリア
CLR_CS1_MASK EQU %11110111 ; NOT(SPI_CS1_BIT) XDCSのみクリア
CLR_AUX0_MASK EQU %11011111 ; NOT(SPI_AUX0_OBIT) RESETのみクリア
SPI_XCS_BASE EQU %00101000 ; RESET(1)+XDCS(1)+XCS(0)
SPI_IDLE_STATE EQU %00111100
VS_OK EQU 0 ; 正常終了
VS_TIMEOUT EQU 1 ; タイムアウト
VS_CLOCK_INIT EQU $9800 ; 3.5倍クロック
VS_VOL_INIT EQU $2020 ; L=32 R=32
VS_MODE_INIT EQU $0800 ; SDI New Mode
VS_DREQ_TIMEOUT EQU 50000
SEND256_CNT EQU 8 ; 8回×32Byte
SEND32_SIZE EQU 32 ; 32Byte
SEND_SDI_CNT EQU VS_WORK_TOP+4 ; SEND_SDIブロックカウンタ
SEND_SDI_PTR EQU VS_WORK_TOP+5 ; SEND_SDI送信ポインタ(2Byte +5/+6)
SECT_BUF EQU COMMON_WORK_TOP ; FDセクタバッファ
; DELAY_1MS
DELAY_1MS: PSHS A,B,X,Y,U,CC
LDX #DLY_1MS_CNT
DLY_LOOP1000: LEAX -1,X
BNE DLY_LOOP1000
PULS CC,U,Y,X,B,A
RTS
; DELAY_10MS
DELAY_10MS: PSHS A,B,X,Y,U,CC
LDB #10 ; 1msを10回繰り返す
DLY_10MS_OUTER: LDX #DLY_1MS_CNT
DLY_10MS_INNER: LEAX -1,X
BNE DLY_10MS_INNER
DECB
BNE DLY_10MS_OUTER
PULS CC,U,Y,X,B,A
RTS
; PIA_INIT
PIA_INIT: CLR PIA_PA_CTRL
CLR PIA_PB_CTRL
RTS
; PIA_DIRA_OUT
PIA_DIRA_OUT: CLR PIA_PA_CTRL ; DDRAアクセス
LDA #PIA_DIR_OUT
STA PIA_PA_DATA ; DDRA=$FF
LDA #PIA_CR_NORMAL
STA PIA_PA_CTRL ; 通常アクセス
CLR PIA_PA_DATA ; 初期出力=0
RTS
; PIA_DIRB_IN
PIA_DIRB_IN: CLR PIA_PB_CTRL ; DDRBアクセス
CLRA
STA PIA_PB_DATA ; DDRB=$00
LDA #PIA_CR_NORMAL
STA PIA_PB_CTRL ; 通常アクセス
RTS
; SPI_XCS_LOW
SPI_XCS_LOW: LDA SPI_PORTA
ANDA #CLR_CS0_MASK ; XCSをLow
STA SPI_PORTA
STA PIA_PA_DATA
RTS
; SPI_XCS_HIGH
SPI_XCS_HIGH: LDA SPI_PORTA
ORA #SPI_CS0_BIT ; XCSをHigh
STA SPI_PORTA
STA PIA_PA_DATA
RTS
SPI_XDCS_LOW: LDA SPI_PORTA ; PortAイメージ取得
ANDA #CLR_CS1_MASK ; XDCSをLow
STA SPI_PORTA ; イメージ更新
STA PIA_PA_DATA ; PIAへ出力
RTS
; SPI_XDCS_HIGH
SPI_XDCS_HIGH: LDA SPI_PORTA
ORA #SPI_CS1_BIT ; XDCSをHigh
STA SPI_PORTA
STA PIA_PA_DATA
RTS
; SPI_INIT
SPI_INIT: LDA #SPI_IDLE_STATE ;アイドル状態値設定
STA SPI_PORTA
STA PIA_PA_DATA
RTS
; SPI_RESET_LOW
SPI_RESET_LOW: LDA SPI_PORTA
ANDA #CLR_AUX0_MASK ; RESETをLow
STA SPI_PORTA
STA PIA_PA_DATA
RTS
; SPI_RESET_HIGH
SPI_RESET_HIGH: LDA SPI_PORTA
ORA #SPI_AUX0_OBIT ; RESETをHigh
STA SPI_PORTA
STA PIA_PA_DATA
RTS
; SPI_SEND_BYTE
SPI_SEND_BYTE: PSHS A,X
LDX #8 ; ビットカウンタ (8bit)
.SPI_LOOP:
BITB #$80
BEQ .MOSI_LOW
.MOSI_HIGH: ORA #SPI_MOSI_BIT ; MOSI(Bit0) = 1
BRA .OUT_PULSE
.MOSI_LOW: ANDA #CLR_MOSI_MASK ; MOSI(Bit0) = 0
.OUT_PULSE:
STA PIA_PA_DATA
ORA #SPI_SCK_BIT ; SCK(Bit1) = 1
STA PIA_PA_DATA
NOP
ANDA #CLR_SCK_MASK ; SCK(Bit1) = 0
STA PIA_PA_DATA
LSLB
LEAX -1,X ; カウンタ減算
BNE .SPI_LOOP
PULS A,X,PC ; 復元して復帰
; SPI_SEND_BLOCK
SPI_SEND_BLOCK:
SEND_BLOCK_LOOP: LDB ,X+ ; 次の1Byte取得
JSR SPI_SEND_BYTE
LEAY -1,Y ; 残りバイト数
BNE SEND_BLOCK_LOOP
RTS
; VS1053_RESET
VS1053_RESET: JSR SPI_INIT
JSR SPI_RESET_LOW
JSR DELAY_1MS
JSR SPI_RESET_HIGH
JSR DELAY_10MS
RTS
; VS1053_WAIT_DREQ
VS1053_WAIT_DREQ: LDX #VS_DREQ_TIMEOUT
WAIT_DREQ_LOOP:
LDA PIA_PB_DATA
BITA #SPI_AUX0_IBIT ; DREQ
BNE DREQ_READY
LEAX -1,X
BNE WAIT_DREQ_LOOP
LDA #VS_TIMEOUT
RTS
; DREQ検出
DREQ_READY: LDA #VS_OK
RTS
; VS1053_INIT
VS1053_INIT:
JSR PIA_INIT
JSR PIA_DIRA_OUT
JSR PIA_DIRB_IN
JSR SPI_INIT
JSR VS1053_RESET
JSR VS1053_WAIT_DREQ
CMPA #VS_OK
BNE INIT_TIMEOUT
LDA #SCI_MODE_REG
LDX #VS_MODE_INIT
JSR VS1053_WRITE_REG
CMPA #VS_OK
BNE INIT_TIMEOUT
LDA #SCI_CLOCKF_REG
LDX #VS_CLOCK_INIT
JSR VS1053_WRITE_REG
CMPA #VS_OK
BNE INIT_TIMEOUT
LDA #SCI_VOL_REG
LDX #VS_VOL_INIT
JSR VS1053_WRITE_REG
CMPA #VS_OK
BNE INIT_TIMEOUT
LDA #VS_OK
RTS
INIT_TIMEOUT: LDA #VS_TIMEOUT
RTS
; VS1053_WRITE_REG
VS1053_WRITE_REG: STA SPI_TEMP ; レジスタ番号
STX SPI_TEMP+1 ; データ
JSR SPI_XCS_LOW ; XCS = Low
LDB #SCI_WRITE_CMD
LDA #SPI_XCS_BASE
JSR SPI_SEND_BYTE
LDB SPI_TEMP ; レジスタ番号
JSR SPI_SEND_BYTE
LDB SPI_TEMP+1 ; Data MSB
JSR SPI_SEND_BYTE
LDB SPI_TEMP+2 ; Data LSB
JSR SPI_SEND_BYTE
JSR SPI_XCS_HIGH ; XCS = High
JSR VS1053_WAIT_DREQ ; 書込み完了待ち
RTS
; VS1053_SEND_SDI
VS1053_SEND_SDI:
STB SEND_SDI_CNT
STX SEND_SDI_PTR
SEND_SDI_LOOP:
JSR VS1053_WAIT_DREQ
CMPA #VS_OK
BNE SEND_SDI_EXIT
JSR SPI_XDCS_LOW
LDX SEND_SDI_PTR
LDY #SEND32_SIZE
JSR SPI_SEND_BLOCK
STX SEND_SDI_PTR
JSR SPI_XDCS_HIGH
DEC SEND_SDI_CNT
BNE SEND_SDI_LOOP
LDA #VS_OK
SEND_SDI_EXIT: RTS
; VSPLAYER
VSPLAYER: PSHS B,X,Y,U,CC
JSR VS1053_INIT
STA VS_WORK_TOP
PULS CC,U,Y,X,B
RTS
SEND_SDI: PSHS B,X,Y,U,CC
LDX #SECT_BUF ; 送信元
LDB #SEND256_CNT ; ブロック数固定(8)
JSR VS1053_SEND_SDI ; SEND_SDI(RTSはSEND_SDI側)
PULS CC,U,Y,X,B
RTS
FCC "V0.1.27"
END一部実験用のごみコードが残っています(^^;;;
L3DISKBASIC側MIDIデータローダ
100 CLEAR 200, &H59FF 110 FLBUF = &H6000: BUFLEN = 256 120 ' =================================================== 130 ' FILE -> BUFFER DATA LOADER PROGRAM for BML3 V0.1.27 140 ' =================================================== 150 LOADM "VSMIDI1": EXEC &H6476 ' VS1053 Init 160 OPEN "I", #1, "MUSIC1.BIN" 170 PRINT "FILE -> BUFFER(256Byte) Start..." 180 ' 190 ' --- MAIN LOOP --- 200 IF EOF(1) THEN 320 210 CNT = 0 220 ' 230 ' 1St 128 Byte 240 IF NOT EOF(1) THEN DAT$ = INPUT$(128, #1): GOSUB 360 250 ' 2nd 128 Byte 260 IF NOT EOF(1) THEN DAT$ = INPUT$(128, #1): GOSUB 360 270 ' 280 ' Buffer(256Byte) To VS1053 Send 290 PRINT "VS_SEND": EXEC &H6481 ' SEND_SDI 300 GOTO 200 310 ' 320 ' --- END --- 330 CLOSE #1 340 PRINT "DATA SEND COMPLETE..." 350 END 360 ' 370 ' =================================================== 380 ' FILE BUFFER WRITE Sub. 390 ' (DAT$ -> FLBUF + CNT POKE) 400 ' =================================================== 410 DTLEN = LEN(DAT$) 420 IF DTLEN = 0 THEN RETURN 430 FOR I = 1 TO DTLEN 440 POKE FLBUF + CNT, ASC(MID$(DAT$, I, 1)) 450 CNT = CNT + 1 460 NEXT I 470 DAT$ = "" 480 RETURN
PIAで生成したSPI信号ですが
![]()
VS1053の初期化はSCIできれいに出力されています。
その後 MThd から始まるMIDIデータをSDIで送っているだけです。
![]()
これなら複雑なMIDIファイルのパースが不要です。ただしSMF0のみ対応のようなのでデータを選びます。
この仕掛けでVS1053bからMIDIデータを無事に再生できました(^^)
しかし、MIDIデータをL3 BASICのシーケンシャルファイルとしてロードすると1セクタ256バイトロードするのに10秒以上かかります(^^;;;
MIDIは再生できますが、0.5秒程度再生して10秒程度ロードに時間がかかります。
こうなると拡張メモリを使用して一度メモリに全てロードして再生しないとダメそうです。
いままで使ったことのなかった64KBの拡張メモリ MP-9764の出番です(^^)
これなら64KBあるので大きなMIDIファイルでなければなんとか一曲分はロードできそうです
MP-9764拡張メモリの使い方を勉強しないと・・・・
これがうまくいけばArduimoやPICマイコンに頼らず6809+PIAだけでMIDI再生できそうです(^^)![]()
そんなMP-1895(PIA)でVS1053を駆動してSMF0 MIDIを再生できた記録・・・ 残件あり