MIDI MAESTRO

HARDWARE INFO

SOFTWARE SUPPORT

The CoCo MIDI pak is well supported with tools such as Colorchestra, Lyra, Ultimuse and many more:
https://colorcomputerarchive.com/repo/Disks/Music/

PROGRAMMING INFO

EXAMPLE CODE

GET AND SEND

* MIDI ROUTINE for CoCo Midi Interface
* Version 1.0 by Allen C. Huffman

MSTAT   EQU     $FF6E            From here on, MSTAT refers to $FF6E
MDATA   EQU     $FF6F                      and MDATA refers to $FF6F

        ORG     $7000            Program starts at $7000

START1  BRA     GET              GET routine at $7000
START2  BRA     SEND             SEND routine at $7002

GET     BSR     INIT             Jump to INIT routine
        LDX     #$7100           Make X point to start of "buffer"
GLOOP   BSR     GETDAT           Loop.  Jump and get byte from pack
        STA     ,X+              Store byte at X, increment X
        CMPA    #$F0             Compare A to $F0
        BLS     GLOOP            If A < $F0, return to GLOOP
        RTS                      Return from subroutine

SEND    BSR     INIT             Jump to INIT routine
        LDX     #$7100           Make X point to start of "buffer"
SLOOP   LDA     ,X+              Loop. Load A from X, increment X
        BSR     SENDAT           Jump and send A to pack
        CMPA    #$F0             Compare A to $F0
        BLS     SLOOP            If A < $F0, return to SLOOP
        RTS

INIT    LDA     #$3              Load A with $3
        STA     MSTAT            Store it at MSTAT
        LDA     #$15             Load A with $21 [SIC]
        STA     MSTAT            Store it at MSTAT
        RTS                      Return from subroutine

GETDAT  LDA     MSTAT            Load A with Status
        BITA    #1               Test bit 1
        BEQ     GETDAT           If it's 0, go back to GETDAT
        LDA     MDATA            Byte received, load it in A
        RTS                      Return from subroutine

SENDAT  LDB     MSTAT            Load B with Status
        BITB    #2               Test bit 2
        BEQ     SENDAT           If it's 0, go back to SENDAT
        STA     MDATA            Pack clear, send A
THEEND  RTS                      Return from subroutine

        END     INIT             That's it!
10 CLEAR 200,&H7000
15 X=0:FORA=&H7000 TO&H7040:READA$:B=VAL("&H"+A$):POKE A,B:X=X+B:NEXT:PRINTX
20 DATA 20,2,20,E,8D,1A,8E,71,0,8D,20,A7,E0,81,F0,23,F8,39,8D,C,8E,71,0,A6,80,8D,1B,81,F0,23,F8,39,86,3,B7,FF,6E,86,15,B7,FF,6E,39,B6,FF,6E,85,1,27,F9,B6,FF,6F,39,F6,FF,6E,C5,2,27,F9,B7,FF,6F,39
30 ' EXEC &H7000 - Execute GET routine
40 ' EXEC &H7002 - Execute SEND routine

TESTMIDI

;*********************************************************************
;* Title: testmidi.asm
;*********************************************************************
;* Author: R. Allen Murphey
;*
;* Description: Support for Jim Brain's MIDI Maestro and compatibles
;*
;* Documentation:
;* Motorola MC6850 Data Sheet
;* Rulaford Research CoCo MIDI Pak by Allen Huffman
;* MIDI Companion by Jeffrey Rona
;*
;* Include Files: none
;*
;* Assembler: lwasm 1.4.2
;*
;* Revision History:
;* Rev #     Date      Who     Comments
;* -----  -----------  ------  ---------------------------------------
;* 00     2020         RAM     Initial driver
;*********************************************************************

MIDICTRL:   equ   $FF6E       ; MC6850 STATUS (R)/CONTROL (W) PORT
MIDIDATA:   equ   $FF6F       ; MC6850 DATA RX (R)/TX (W) PORT

;*********************************************************************
;* MIDITEST - play a 12 note scale on MIDI device
;*
;* I/O:
;* Read from $FF6E for Status
;* Write to $FF6E for Control settings
;* Read from $FF6F for Received data
;* Write to $FF6F to Transmit data
;* Use STATUS bit 2 to make sure transmit buffer is empty before send
;*
;* Calling Convention:
;*
;* Returns:
;*
;* Stack Usage: S - save PCs for BSRs
;*
;* Calls:
;*
;* Changes: A,B,X,Y
;*********************************************************************

            org   $7000

