@ -40,8 +40,6 @@ ENA_XM .EQU TRUE ; INCLUDE XMODEM IF SPACE AVAILABLE
;
ENA_MBC6502 .EQU FALSE ; ENABLE OR DISABLE MBC6502 OPTION
;
# INCLUDE "util.asm"
;
;__UART_ENTRY_________________________________________________________________
;
; SERIAL MONITOR STARTUP
@ -1846,6 +1844,233 @@ DSKY_ENTRY:
;
# ENDIF
;
;==================================================================================================
; UTILITY FUNCTIONS
;==================================================================================================
;
;
CHR_BEL .EQU 07H
CHR_CR .EQU 0DH
CHR_LF .EQU 0AH
CHR_BS .EQU 08H
CHR_ESC .EQU 1BH
;
;__________________________________________________________________________________________________
;
; UTILITY PROCS TO PRINT SINGLE CHARACTERS WITHOUT TRASHING ANY REGISTERS
;
PC_SPACE:
PUSH AF
LD A , ' '
JR PC_PRTCHR
PC_COLON:
PUSH AF
LD A , ':'
JR PC_PRTCHR
PC_CR:
PUSH AF
LD A , CH R_CR
JR PC_PRTCHR
PC_LF:
PUSH AF
LD A , CH R_LF
JR PC_PRTCHR
PC_PRTCHR:
CALL COUT
POP AF
RET
NEWLINE2:
CALL NEWLINE
NEWLINE:
CALL PC_CR
CALL PC_LF
RET
PRTSTR:
LD A ,( HL )
INC HL
CP '$'
RET Z
CALL COUT
JR PRTSTR
;
; PRINT THE HEX BYTE VALUE IN A
;
PRTHEXBYTE:
PUSH AF
PUSH DE
CALL HEXASCII
LD A , D
CALL COUT
LD A , E
CALL COUT
POP DE
POP AF
RET
;
; CONVERT BINARY VALUE IN A TO ASCII HEX CHARACTERS IN DE
;
HEXASCII:
LD D , A
CALL HEXCONV
LD E , A
LD A , D
RLCA
RLCA
RLCA
RLCA
CALL HEXCONV
LD D , A
RET
;
; CONVERT LOW NIBBLE OF A TO ASCII HEX
;
HEXCONV:
AND 0FH ;LOW NIBBLE ONLY
ADD A , 90H
DAA
ADC A , 40H
DAA
RET
;
; ADD HL,A
;
; A REGISTER IS DESTROYED!
;
ADDHLA:
ADD A , L
LD L , A
RET NC
INC H
RET
;
; DELAY 16US (CPU SPEED COMPENSATED) INCUDING CALL/RET INVOCATION
; REGISTER A AND FLAGS DESTROYED
; NO COMPENSATION FOR Z180 MEMORY WAIT STATES
; THERE IS AN OVERHEAD OF 3TS PER INVOCATION
; IMPACT OF OVERHEAD DIMINISHES AS CPU SPEED INCREASES
;
; CPU SCALER (CPUSCL) = (CPUHMZ - 2) FOR 16US + 3TS DELAY
; NOTE: CPUSCL MUST BE >= 1!
;
; EXAMPLE: 8MHZ CPU (DELAY GOAL IS 16US)
; LOOP = ((6 * 16) - 5) = 91TS
; TOTAL COST = (91 + 40) = 131TS
; ACTUAL DELAY = (131 / 8) = 16.375US
;
; --- TOTAL COST = (LOOP COST + 40) TS -----------------+
DELAY: ; 17TS (FROM INVOKING CALL) |
LD A ,( CPUSCL ) ; 13TS |
; |
DELAY1: ; |
; --- LOOP = ((CPUSCL * 16) - 5) TS ------------+ |
DEC A ; 4TS | |
# IF ( BIOS = = BIOS_WBW ) ; | |
# IF ( CPUFAM = = CPU_Z180 ) ; | |
OR A ; +4TS FOR Z180 | |
# ENDIF ; | |
# ENDIF ; | |
JR NZ , DELAY1 ; 12TS (NZ) / 7TS (Z) | |
; ----------------------------------------------+ |
; |
RET ; 10TS (RETURN) |
;-------------------------------------------------------+
;
; DELAY 16US * DE (CPU SPEED COMPENSATED)
; REGISTER DE, A, AND FLAGS DESTROYED
; NO COMPENSATION FOR Z180 MEMORY WAIT STATES
; THERE IS A 27TS OVERHEAD FOR CALL/RET PER INVOCATION
; IMPACT OF OVERHEAD DIMINISHES AS DE AND/OR CPU SPEED INCREASES
;
; CPU SCALER (CPUSCL) = (CPUHMZ - 2) FOR 16US OUTER LOOP COST
; NOTE: CPUSCL MUST BE > 0!
;
; EXAMPLE: 8MHZ CPU, DE=6250 (DELAY GOAL IS .1 SEC OR 100,000US)
; INNER LOOP = ((16 * 6) - 5) = 91TS
; OUTER LOOP = ((91 + 37) * 6250) = 800,000TS
; ACTUAL DELAY = ((800,000 + 27) / 8) = 100,003US
;
; --- TOTAL COST = (OUTER LOOP + 27) TS ------------------------+
VDELAY: ; 17TS (FROM INVOKING CALL) |
; |
; --- OUTER LOOP = ((INNER LOOP + 37) * DE) TS ---------+ |
LD A ,( CPUSCL ) ; 13TS | |
; | |
VDELAY1: ; | |
; --- INNER LOOP = ((CPUSCL * 16) - 5) TS ------+ | |
# IF ( BIOS = = BIOS_WBW ) ; | | |
# IF ( CPUFAM = = CPU_Z180 ) ; | | |
OR A ; +4TS FOR Z180 | | |
# ENDIF ; | | |
# ENDIF ; | | |
DEC A ; 4TS | | |
JR NZ , VDELAY1 ; 12TS (NZ) / 7TS (Z) | | |
; ----------------------------------------------+ | |
; | |
DEC DE ; 6TS | |
# IF ( BIOS = = BIOS_WBW ) ; | | |
# IF ( CPUFAM = = CPU_Z180 ) ; | |
OR A ; +4TS FOR Z180 | |
# ENDIF ; | |
# ENDIF ; | |
LD A , D ; 4TS | |
OR E ; 4TS | |
JP NZ , VDELAY ; 10TS | |
;-------------------------------------------------------+ |
; |
RET ; 10TS (FINAL RETURN) |
;---------------------------------------------------------------+
;
; DELAY ABOUT 0.5 SECONDS
; 500000US / 16US = 31250
;
LDELAY:
PUSH AF
PUSH DE
LD DE , 31250
CALL VDELAY
POP DE
POP AF
RET
;
; INITIALIZE DELAY SCALER BASED ON OPERATING CPU SPEED
; ENTER WITH A = CPU SPEED IN MHZ
;
DELAY_INIT:
CP 3 ; TEST FOR <= 2 (SPECIAL HANDLING)
JR C , DELAY_INIT1 ; IF <= 2, SPECIAL PROCESSING
SUB 2 ; ADJUST AS REQUIRED BY DELAY FUNCTIONS
JR DELAY_INIT2 ; AND CONTINUE
DELAY_INIT1:
LD A , 1 ; USE THE MIN VALUE OF 1
DELAY_INIT2:
LD ( CPUSCL ), A ; UPDATE CPU SCALER VALUE
RET
# IF ( CPUMHZ < 3 )
CPU SCL .DB 1 ; CPU SCALER MUST BE > 0
# ELSE
CPU SCL .DB CPUMHZ - 2 ; OTHERWISE 2 LESS THAN PHI MHZ
# ENDIF
;
; SHORT DELAY FUNCTIONS. NO CLOCK SPEED COMPENSATION, SO THEY
; WILL RUN LONGER ON SLOWER SYSTEMS. THE NUMBER INDICATES THE
; NUMBER OF CALL/RET INVOCATIONS. A SINGLE CALL/RET IS
; 27 T-STATES ON A Z80, 25 T-STATES ON A Z180
;
; ; Z80 Z180
; ; ---- ----
DLY64: CALL DL Y32 ; 1728 1600
DLY32: CALL DL Y16 ; 864 800
DLY16: CALL DL Y8 ; 432 400
DLY8: CALL DL Y4 ; 216 200
DLY4: CALL DL Y2 ; 108 100
DLY2: CALL DL Y1 ; 54 50
DLY1: RET ; 27 25
;
;
;
.FILL 16 , 0 ; SET MINIMUM STACK DEPTH
SLACK .EQU ( MON_END - $ )