diff --git a/Source/HBIOS/duart.asm b/Source/HBIOS/duart.asm index ef1da758..af716ece 100644 --- a/Source/HBIOS/duart.asm +++ b/Source/HBIOS/duart.asm @@ -144,6 +144,12 @@ DUART_SR_PARITY .EQU %00100000 ; PARITY ERROR DUART_SR_FRAMING .EQU %01000000 ; FRAMING ERROR DUART_SR_BREAK .EQU %10000000 ; RECEIVED BREAK ; +; DUART MODE REGISTER 0 +; +DUART_MR0_NORMAL .EQU %00000000 ; NORMAL BAUD RATE TABLE +DUART_MR0_EXT1 .EQU %00000001 ; EXTENDED BAUD RATE TABLE 1 +DUART_MR0_EXT2 .EQU %00000100 ; EXTENDED BAUD RATE TABLE 2 +; ; DUART MODE REGISTER 1 ; DUART_MR1_RXRTS .EQU %10000000 ; RECEIVER CONTROLS RTS @@ -341,33 +347,16 @@ DUART_INITDEV1A: DUART_OUTP(DUART_CR) ; RESET TRANSMITTER LD A,DUART_CR_RESET_ERR DUART_OUTP(DUART_CR) ; RESET ERROR STATUS - LD A,L ; GET BAUD TABLE ENTRY IN A - AND DUART_BAUD_X1 ; SEE IF SELECT EXTEND BIT SHOULD BE SET - JR Z,DUART_INITDEV2 ; NO, CLEAR IT - LD A,DUART_CR_SET_RX_X ; YES, SET EXTEND BIT - DUART_OUTP(DUART_CR) ; SET FOR RECEIVER - LD A,DUART_CR_SET_TX_X - DUART_OUTP(DUART_CR) ; SET FOR TRANSMITTER - JR DUART_INITDEV3 + LD A,(IY + 1) ; GET DUART TYPE + CP DUART_26C92 ; IS IT A 26C92? + JR Z,DUART_INITDEV1B ; YES + CALL DUART_SETBAUD_681 ; NO, CALL '681 BRG SETUP + JR DUART_INITDEV2 ; -DUART_INITDEV2: - ; CLEAR EXTEND BIT - LD A,DUART_CR_CLR_RX_X - DUART_OUTP(DUART_CR) ; CLEAR FOR RECEIVER - LD A,DUART_CR_CLR_TX_X - DUART_OUTP(DUART_CR) ; CLEAR FOR TRANSMITTER +DUART_INITDEV1B: + CALL DUART_SETBAUD_92 ; CALL '92 BRG SETUP ; -DUART_INITDEV3: - ; SET BRG CLOCK SELECT - LD A,L ; GET BAUD TABLE ENTRY IN A - AND $0F ; GET CLOCK SELECT BITS - LD L,A ; SAVE IT IN L - RLA - RLA - RLA - RLA ; MOVE IT INTO THE HIGH NIBBLE - OR L ; AND MERGE BACK IN LOW NIBBLE - DUART_OUTP(DUART_CSR) ; SET CLOCK SELECT +DUART_INITDEV2: ; ; SET PARITY AND WORD SIZE LD A,DUART_CR_MR1 @@ -420,13 +409,59 @@ DUART_INITDEV5: ; DUART_INITDEVZ: ; -#IF (DUART_DEBUG) - PRTC(']') -#ENDIF ; INVALID BAUD RATE DEC A ; A WAS $00, GET BACK $FF RET ; RETURN ERROR STATUS ; +; INITIALIZE BRG FOR '681 DUART +; +DUART_SETBAUD_681: + ; SET ACR + LD C,(IY + 6) ; GET SHADOW ACR FOR THIS CHIP + LD B,(IY + 7) ; BC IS POINTER + LD A,(BC) ; GET SHADOW ACR IN A + AND %01111111 ; MASK OUT BIT 7 + LD H,A ; SAVE IT IN H + LD A,L ; TABLE ENTRY IS IN L, GET IT IN A + AND DUART_BAUD_ACR7 ; SEE IF ACR[7] SHOULD BE SET (BIT MASK SHOULD ACTUALLY _BE_ BIT 7) + OR H ; MERGE IN REST OF ACR + LD H,A ; SAVE IT IN H + LD A,(IY + 2) ; GET CHIP BASE IN A + ADD A,DUART_ACR ; ADD OFFSET OF ACR + LD C,A ; C = ACR PORT + ; YES, THIS OVERWRITES ACR[7] REGARDLESS OF THE OTHER CHANNEL, + ; BUT CURRENTLY THE TABLE IS SET SO EVERY VALID RATE HAS ACR[7] SET + OUT (C),H ; WRITE VALUE + ; SELECT PER-CHANNEL EXTENDED TABLE + LD A,L ; CALLED WITH TABLE ENTRY IN L, MOVE IT TO A + AND DUART_BAUD_X1 ; SEE IF SELECT EXTEND BIT SHOULD BE SET + JR Z,DUART_SETBAUD_681A ; NO, CLEAR IT + LD A,DUART_CR_SET_RX_X ; YES, SET EXTEND BIT + DUART_OUTP(DUART_CR) ; SET FOR RECEIVER + LD A,DUART_CR_SET_TX_X + DUART_OUTP(DUART_CR) ; SET FOR TRANSMITTER + JR DUART_SETBAUD_681B +; +DUART_SETBAUD_681A: + ; CLEAR EXTEND BIT + LD A,DUART_CR_CLR_RX_X + DUART_OUTP(DUART_CR) ; CLEAR FOR RECEIVER + LD A,DUART_CR_CLR_TX_X + DUART_OUTP(DUART_CR) ; CLEAR FOR TRANSMITTER +; +DUART_SETBAUD_681B: + ; SET BRG CLOCK SELECT + LD A,L ; GET BAUD TABLE ENTRY IN A + AND $0F ; GET CLOCK SELECT BITS + LD L,A ; SAVE IT IN L + RLA + RLA + RLA + RLA ; MOVE IT INTO THE HIGH NIBBLE + OR L ; AND MERGE BACK IN LOW NIBBLE + DUART_OUTP(DUART_CSR) ; SET CLOCK SELECT + RET +; DUART_BAUDTBL_681: ; ASSUME XR88C681 RUNS AT 3.6864MHZ .DB %0000 | DUART_BAUD_X1 ; 75 @@ -462,6 +497,64 @@ DUART_BAUDTBL_681: .DB DUART_BAUD_INV ; 3686400 .DB DUART_BAUD_INV ; 7372800 ; +; INITIALIZE BRG FOR '92 DUART +; +DUART_SETBAUD_92: + ; SET ACR + LD C,(IY + 6) ; GET SHADOW ACR FOR THIS CHIP + LD B,(IY + 7) ; BC IS POINTER + LD A,(BC) ; GET SHADOW ACR IN A + AND %01111111 ; MASK OUT BIT 7 + LD H,A ; SAVE IT IN H + LD A,L ; TABLE ENTRY IS IN L, GET IT IN A + AND DUART_BAUD_ACR7 ; SEE IF ACR[7] SHOULD BE SET (BIT MASK SHOULD ACTUALLY _BE_ BIT 7) + OR H ; MERGE IN REST OF ACR + LD H,A ; SAVE IT IN H + LD A,(IY + 2) ; GET CHIP BASE IN A + ADD A,DUART_ACR ; ADD OFFSET OF ACR + LD C,A ; C = ACR PORT + ; YES, THIS OVERWRITES ACR[7] REGARDLESS OF THE OTHER CHANNEL, + ; BUT CURRENTLY THE TABLE IS SET SO EVERY VALID RATE HAS ACR[7] SET + OUT (C),H ; WRITE VALUE + ; SELECT NORMAL OR EXTENDED BAUD RATE TABLES + LD H,DUART_MR0_NORMAL ; ASSUME NORMAL + LD A,L ; GET TABLE ENTRY IN A AGAIN + AND DUART_BAUD_EXT1 ; SHOULD EXT1 BE SET? + JR Z,DUART_SETBAUD_92A ; NO, CHECK NEXT VALUE + LD H,DUART_MR0_EXT1 ; YES, SET IT + JR DUART_SETBAUD_92C +; +DUART_SETBAUD_92A: + LD A,L ; GET TABLE ENTRY IN A ONCE MORE + AND DUART_BAUD_EXT2 ; SHOULD EXT2 BE SET? + JR Z,DUART_SETBAUD_92C ; NO, CONTINUE + LD H,DUART_MR0_EXT2 ; YES, SET IT +; +DUART_SETBAUD_92C: + ; H NOW CONTAINS MR0 + LD A,(IY + 2) ; GET CHIP BASE IN A + ADD A,DUART_CR ; WE WANT TO WRITE THE COMMAND REGISTER OF CHANNEL A, EVEN IF WE'RE CHANNEL B + LD C,A ; C = CRA + LD A,DUART_CR_MR0 ; RESET MR POINTER TO MR0 + OUT (C),A ; WRITE COMMAND + LD A,(IY + 2) ; GET CHIP BASE IN A + ADD A,DUART_MR ; NOW WE WANT TO WRITE TO MR0 OF CHANNEL A + LD C,A ; C = MRA + ; AS WITH ACR[7] THE TABLE IS SET SO EVERY VALID RATE IS FROM + ; THE SAME TABLE + OUT (C),H + ; SET BRG CLOCK SELECT + LD A,L ; GET BAUD TABLE ENTRY IN A YET AGAIN + AND $0F ; GET CLOCK SELECT BITS + LD L,A ; SAVE IT IN L + RLA + RLA + RLA + RLA ; MOVE IT INTO THE HIGH NIBBLE + OR L ; AND MERGE BACK IN LOW NIBBLE + DUART_OUTP(DUART_CSR) ; SET CLOCK SELECT OF CURRENT CHANNEL + RET +; DUART_BAUDTBL_92: ; ASSUME SC26C92 RUNS AT 7.3728MHZ .DB DUART_BAUD_INV ; 75 @@ -530,12 +623,21 @@ DUART_DETECT: ; ; FIRST SEE IF IT LOOKS LIKE A 16X50-STYLE UART LD A,(IY + 2) ; GET BASE PORT OF CHIP - ADD A,6 ; BASE + 6 = CTU (DUART), MSR (1ST 16X50) + ADD A,4 ; BASE + 4 = ACR (DUART), MCR (1ST 16X50) + LD H,A ; H := ACR/MCR PORT ADDRESS + ADD A,2 ; BASE + 6 = CTU (DUART), MSR (1ST 16X50) LD B,A ; B := CTU/MSR PORT ADDRESS INC A ; BASE + 7 = CTL (DUART), SCR (1ST 16X50) LD D,A ; D := CTL/SCR PORT ADDRESS ADD A,7 ; BASE + 14 = STCR (DUART), MSR (2ND 16X50) LD E,A ; E := STCR/MSR PORT ADDRESS + INC A ; BASE + 15 = SPCR (DUART), SCR (2ND 16X50) + LD C,A ; SPCR + IN A,(C) ; STOP COUNTER/TIMER, JUST IN CASE + LD C,H ; ACR/MCR + IN L,(C) ; GET ORIGINAL VALUE (ACTUALLY IPCR ON DUART) IN L + LD A,$30 ; ENABLE A SOURCE FOR THE COUNTER/TIMER + OUT (C),A ; WRITE TO ACR/MCR LD A,$A5 ; TEST VALUE LD C,B ; CTU OUT (C),A ; WRITE TEST VALUE TO CTU @@ -544,6 +646,10 @@ DUART_DETECT: OUT (C),A ; WRITE LARGE VALUE TO CTL LD C,E ; STCR IN A,(C) ; START COUNTER/TIMER (LATCH CTU, CTL) + INC C ; C := SPCR + IN A,(C) ; STOP COUNTER/TIMER + LD C,H ; ACR/MCR + OUT (C),L ; WRITE ORIGINAL VALUE OF MCR (ACR GETS SET ON DUART LATER) LD C,B ; CTU IN A,(C) ; READ BACK TEST VALUE CP $A5 ; CHECK FOR TEST VALUE