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.
 
 
 
 
 
 

452 lines
12 KiB

;
;==================================================================================================
; ASCI DRIVER (Z180 SERIAL PORTS)
;==================================================================================================
;
; SETUP PARAMETER WORD:
; +-------+---+-------------------+ +---+---+-----------+---+-------+
; | |RTS| ENCODED BAUD RATE | |DTR|XON| PARITY |STP| 8/7/6 |
; +-------+---+---+---------------+ ----+---+-----------+---+-------+
; F E D C B A 9 8 7 6 5 4 3 2 1 0
; -- MSB (D REGISTER) -- -- LSB (E REGISTER) --
;
; 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_PREINIT:
;
; SETUP THE DISPATCH TABLE ENTRIES
;
LD B,2 ; ALWAYS 2 ASCI UNITS ON Z180
LD C,0 ; PHYSICAL UNIT INDEX
ASCI_PREINIT1:
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_PREINIT1 ; LOOP UNTIL DONE
;
LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG
CALL ASCI0_INITDEV ; INIT DEVICE
;
LD DE,-1 ; DE := -1 TO INIT DEFAULT CONFIG
CALL ASCI1_INITDEV ; INIT DEVICE
;
XOR A ; SIGNAL SUCCESS
RET
;
;
;
ASCI_INIT:
;
; ASCI0
CALL NEWLINE ; FORMATTING
PRTS("ASCI0: IO=0x$") ; PREFIX
LD A,Z180_TDR0 ; LOAD TDR PORT ADDRESS
CALL PRTHEXBYTE ; PRINT IT
CALL PC_COMMA ; FORMATTING
LD A,Z180_RDR0 ; LOAD RDR PORT ADDRESS
CALL PRTHEXBYTE ; PRINT IT
CALL PC_SPACE ; FORMATTING
LD DE,(ASCI0_CONFIG) ; LOAD CONFIG
CALL PS_PRTSC0 ; PRINT IT
;
; ASCI1
CALL NEWLINE ; FORMATTING
PRTS("ASCI1: IO=0x$") ; PREFIX
LD A,Z180_TDR1 ; LOAD TDR PORT ADDRESS
CALL PRTHEXBYTE ; PRINT IT
CALL PC_COMMA ; FORMATTING
LD A,Z180_RDR1 ; LOAD RDR PORT ADDRESS
CALL PRTHEXBYTE ; PRINT IT
CALL PC_SPACE ; FORMATTING
LD DE,(ASCI1_CONFIG) ; LOAD CONFIG
CALL PS_PRTSC0 ; PRINT IT
;
XOR A
RET
;
; DISPATCH TO SPECIFIC ASCI UNIT
;
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
;
; ASCI 0 FUNCTIONS
;
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
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:
; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT)
LD A,D ; TEST DE FOR
AND E ; ... VALUE OF -1
INC A ; ... SO Z SET IF -1
JR NZ,ASCI0_INITDEV1 ; IF NEW CONFIG (NOT -1), IMPLEMENT IT
LD DE,(ASCI0_CONFIG) ; OTHERWISE, LOAD EXISTING CONFIG
;
ASCI0_INITDEV1:
; DETERMINE APPROPRIATE CNTLB VALUE (BASED ON BAUDRATE & CPU SPEED)
LD A,D ; BYTE W/ ENCODED BAUD RATE
AND $1F ; ISOLATE BITS
LD L,A ; MOVE TO L
LD H,0 ; CLEAR MSB
PUSH DE ; SAVE CONFIG
CALL ASCI_CNTLB ; DERIVE CNTLB VALUE
POP DE ; RESTORE CONFIG
;CALL TSTPT
RET NZ ; ABORT ON ERROR
LD (ASCI0_CONFIG),DE ; RECORD UPDATED CONFIG
;
; IMPLEMENT CONFIGURATION
LD A,66H ; LOAD DEFAULT ASEXT VALUE
OUT0 (Z180_ASEXT0),A ; SET IT
LD A,64H ; LOAD DEFAULT CNTLA VALUE
OUT0 (Z180_CNTLA0),A ; SET IT
LD A,C ; LOAD CNTLB VALUE DETERMINED ABOVE
OUT0 (Z180_CNTLB0),A ; SET IT
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
ASCI0_QUERY:
LD DE,(ASCI0_CONFIG)
XOR A
RET
;
ASCI0_DEVICE:
LD D,CIODEV_ASCI ; D := DEVICE TYPE
LD E,0 ; E := PHYSICAL UNIT
XOR A ; SIGNAL SUCCESS
RET
;
; ASCI 1 FUNCTIONS
;
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
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:
; TEST FOR -1 WHICH MEANS USE CURRENT CONFIG (JUST REINIT)
LD A,D ; TEST DE FOR
AND E ; ... VALUE OF -1
INC A ; ... SO Z SET IF -1
JR NZ,ASCI1_INITDEV1 ; IF NEW CONFIG (NOT -1), IMPLEMENT IT
LD DE,(ASCI1_CONFIG) ; OTHERWISE, LOAD EXISTING CONFIG
;
ASCI1_INITDEV1:
; DETERMINE APPROPRIATE CNTLB VALUE (BASED ON BAUDRATE & CPU SPEED)
LD A,D ; BYTE W/ ENCODED BAUD RATE
AND $1F ; ISOLATE BITS
LD L,A ; MOVE TO L
LD H,0 ; CLEAR MSB
PUSH DE ; SAVE CONFIG
CALL ASCI_CNTLB ; DERIVE CNTLB VALUE
POP DE ; RESTORE CONFIG
;CALL TSTPT
RET NZ ; ABORT ON ERROR
LD (ASCI1_CONFIG),DE ; RECORD UPDATED CONFIG
;
; IMPLEMENT CONFIGURATION
LD A,66H ; LOAD DEFAULT ASEXT VALUE
OUT0 (Z180_ASEXT1),A ; SET IT
LD A,64H ; LOAD DEFAULT CNTLA VALUE
OUT0 (Z180_CNTLA1),A ; SET IT
LD A,C ; LOAD CNTLB VALUE DETERMINED ABOVE
OUT0 (Z180_CNTLB1),A ; SET IT
;
XOR A ; SIGNAL SUCCESS
RET ; DONE
;
ASCI1_QUERY:
LD DE,(ASCI1_CONFIG)
XOR A
RET
;
ASCI1_DEVICE:
LD D,CIODEV_ASCI ; D := DEVICE TYPE
LD E,1 ; E := PHYSICAL UNIT
XOR A ; SIGNAL SUCCESS
RET
;
; LOCAL DATA
;
ASCI0_CONFIG .DW DEFSERCFG ; SAVED CONFIG FOR ASCI0
ASCI1_CONFIG .DW DEFSERCFG ; SAVED CONFIG FOR ASCI1
;
; 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 IFF SUCCESS
;
; DESIRED DIVISOR == CPUHZ / BAUD
; DUE TO ENCODING BAUD IS ALWAYS DIVISIBLE BY 75
; Z180 DIVISOR IS ALWAYS A FACTOR OF 160
;
; X = CPU_HZ / 160 / 75 ==> SIMPLIFIED ==> X = CPU_KHZ / 12
; X = X / (BAUD / 75)
; IF X % 3 == 0, THEN (PS=1, X := X / 3) ELSE PS=0
; IF X % 4 == 0, THEN (DR=1, X := X / 4) ELSE DR=0
; SS := LOG2(X)
;
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
;CALL TSTPT
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 HL,9216 ; *DEBUG*
; DUE TO THE LIMITED DIVISORS POSSIBLE WITH CNTLB, YOU PRETTY MUCH
; NEED TO USE A CPU SPEED THAT IS A MULTIPLE OF 128KHZ. BELOW, WE
; ATTEMPT TO ROUND THE CPU SPEED DETECTED TO A MULTIPLE OF 128KHZ
; WITH ROUNDING. THIS JUST MAXIMIZES POSSIBILITY OF SUCCESS COMPUTING
; THE DIVISOR.
LD DE,$0040 ; HALF OF 128 IS 64
ADD HL,DE ; ADD FOR ROUNDING
LD A,L ; MOVE TO ACCUM
AND $80 ; STRIP LOW ORDER 7 BITS
LD L,A ; ... AND PUT IT BACK
LD DE,12 ; PREPARE TO DIVIDE BY 12
CALL DIV16 ; BC := (CPU_KHZ / 12), REM IN HL, ZF
;CALL TSTPT
POP DE ; RESTORE (BAUD / 75)
RET NZ ; ABORT IF REMAINDER
PUSH BC ; MOVE WORKING VALUE
POP HL ; ... BACK TO HL
CALL DIV16 ; BC := X / (BAUD / 75)
;CALL TSTPT
RET NZ ; ABORT IF REMAINDER
;
; DETERMINE PS BIT BY ATTEMPTING DIVIDE BY 3
PUSH BC ; SAVE WORKING VALUE ON STACK
PUSH BC ; MOVE WORKING VALUE
POP HL ; ... TO HL
LD DE,3 ; SETUP TO DIVIDE BY 3
CALL DIV16 ; BC := X / 3, REM IN HL, ZF
;CALL TSTPT
POP HL ; HL := PRIOR WORKING VALUE
LD E,0 ; INIT E := 0 AS WORKING CNTLB VALUE
JR NZ,ASCI_CNTLB1 ; DID NOT WORK, LEAVE PS==0, SKIP AHEAD
SET 5,E ; SET PS BIT
PUSH BC ; MOVE NEW WORKING
POP HL ; ... VALUE TO HL
;
ASCI_CNTLB1:
;CALL TSTPT
; DETERMINE DR BIT BY ATTEMPTING DIVIDE BY 4
LD A,L ; LOAD LSB OF WORKING VALUE
AND $03 ; ISOLATE LOW ORDER BITS
JR NZ,ASCI_CNTLB2 ; NOT DIVISIBLE BY 4, SKIP AHEAD
SET 3,E ; SET PS BIT
SRL H ; DIVIDE HL BY 4
RR L ; ...
SRL H ; ...
RR L ; ...
;
ASCI_CNTLB2:
;CALL TSTPT
; DETERMINE SS BITS BY RIGHT SHIFTING AND INCREMENTING
LD B,7 ; LOOP COUNTER, MAX VALUE OF SS IS 7
LD C,E ; MOVE WORKING CNTLB VALUE TO C
ASCI_CNTLB3:
BIT 0,L ; CAN WE SHIFT AGAIN?
JR NZ,ASCI_CNTLB4 ; NOPE, DONE
SRL H ; IMPLEMENT THE
RR L ; ... SHIFT OPERATION
INC C ; INCREMENT SS BITS
DJNZ ASCI_CNTLB3 ; LOOP IF MORE SHIFTING POSSIBLE
;
; AT THIS POINT HL MUST BE EQUAL TO 1 OR WE FAILED!
DEC HL ; IF HL == 1, SHOULD BECOME ZERO
LD A,H ; TEST HL
OR L ; ... FOR ZERO
RET NZ ; ABORT IF NOT ZERO
;
ASCI_CNTLB4:
;CALL TSTPT
XOR A
RET
;