                        ; RS232<->MIDI Gateway for use with Host Port software and/or YAMAHA CBX driver
                        ; Hardware/Software : Benoît BOUCHEZ for ELEKTOR
                        ; Version 1.00 : 10/1999
                        ; Version 1.10 : 05/2000 : 	- New buffering system for MIDI->RS
                        ;			- P1.6 pushbutton to clear overflow LED
                        ;			- MIDI RESET message on RS232 clears overflow LED
                        ;			- Simplified RTS/CTS handling (CTS set to 1)
                        ;			- T2 = test output for MIDI Clock
                        
 0000                   	CPU "C:\WINC32\8051.TBL"	; Use 8051 assembly model
 0000                   	HOF "INT8"		; Output format is Intel HEX
                        
 0000                   	INCL "INC80320.ASM"	; Add 80C320 specific registers
                        ; Table des bits et registres du DALLAS 80C320
                        ; Registres
 00F0 =                 B:	EQU	0F0H	;B REGISTER
 00E0 =                 ACC:	EQU	0E0H	;ACCUMULATOR
 00D0 =                 PSW:	EQU	0D0H	;PROGRAM STATUS WORD
 00B8 =                 IPC:	EQU	0B8H	;INTERRUPT PRIORITY
 00B0 =                 P3:	EQU	0B0H	;PORT 3
 00A8 =                 IEC:	EQU	0A8H	;INTERRUPT ENABLE
 00A0 =                 P2:	EQU	0A0H	;PORT 2
 0099 =                 SBUF0:		EQU	$99	; Serial Buffer Port 0
 0098 =                 SCON0:		EQU	$98	; Serial Control Port 0
 0090 =                 P1:	EQU	90H	;PORT 1
 008D =                 TH1:	EQU	8DH	;TIMER 1 HIGH
 008C =                 TH0:	EQU	8CH	;TIMER 0 HIGH
 008B =                 TL1:	EQU	8BH	;TIMER 1 LOW
 008A =                 TL0:	EQU	8AH	;TIMER 0 LOW
 0089 =                 TMOD:	EQU	89H	;TIMER MODE
 0088 =                 TCON:	EQU	88H	;TIMER CONTROL
 0087 =                 PCON:	EQU	87H	;POWER CONTROL REGISTER
 0083 =                 DPH:	EQU	83H	;DATA POINTER HIGH
 0082 =                 DPL:	EQU	82H	;DATA POINTER LOW
 0081 =                 SP:	EQU	81H	;STACK POINTER
 0080 =                 P0:	EQU	80H	;PORT 0
 00C0 =                 SCON1:		EQU $C0		; Serial Control Port 1
 00C1 =                 SBUF1:		EQU $C1		; Serial Buffer Port 1
 00C8 =                 T2CON:		EQU $C8		; Timer 2 Control 
 00C9 =                 T2MOD:		EQU $C9		; Timer 2 Mode
 00CA =                 RCAP2L:		EQU $CA		; Timer 2 Capture Low
 00CB =                 RCAP2H:		EQU $CB		; Timer 2 Capture High
 00CC =                 TL2:		EQU $CC		; Timer 2 Low
 00CD =                 TH2:		EQU $CD		; Timer 2 High
                        
                        ;Bits
 00D7 =                 CY:	EQU	0D7H	;CARRY FLAG
 00D6 =                 AC:	EQU	0D6H	;AUXILIARY-CARRY FLAG
 00D5 =                 F0:	EQU	0D5H	;USER FLAG 0
 00D4 =                 RS1:	EQU	0D4H	;REGISTER SELECT MSB
 00D3 =                 RS0:	EQU	0D3H	;REGISTER SELECT LSB
 00D2 =                 OV:	EQU	0D2H	;OVERFLOW FLAG
 00D0 =                 P:	EQU	0D0H	;PARITY FLAG
 00BC =                 PS:	EQU	0BCH	;PRIORITY SERIAL PORT
 00BB =                 PT1:	EQU	0BBH	;PRIORITY TIMER 1
 00BA =                 PX1:	EQU	0BAH	;PRIORITY EXTERNAL 1
 00B9 =                 PT0:	EQU	0B9H	;PRIORITY TIMER 0
 00B8 =                 PX0:	EQU	0B8H	;PRIORITY EXTERNAL 0
 00AF =                 EA:	EQU	0AFH	;ENABLE ALL INTERRUPT
 00AC =                 ES:	EQU	0ACH	;ENABLE SERIAL INTERRUPT
 00AB =                 ET1:	EQU	0ABH	;ENABLE TIMER 1 INTERRUPT
 00AA =                 EX1:	EQU	0AAH	;ENABLE EXTERNAL 1 INTERR
 00A9 =                 ET0:	EQU	0A9H	;ENABLE TIMER 0 INTERRUPT
 00A8 =                 EX0:	EQU	0A8H	;ENABLE EXTERNAL 0 INTERR
 009F =                 SM0:	EQU	09FH	;SERIAL MODE 0
 009E =                 SM1:	EQU	09EH	;SERIAL MODE 1
 009D =                 SM2:	EQU	09DH	;SERIAL MODE 2
 009C =                 REN:	EQU	09CH	;SERIAL RECEPTION ENABLE
 009B =                 TB8:	EQU	09BH	;TRANSMIT BIT 8
 009A =                 RB8:	EQU	09AH	;RECEIVE BIT 8
 0099 =                 TI0:		EQU $99		; Transmit Interrupt Port 0
 0098 =                 RI0:		EQU $98		; Receive Interrupt Port 0
 008F =                 TF1:	EQU	08FH	;TIMER 1 OVERFLOW FLAG
 008E =                 TR1:		EQU	$8E	; Timer 1 Run Control
 008D =                 TF0:	EQU	08DH	;TIMER 0 OVERFLOW FLAG
 008C =                 TR0:	EQU	08CH	;TIMER 0 RUN CONTROL BIT
 008B =                 IE1:	EQU	08BH	;EXT INTERR. 1 EDGE FLAG
 008A =                 IT1:	EQU	08AH	;EXT INTERR. 1 TYPE FLAG
 0089 =                 IE0:	EQU	089H	;EXT INTERR. 0 EDGE FLAG
 0088 =                 IT0:	EQU	088H	;EXT INTERR. 0 TYPE FLAG
 00C0 =                 RI1:		EQU $C0		; Receive Interrupt Port 1
 00C1 =                 TI1:		EQU $C1		; Transmit Interrupt Port 1
 00DF =                 SMOD1:		EQU $DF		; Doublage baud rate port 1
 00C9 =                 CT2:		EQU $C9		; Compteur/Timer 2
 00CA =                 TR2:		EQU $CA		; Contrôle Timer 2
 00CC =                 TCLK2:		EQU $CC		; Horloge réception port 0 sur timer 2
 00CD =                 RCLK2:		EQU $CD		; Horloge transmission port 0 sur timer 2
                        
                        ; Target specific definitions
 0098 =                 RI_MIDI:		EQU RI0		; MIDI is on port 0
 0099 =                 TI_MIDI:		EQU TI0
 0099 =                 SBUF_MIDI:	EQU SBUF0
 00C0 =                 RI_RS:		EQU RI1		; RS232 is on port 1
 00C1 =                 TI_RS:		EQU TI1
 00C1 =                 SBUF_RS:	EQU SBUF1
 0094 =                 RTS_RS:		EQU P1+4	; RTS line status
 0095 =                 CTS_RS:		EQU P1+5	; CTS line control
 0096 =                 RAZ_OVR:	EQU P1+6	; Push Button input for overflow clear
 0097 =                 LED_OVR:	EQU P1+7	; Overflow indicator
                        
                        ; System variables (bytes)
 0050                   	ORG $50
 0050                   CHAR_RS:	DFS 1		; Byte read on RS
 0051                   PTR_IN:		DFS 1		; FIFO input pointer
 0052                   PTR_OUT:	DFS 1		; FIFO output pointer
 0053                   MIDI_DATA:	DFS 1		; MIDI Byte waiting for retransmission on RS
                        
 0080                   	ORG $80			; Indirect RAM = FIFO Buffer
 0080                   FIFO:		DFS 128
                        
                        ; System variables (bits)
 0070                   	ORG $70
 0070                   MIDI_DATA_AVAIL:	DFS 1
                        
                        ; CODE Section
 0000                   	ORG $0
                        
 0000 020003            	LJMP START		; RESET vector
                        
                        ; ****************************************
                        ; Microcontroller configuration
                        ; ****************************************
 0003                   START:
                        
                        ; ****************************************
                        ; Timer 2 is clock source for serial port 0 (31250 bauds * 16=500kHz)
 0003 75C902            	MOV T2MOD, #$02		; Outputs clock for test purpose
 0006 C2C9              	CLR CT2			; Source Timer 2 = Internal clock after divide / 2
                        
 0008 D2CC              	SETB TCLK2		; Set Timer 2 as Baud Rate Generator
 000A D2CD              	SETB RCLK2
                        
 000C C2CA              	CLR TR2			; Freeze Timer 2
                        
 000E 75CAE8            	MOV RCAP2L, #$E8		; 65536-24=65512 (FFE8)
 0011 75CBFF            	MOV RCAP2H, #$FF
 0014 75CCE8            	MOV TL2, #$E8
 0017 75CDFF            	MOV TH2, #$FF
                        
 001A D2CA              	SETB TR2
                        
                        ; Setup serial port 0
 001C 759850            	MOV SCON0, #01010000B
                        
                        ; ****************************************
                        ; Timer 1 is clock source for serial port 1 (38400 * 16=614400Hz from external 1.8432MHz)
                        
 001F D2DF              	SETB SMOD1		; Baud Clock divider off
 0021 C28E              	CLR TR1			; Freeze Timer 1
 0023 758962            	MOV TMOD, #$62		; Setup Timer 1 and Timer 0
 0026 758DFD            	MOV TH1, #253
 0029 758BFD            	MOV TL1, #253
 002C D28E              	SETB TR1
                        
                        ; Setup serial port 1
 002E 75C050            	MOV SCON1, #01010000B
                        
                        ; ****************************************
                        ; Setup application variables
 0031 C297              	CLR LED_OVR
 0033 755180            	MOV PTR_IN, #FIFO	; FIFO init
 0036 755280            	MOV PTR_OUT, #FIFO
 0039 D299              	SETB TI_MIDI
 003B D2C1              	SETB TI_RS
 003D C298              	CLR RI_MIDI
 003F C2C0              	CLR RI_RS
 0041 C270              	CLR MIDI_DATA_AVAIL	; No MIDI data available
 0043 C295              	CLR CTS_RS		; Activate CTS (allow transmission)
                        
                        ; Main application loop
 0045                   MAINLOOP:
 0045 120058            	LCALL GETMIDI
 0048 120069            	LCALL MIDI2RS
                        
 004B 120078            	LCALL GETRS
 004E 120096            	LCALL RS2MIDI
                        
 0051 209602            	JB RAZ_OVR, END_MAINLOOP	; If CLEAR pushbutton depressed
 0054 C297              	CLR LED_OVR			; then clears LED
                        
 0056                   END_MAINLOOP:
 0056 80ED              	JMP MAINLOOP
                        
                        ; ********************************************
                        ; GETMIDI : get MIDI Byte and store it temporarily to let RS232 buffer empty completely
                        ; before sending it
 0058                   GETMIDI:
 0058 30980D            	JNB RI_MIDI, END_GETMIDI		; MIDI Byte available
 005B E599              	MOV A, SBUF_MIDI			; Yes : get it
 005D C298              	CLR RI_MIDI
 005F F553              	MOV MIDI_DATA, A			; Save it
 0061 D270              	SETB MIDI_DATA_AVAIL		; Mark MIDI byte pending
                        
 0063                   CHK_SYS_RESET:
 0063 B4FF02            	CJNE A, #$FF, END_GETMIDI		; If MIDI System Reset message
 0066 C297              	CLR LED_OVR			; then clear overflow LED
                        
 0068                   END_GETMIDI:
 0068 22                	RET
                        
                        ; ********************************************
                        ; MIDI2RS : Send received MIDI byte to RS232
 0069                   MIDI2RS:
 0069 30C10B            	JNB TI_RS, END_MIDI2RS		; If RS232 buffer empty
 006C 307008            	JNB MIDI_DATA_AVAIL, END_MIDI2RS	; and MIDI byte to send
 006F E553              	MOV A, MIDI_DATA			; Get back MIDI byte
 0071 C2C1              	CLR TI_RS
 0073 C270              	CLR MIDI_DATA_AVAIL		; Mark no MIDI byte pending
 0075 F5C1              	MOV SBUF_RS, A			; Send MIDI byte to RS232
                        
 0077                   END_MIDI2RS:
 0077 22                	RET
                        
                        ; ********************************************
                        ; GETRS : Read RS received byte et store it in FIFO
 0078                   GETRS:
 0078 30C01A            	JNB RI_RS, END_GETRS		; Something available on RS port ?
 007B                   GETRS_CHAR:
 007B E5C1              	MOV A, SBUF_RS			; Yes :
 007D F550              	MOV CHAR_RS, A			; CHAR_RS:=SBUF_RS
 007F C2C0              	CLR RI_RS			; Prepare uC for next RS byte
                        
 0081                   CHK_FIFO:				; Enough room in FIFO ?
 0081 E551              	MOV A, PTR_IN			; Yes :
 0083 04                	INC A				;  A:=PTR_IN+1
 0084 7002              	JNZ NO_LOOP_IN			; If FIFO loop back
 0086 7480              	MOV A, #FIFO			; then A:=Debut file
                        		
 0088                   NO_LOOP_IN:
 0088 B55204            	CJNE A, PTR_OUT, FIFO_LIBRE	; Compare A with PTR_OUT
                        
 008B                   FIFO_PLEIN:				; FIFO is full :
 008B D297              	SETB LED_OVR			; Show the problem to user
 008D 8006              	JMP END_GETRS
                        
 008F                   FIFO_LIBRE:				; FIFO is not full :
 008F F551              	MOV PTR_IN, A			; PTR_IN:=Computed pointer
 0091 F8                	MOV R0, A
 0092 E550              	MOV A, CHAR_RS
 0094 F6                	MOV @R0, A			; FIFO[PTR_IN]:=CHAR_RS
                        	
 0095                   END_GETRS:
 0095 22                	RET
                        
                        ; ********************************************
                        ; RS2MIDI : Send to MIDI datas stored in FIFO if MIDI port is free
 0096                   RS2MIDI:
 0096 E552              	MOV A, PTR_OUT			; Something waiting in FIFO ?
 0098 B55102            	CJNE A, PTR_IN, DATA_IN_FIFO	; Yes if PTR_IN<>PTR_OUT
 009B 8010              	JMP END_RS2MIDI
                        
 009D                   DATA_IN_FIFO:
 009D 04                	INC A				; Compute pointer to next data
 009E 7002              	JNZ NO_LOOP_OUT		; If FIFO end is reached
 00A0 7480              	MOV A, #FIFO			; return to beginning
                        
 00A2                   NO_LOOP_OUT:
 00A2 309908            	JNB TI_MIDI, END_RS2MIDI		; If MIDI buffer not empty, leave process (PTR_OUT is not yet affected)
 00A5 C299              	CLR TI_MIDI
                        
 00A7                   SBUF_MIDI_VIDE:
 00A7 F552              	MOV PTR_OUT, A			; Store new pointer value
 00A9 F8                	MOV R0, A
 00AA E6                	MOV A, @R0			; Get data waiting in FIFO
 00AB F599              	MOV SBUF_MIDI, A			; Send it on MIDI
                        
 00AD                   END_RS2MIDI:
 00AD 22                	RET
                        
 0000                   	END