MIDITEST:
                              ; switch MPI to slot 1
            lda   $FF7F       ; get current MPI slot setting
            anda  #$F0        ; keep all CTS values, turn off all SCS
            sta   $FF7F       ; switch MPI to slot 1 with SCS %0000

            ;                  ; enable CART sound on MUX
            ;lda   PIA0AC      ; Read current PIA register settings
            ;anda  #%11110111  ; Force bit 3 MUX SEL 1 off for cart
            ;sta   PIA0AC      ; Write modified PIA register back out
            ;                  ;
            ;lda   PIA0BC      ; Read current PIA register setting
            ;ora   #%00001000  ; Force bit 3 MUX SEL 2 on for cart
            ;sta   PIA0BC      ; Write modified PIA register back out
            ;                  ;
            ;lda   PIA1BC      ; Read current PIA register settings
            ;ora   #%00001000  ; Force bit 3 SNDEN on to enable sound
            ;sta   PIA1BC      ; Write modified PIA register back out

INITMIDI:
            lda   #%00000011  ; CR1/CR0 = 11 for MC6850 Master Reset
            sta   MIDICTRL    ; Trigger master reset
            lda   #%00010101  ; 8N1 serial, counter / 16 for 31250bps
            sta   MIDICTRL    ; Configure divider and serial encoding
 
                              ; MAIN
            clrb
            ldy   #MIDINOTES
                              
PLAYMIDI:
                              ; First we turn note on
            lda   #%10010000  ; MIDI STATUS - NOTE ON - CHANNEL 1
            sta   MIDIDATA    ; Write Status to MIDI
            jsr   WAITSTAT    ; Wait for send

            lda   b,y         ; load note from table
            sta   MIDIDATA    ; write note on to MIDI
            jsr   WAITSTAT    ; Wait for send

            lda   #64         ; MIDI DATA - VELOCITY 64
            sta   MIDIDATA    ; Write Status to MIDI
            bsr   DELAY4K     ; leave NOTE ON for a while

                              ; Next we turn note off
            lda   #%10000000  ; MIDI STATUS - NOTE OFF - CHANNEL 1
            sta   MIDIDATA    ; Write Status to MIDI
            jsr   WAITSTAT    ; Wait for send

            lda   b,y         ; reload note from table
            sta   MIDIDATA    ; write note on to MIDI
            jsr   WAITSTAT    ; Wait for send

            lda   #0          ; MIDI DATA - VELOCITY 0
            sta   MIDIDATA    ; Write Status to MIDI
            bsr   DELAY4K     ; wait between notes
                              ;
            incb              ; move to next item: note length
            incb              ; move to next item: next note data 
            cmpb  #24         ; have we read all 12 x 12bit notes?
            bne   PLAYMIDI    ; no keep playing notes
                              
            rts               ; done, exit

DELAY4K:
            ldx   #$4000
DELAYX:     leax  -1,X
            bne   DELAYX
WAITSTAT:   lda   MIDICTRL    ; read MIDI status
            bita  #2          ; check bit 2
            beq   WAITSTAT    ; if zero, buffer full, wait more
            rts

MIDINOTES:
            fcb   $3C,$3C     ; C4  261.626 Hz Middle C
            fcb   $3D,$3C     ; C#4 277.183 Hz
            fcb   $3E,$3C     ; D4  293.665 Hz
            fcb   $3F,$3C     ; D#4 311.127 Hz
            fcb   $40,$3C     ; E4  329.628 Hz
            fcb   $41,$3C     ; F4  349.228 Hz
            fcb   $42,$3C     ; F#4 369.994 Hz
            fcb   $43,$3C     ; G4  391.995 Hz
            fcb   $44,$3C     ; G#4 415.305 Hz
            fcb   $45,$3C     ; A4  440.000 Hz
            fcb   $46,$3C     ; A#4 466.164 Hz
            fcb   $47,$3C     ; B4  493.883 Hz

            END   MIDITEST

;*********************************************************************
;* End of testmidi.asm
;*********************************************************************

RTS