;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; CODE FOR MIDI TO RS-232 CONVERTER. ALLOWS THE READING ; ; OF INCOMING MIDI MESSAGES AND DISPLAYS ON THE TERMINAL ; ; THE BINARY BYTE, AS WELL AS WHICH NOTE IS PLAYED. ; ; THE 8751 TRANSMIT MUST GO THROUGH A MAXIM -MAX232CPE ; CONVERTER CHIP. IT'S A SIMPLE CHIP TO USE. THE MIDI ; ; IS HOOKED STRAIGHT IN. CLOCK PIN IS PIN 5, GROUND IS ; ; PIN 2, AND +5V IS PIN 4. WHILE IT IS POSSIBLE TO GET ; ; ENOUGH POWER FROM THE MIDI LINE, I SUGGEST A 7805 INSTEAD. ; ; CODE BY ROBERT ADRIAN. SECTIONS c.1993 ADRIONICS. ; ; USE FOR NON-PROFIT APPLICATION ONLY. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; REGISTER # ;; USED FOR: ; ; 0 BYTE INC AND STORAGE ; ; 1 NOT USED ; ; 2 NOT USED ; ; 3 NOT USED ; ; 4 NOT USED ; ; 5 NOT USED ; ; 6 NOT USED ; ; 7 BIT COUNT REGISTER FOR BIT CONVERSION ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TO USE THE BYTE-BIT FUNCTION PASS THE VALUE IN *DATAOUT* ; TO USE THE SERIAL_INFORMATION FUNCTION PASS THE VALUE IN *SEND* ; -------------------------------------------------------- ********* ; -------------------------------------------------------- ********* ; -------------------------------------------------------- ********* ; -------------------------------------------------------- ********* ; -------------------------------------------------------- ********* ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Interrupt Vectors ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ORG 0000H ; Power on / RE_SET JMP BODY_O_CODE ; ; ORG 0003H ; External Interrupt 0 (pin 12) JMP XINT0 ; ; ORG 000BH ; Timer 0 Overflow JMP TMR0 ; ; ORG 0013H ; External Interrupt 1 (pin 13) JMP XINT1 ; ; ORG 001BH ; Timer 1 Overflow JMP TMR1 ; ; ORG 0023H ; Serial Communications (TX and RX) JMP SERIAL ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Timer 0 ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This is the routine for handling ; ; overflow events from Timer 0. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TMR0: ; RETI ; Does nothing. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Timer 1 ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This is the routine for handling ; ; overflow events from Timer 1. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TMR1: ; RETI ; Does nothing. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Interrupt 0 ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This is the routine for handling ; ; interrupts on channel 0. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; XINT0: ; RETI ; Does nothing. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Interrupt 1 ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This is the routine for handling ; ; interrupts an channel 1. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; XINT1: ; RETI ; Does nothing. ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Serial I/O ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This is the routine for handling ; ; serial communications. It has to ; ; distinguish between transmit and ; ; receive events by polling SCON. ; ; We use SCON.0 and SCON.1 to refer ; ; to receive and transmit events ; ; because the assembler doesn't ; ; handle TI properly. ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SERIAL: ; JB SCON.1,TXEVENT ; Revector on transmit events ; JB SCON.0,RXEVENT ; Revector on receive events ; SERR: ; JMP SERR ; This is an error condition ; TXEVENT: ; CLR TI CLR TFLAG RETI ; Does nothing. ; RXEVENT: CLR RI SETB RFLAG RETI ; Does nothing. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; INITIALIZE: BSEG AT 00H BSEG TFLAG: DBIT 1 RFLAG: DBIT 1 STATUS_FLAG: DBIT 1 CSEG DATAOUT EQU 7CH SEND EQU 7BH PCON EQU 87H TICKS EQU 7AH TWDLS EQU 79H BAUD EQU 78H ; 230=2400 BAUD MOV TICKS,#198 MOV TWDLS,#50 ; NUMBER = MILLI SEC MOV BAUD,#254 ; BAUD RATE =31.25K MOV PCON,#128 ; SET UP SMOD, CLEAR GF?,PD,ID MOV SCON,#080 ; SET UP SERIAL PORT MOV TMOD,#020H ; SET UP TIMER 1 FOR BAUD GENERATOR MOV P0,#0FFH MOV P1,#0FFH MOV P2,#0FFH MOV P3,#0FFH SETB ES SETB EA SETB TR1 ; START THE TIMER RET TEST: MOV TH1,#230 ; BAUD =2400 BPS MOV DPTR,#TEST_MESSAGE INNER_TEST: MOV A,#0 MOVC A,@A+DPTR CJNE A,#0,PASS MOV DATAOUT,#10100101B CALL BIT_OUT MOV TH1,BAUD RET PASS: MOV SEND,A CALL SERIAL_OUT INC DPTR JMP INNER_TEST BODY: SETB STATUS_FLAG MOV TH1,BAUD MOV R0,#7DH ; SEE BELOW FOR BYTE STORAGE ADDRESSES INNER_BODY: JNB RFLAG,$ ; LOOP UNTIL BYTE RECIEVED MOV A,SBUF ; BYTE IN CLR RFLAG ; RESET RECIEVE FLAG JNB STATUS_FLAG,DATA_VALID CJNE A,#10010000B,INNER_BODY ; WAIT UNTIL STATUS BYTE IS VALID DATA_VALID: CLR STATUS_FLAG MOV @R0,A ; STORE THE BYTE IN VALUE OF R0 INC R0 CJNE R0,#80H,INNER_BODY ;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; 7DH = BYTE 1 ; ; 7EH = BYTE 2 ; ; 7FH = BYTE 3 ; RET ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; PASS A BYTE TO BE DISPLAYED IN DATAOUT;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;; THEN CALL THE FUNCTION BIT_OUT ;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; DISPLAY: MOV DATAOUT,7DH ; BYTE 1 ; to show binary data stream CALL BIT_OUT ; remove all the ';' before CALL SPACE ; the code in display. MOV DATAOUT,7EH ; BYTE 2 ; CALL BIT_OUT ; CALL SPACE ; MOV DATAOUT,7FH ; BYTE 3 ; CALL BIT_OUT ; CALL SPACE ; CALL SPACE ; MOV DATAOUT,7EH ; BYTE 2 CALL NOTE_OUT MOV DATAOUT,7EH CALL NOTE_SIGN RET NOTE_SIGN: MOV A,DATAOUT MOV B,#2 MUL AB SUBB A,#1 FLAT: MOV DPTR,#NOTE_CHART MOVC A,@A+DPTR MOV SEND,A CALL SERIAL_OUT RET NOTE_OUT: MOV A,DATAOUT MOV B,#2 MUL AB SUBB A,#2 MOV DPTR,#NOTE_CHART MOVC A,@A+DPTR MOV SEND,A CALL SERIAL_OUT RET SPACE: MOV TH1,#230 MOV SEND,#13 CALL SERIAL_OUT MOV SEND,#10 CALL SERIAL_OUT MOV TH1,BAUD RET BIT_OUT: MOV TH1,#230 ; SET FOR 2400 BPS MOV R7,#8 DECODE: MOV A,DATAOUT RLC A MOV DATAOUT,A JC BIT_ONE MOV SEND,#'0' RETT: CALL SERIAL_OUT DJNZ R7,DECODE CALL SPACE RET BIT_ONE: MOV SEND,#'1' JMP RETT ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SERIAL_OUT: MOV TH1,#230 SETB TFLAG MOV A,SEND MOV SBUF,A ; ANYTHING MOVED INTO SBUF, STARTS TRANSMIT JB TFLAG,$ RET ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; MILLI: ; PUSH ACC ; (024) Save Accumulator ; MOV A,TICKS ; (024) Initialize loop MLOOP: ; NOP ; (012) NOP ; (012) NOP ; (012) DJNZ ACC,MLOOP ; (024) ; POP ACC ; (024) Restore Accumulator RET ; (048) (Includes CALL) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Long Delay ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; This routine waits a long time. How ; ; long it waits is determined by the ; ; value of TWDLS. (It's that many ; ; milliseconds plus a little overhead.) ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; TWIDDLE: ; PUSH ACC ; Save the accumulator MOV A,TWDLS ; Load the Accumulator LOOP: ; CALL MILLI ; Wait 1 millisecond DJNZ ACC,LOOP ; Done yet? ; POP ACC ; Yes, restore the accumulator RET ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; ; Wait a second! ; ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; SECOND: ; PUSH ACC ; MOV A,#250 ; SL1: CALL MILLI ; CALL MILLI ; CALL MILLI ; CALL MILLI ; DJNZ ACC,SL1 ; ; POP ACC ; RET ; BODY_O_CODE: CALL INITIALIZE CALL TEST MAIN: CALL BODY CALL DISPLAY JMP MAIN NOTE_CHART: DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' DB 'C#D D#E F F#G G#A A#B C ' TEST_MESSAGE: DB ' HELLO WORLD ' DB 0 END