;------------------------------------------------------------------------- ; APPLE ][ SERIES ANNUNCIATOR MIDI DRIVER ; Copyright © 1998-2018 Eric Rangell. MIT License. ;-------------------------------------------------------------------------; ; main.s ; A2NoSlotMidi ; Created by Eric Rangell on 17 JULY 2018. ; VERSION 1.0.1 released 26 JULY 2018 ; VERSION 1.0.2 released 29 JULY 2018 ;------------------------------------------------------------------------- ; THIS DRIVER IMPLEMENTS ASYNCHRONOUS SERIAL DATA TRANSMISSION ; THROUGH AN APPLE ][ ANNUNCIATOR OUTPUT PORT OF THE GAME CONNECTOR ; USING 32 CYCLES PER BIT TO ACHIEVE A 31.25K MIDI BAUD RATE. ; ; APPLE //GS USERS NEED TO RUN THIS PROGRAM IN NORMAL SPEED MODE (1MHZ) ; ; THE OUTPUT IS INITIALIZED TO A HIGH LOGIC VOLTAGE. WHEN IT GOES ; LOW FOR 32 MICROSECONDS, THAT INDICATES THE START BIT OF A MIDI BYTE. ; THEN 8 BYTES OF DATA ARE TRANSMITTED, FOLLOWED BY A HIGH STOP BIT. ; THE DATA BYTES REPRESENT MIDI MESSAGES WHICH CAN BE INTERPRETED BY ; ANY MUSICAL INSTRUMENT THAT IMPLEMENTS MIDI. ; ; ENTRY POINTS: (Note: Origin must be set in Makefile) ; ; $9000 = INITIALIZE - TURNS ON ANNUNCIATOR 0 - MUST BE CALLED ONCE ; $9003 = APPLESOFT CALL TO SEND ONE MIDI BYTE. POKE THE BYTE IN $9004. ; $9005 = ASSEMBLY CALL TO SEND ONE MIDI BYTE FROM ACCUMULATOR ; $9008 = APPLESOFT OR ASSEMBLY CALL TO SEND SEVERAL BYTES AT ONCE: ; THE CALLER POPULATES LOCATION $D7 WITH THE NUMBER OF BYTES TO BE ; TRANSMITTED, AND A POINTER IN $CE,CF (LO,HI) WITH THE ADDRESS OF ; THE DATA BYTES, THEN CALLS THE ENTRY POINT "SENDMSG" TO TRANSMIT ; THE MESSAGE. ; $900B = TURN ALL NOTES OFF ; $900E = SEND A TEST MESSAGE - C MAJOR CHORD NOTE ONS ; $9011 = SEND A TEST MESSAGE - C MAJOR CHORD NOTE OFFS ; ; IF THE FOLLOWING ROUTINE IS USED, IT SHOULD BE CALLED IMMEDIATELY AFTER BLOADING ; THE BINARY. AT THE END, IT WILL CALL THE INIT ROUTINE FOR THE SELECTED ANNUNCIATOR. ; ; $9014 = CHANGE ANNUNCIATOR - MODIFIES CODE TO USE DIFFERENT ANNUNCIATOR ; $9017 = ANNUNCIATOR TO USE: 0-3 - only looks at least significant 2 bits ; ; $9018 = SET TO 1 TO USE NEGATIVE LOGIC (ONLY ONE INVERTER IN THE MIDI CIRCUIT) ;------------------------------------------------------------------------- ; Enhancements for 2018: ; 1. Disable interrupts during critical timing sections, preserve interrupt status ; 2. Entry point to reconfigure program to use a different annunciator pair ; 3. Entry point to reconfigure program for hardware interface using inverters only (not buffers) ;------------------------------------------------------------------------- ; CALLER MUST POPULATE THE FOLLOWING TWO ZERO PAGE LOCATIONS FOR SENDMSG: NUMBYTES = $D7 ;NUMBER OF BYTES TO BE TRANSMITTED NOW (1-256) ; ;THE VALUE 0 WILL TRANSMIT 256 BYTES. DATAPTR = $CE ;POINTER TO THE BYTES TO BE TRANSMITTED NOW ;------------------------------------------------------------------------- AN0OFF = $C058 ;APPLE ADDRESSES THAT CONTROL ANNUNCIATOR OUTPUTS AN0ON = $C059 ;PROGRAM REFERNCES ARE RELATIVE TO AN0 ;AN1OFF = $C05A ;AN1ON = $C05B ;AN2OFF = $C05C ;AN2ON = $C05D ;AN3OFF = $C05E ;AN3ON = $C05F ;------------------------------------------------------------------------- .proc main ;--------------------------------------------------------------------------- START: JMP INIT ;MAIN ENTRY POINT - INITIALIZES ANNUNCIATORS SENDFP: LDA #$90 ;ENTRY POINT FOR APPLESOFT: POKE BYTE AND CALL SENDONE: JMP XMITONE ;ENTRY POINT FOR TRANSMITTING ONE BYTE FROM ACCUM SENDMSG: JMP XMITMSG ;ENTRY POINT FOR TRANSMITTING A MIDI MESSAGE ALLNOFF: JMP QUIET ;TURN ALL NOTES OFF TEST1: JMP TESTMSG1 ;SEND TEST MESSAGE 1 - C MAJOR CHORD ON TEST2: JMP TESTMSG2 ;SEND TEST MESSAGE 2 - C MAJOR CHORD OFF CHNGANNC: JMP CHGANNC ;RECONFIGURE PROGRAM TO USE ANNUNCIATOR NUMBER IN NEXT BYTE ANNC2USE: .byte $00 ;ONLY LEAST SIGNIFICANT 2 BITS ARE USED NEGLOGIC: .byte $00 ;SET TO 1 TO USE NEGATIVE LOGIC, OTHERWISE LEAVE 0 FOR POSITIVE LOGIC (DEFAULT). DO NOT USE ANY OTHER VALUES! ;--------------------------------------------------------------------------- MAJVER: .byte $01 ;BYTES USED TO TRACK VERSION OF RELEASED EXECUTABLES MINVER: .byte $02 ;NIBBLES ARE USED FOR THE VERSION NUMBER ($0102 = VERSION 1.0.2) ASAVE: .byte $00 ;SAVE AREA FOR ACCUMULATOR SAVENBYT: .byte $00 ;SAVE AREA FOR NUMBYTES ;--------------------------------------------------------------------------- INIT: LDA NEGLOGIC AND #$FE BEQ OK2INIT BRK ;ABEND IF NEGLOGIC NOT 0 OR 1 OK2INIT: LDA #TESTDAT1 STA DATAPTR+1 JSR SENDMSG RTS ;----------------------------------------------------------------------- TESTMSG2: LDA #7 STA NUMBYTES LDA #TESTDAT2 STA DATAPTR+1 JSR SENDMSG RTS ;----------------------------------------------------------------------- QUIET: LDA #$90 STA NUMBYTES LDA #QUIETMSG STA DATAPTR+1 JSR SENDMSG RTS ;----------------------------------------------------------------------- CHGANNC: LDA ANNC2USE AND #$03 ;KEEP ONLY 2 LEAST SIGNIFICANT BITS ASL ;MULTIPLY BY 2 PHA ;SAVE THIS VALUE FOR EACH MOD BEING DONE BELOW CLC ADC #