diff --git a/Source/HBIOS/Config/plt_mk4.asm b/Source/HBIOS/Config/plt_mk4.asm
index 061f509b..58ee3bff 100644
--- a/Source/HBIOS/Config/plt_mk4.asm
+++ b/Source/HBIOS/Config/plt_mk4.asm
@@ -7,7 +7,6 @@
;
CPUOSC .EQU 18432000 ; CPU OSC FREQ
RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!!
-CONBAUD .EQU 38400 ; CONSOLE BAUDRATE AT STARTUP
DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE)
;
CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP
@@ -32,8 +31,8 @@ UART3IOB .EQU $D8 ; IOBASE (4UART PORT D)
UART3CFG .EQU DEFSERCFG ; CONFIG (BAUDRATE, DATA BITS, PARITY, STOP BITS, ETC.)
;
ASCIENABLE .EQU TRUE ; TRUE FOR Z180 ASCI SUPPORT
-ASCI0BAUD .EQU CONBAUD ; ASCI0 BAUDRATE (IMPLEMENTED BY Z180_ASCIB0)
-ASCI1BAUD .EQU CONBAUD ; ASCI1 BAUDRATE (IMPLEMENTED BY Z180_ASCIB1)
+ASCI0CFG .EQU DEFSERCFG ; CONFIG (BAUDRATE, DATA BITS, PARITY, STOP BITS, ETC.)
+ASCI1CFG .EQU DEFSERCFG ; CONFIG (BAUDRATE, DATA BITS, PARITY, STOP BITS, ETC.)
;
VDUENABLE .EQU FALSE ; TRUE FOR VDU BOARD SUPPORT
CVDUENABLE .EQU FALSE ; TRUE FOR CVDU BOARD SUPPORT
@@ -95,18 +94,14 @@ BOOTTYPE .EQU BT_MENU ; BT_MENU (WAIT FOR KEYPRESS), BT_AUTO (BOOT_DEFAULT AFTE
BOOT_TIMEOUT .EQU 20 ; APPROX TIMEOUT IN SECONDS FOR AUTOBOOT, 0 FOR IMMEDIATE
BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT
;
-; 18.432MHz OSC @ FULL SPEED, 38.4Kbps
+; 18.432MHz OSC @ FULL SPEED
;
Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .EQU 0 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .EQU 0 ; IO WAIT STATES TO INSERT (0-3)
-Z180_ASCIB0 .EQU 20H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT
-Z180_ASCIB1 .EQU 20H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT
;
-; 18.432MHz OSC @ DOUBLE SPEED, 38.4Kbps
+; 18.432MHz OSC @ DOUBLE SPEED
;
;Z180_CLKDIV .EQU 2 ; 0=OSC/2, 1=OSC, 2=OSC*2
;Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3)
;Z180_IOWAIT .EQU 1 ; IO WAIT STATES TO INSERT (0-3)
-;Z180_ASCIB0 .EQU 21H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT
-;Z180_ASCIB1 .EQU 21H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT
diff --git a/Source/HBIOS/Config/plt_n8.asm b/Source/HBIOS/Config/plt_n8.asm
index b76ddf02..f8b10ce2 100644
--- a/Source/HBIOS/Config/plt_n8.asm
+++ b/Source/HBIOS/Config/plt_n8.asm
@@ -7,7 +7,6 @@
;
CPUOSC .EQU 18432000 ; CPU OSC FREQ
RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!!
-CONBAUD .EQU 38400 ; CONSOLE BAUDRATE AT STARTUP
DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE)
;
CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP
@@ -23,8 +22,8 @@ UARTENABLE .EQU FALSE ; TRUE FOR UART SUPPORT (N8 USES ASCI DRIVER)
UARTCNT .EQU 0 ; NUMBER OF UARTS
;
ASCIENABLE .EQU TRUE ; TRUE FOR Z180 ASCI SUPPORT
-ASCI0BAUD .EQU CONBAUD ; ASCI0 BAUDRATE (IMPLEMENTED BY Z180_ASCIB0)
-ASCI1BAUD .EQU CONBAUD ; ASCI1 BAUDRATE (IMPLEMENTED BY Z180_ASCIB1)
+ASCI0CFG .EQU DEFSERCFG ; CONFIG (BAUDRATE, DATA BITS, PARITY, STOP BITS, ETC.)
+ASCI1CFG .EQU DEFSERCFG ; CONFIG (BAUDRATE, DATA BITS, PARITY, STOP BITS, ETC.)
;
VDUENABLE .EQU FALSE ; TRUE FOR VDU BOARD SUPPORT
CVDUENABLE .EQU FALSE ; TRUE FOR CVDU BOARD SUPPORT
@@ -82,8 +81,6 @@ BOOTTYPE .EQU BT_MENU ; BT_MENU (WAIT FOR KEYPRESS), BT_AUTO (BOOT_DEFAULT AFTE
BOOT_TIMEOUT .EQU 20 ; APPROX TIMEOUT IN SECONDS FOR AUTOBOOT, 0 FOR IMMEDIATE
BOOT_DEFAULT .EQU 'Z' ; SELECTION TO INVOKE AT TIMEOUT
;
-Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC/1
+Z180_CLKDIV .EQU 1 ; 0=OSC/2, 1=OSC, 2=OSC*2
Z180_MEMWAIT .EQU 1 ; MEMORY WAIT STATES TO INSERT (0-3)
Z180_IOWAIT .EQU 3 ; IO WAIT STATES TO INSERT (0-3)
-Z180_ASCIB0 .EQU 20H ; SERIAL PORT 0 DIV, SEE Z180 CLOCKING DOCUMENT
-Z180_ASCIB1 .EQU 20H ; SERIAL PORT 1 DIV, SEE Z180 CLOCKING DOCUMENT
diff --git a/Source/HBIOS/Config/plt_sbc.asm b/Source/HBIOS/Config/plt_sbc.asm
index a2eda248..8bce0e8a 100644
--- a/Source/HBIOS/Config/plt_sbc.asm
+++ b/Source/HBIOS/Config/plt_sbc.asm
@@ -7,7 +7,6 @@
;
CPUOSC .EQU 8000000 ; CPU OSC FREQ
RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!!
-CONBAUD .EQU 38400 ; CONSOLE BAUDRATE AT STARTUP
DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE)
;
CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP
diff --git a/Source/HBIOS/Config/plt_zeta.asm b/Source/HBIOS/Config/plt_zeta.asm
index 3329903d..cdaf4163 100644
--- a/Source/HBIOS/Config/plt_zeta.asm
+++ b/Source/HBIOS/Config/plt_zeta.asm
@@ -7,7 +7,6 @@
;
CPUOSC .EQU 20000000 ; CPU OSC FREQ
RAMSIZE .EQU 512 ; SIZE OF RAM IN KB, MUST MATCH YOUR HARDWARE!!!
-CONBAUD .EQU 38400 ; CONSOLE BAUDRATE AT STARTUP
DEFSERCFG .EQU SER_38400_8N1 ; DEFAULT SERIAL LINE CONFIG (SHOULD MATCH ABOVE)
;
CRTACT .EQU FALSE ; CRT ACTIVATION AT STARTUP
diff --git a/Source/HBIOS/asci.asm b/Source/HBIOS/asci.asm
index 0ff45d6d..00b4c101 100644
--- a/Source/HBIOS/asci.asm
+++ b/Source/HBIOS/asci.asm
@@ -3,74 +3,38 @@
; ASCI DRIVER (Z180 SERIAL PORTS)
;==================================================================================================
;
-; BAUD RATE PROGRAMMING:
-; Given a known clock speed (PHI) and target Baud Rate (BAUD):
-;
-; Divisor = PHI / BAUD
-;
-; Program PS, DR, SS bits based on divisor table lookup
-;
-; Divisor = PHI / BAUD
-; Lookup = PHI / BAUD / 160
-;
-; To allow easier computation:
-;
-; Let xPHI = PHI / 1000 (PHI is always divisible by 1000)
-; Let xBAUD = BAUD / 100 (BAUD is always divisible by 100)
-; xPHI will always fit in 2 byte int
-; xBAUD will always fit in 2 byte int
-;
-; Lookup = (xPHI >> 4) / xBAUD
-;
-; If failure to match, fallback to 9600 baud and try again
-;
-; 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
-;
-; CNTLB0/1:
+; 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)
@@ -79,25 +43,35 @@ ASCI_LKUPCNT .EQU ($ - ASCI_LKUP) / 3
; | +-------------- 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_INIT0:
- PUSH BC ; SAVE LOOP CONTROL
- LD D,C ; PHYSICAL UNIT
- LD E,CIODEV_ASCI ; DEVICE TYPE
+ 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_INIT0 ; LOOP UNTIL DONE
+ 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
@@ -108,23 +82,31 @@ ASCI_INIT0:
CALL PC_COMMA
LD A,Z180_RDR0
CALL PRTHEXBYTE
- PRTS(" BAUD=$")
-
- LD DE,ASCI0BAUD >> 16 ; SET DE:HL TO
- LD HL,ASCI0BAUD & $FFFF ; ... BAUD RATE
- LD BC,HB_BCDTMP ; POINT TO TEMP BCD
- CALL BIN2BCD ; CONVERT TO BCD
- CALL PRTBCD ; AND PRINT IT
-#IF (PLATFORM != PLT_MK4)
+ 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,Z180_ASCIB0
+ LD A,C
OUT0 (Z180_CNTLB0),A
-#ENDIF
-;
+
+ASCI_INIT3:
; ASCI1
CALL NEWLINE ; FORMATTING
PRTS("ASCI1: IO=0x$")
@@ -133,22 +115,32 @@ ASCI_INIT0:
CALL PC_COMMA
LD A,Z180_RDR1
CALL PRTHEXBYTE
- PRTS(" BAUD=$")
- LD DE,ASCI0BAUD >> 16 ; SET DE:HL TO
- LD HL,ASCI0BAUD & $FFFF ; ... BAUD RATE
- LD BC,HB_BCDTMP ; POINT TO TEMP BCD
- CALL BIN2BCD ; CONVERT TO BCD
- CALL PRTBCD ; AND PRINT IT
+
+ 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
-#IF (PLATFORM != PLT_MK4)
+ASCI_INIT4:
LD A,66H
OUT0 (Z180_ASEXT1),A
LD A,64H
OUT0 (Z180_CNTLA1),A
- LD A,Z180_ASCIB1
+ LD A,C
OUT0 (Z180_CNTLB1),A
-#ENDIF
+ASCI_INIT5:
+ XOR A
RET
;
; CHARACTER DEVICE DRIVER ENTRY
@@ -238,8 +230,9 @@ ASCI0_INITDEV:
;
;
ASCI0_QUERY:
- LD DE,ASCI0BAUD >> 16
- LD HL,ASCI0BAUD & $FFFF
+ LD DE,ASCI0CFG
+ ;LD DE,ASCI0BAUD >> 16
+ ;LD HL,ASCI0BAUD & $FFFF
XOR A
RET
;
@@ -330,8 +323,9 @@ ASCI1_INITDEV:
;
;
ASCI1_QUERY:
- LD DE,ASCI1BAUD >> 16
- LD HL,ASCI1BAUD & $FFFF
+ ;LD DE,ASCI1BAUD >> 16
+ ;LD HL,ASCI1BAUD & $FFFF
+ LD DE,ASCI1CFG
XOR A
RET
;
@@ -342,3 +336,100 @@ ASCI1_DEVICE:
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
\ No newline at end of file
diff --git a/Source/HBIOS/decode.asm b/Source/HBIOS/decode.asm
new file mode 100644
index 00000000..15ea319d
--- /dev/null
+++ b/Source/HBIOS/decode.asm
@@ -0,0 +1,79 @@
+;
+;==================================================================================================
+; DECODE 32-BIT VALUES FROM A 5-BIT SHIFT-ENCODED VALUE
+;==================================================================================================
+;
+; Copyright (C) 2014 John R. Coffman. All rights reserved.
+; Provided for hobbyist use on the Z180 SBC Mark IV board.
+;
+; This program is free software: you can redistribute it and/or modify
+; it under the terms of the GNU General Public License as published by
+; the Free Software Foundation, either version 3 of the License, or
+; (at your option) any later version.
+;
+; This program is distributed in the hope that it will be useful,
+; but WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+; GNU General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program. If not, see .
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; THE FUNCTION(S) IN THIS FILE ARE BASED ON LIKE FUNCTIONS CREATED BY JOHN COFFMAN
+; IN HIS UNA BIOS PROJECT. THEY ARE INCLUDED HERE BASED ON GPLV3 PERMISSIBLE USE.
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+; An encoded value (V) is defined as V = C * 2^X * 3^Y
+; where C is a prearranged constant, X is 0 or 1 and Y is 0-15
+; The encoded value is stored as 5 bits: YXXXX
+; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding
+;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; DECODE
+;
+; Enter with:
+; HL = word to be decoded (5-bits) FXXXX
+; F=extra 3 factor, XXXX=shift factor, reg H must be zero
+; DE = encode divisor OSC_DIV = 3, or BAUD_DIV = 75
+;
+; Exit with:
+; DE:HL = decoded value
+; A = non-zero on error
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;
+DECODE:
+ LD A,H ; SET TO TEST
+ LD C,$FF ; PRESUME ERROR CONDITION
+ OR A ; TEST FOR ZERO
+ JR NZ,DECODE9 ; NOT AN ENCODED VALUE
+ LD A,L ; GET LOW ORDER 5 BITS
+ CP 32 ; TEST FOR ERROR
+ JR NC,DECODE9 ; ERROR RETURN IF NOT BELOW
+ ; ARGUMENT HL IS VALIDATED
+ LD H,D
+ LD L,E ; COPY TO HL
+ CP 16
+ JR C,DECODE2 ; IF < 16, NO 3 FACTOR
+ ADD HL,DE ; INTRODUCE FACTOR OF 3
+ ADD HL,DE ; **
+DECODE2:
+ LD DE,0 ; ZERO THE HIGH ORDER
+ AND 15 ; MASK TO 4 BITS
+ JR Z,DECODE8 ; GOOD EXIT
+ LD C,B ; SAVE B-REG
+ LD B,A ;
+DECODE3:
+ ADD HL,HL ; SHIFT LEFT BY 1, SET CARRY
+ RL E
+ RL D ; **
+ DJNZ DECODE3
+ LD B,C ; RESTORE B-REG
+DECODE8:
+ LD C,0 ; SIGNAL GOOD RETURN
+DECODE9:
+ LD A,C ; ERROR CODE TEST
+ OR A ; ERROR CODE IN REG-C AND Z-FLAG
+ RET
diff --git a/Source/HBIOS/encode.asm b/Source/HBIOS/encode.asm
index b8100921..4ef49a04 100644
--- a/Source/HBIOS/encode.asm
+++ b/Source/HBIOS/encode.asm
@@ -1,74 +1,14 @@
;
;==================================================================================================
-; FUNCTIONS TO ENCODE/DECODE 32-BIT VALUES TO/FROM A 5-BIT SHIFT-ENCODED VALUE
+; ENCODE 32-BIT VALUES TO A 5-BIT SHIFT-ENCODED VALUE
;==================================================================================================
;
-; THE FUNCTIONS IN THIS FILE ARE BASED ON LIKE FUNCTIONS CREATED BY JOHN COFFMAN
-; IN HIS UNA BIOS PROJECT. THEY ARE INCLUDED HERE BASED ON GPLV3 PERMISSIBLE USE.
-;
-; Copyright (C) 2014 John R. Coffman. All rights reserved.
-; Provided for hobbyist use on the Z180 SBC Mark IV board.
-;
-; This program is free software: you can redistribute it and/or modify
-; it under the terms of the GNU General Public License as published by
-; the Free Software Foundation, either version 3 of the License, or
-; (at your option) any later version.
-;
-; This program is distributed in the hope that it will be useful,
-; but WITHOUT ANY WARRANTY; without even the implied warranty of
-; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-; GNU General Public License for more details.
-;
-; You should have received a copy of the GNU General Public License
-; along with this program. If not, see .
-;
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-; DECODE
-;
-; Enter with:
-; HL = word to be decoded (5-bits) FXXXX
-; F=extra 3 factor, XXXX=shift factor, reg H must be zero
-; DE = encode divisor OSC_DIV = 3, or BAUD_DIV = 75
-;
-; Exit with:
-; DE:HL = decoded value
-; A = non-zero on error
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
-DECODE:
- LD A,H ; SET TO TEST
- LD C,$FF ; PRESUME ERROR CONDITION
- OR A ; TEST FOR ZERO
- JR NZ,DECODE9 ; NOT AN ENCODED VALUE
- LD A,L ; GET LOW ORDER 5 BITS
- CP 32 ; TEST FOR ERROR
- JR NC,DECODE9 ; ERROR RETURN IF NOT BELOW
- ; ARGUMENT HL IS VALIDATED
- LD H,D
- LD L,E ; COPY TO HL
- CP 16
- JR C,DECODE2 ; IF < 16, NO 3 FACTOR
- ADD HL,DE ; INTRODUCE FACTOR OF 3
- ADD HL,DE ; **
-DECODE2:
- LD DE,0 ; ZERO THE HIGH ORDER
- AND 15 ; MASK TO 4 BITS
- JR Z,DECODE8 ; GOOD EXIT
- LD C,B ; SAVE B-REG
- LD B,A ;
-DECODE3:
- ADD HL,HL ; SHIFT LEFT BY 1, SET CARRY
- RL E
- RL D ; **
- DJNZ DECODE3
- LD B,C ; RESTORE B-REG
-DECODE8:
- LD C,0 ; SIGNAL GOOD RETURN
-DECODE9:
- LD A,C ; ERROR CODE TEST
- OR A ; ERROR CODE IN REG-C AND Z-FLAG
- RET
+; An encoded value (V) is defined as V = C * 2^X * 3^Y
+; where C is a prearranged constant, X is 0 or 1 and Y is 0-15
+; The encoded value is stored as 5 bits: YXXXX
+; At present, C=75 for baud rate encoding and C=3 for CPU OSC encoding
;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ENCODE
diff --git a/Source/HBIOS/hbios.asm b/Source/HBIOS/hbios.asm
index 14c73dff..43554068 100644
--- a/Source/HBIOS/hbios.asm
+++ b/Source/HBIOS/hbios.asm
@@ -1773,7 +1773,7 @@ SIZ_TERM .EQU $ - ORG_TERM
#INCLUDE "util.asm"
#INCLUDE "time.asm"
#INCLUDE "bcd.asm"
-#INCLUDE "encode.asm"
+#INCLUDE "decode.asm"
#INCLUDE "xio.asm"
;
#IF (DSKYENABLE)
@@ -2263,6 +2263,7 @@ PS_PRTSC:
INC A ; SET Z IF DE == $FF
JP Z,PS_PRTNUL ; $FF == NO CONFIG DEFINED
;
+PS_PRTSC0:
; PRINT BAUD RATE
PUSH DE ; PRESERVE DE
LD A,D
diff --git a/Source/HBIOS/loader.asm b/Source/HBIOS/loader.asm
index c7a766e6..8e6889f1 100644
--- a/Source/HBIOS/loader.asm
+++ b/Source/HBIOS/loader.asm
@@ -163,6 +163,7 @@ STR_BOOT .DB "RomWBW$"
; IMBED DIRECT SERIAL I/O ROUTINES
;
#INCLUDE "xio.asm"
+#INCLUDE "decode.asm"
;
;______________________________________________________________________________________________________________________
;
diff --git a/Source/HBIOS/std.asm b/Source/HBIOS/std.asm
index 977b73e7..4b51aab8 100644
--- a/Source/HBIOS/std.asm
+++ b/Source/HBIOS/std.asm
@@ -121,6 +121,9 @@ SER_PARSPACE .EQU 7 << 3
SER_STOP1 .EQU 0 << 2
SER_STOP2 .EQU 1 << 2
;
+; SEREIAL BAUD RATES ENCODED AS V = 75 * 2^X * 3^Y
+; AND STORED AS 5 BITS: YXXXX
+;
SER_BAUD300 .EQU $02 << 8
SER_BAUD600 .EQU $03 << 8
SER_BAUD1200 .EQU $04 << 8
@@ -131,6 +134,8 @@ SER_BAUD19200 .EQU $08 << 8
SER_BAUD38400 .EQU $09 << 8
SER_BAUD76800 .EQU $0A << 8
SER_BAUD115200 .EQU $19 << 8
+SER_BAUD230400 .EQU $1A << 8
+SER_BAUD460800 .EQU $1B << 8
;
SER_XON .EQU 1 << 6
SER_DTR .EQU 1 << 7
@@ -146,9 +151,8 @@ SER_19200_8N1 .EQU SER_BAUD19200 | SER_DATA8 | SER_PARNONE | SER_STOP1
SER_38400_8N1 .EQU SER_BAUD38400 | SER_DATA8 | SER_PARNONE | SER_STOP1
SER_76800_8N1 .EQU SER_BAUD76800 | SER_DATA8 | SER_PARNONE | SER_STOP1
SER_115200_8N1 .EQU SER_BAUD115200 | SER_DATA8 | SER_PARNONE | SER_STOP1
-;
-;UF_FIFO .EQU $01 ; BIT 0 IS FIFO ENABLE
-;UF_AFC .EQU $02 ; BIT 1 IS AUTO FLOW CONTROL ENABLE
+SER_230400_8N1 .EQU SER_BAUD230400 | SER_DATA8 | SER_PARNONE | SER_STOP1
+SER_460800_8N1 .EQU SER_BAUD460800 | SER_DATA8 | SER_PARNONE | SER_STOP1
;
#INCLUDE "build.inc" ; INCLUDE USER CONFIG, ADD VARIANT, TIMESTAMP, & ROMSIZE
;
diff --git a/Source/HBIOS/uart.asm b/Source/HBIOS/uart.asm
index 93a009f0..685cd4a8 100644
--- a/Source/HBIOS/uart.asm
+++ b/Source/HBIOS/uart.asm
@@ -210,7 +210,7 @@ UART_INITDEV:
LD A,D
AND E
INC A
- JR Z,UART_INITDEV1 ; IF DE == -1, BYPASS UPDATE
+ JR Z,UART_INITDEV1 ; IF DE == -1, REINIT CURRENT CONFIG
;
; UDPATE CONFIG BYTES
LD (IY + 4),E ; SAVE LOW WORD
@@ -218,6 +218,8 @@ UART_INITDEV:
;
UART_INITDEV1:
; START OF UART INITIALIZATION, SET BAUD RATE
+ LD E,(IY + 4) ; GET LOW WORD
+ LD D,(IY + 5) ; GET HI WORD
CALL UART_COMPDIV ; COMPUTE DIVISOR TO BC
LD A,80H ; DLAB IS BIT 7 OF LCR
UART_OUTP(UART_LCR) ; DLAB ON
@@ -253,7 +255,7 @@ UART_INITDEV1:
JR UART_INITDEV3 ; NO EFT, SKIP AHEAD
;
UART_INITDEV2:
- ; WE HAVE AN EFR CAPABLE CHIP, SET AUTOFLOW
+ ; WE HAVE AN EFR CAPABLE CHIP, SET AUTOFLOW IN EFR REGISTER
UART_INP(UART_LCR) ; GET CURRENT LCR VALUE
PUSH AF ; SAVE IT
LD A,$BF ; VALUE TO ACCESS EFR
@@ -441,7 +443,7 @@ UART_COMPDIV:
; FIRST WE DECODE THE BAUDRATE, BUT WE USE A CONSTANT OF 1 INSTEAD
; OF THE NORMAL 75. THIS PRODUCES (BAUDRATE / 75).
;
- LD A,(IY + 5) ; GET SECOND CONFIG BYTE
+ LD A,D ; GET CONFIG MSB
AND $1F ; ISOLATE ENCODED BAUD RATE
LD L,A ; PUT IN L
LD H,0 ; H IS ALWAYS ZERO
@@ -479,47 +481,11 @@ UART_PRTCFG:
OR A ; SET FLAGS
RET Z ; IF ZERO, NOT PRESENT
;
- ; PRINT BAUD RATE
- CALL PC_SPACE
- LD A,(IY + 5) ; GET SECOND CONFIG BYTE
- AND $1F ; ISOLATE ENCODED BAUD RATE
- LD L,A ; PUT IN L
- LD H,0 ; H IS ALWAYS ZERO
- LD DE,75 ; BAUD RATE DECODE CONSTANT
- CALL DECODE ; DE:HL := BAUD RATE
- LD BC,HB_BCDTMP ; POINT TO TEMP BCD BUF
- CALL BIN2BCD ; CONVERT TO BCD
- CALL PRTBCD ; AND PRINT IN DECIMAL
-;
- ; PRINT DATA BITS
- CALL PC_COMMA ; FORMATTING
- LD A,(IY + 4) ; GET CONFIG BYTE
- AND $03 ; ISOLATE DATA BITS VALUE
- ADD A,'5' ; CONVERT TO CHARACTER
- CALL COUT ; AND PRINT
-;
- ; PRINT PARITY
- CALL PC_COMMA ; FORMATTING
- LD A,(IY + 4) ; GET CONFIG BYTE
- RLCA ; SHIFT RELEVANT BITS
- RLCA ; ...
- RLCA ; ...
- AND $07 ; AND ISOLATE DATA BITS VALUE
- LD HL,UART_PAR_MAP ; CHARACTER LOOKUP TABLE
- CALL ADDHLA ; APPLY OFFSET
- LD A,(HL) ; GET CHARACTER
- CALL COUT ; AND PRINT
-;
- ; PRINT STOP BITS
- CALL PC_COMMA ; FORMATTING
- LD A,(IY + 4) ; GET CONFIG BYTE
- RLCA ; SHIFT RELEVANT BITS
- RLCA ; ...
- AND $01 ; AND ISOLATE DATA BITS VALUE
- ADD A,'1' ; MAKE IT A CHARACTER
- CALL COUT ; AND PRINT
+ CALL PC_SPACE ; FORMATTING
+ LD E,(IY + 4) ; LOAD CONFIG
+ LD D,(IY + 5) ; ... WORD TO DE
+ CALL PS_PRTSC0 ; PRINT CONFIG
;
-;;
; ; PRINT FEATURES ENABLED
; LD A,(UART_FEAT)
; BIT UART_FIFO,A
diff --git a/Source/HBIOS/util.asm b/Source/HBIOS/util.asm
index 0cdd76ef..284969a9 100644
--- a/Source/HBIOS/util.asm
+++ b/Source/HBIOS/util.asm
@@ -693,37 +693,30 @@ MULT8X16_2:
; RET
;===============================================================
;
-; COMPUTE HL / DE = BC W/ REMAINDER IN HL
+; COMPUTE HL / DE = BC W/ REMAINDER IN HL & ZF
;
DIV16:
- ; HL -> AC
- LD A,H
- LD C,L
-
- ; SETUP
- LD HL,0
- LD B,16
-;
+ LD A,H ; HL -> AC
+ LD C,L ; ...
+ LD HL,0 ; INIT HL
+ LD B,16 ; INIT LOOP COUNT
DIV16A:
- ; LOOP
-; .DB $CB,$31 ; SLL C
- SLA C
- SET 0,C
- RLA
- ADC HL,HL
- SBC HL,DE
- JR NC,DIV16B
- ADD HL,DE
- DEC C
-DIV16B:
- DJNZ DIV16A
-
- ; AC -> BC
- LD B,A
-
- RET
-;
-; INTEGER DIVIDES DE:HL BY C
+ SCF
+ RL C
+ RLA
+ ADC HL,HL
+ SBC HL,DE
+ JR NC,DIV16B
+ ADD HL,DE
+ DEC C
+DIV16B:
+ DJNZ DIV16A ; LOOP AS NEEDED
+ LD B,A ; AC -> BC
+ LD A,H ; SET ZF
+ OR L ; ... BASED ON REMAINDER
+ RET ; DONE
+;
+; INTEGER DIVIDE DE:HL BY C
; RESULT IN DE:HL, REMAINDER IN A
; CLOBBERS F, B
;
diff --git a/Source/HBIOS/xio.asm b/Source/HBIOS/xio.asm
index 74e91e9e..c410cb38 100644
--- a/Source/HBIOS/xio.asm
+++ b/Source/HBIOS/xio.asm
@@ -23,7 +23,7 @@ SIO_DLL .EQU UART0IOB + 0 ; DLAB=1: DIVISOR LATCH (LS)
SIO_DLM .EQU UART0IOB + 1 ; DLAB=1: DIVISOR LATCH (MS)
;
#ENDIF
-;
+
XIO_INIT: ; MINIMAL UART INIT
#IF (PLATFORM == PLT_UNA)
@@ -32,25 +32,41 @@ XIO_INIT: ; MINIMAL UART INIT
#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4))
- ; ASCI0
- LD A,66H
- OUT0 (Z180_ASEXT0),A
- LD A,64H
- OUT0 (Z180_CNTLA0),A
- LD A,Z180_ASCIB0
- OUT0 (Z180_CNTLB0),A
+ ; INIT ASCI0 WITH BASIC VALUES AND FAILSAFE DIVISOR
+ LD A,$66 ; IGNORE CTS/DCD, NO BREAK DETECT
+ OUT0 (Z180_ASEXT0),A ; -> ASEXT0
+ LD A,$64 ; ENABLE XMT/RCV, 8 DATA, NO PARITY, 1 STOP
+ OUT0 (Z180_CNTLA0),A ; -> CNTLA0
+ LD A,$22 ; FAILSAFE VALUE, 9600 BAUD AT 18.432 MHZ
+ OUT0 (Z180_CNTLB0),A ; -> CNTLB0
+ ; TRY TO IMPLEMENT CONFIGURED BAUD RATE
+ 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 XIO_CNTLB ; DERIVE CNTLB VALUE
+ JR NZ,XIO_INIT1 ; BYPASS ON FAILURE
+ LD A,C ; PUT INT C
+ OUT0 (Z180_CNTLB0),A ; AND SET THE VALUE
+
#ENDIF
#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2))
-XIO_DIV .EQU (UARTOSC / (16 * CONBAUD))
+;XIO_DIV .EQU (UARTOSC / (16 * CONBAUD))
+
+ LD DE,UART0CFG ; SERIAL CONFIG WORD
+ CALL XIO_COMPDIV ; COMPUTE DIVISOR TO BC
LD A,$80 ; LCR := DLAB ON
OUT (SIO_LCR),A ; SET LCR
- LD A,XIO_DIV % $100 ; BAUD RATE DIVISOR (LSB)
+ ;LD A,XIO_DIV % $100 ; BAUD RATE DIVISOR (LSB)
+ LD A,C ; LOW BYTE OF DIVISOR
OUT (SIO_DLL),A ; SET DIVISOR (LSB)
- LD A,XIO_DIV / $100 ; BAUD RATE DIVISOR (MSB)
+ ;LD A,XIO_DIV / $100 ; BAUD RATE DIVISOR (MSB)
+ LD A,B ; HIGH BYTE OF DIVISOR
OUT (SIO_DLM),A ; SET DIVISOR (MSB)
LD A,03H ; VALUE FOR LCR AND MCR
OUT (SIO_LCR),A ; LCR := 3, DLAB OFF, 8 DATA, 1 STOP, NO PARITY
@@ -60,6 +76,7 @@ XIO_DIV .EQU (UARTOSC / (16 * CONBAUD))
#ENDIF
+XIO_INIT1:
RET
;
XIO_CRLF: ; OUTPUT A NEWLINE
@@ -115,3 +132,157 @@ XIO_OUTS: ; OUTPUT '$' TERMINATED STRING AT ADDRESS IN HL
CALL XIO_OUTC ; OTHERWISE, WRITE IT
INC HL ; POINT TO NEXT BYTE
JR XIO_OUTS ; AND LOOP
+
+#IF ((PLATFORM == PLT_SBC) | (PLATFORM == PLT_ZETA) | (PLATFORM == PLT_ZETA2))
+;
+; COMPUTE DIVISOR TO BC
+;
+XIO_COMPDIV:
+ ; WE WANT TO DETERMINE A DIVISOR FOR THE UART CLOCK
+ ; THAT RESULTS IN THE DESIRED BAUD RATE.
+ ; BAUD RATE = UART CLK / DIVISOR, OR TO SOLVE FOR DIVISOR
+ ; DIVISOR = UART CLK / BAUDRATE.
+ ; THE UART CLOCK IS THE UART OSC PRESCALED BY 16. ALSO, WE CAN
+ ; TAKE ADVANTAGE OF ENCODED BAUD RATES ALWAYS BEING A FACTOR OF 75.
+ ; SO, WE CAN USE (UART OSC / 16 / 75) / (BAUDRATE / 75)
+;
+ ; FIRST WE DECODE THE BAUDRATE, BUT WE USE A CONSTANT OF 1 INSTEAD
+ ; OF THE NORMAL 75. THIS PRODUCES (BAUDRATE / 75).
+;
+ LD A,D ; GET CONFIG MSB
+ AND $1F ; ISOLATE ENCODED BAUD RATE
+ LD L,A ; PUT IN L
+ LD H,0 ; H IS ALWAYS ZERO
+ LD DE,1 ; USE 1 FOR ENCODING CONSTANT
+ CALL DECODE ; DE:HL := BAUD RATE, ERRORS IGNORED
+ EX DE,HL ; DE := (BAUDRATE / 75), DISCARD HL
+ LD HL,UARTOSC / 16 / 75 ; HL := (UART OSC / 16 / 75)
+ JP XIO_DIV16 ; BC := HL/DE == DIVISOR AND RETURN
+;
+#ENDIF
+;
+; COMPUTE HL / DE = BC W/ REMAINDER IN HL & ZF
+;
+XIO_DIV16:
+ LD A,H ; HL -> AC
+ LD C,L ; ...
+ LD HL,0 ; INIT HL
+ LD B,16 ; INIT LOOP COUNT
+XIO_DIV16A:
+ SCF
+ RL C
+ RLA
+ ADC HL,HL
+ SBC HL,DE
+ JR NC,XIO_DIV16B
+ ADD HL,DE
+ DEC C
+XIO_DIV16B:
+ DJNZ XIO_DIV16A ; LOOP AS NEEDED
+ LD B,A ; AC -> BC
+ LD A,H ; SET ZF
+ OR L ; ... BASED ON REMAINDER
+ RET ; DONE
+;
+;
+;
+#IF ((PLATFORM == PLT_N8) | (PLATFORM == PLT_MK4))
+;
+; 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
+;
+XIO_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 XIO_DIV16 ; BC := (CPU CLK KHZ / 12), REMAINDER IN HL, ZF
+ POP DE ; RESTORE DENOMINATOR
+ JR NZ,XIO_CNTLB2 ; ABORT IF REMAINDER
+ PUSH BC ; MOVE VALUE
+ POP HL ; ... TO HL NUMERATOR
+ CALL XIO_DIV16 ; BC := LOOKUP VALUE, REMAINDER IN HL, ZF
+ JR NZ,XIO_CNTLB2 ; ABORT IF REMAINDER
+ PUSH BC ; MOVE LOOKUP VALUE
+ POP DE ; TO DE
+ LD B,XIO_LKUPCNT ; INIT LOOP COUNT
+ LD HL,XIO_LKUP ; POINT TO START OF TABLE
+XIO_CNTLB0:
+ LD A,(HL) ; GET BYTE TO COMPARE
+ INC HL ; INCREMENT HL FOR NEXT
+ CP E ; COMPARE LSB
+ JR NZ,XIO_CNTLB1 ; NO MATCH, LOOP
+ LD A,(HL) ; GET BYTE TO COMPARE
+ CP D ; COMPARE MSB
+ JR NZ,XIO_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
+XIO_CNTLB1:
+ INC HL ; BUMP TO
+ INC HL ; ... NEXT ENTRY
+ DJNZ XIO_CNTLB0 ; LOOP IF MORE TO CHECK
+XIO_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
+;
+XIO_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
+;
+XIO_LKUPCNT .EQU ($ - XIO_LKUP) / 3
+;
+#ENDIF