レベル3+MP-1895(PIAカード)で VS1053b(VS1003b)を鳴らしてみる

こちらで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を再生できた記録・・・  残件あり

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

Maximum file size: 2 MB.
Allowed formats: JPG, JPEG, PNG.
Drop image here

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください