forked from MirrorRepos/RomWBW
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
435 lines
10 KiB
435 lines
10 KiB
;
|
|
;==================================================================================================
|
|
; ASCI DRIVER (Z180 SERIAL PORTS)
|
|
;==================================================================================================
|
|
;
|
|
; STAT:
|
|
; 7 6 5 4 3 2 1 0
|
|
; R O P F R C T T
|
|
; 0 0 0 0 0 0 0 0 DEFAULT VALUES
|
|
; | | | | | | | |
|
|
; | | | | | | | +-- TIE: TRANSMIT INTERRUPT ENABLE
|
|
; | | | | | | +---- TDRE: TRANSMIT DATA REGISTER EMPTY
|
|
; | | | | | +------ DCD0/CTS1E: CH0 CARRIER DETECT, CH1 CTS ENABLE
|
|
; | | | | +-------- RIE: RECEIVE INTERRUPT ENABLE
|
|
; | | | +---------- FE: FRAMING ERROR
|
|
; | | +------------ PE: PARITY ERROR
|
|
; | +-------------- OVRN: OVERRUN ERROR
|
|
; +---------------- RDRF: RECEIVE DATA REGISTER FULL
|
|
;
|
|
; CNTLA:
|
|
; 7 6 5 4 3 2 1 0
|
|
; M R T R E M M M
|
|
; 0 1 1 0 0 1 0 0 DEFAULT VALUES
|
|
; | | | | | | | |
|
|
; | | | | | | | +-- MOD0: STOP BITS: 0=1 BIT, 1=2 BITS
|
|
; | | | | | | +---- MOD1: PARITY: 0=NONE, 1=ENABLED
|
|
; | | | | | +------ MOD2: DATA BITS: 0=7 BITS, 1=8 BITS
|
|
; | | | | +-------- MPBR/EFR: MULTIPROCESSOR BIT RECEIVE / ERROR FLAG RESET
|
|
; | | | +---------- RTS0/CKA1D: CH0 RTS, CH1 CLOCK DISABLE
|
|
; | | +------------ TE: TRANSMITTER ENABLE
|
|
; | +-------------- RE: RECEIVER ENABLE
|
|
; +---------------- MPE: MULTI-PROCESSOR MODE ENABLE
|
|
;
|
|
; CNTLB:
|
|
; 7 6 5 4 3 2 1 0
|
|
; T M P R D S S S
|
|
; 0 0 X 0 X X X X DEFAULT VALUES
|
|
; | | | | | | | |
|
|
; | | | | | + + +-- SS: SOURCE/SPEED SELECT (R/W)
|
|
; | | | | +-------- DR: DIVIDE RATIO (R/W)
|
|
; | | | +---------- PEO: PARITY EVEN ODD (R/W)
|
|
; | | +------------ PS: ~CTS/PS: CLEAR TO SEND(R) / PRESCALE(W)
|
|
; | +-------------- MP: MULTIPROCESSOR MODE (R/W)
|
|
; +---------------- MPBT: MULTIPROCESSOR BIT TRANSMIT (R/W)
|
|
;
|
|
; ASEXT:
|
|
; 7 6 5 4 3 2 1 0
|
|
; R D C X B F D S
|
|
; 0 1 1 0 0 1 1 0 DEFAULT VALUES
|
|
; | | | | | | | |
|
|
; | | | | | | | +-- SEND BREAK
|
|
; | | | | | | +---- BREAK DETECT (RO)
|
|
; | | | | | +------ BREAK FEATURE ENABLE
|
|
; | | | | +-------- BRG MODE
|
|
; | | | +---------- X1 BIT CLK ASCI
|
|
; | | +------------ CTS0 DISABLE
|
|
; | +-------------- DCD0 DISABLE
|
|
; +---------------- RDRF INT INHIBIT
|
|
;
|
|
ASCI_INIT:
|
|
;
|
|
; SETUP THE DISPATCH TABLE ENTRIES
|
|
;
|
|
LD B,2 ; ALWAYS 2 ASCI UNITS ON Z180
|
|
LD C,0 ; PHYSICAL UNIT INDEX
|
|
ASCI_INIT1:
|
|
PUSH BC ; SAVE LOOP CONTROL
|
|
LD D,C ; PHYSICAL UNIT
|
|
LD E,CIODEV_ASCI ; DEVICE TYPE
|
|
LD BC,ASCI_DISPATCH ; BC := DISPATCH ADDRESS
|
|
CALL CIO_ADDENT ; ADD ENTRY, BC IS NOT DESTROYED
|
|
POP BC ; RESTORE LOOP CONTROL
|
|
INC C ; NEXT PHYSICAL UNIT
|
|
DJNZ ASCI_INIT1 ; LOOP UNTIL DONE
|
|
;
|
|
; ASCI0
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("ASCI0: IO=0x$")
|
|
LD A,Z180_TDR0
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_COMMA
|
|
LD A,Z180_RDR0
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE ; FORMATTING
|
|
LD DE,ASCI0CFG ; LOAD CONFIG
|
|
CALL PS_PRTSC0 ; PRINT IT
|
|
|
|
LD HL,ASCI0CFG ; SERIAL CONFIG WORD
|
|
LD A,H ; BYTE W/ ENCODED BAUD RATE
|
|
AND $1F ; ISOLATE BITS
|
|
LD L,A ; MOVE TO L
|
|
LD H,0 ; CLEAR MSB
|
|
CALL ASCI_CNTLB ; DERIVE CNTLB VALUE
|
|
;CALL TSTPT
|
|
JR Z,ASCI_INIT2 ; IMPLEMENT IF NO ERROR
|
|
PRTS(" ERROR!$")
|
|
JR ASCI_INIT3 ; DO NEXT UNIT
|
|
|
|
ASCI_INIT2:
|
|
LD A,66H
|
|
OUT0 (Z180_ASEXT0),A
|
|
LD A,64H
|
|
OUT0 (Z180_CNTLA0),A
|
|
LD A,C
|
|
OUT0 (Z180_CNTLB0),A
|
|
|
|
ASCI_INIT3:
|
|
; ASCI1
|
|
CALL NEWLINE ; FORMATTING
|
|
PRTS("ASCI1: IO=0x$")
|
|
LD A,Z180_TDR1
|
|
CALL PRTHEXBYTE
|
|
CALL PC_COMMA
|
|
LD A,Z180_RDR1
|
|
CALL PRTHEXBYTE
|
|
|
|
CALL PC_SPACE ; FORMATTING
|
|
LD DE,ASCI1CFG ; LOAD CONFIG
|
|
CALL PS_PRTSC0 ; PRINT IT
|
|
|
|
LD HL,ASCI1CFG ; SERIAL CONFIG WORD
|
|
LD A,H ; BYTE W/ ENCODED BAUD RATE
|
|
AND $1F ; ISOLATE BITS
|
|
LD L,A ; MOVE TO L
|
|
LD H,0 ; CLEAR MSB
|
|
CALL ASCI_CNTLB ; DERIVE CNTLB VALUE
|
|
;CALL TSTPT
|
|
JR Z,ASCI_INIT4 ; IMPLEMENT IF NO ERROR
|
|
PRTS(" ERROR!$")
|
|
JR ASCI_INIT5 ; DO NEXT UNIT
|
|
|
|
ASCI_INIT4:
|
|
LD A,66H
|
|
OUT0 (Z180_ASEXT1),A
|
|
LD A,64H
|
|
OUT0 (Z180_CNTLA1),A
|
|
LD A,C
|
|
OUT0 (Z180_CNTLB1),A
|
|
|
|
ASCI_INIT5:
|
|
XOR A
|
|
RET
|
|
;
|
|
; CHARACTER DEVICE DRIVER ENTRY
|
|
;
|
|
ASCI_DISPATCH:
|
|
PUSH IY ; PUSH UNIT DATA WORD
|
|
POP AF ; POP TO AF, A := DEVICE NUM
|
|
OR A ; SET FLAGS
|
|
JP Z,ASCI0
|
|
DEC A
|
|
JP Z,ASCI1
|
|
CALL PANIC
|
|
;
|
|
ASCI0:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JP Z,ASCI0_IN
|
|
DEC A
|
|
JP Z,ASCI0_OUT
|
|
DEC A
|
|
JP Z,ASCI0_IST
|
|
DEC A
|
|
JP Z,ASCI0_OST
|
|
DEC A
|
|
JP Z,ASCI0_INITDEV
|
|
DEC A
|
|
JP Z,ASCI0_QUERY
|
|
DEC A
|
|
JP Z,ASCI0_DEVICE
|
|
CALL PANIC
|
|
;
|
|
;
|
|
;
|
|
ASCI0_IN:
|
|
CALL ASCI0_IST
|
|
OR A
|
|
JR Z,ASCI0_IN
|
|
IN0 A,(Z180_RDR0) ; READ THE CHAR FROM THE ASCI
|
|
LD E,A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI0_IST:
|
|
; CHECK FOR ERROR FLAGS
|
|
IN0 A,(Z180_STAT0)
|
|
AND 70H ; PARITY, FRAMING, OR OVERRUN ERROR
|
|
JR Z,ASCI0_IST1 ; ALL IS WELL, CHECK FOR DATA
|
|
|
|
; CLEAR ERROR(S) OR NOTHING FURTHER CAN BE RECEIVED!!!
|
|
IN0 A,(Z180_CNTLA0)
|
|
RES 3,A ; CLEAR EFR (ERROR FLAG RESET)
|
|
OUT0 (Z180_CNTLA0),A
|
|
|
|
ASCI0_IST1: ; CHECK FOR STAT0.RDRF (DATA READY)
|
|
IN0 A,(Z180_STAT0) ; READ LINE STATUS REGISTER
|
|
AND $80 ; 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
|
|
;
|
|
;
|
|
;
|
|
ASCI0_OUT:
|
|
CALL ASCI0_OST
|
|
OR A
|
|
JR Z,ASCI0_OUT
|
|
LD A,E
|
|
OUT0 (Z180_TDR0),A
|
|
RET
|
|
;
|
|
ASCI0_OST:
|
|
IN0 A,(Z180_STAT0)
|
|
AND $02
|
|
JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN
|
|
XOR A
|
|
INC A ; SIGNAL BUFFER EMPTY, A = 1
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI0_INITDEV:
|
|
XOR A ; NOT IMPLEMENTED!!!
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI0_QUERY:
|
|
LD DE,ASCI0CFG
|
|
;LD DE,ASCI0BAUD >> 16
|
|
;LD HL,ASCI0BAUD & $FFFF
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI0_DEVICE:
|
|
LD D,CIODEV_ASCI ; D := DEVICE TYPE
|
|
LD E,0 ; E := PHYSICAL UNIT
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI1:
|
|
LD A,B ; GET REQUESTED FUNCTION
|
|
AND $0F ; ISOLATE SUB-FUNCTION
|
|
JR Z,ASCI1_IN
|
|
DEC A
|
|
JR Z,ASCI1_OUT
|
|
DEC A
|
|
JR Z,ASCI1_IST
|
|
DEC A
|
|
JR Z,ASCI1_OST
|
|
DEC A
|
|
JP Z,ASCI1_INITDEV
|
|
DEC A
|
|
JP Z,ASCI1_QUERY
|
|
DEC A
|
|
JP Z,ASCI1_DEVICE
|
|
CALL PANIC
|
|
;
|
|
;
|
|
;
|
|
ASCI1_IN:
|
|
CALL ASCI1_IST
|
|
OR A
|
|
JR Z,ASCI1_IN
|
|
IN0 A,(Z180_RDR1) ; READ THE CHAR FROM THE ASCI
|
|
LD E,A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI1_IST:
|
|
; CHECK FOR ERROR FLAGS
|
|
IN0 A,(Z180_STAT1)
|
|
AND 70H ; PARITY, FRAMING, OR OVERRUN ERROR
|
|
JR Z,ASCI1_IST1 ; ALL IS WELL, CHECK FOR DATA
|
|
|
|
; CLEAR ERROR(S) OR NOTHING FURTHER CAN BE RECEIVED!!!
|
|
IN0 A,(Z180_CNTLA1)
|
|
RES 3,A ; CLEAR EFR (ERROR FLAG RESET)
|
|
OUT0 (Z180_CNTLA1),A
|
|
|
|
ASCI1_IST1: ; CHECK FOR STAT0.RDRF (DATA READY)
|
|
IN0 A,(Z180_STAT1) ; READ LINE STATUS REGISTER
|
|
AND $80 ; 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
|
|
;
|
|
;
|
|
;
|
|
ASCI1_OUT:
|
|
CALL ASCI1_OST
|
|
OR A
|
|
JR Z,ASCI1_OUT
|
|
LD A,E
|
|
OUT0 (Z180_TDR1),A
|
|
RET
|
|
;
|
|
ASCI1_OST:
|
|
IN0 A,(Z180_STAT1)
|
|
AND $02
|
|
JR Z,ASCI1_OST
|
|
JP Z,CIO_IDLE ; DO IDLE PROCESSING AND RETURN
|
|
XOR A
|
|
INC A ; SIGNAL BUFFER EMPTY, A = 1
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI1_INITDEV:
|
|
XOR A ; NOT IMPLEMENTED!!!
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI1_QUERY:
|
|
;LD DE,ASCI1BAUD >> 16
|
|
;LD HL,ASCI1BAUD & $FFFF
|
|
LD DE,ASCI1CFG
|
|
XOR A
|
|
RET
|
|
;
|
|
;
|
|
;
|
|
ASCI1_DEVICE:
|
|
LD D,CIODEV_ASCI ; D := DEVICE TYPE
|
|
LD E,1 ; E := PHYSICAL UNIT
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET
|
|
;
|
|
; DERIVE A CNTLB VALUE BASED ON AN ENCODED BAUD RATE AND CURRENT CPU SPEED
|
|
; ENTRY: HL = ENCODED BAUD RATE
|
|
; EXIT: C = CNTLB VALUE, A=0, Z SET INDICATES SUCCESS
|
|
;
|
|
; GIVEN DIVISOR = CLK HZ / BAUD
|
|
; LET LOOKUP = DIVISOR / 160
|
|
; LOOKUP = CLK / BAUD / 160
|
|
; LET KCLK = CLK / 1000, SO CLK = KCLK * 1000
|
|
; LOOKUP = KCLK * 1000 / BAUD / 160
|
|
; OR, LOOKUP = (KCLK / 12) / (BAUD / 75)
|
|
;
|
|
; SO, WE USE (CPUKHZ / 12) / (BAUD RATE / 75) TO GET LOOKUP VALUE
|
|
; THEN LOOKUP THE CORRECT CNTLB0 VALUE
|
|
;
|
|
ASCI_CNTLB:
|
|
LD DE,1 ; USE DECODE CONSTANT OF 1 TO GET BAUD RATE ALREADY DIVIDED BY 75
|
|
CALL DECODE ; DECODE THE BAUDATE INTO DE:HL, DE IS DISCARDED
|
|
RET NZ ; ABORT ON ERROR
|
|
PUSH HL ; HL HAS (BAUD / 75), SAVE IT
|
|
;LD HL,(HCB + HCB_CPUKHZ) ; GET CPU CLK IN KHZ
|
|
LD HL,CPUKHZ ; CPU CLK IN KHZ
|
|
LD DE,12 ; PREPARE TO DIVIDE BY 12
|
|
CALL DIV16 ; BC := (CPU CLK KHZ / 12), REMAINDER IN HL, ZF
|
|
POP DE ; RESTORE DENOMINATOR
|
|
JR NZ,ASCI_CNTLB2 ; ABORT IF REMAINDER
|
|
PUSH BC ; MOVE VALUE
|
|
POP HL ; ... TO HL NUMERATOR
|
|
CALL DIV16 ; BC := LOOKUP VALUE, REMAINDER IN HL, ZF
|
|
JR NZ,ASCI_CNTLB2 ; ABORT IF REMAINDER
|
|
PUSH BC ; MOVE LOOKUP VALUE
|
|
POP DE ; TO DE
|
|
LD B,ASCI_LKUPCNT ; INIT LOOP COUNT
|
|
LD HL,ASCI_LKUP ; POINT TO START OF TABLE
|
|
ASCI_CNTLB0:
|
|
LD A,(HL) ; GET BYTE TO COMPARE
|
|
INC HL ; INCREMENT HL FOR NEXT
|
|
CP E ; COMPARE LSB
|
|
JR NZ,ASCI_CNTLB1 ; NO MATCH, LOOP
|
|
LD A,(HL) ; GET BYTE TO COMPARE
|
|
CP D ; COMPARE MSB
|
|
JR NZ,ASCI_CNTLB1 ; NO MATCH, LOOP
|
|
; MATCH FOUND
|
|
INC HL ; POINT TO CNTLB VALUE
|
|
LD C,(HL) ; LOAD IN C
|
|
XOR A ; SIGNAL SUCCESS
|
|
RET ; AND DONE
|
|
ASCI_CNTLB1:
|
|
INC HL ; BUMP TO
|
|
INC HL ; ... NEXT ENTRY
|
|
DJNZ ASCI_CNTLB0 ; LOOP IF MORE TO CHECK
|
|
ASCI_CNTLB2:
|
|
OR $FF ; NOT FOUND, SET ERROR
|
|
RET ; AND RETURN
|
|
;
|
|
; LOOKUP PS BIT PS DIV DR BIT DR DIV SS BITS SS DIV DIVISOR CNTLB
|
|
; ------ ------ ------ ------ ------ ------- ------ ------- --------
|
|
; 1 0 10 0 16 0 1 160 XX0X0000
|
|
; 2 0 10 0 16 1 2 320 XX0X0001
|
|
; 3 1 30 0 16 0 1 480 XX1X0000
|
|
; 4 0 10 0 16 2 4 640 XX0X0010
|
|
; 6 1 30 0 16 1 2 960 XX1X0001
|
|
; 8 0 10 0 16 3 8 1280 XX0X0011
|
|
; 12 1 30 0 16 2 4 1920 XX1X0010
|
|
; 16 0 10 0 16 4 16 2560 XX0X0100
|
|
; 24 1 30 0 16 3 8 3840 XX1X0011
|
|
; 32 0 10 0 16 5 32 5120 XX0X0101
|
|
; 48 1 30 0 16 4 16 7680 XX1X0100
|
|
; 64 0 10 0 16 6 64 10240 XX0X0110
|
|
; 96 1 30 0 16 5 32 15360 XX1X0101
|
|
; 128 0 10 1 64 5 32 20480 XX0X1101
|
|
; 192 1 30 0 16 6 64 30720 XX1X0110
|
|
; 256 0 10 1 64 6 64 40960 XX0X1110
|
|
; 384 1 30 1 64 5 32 61440 XX1X1101
|
|
; 768 1 30 1 64 6 64 122880 XX1X1110
|
|
;
|
|
ASCI_LKUP: ; LOOKUP CNTLB VAL
|
|
.DW 1 \ .DB %00000000
|
|
.DW 2 \ .DB %00000001
|
|
.DW 3 \ .DB %00100000
|
|
.DW 4 \ .DB %00000010
|
|
.DW 6 \ .DB %00100001
|
|
.DW 8 \ .DB %00000011
|
|
.DW 12 \ .DB %00100010
|
|
.DW 16 \ .DB %00000100
|
|
.DW 24 \ .DB %00100011
|
|
.DW 32 \ .DB %00000101
|
|
.DW 48 \ .DB %00100100
|
|
.DW 64 \ .DB %00000110
|
|
.DW 96 \ .DB %00100101
|
|
.DW 128 \ .DB %00001101
|
|
.DW 192 \ .DB %00100110
|
|
.DW 256 \ .DB %00001110
|
|
.DW 384 \ .DB %00101101
|
|
.DW 768 \ .DB %00101110
|
|
;
|
|
ASCI_LKUPCNT .EQU ($ - ASCI_LKUP) / 3
|