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

;
;==================================================================================================
; 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