00D6  AC                 00E0  ACC                00F0  B                  
0050  CHAR_RS            0081  CHK_FIFO           0063  CHK_SYS_RESET      
00C9  CT2                0095  CTS_RS             00D7  CY                 
009D  DATA_IN_FIFO       0083  DPH                0082  DPL                
00AF  EA                 0068  END_GETMIDI        0095  END_GETRS          
0056  END_MAINLOOP       0077  END_MIDI2RS        00AD  END_RS2MIDI        
00AC  ES                 00A9  ET0                00AB  ET1                
00A8  EX0                00AA  EX1                00D5  F0                 
0080  FIFO               008F  FIFO_LIBRE         008B  FIFO_PLEIN         
0058  GETMIDI            0078  GETRS              007B  GETRS_CHAR         
0089  IE0                008B  IE1                00A8  IEC                
00B8  IPC                0088  IT0                008A  IT1                
0097  LED_OVR            0045  MAINLOOP           0069  MIDI2RS            
0053  MIDI_DATA          0070  MIDI_DATA_AVAIL    0088  NO_LOOP_IN         
00A2  NO_LOOP_OUT        00D2  OV                 00D0  P                  
0080  P0                 0090  P1                 00A0  P2                 
00B0  P3                 0087  PCON               00BC  PS                 
00D0  PSW                00B9  PT0                00BB  PT1                
0051  PTR_IN             0052  PTR_OUT            00B8  PX0                
00BA  PX1                0096  RAZ_OVR            009A  RB8                
00CB  RCAP2H             00CA  RCAP2L             00CD  RCLK2              
009C  REN                0098  RI0                00C0  RI1                
0098  RI_MIDI            00C0  RI_RS              00D3  RS0                
00D4  RS1                0096  RS2MIDI            0094  RTS_RS             
0099  SBUF0              00C1  SBUF1              0099  SBUF_MIDI          
00A7  SBUF_MIDI_VIDE     00C1  SBUF_RS            0098  SCON0              
00C0  SCON1              009F  SM0                009E  SM1                
009D  SM2                00DF  SMOD1              0081  SP                 
0003  START              00C8  T2CON              00C9  T2MOD              
009B  TB8                00CC  TCLK2              0088  TCON               
008D  TF0                008F  TF1                008C  TH0                
008D  TH1                00CD  TH2                0099  TI0                
00C1  TI1                0099  TI_MIDI            00C1  TI_RS              
008A  TL0                008B  TL1                00CC  TL2                
0089  TMOD               008C  TR0                008E  TR1                
00CA  TR2                
