Browse Source

DUART: actually support 26C92 baud rate generator

also improve detection
pull/133/head
Chris Odorjan 6 years ago
parent
commit
74d357ed4b
  1. 164
      Source/HBIOS/duart.asm

164
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

Loading…
Cancel
Save