Table of Contents

MIDI MAESTRO

MIDI Maestro project page

HARDWARE INFO

Schematics and more on github

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

Rulaford Research CoCo MIDI Pak

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

Return to Tandy Color Computer