; ;================================================================================================== ; UART DRIVER (SERIAL PORT) ;================================================================================================== ; #IF (UARTCNT >= 1) UART0_RBR .EQU UART0IOB + 0 ; DLAB=0: RCVR BUFFER REG (READ ONLY) UART0_THR .EQU UART0IOB + 0 ; DLAB=0: XMIT HOLDING REG (WRITE ONLY) UART0_IER .EQU UART0IOB + 1 ; DLAB=0: INT ENABLE REG UART0_IIR .EQU UART0IOB + 2 ; INT IDENT REGISTER (READ ONLY) UART0_FCR .EQU UART0IOB + 2 ; FIFO CONTROL REG (WRITE ONLY) UART0_LCR .EQU UART0IOB + 3 ; LINE CONTROL REG UART0_MCR .EQU UART0IOB + 4 ; MODEM CONTROL REG UART0_LSR .EQU UART0IOB + 5 ; LINE STATUS REG UART0_MSR .EQU UART0IOB + 6 ; MODEM STATUS REG UART0_SCR .EQU UART0IOB + 7 ; SCRATCH REGISTER UART0_DLL .EQU UART0IOB + 0 ; DLAB=1: DIVISOR LATCH (LS) UART0_DLM .EQU UART0IOB + 1 ; DLAB=1: DIVISOR LATCH (MS) ; UART0_DIV .EQU (1843200 / (16 * UART0BAUD)) #ENDIF ; #IF (UARTCNT >= 2) UART1_RBR .EQU UART1IOB + 0 ; DLAB=0: RCVR BUFFER REG (READ ONLY) UART1_THR .EQU UART1IOB + 0 ; DLAB=0: XMIT HOLDING REG (WRITE ONLY) UART1_IER .EQU UART1IOB + 1 ; DLAB=0: INT ENABLE REG UART1_IIR .EQU UART1IOB + 2 ; INT IDENT REGISTER (READ ONLY) UART1_FCR .EQU UART1IOB + 2 ; FIFO CONTROL REG (WRITE ONLY) UART1_LCR .EQU UART1IOB + 3 ; LINE CONTROL REG UART1_MCR .EQU UART1IOB + 4 ; MODEM CONTROL REG UART1_LSR .EQU UART1IOB + 5 ; LINE STATUS REG UART1_MSR .EQU UART1IOB + 6 ; MODEM STATUS REG UART1_SCR .EQU UART1IOB + 7 ; SCRATCH REGISTER UART1_DLL .EQU UART1IOB + 0 ; DLAB=1: DIVISOR LATCH (LS) UART1_DLM .EQU UART1IOB + 1 ; DLAB=1: DIVISOR LATCH (MS) ; UART1_DIV .EQU (1843200 / (16 * UART1BAUD)) #ENDIF ; #IF (UARTCNT >= 3) UART2_RBR .EQU UART2IOB + 0 ; DLAB=0: RCVR BUFFER REG (READ ONLY) UART2_THR .EQU UART2IOB + 0 ; DLAB=0: XMIT HOLDING REG (WRITE ONLY) UART2_IER .EQU UART2IOB + 1 ; DLAB=0: INT ENABLE REG UART2_IIR .EQU UART2IOB + 2 ; INT IDENT REGISTER (READ ONLY) UART2_FCR .EQU UART2IOB + 2 ; FIFO CONTROL REG (WRITE ONLY) UART2_LCR .EQU UART2IOB + 3 ; LINE CONTROL REG UART2_MCR .EQU UART2IOB + 4 ; MODEM CONTROL REG UART2_LSR .EQU UART2IOB + 5 ; LINE STATUS REG UART2_MSR .EQU UART2IOB + 6 ; MODEM STATUS REG UART2_SCR .EQU UART2IOB + 7 ; SCRATCH REGISTER UART2_DLL .EQU UART2IOB + 0 ; DLAB=1: DIVISOR LATCH (LS) UART2_DLM .EQU UART2IOB + 1 ; DLAB=1: DIVISOR LATCH (MS) ; UART2_DIV .EQU (1843200 / (16 * UART2BAUD)) #ENDIF ; #IF (UARTCNT >= 4) UART3_RBR .EQU UART3IOB + 0 ; DLAB=0: RCVR BUFFER REG (READ ONLY) UART3_THR .EQU UART3IOB + 0 ; DLAB=0: XMIT HOLDING REG (WRITE ONLY) UART3_IER .EQU UART3IOB + 1 ; DLAB=0: INT ENABLE REG UART3_IIR .EQU UART3IOB + 2 ; INT IDENT REGISTER (READ ONLY) UART3_FCR .EQU UART3IOB + 2 ; FIFO CONTROL REG (WRITE ONLY) UART3_LCR .EQU UART3IOB + 3 ; LINE CONTROL REG UART3_MCR .EQU UART3IOB + 4 ; MODEM CONTROL REG UART3_LSR .EQU UART3IOB + 5 ; LINE STATUS REG UART3_MSR .EQU UART3IOB + 6 ; MODEM STATUS REG UART3_SCR .EQU UART3IOB + 7 ; SCRATCH REGISTER UART3_DLL .EQU UART3IOB + 0 ; DLAB=1: DIVISOR LATCH (LS) UART3_DLM .EQU UART3IOB + 1 ; DLAB=1: DIVISOR LATCH (MS) ; UART3_DIV .EQU (1843200 / (16 * UART3BAUD)) #ENDIF ; ; CHARACTER DEVICE DRIVER ENTRY ; A: RESULT (OUT), CF=ERR ; B: FUNCTION (IN) ; C: CHARACTER (IN/OUT) ; E: DEVICE/UNIT (IN) ; ; UART_INIT: #IF (UARTCNT >= 1) CALL UART0_INIT #ENDIF #IF (UARTCNT >= 2) CALL UART1_INIT #ENDIF #IF (UARTCNT >= 3) CALL UART2_INIT #ENDIF #IF (UARTCNT >= 4) CALL UART3_INIT #ENDIF RET ; ; ; UART_DISPATCH: LD A,C ; GET DEVICE/UNIT AND $0F ; ISOLATE UNIT #IF (UARTCNT >= 1) JP Z,UART0_DISPATCH #ENDIF #IF (UARTCNT >= 2) DEC A JP Z,UART1_DISPATCH #ENDIF #IF (UARTCNT >= 3) DEC A JP Z,UART2_DISPATCH #ENDIF #IF (UARTCNT >= 4) DEC A JP Z,UART3_DISPATCH #ENDIF CALL PANIC ; ; ; #IF (UARTCNT >= 1) ; UART0_INIT: PRTS("UART0: IO=0x$") LD A,UART0IOB CALL PRTHEXBYTE PRTS(" BAUD=$") LD HL,UART0BAUD / 10 CALL PRTDEC PRTC('0') LD A,80H OUT (UART0_LCR),A ; DLAB ON LD A,UART0_DIV % $100 OUT (UART0_DLL),A ; SET DIVISOR (LS) LD A,UART0_DIV / $100 OUT (UART0_DLM),A ; SET DIVISOR (MS) LD B,03H ; B = DEFAULT SETTING FOR MCR (DTR + RTS) #IF (UART0AFC) PRTS(" AFC$") LD A,$55 ; TEST VALUE OUT (UART0_SCR),A ; SET SCRATCH REG TO TEST VALUE LD A,0BFH OUT (UART0_LCR),A ; SET LCR=$BF TO ATTEMPT TO ACCESS EFR IN A,(UART0_SCR) ; READ SCRATCH REGISTER CP $55 ; IF $55, NO EFR JR NZ,UART0_AFC1 ; NZ, HAVE EFR, DO IT SET 5,B ; ENABLE AUTO FLOW CONTROL JR UART0_AFC2 UART0_AFC1: LD A,0C0H ; ENABLE CTS/RTS FLOW CONTROL OUT (UART0_EFR),A ; SAVE IT UART0_AFC2: #ENDIF LD A,03H OUT (UART0_LCR),A ; DLAB OFF, 8 DATA, 1 STOP, NO PARITY LD A,B ; LOAD MCR VALUE TO SET OUT (UART0_MCR),A ; SAVE IT #IF (UART0FIFO) ; LD A,07H ; ENABLE AND RESET FIFOS LD A,01H ; ENABLE AND RESET FIFOS OUT (UART0_FCR),A ; ENABLE FIFOS PRTS(" FIFO$") #ENDIF RET ; ; ; UART0_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,UART0_IN DEC A JP Z,UART0_OUT DEC A JP Z,UART0_IST DEC A JP Z,UART0_OST CALL PANIC ; ; ; UART0_IN: CALL UART0_IST OR A JR Z,UART0_IN IN A,(UART0_RBR) ; READ THE CHAR FROM THE UART LD E,A RET ; ; ; UART0_IST: IN A,(UART0_LSR) ; READ LINE STATUS REGISTER AND $01 ; TEST IF DATA IN RECEIVE BUFFER JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN XOR A INC A ; SIGNAL CHAR READY, A = 1 RET ; ; ; UART0_OUT: CALL UART0_OST OR A JR Z,UART0_OUT LD A,E OUT (UART0_THR),A ; THEN WRITE THE CHAR TO UART RET ; UART0_OST: IN A,(UART0_LSR) ; READ LINE STATUS REGISTER AND $20 JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN XOR A INC A ; SIGNAL BUFFER EMPTY, A = 1 RET ; #ENDIF ; ; ; #IF (UARTCNT >= 2) ; UART1_INIT: CALL NEWLINE PRTS("UART1: IO=0x$") LD A,UART1IOB CALL PRTHEXBYTE PRTS(" BAUD=$") LD HL,UART1BAUD / 10 CALL PRTDEC PRTC('0') LD A,80H OUT (UART1_LCR),A ; DLAB ON LD A,UART1_DIV % $100 OUT (UART1_DLL),A ; SET DIVISOR (LS) LD A,UART1_DIV / $100 OUT (UART1_DLM),A ; SET DIVISOR (MS) LD B,03H ; B = DEFAULT SETTING FOR MCR (DTR + RTS) #IF (UART1AFC) PRTS(" AFC$") LD A,$55 ; TEST VALUE OUT (UART1_SCR),A ; SET SCRATCH REG TO TEST VALUE LD A,0BFH OUT (UART1_LCR),A ; SET LCR=$BF TO ATTEMPT TO ACCESS EFR IN A,(UART1_SCR) ; READ SCRATCH REGISTER CP $55 ; IF $55, NO EFR JR NZ,UART1_AFC1 ; NZ, HAVE EFR, DO IT SET 5,B ; ENABLE AUTO FLOW CONTROL JR UART1_AFC2 UART1_AFC1: LD A,0C0H ; ENABLE CTS/RTS FLOW CONTROL OUT (UART1_EFR),A ; SAVE IT UART1_AFC2: #ENDIF LD A,03H OUT (UART1_LCR),A ; DLAB OFF, 8 DATA, 1 STOP, NO PARITY LD A,B ; LOAD MCR VALUE TO SET OUT (UART1_MCR),A ; SAVE IT #IF (UART1FIFO) ; LD A,07H ; ENABLE AND RESET FIFOS LD A,01H ; ENABLE AND RESET FIFOS OUT (UART1_FCR),A ; ENABLE FIFOS PRTS(" FIFO$") #ENDIF RET ; ; ; UART1_DISPATCH: LD A,B ; GET REQUESTED FUNCTION AND $0F ; ISOLATE SUB-FUNCTION JP Z,UART1_IN DEC A JP Z,UART1_OUT DEC A JP Z,UART1_IST DEC A JP Z,UART1_OST CALL PANIC ; ; ; UART1_IN: CALL UART1_IST OR A JR Z,UART1_IN IN A,(UART1_RBR) ; READ THE CHAR FROM THE UART LD E,A RET ; ; ; UART1_IST: IN A,(UART1_LSR) ; READ LINE STATUS REGISTER AND $01 ; TEST IF DATA IN RECEIVE BUFFER JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN XOR A INC A ; SIGNAL CHAR READY, A = 1 RET ; ; ; UART1_OUT: CALL UART1_OST OR A JR Z,UART1_OUT LD A,E OUT (UART1_THR),A ; THEN WRITE THE CHAR TO UART RET ; UART1_OST: IN A,(UART1_LSR) ; READ LINE STATUS REGISTER AND $20 JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN XOR A INC A ; SIGNAL BUFFER EMPTY, A = 1 RET ; #ENDIF