|
|
|
@ -1,9 +1,10 @@ |
|
|
|
;=============================================================================== |
|
|
|
; TIMER - Display system timer value |
|
|
|
; |
|
|
|
; Version 1.21 30-June-2024 |
|
|
|
;=============================================================================== |
|
|
|
; |
|
|
|
; Author: Wayne Warthen (wwarthen@gmail.com) |
|
|
|
; Updated: MartinR (June 2024) |
|
|
|
;_______________________________________________________________________________ |
|
|
|
; |
|
|
|
; Usage: |
|
|
|
@ -14,38 +15,58 @@ |
|
|
|
; |
|
|
|
; Operation: |
|
|
|
; Reads and displays system timer value. |
|
|
|
; |
|
|
|
; This code will only execute on a Z80 CPU (or derivitive) |
|
|
|
; |
|
|
|
; This source code assembles with TASM V3.2 under Windows-11 using the |
|
|
|
; following command line: |
|
|
|
; tasm -80 -g3 -l TIMER.ASM TIMER.COM |
|
|
|
; ie: Z80 CPU; output format 'binary' named .COM (rather than .OBJ) |
|
|
|
; and includes a symbol table as part of the listing file. |
|
|
|
;_______________________________________________________________________________ |
|
|
|
; |
|
|
|
; Change Log: |
|
|
|
; 2018-01-14 [WBW] Initial release |
|
|
|
; 2018-01-17 [WBW] Add HBIOS check |
|
|
|
; 2019-11-08 [WBW] Add seconds support |
|
|
|
; 2024-06-30 [MR ] Display values in decimal rather than hexadecimal |
|
|
|
;_______________________________________________________________________________ |
|
|
|
; |
|
|
|
; Includes binary-to-decimal subroutine by Alwin Henseler |
|
|
|
; Located at: https://www.msx.org/forum/development/msx-development/32-bit-long-ascii |
|
|
|
;_______________________________________________________________________________ |
|
|
|
; |
|
|
|
; ToDo: |
|
|
|
; Display the elapsed time in HH:MM:SS |
|
|
|
;_______________________________________________________________________________ |
|
|
|
; |
|
|
|
#include "../ver.inc" |
|
|
|
#include "../ver.inc" ; Used for building RomWBW |
|
|
|
;#include "ver.inc" ; Used for testing purposes during code development |
|
|
|
; |
|
|
|
;=============================================================================== |
|
|
|
; Definitions |
|
|
|
;=============================================================================== |
|
|
|
; |
|
|
|
stksiz .equ $40 ; Working stack size |
|
|
|
; |
|
|
|
restart .equ $0000 ; CP/M restart vector |
|
|
|
bdos .equ $0005 ; BDOS invocation vector |
|
|
|
; |
|
|
|
ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr |
|
|
|
stksiz .equ $80 ; Working stack size (was $40) |
|
|
|
; |
|
|
|
restart .equ $0000 ; CP/M restart vector |
|
|
|
bdos .equ $0005 ; BDOS invocation vector |
|
|
|
; |
|
|
|
ident .equ $FFFE ; loc of RomWBW HBIOS ident ptr |
|
|
|
; |
|
|
|
bf_sysver .equ $F1 ; BIOS: VER function |
|
|
|
bf_sysget .equ $F8 ; HBIOS: SYSGET function |
|
|
|
bf_sysset .equ $F9 ; HBIOS: SYSGET function |
|
|
|
bf_sysset .equ $F9 ; HBIOS: SYSSET function |
|
|
|
bf_sysgettimer .equ $D0 ; TIMER subfunction |
|
|
|
bf_syssettimer .equ $D0 ; TIMER subfunction |
|
|
|
bf_sysgetsecs .equ $D1 ; SECONDS subfunction |
|
|
|
bf_syssetsecs .equ $D1 ; SECONDS subfunction |
|
|
|
; |
|
|
|
; ASCII Control Characters |
|
|
|
; |
|
|
|
lf .equ $0A ; Line Feed |
|
|
|
cr .equ $0D ; Carriage Return |
|
|
|
; |
|
|
|
;=============================================================================== |
|
|
|
; Code Section |
|
|
|
;=============================================================================== |
|
|
|
@ -73,17 +94,17 @@ exit: ; clean up and return to command processor |
|
|
|
; Initialization |
|
|
|
; |
|
|
|
init: |
|
|
|
call crlf ; formatting |
|
|
|
ld de,msgban ; point to version message part 1 |
|
|
|
call prtstr ; print it |
|
|
|
; |
|
|
|
call idbio ; identify active BIOS |
|
|
|
cp 1 ; check for HBIOS |
|
|
|
jp nz,errbio ; handle BIOS error |
|
|
|
; |
|
|
|
call crlf ; formatting |
|
|
|
ld de,msgban ; point to version message part 1 |
|
|
|
call prtstr ; print it |
|
|
|
; |
|
|
|
call idbio ; identify active BIOS |
|
|
|
cp 1 ; check for HBIOS |
|
|
|
jp nz,errbio ; handle BIOS error |
|
|
|
; |
|
|
|
ld a,rmj << 4 | rmn ; expected HBIOS ver |
|
|
|
cp d ; compare with result above |
|
|
|
jp nz,errbio ; handle BIOS error |
|
|
|
cp d ; compare with result above |
|
|
|
jp nz,errbio ; handle BIOS error |
|
|
|
; |
|
|
|
initx |
|
|
|
; initialization complete |
|
|
|
@ -120,9 +141,9 @@ process0: |
|
|
|
call crlf2 ; formatting |
|
|
|
; |
|
|
|
process1: |
|
|
|
ld b,bf_sysget ; HBIOS SYSGET function |
|
|
|
ld b,bf_sysget ; HBIOS SYSGET function |
|
|
|
ld c,bf_sysgettimer ; TIMER subfunction |
|
|
|
rst 08 ; call HBIOS, DE:HL := timer value |
|
|
|
rst 08 ; call HBIOS, DE:HL := timer value |
|
|
|
|
|
|
|
ld a,(first) |
|
|
|
or a |
|
|
|
@ -135,28 +156,50 @@ process1: |
|
|
|
cp l ; compare to current LSB |
|
|
|
jr z,process2 ; if equal, bypass display |
|
|
|
|
|
|
|
process1a: |
|
|
|
;******************************************************************************* |
|
|
|
|
|
|
|
; Code added/amended to print values in decimal |
|
|
|
; MartinR June2024 |
|
|
|
|
|
|
|
process1a: |
|
|
|
; save and print new value |
|
|
|
ld a,l ; new LSB value to A |
|
|
|
ld (last),a ; save as last value |
|
|
|
call prtcr ; back to start of line |
|
|
|
;call nz,prthex32 ; display it |
|
|
|
call prthex32 ; display it |
|
|
|
ld de,strtick ; tag |
|
|
|
call prtstr ; display it |
|
|
|
ld a,l ; new LSB value to A |
|
|
|
ld (last),a ; save as last value |
|
|
|
call prtcr ; back to start of line |
|
|
|
|
|
|
|
call b2d32 ; Convert DE:HL into ASCII; Start of ASCII buffer returned in HL |
|
|
|
ex de,hl |
|
|
|
call prtstr ; Display the value |
|
|
|
|
|
|
|
ld de,strtick ; "Ticks" message |
|
|
|
call prtstr ; Display it |
|
|
|
|
|
|
|
; get and print seconds value |
|
|
|
ld b,bf_sysget ; HBIOS SYSGET function |
|
|
|
ld c,bf_sysgetsecs ; SECONDS subfunction |
|
|
|
rst 08 ; call HBIOS, DE:HL := seconds value |
|
|
|
call prthex32 ; display it |
|
|
|
ld a,'.' ; fraction separator |
|
|
|
call prtchr ; print it |
|
|
|
ld a,c ; get fractional component |
|
|
|
call prthex ; print it |
|
|
|
ld de,strsec ; tag |
|
|
|
call prtstr ; display it |
|
|
|
; |
|
|
|
ld b,bf_sysget ; HBIOS SYSGET function |
|
|
|
ld c,bf_sysgetsecs ; SECONDS subfunction |
|
|
|
rst 08 ; Call HBIOS; DE:HL := seconds value; C := fractional part |
|
|
|
push bc ; Preserve the fractional part on the stack |
|
|
|
|
|
|
|
call b2d32 ; Convert DE:HL into ASCII; Start of ASCII buffer returned in HL |
|
|
|
ex de,hl |
|
|
|
call prtstr ; Display the value |
|
|
|
|
|
|
|
ld a,'.' ; Fraction separator, ie decimal point |
|
|
|
call prtchr ; Print it |
|
|
|
|
|
|
|
pop bc ; Retrieve fractional part into A |
|
|
|
ld a,c |
|
|
|
sla a ; Double the 50Hz 'ticks' value to give 1/100s of a second |
|
|
|
|
|
|
|
call b2d8 ; Convert into ASCII - up to 3 digits |
|
|
|
ex de,hl ; Start of ASCII buffer returned in HL |
|
|
|
call prtstr ; Display fractional part of the value |
|
|
|
|
|
|
|
ld de,strsec ; "Seconds" message |
|
|
|
call prtstr ; Display it |
|
|
|
|
|
|
|
;******************************************************************************* |
|
|
|
|
|
|
|
process2: |
|
|
|
ld a,(cont) ; continuous display? |
|
|
|
or a ; test for true/false |
|
|
|
@ -269,9 +312,9 @@ prtdot: |
|
|
|
; |
|
|
|
prtcr: |
|
|
|
; |
|
|
|
; shortcut to print a dot preserving all regs |
|
|
|
; shortcut to print carriage return preserving all regs |
|
|
|
push af ; save af |
|
|
|
ld a,13 ; load CR value |
|
|
|
ld a,cr ; load CR value |
|
|
|
call prtchr ; print it |
|
|
|
pop af ; restore af |
|
|
|
ret ; done |
|
|
|
@ -477,6 +520,124 @@ err2: ; without the string |
|
|
|
or $FF ; signal error |
|
|
|
ret ; done |
|
|
|
; |
|
|
|
; |
|
|
|
;=============================================================================== |
|
|
|
; Subroutine to print decimal numbers |
|
|
|
;=============================================================================== |
|
|
|
; |
|
|
|
; Combined routine for conversion of different sized binary numbers into |
|
|
|
; directly printable ASCII(Z)-string |
|
|
|
; Input value in registers, number size and -related to that- registers to fill |
|
|
|
; is selected by calling the correct entry: |
|
|
|
; |
|
|
|
; entry input decimal value 0 to: |
|
|
|
; b2d8 A 255 (3 digits) |
|
|
|
; b2d16 HL 65535 5 " |
|
|
|
; b2d24 E:HL 16777215 8 " |
|
|
|
; b2d32 DE:HL 4294967295 10 " |
|
|
|
; b2d48 BC:DE:HL 281474976710655 15 " |
|
|
|
; b2d64 IX:BC:DE:HL 18446744073709551615 20 " |
|
|
|
; |
|
|
|
; The resulting string is placed into a small buffer attached to this routine, |
|
|
|
; this buffer needs no initialization and can be modified as desired. |
|
|
|
; The number is aligned to the right, and leading 0's are replaced with spaces. |
|
|
|
; On exit HL points to the first digit, (B)C = number of decimals |
|
|
|
; This way any re-alignment / postprocessing is made easy. |
|
|
|
; Changes: AF,BC,DE,HL,IX |
|
|
|
; |
|
|
|
; by Alwin Henseler |
|
|
|
; https://msx.org/forum/topic/who-who/dutch-hardware-guy-pops-back-sort |
|
|
|
; |
|
|
|
; Found at: |
|
|
|
; https://www.msx.org/forum/development/msx-development/32-bit-long-ascii |
|
|
|
; |
|
|
|
; Tweaked to assemble using TASM 3.2 by MartinR 23June2024 |
|
|
|
; |
|
|
|
b2d8: ld h,0 |
|
|
|
ld l,a |
|
|
|
b2d16: ld e,0 |
|
|
|
b2d24: ld d,0 |
|
|
|
b2d32: ld bc,0 |
|
|
|
b2d48: ld ix,0 ; zero all non-used bits |
|
|
|
b2d64: ld (b2dinv),hl |
|
|
|
ld (b2dinv+2),de |
|
|
|
ld (b2dinv+4),bc |
|
|
|
ld (b2dinv+6),ix ; place full 64-bit input value in buffer |
|
|
|
ld hl,b2dbuf |
|
|
|
ld de,b2dbuf+1 |
|
|
|
ld (hl),' ' |
|
|
|
b2dfilc:.equ $-1 ; address of fill-character |
|
|
|
ld bc,18 |
|
|
|
ldir ; fill 1st 19 bytes of buffer with spaces |
|
|
|
ld (b2dend-1),bc ; set BCD value to "0" & place terminating 0 |
|
|
|
ld e,1 ; no. of bytes in BCD value |
|
|
|
ld hl,b2dinv+8 ; (address MSB input)+1 |
|
|
|
ld bc,$0909 |
|
|
|
xor a |
|
|
|
b2dskp0:dec b |
|
|
|
jr z,b2dsiz ; all 0: continue with postprocessing |
|
|
|
dec hl |
|
|
|
or (hl) ; find first byte <> 0 |
|
|
|
jr z,b2dskp0 |
|
|
|
b2dfnd1:dec c |
|
|
|
rla |
|
|
|
jr nc,b2dfnd1 ; determine no. of most significant 1-bit |
|
|
|
rra |
|
|
|
ld d,a ; byte from binary input value |
|
|
|
b2dlus2:push hl |
|
|
|
push bc |
|
|
|
b2dlus1:ld hl,b2dend-1 ; address LSB of bcd value |
|
|
|
ld b,e ; current length of BCD value in bytes |
|
|
|
rl d ; highest bit from input value -> carry |
|
|
|
b2dlus0:ld a,(hl) |
|
|
|
adc a,a |
|
|
|
daa |
|
|
|
ld (hl),a ; double 1 BCD byte from intermediate result |
|
|
|
dec hl |
|
|
|
djnz b2dlus0 ; and go on to double entire BCD value (+carry!) |
|
|
|
jr nc,b2dnxt |
|
|
|
inc e ; carry at MSB -> BCD value grew 1 byte larger |
|
|
|
ld (hl),1 ; initialize new MSB of BCD value |
|
|
|
b2dnxt: dec c |
|
|
|
jr nz,b2dlus1 ; repeat for remaining bits from 1 input byte |
|
|
|
pop bc ; no. of remaining bytes in input value |
|
|
|
ld c,8 ; reset bit-counter |
|
|
|
pop hl ; pointer to byte from input value |
|
|
|
dec hl |
|
|
|
ld d,(hl) ; get next group of 8 bits |
|
|
|
djnz b2dlus2 ; and repeat until last byte from input value |
|
|
|
b2dsiz: ld hl,b2dend ; address of terminating 0 |
|
|
|
ld c,e ; size of bcd value in bytes |
|
|
|
or a |
|
|
|
sbc hl,bc ; calculate address of MSB BCD |
|
|
|
ld d,h |
|
|
|
ld e,l |
|
|
|
sbc hl,bc |
|
|
|
ex de,hl ; HL=address BCD value, de=start of decimal value |
|
|
|
ld b,c ; no. of bytes BCD |
|
|
|
sla c ; no. of bytes decimal (possibly 1 too high) |
|
|
|
ld a,'0' |
|
|
|
rld ; shift bits 4-7 of (HL) into bit 0-3 of A |
|
|
|
cp '0' ; (HL) was > 9h? |
|
|
|
jr nz,b2dexph ; if yes, start with recording high digit |
|
|
|
dec c ; correct number of decimals |
|
|
|
inc de ; correct start address |
|
|
|
jr b2dexpl ; continue with converting low digit |
|
|
|
b2dexp: rld ; shift high digit (HL) into low digit of a |
|
|
|
b2dexph:ld (de),a ; record resulting ascii-code |
|
|
|
inc de |
|
|
|
b2dexpl:rld |
|
|
|
ld (de),a |
|
|
|
inc de |
|
|
|
inc hl ; next BCD-byte |
|
|
|
djnz b2dexp ; and go on to convert each BCD-byte into 2 ASCII |
|
|
|
sbc hl,bc ; return with HL pointing to 1st decimal |
|
|
|
ret |
|
|
|
|
|
|
|
b2dinv .fill 8 ; space for 64-bit input value (LSB first) |
|
|
|
b2dbuf .fill 20 ; space for 20 decimal digits |
|
|
|
b2dend .db 0 ; space for terminating character |
|
|
|
; |
|
|
|
;=============================================================================== |
|
|
|
; Storage Section |
|
|
|
;=============================================================================== |
|
|
|
@ -487,20 +648,21 @@ first .db $FF ; first pass flag (true at start) |
|
|
|
; |
|
|
|
stksav .dw 0 ; stack pointer saved at start |
|
|
|
.fill stksiz,0 ; stack |
|
|
|
stack .equ $ ; stack top |
|
|
|
stack .equ $ ; new stack top |
|
|
|
; |
|
|
|
; Messages |
|
|
|
; |
|
|
|
msgban .db "TIMER v1.1, 10-Nov-2019",13,10 |
|
|
|
.db "Copyright (C) 2019, Wayne Warthen, GNU GPL v3",0 |
|
|
|
msguse .db "Usage: TIMER [/C] [/?]",13,10 |
|
|
|
.db " ex. TIMER (display current timer value)",13,10 |
|
|
|
.db " TIMER /? (display version and usage)",13,10 |
|
|
|
msgban .db "TIMER v1.21, 30-Jun-2024",cr,lf |
|
|
|
.db "Copyright (C) 2019, Wayne Warthen, GNU GPL v3",cr,lf |
|
|
|
.db "Updated by MartinR 2024",0 |
|
|
|
msguse .db "Usage: TIMER [/C] [/?]",cr,lf |
|
|
|
.db " ex. TIMER (display current timer value)",cr,lf |
|
|
|
.db " TIMER /? (display version and usage)",cr,lf |
|
|
|
.db " TIMER /C (display timer value continuously)",0 |
|
|
|
msgprm .db "Parameter error (TIMER /? for usage)",0 |
|
|
|
msgbio .db "Incompatible BIOS or version, " |
|
|
|
.db "HBIOS v", '0' + rmj, ".", '0' + rmn, " required",0 |
|
|
|
strtick .db " Ticks, ",0 |
|
|
|
strsec .db " Seconds",0 |
|
|
|
strtick .db " Ticks ",0 |
|
|
|
strsec .db " Seconds ",0 |
|
|
|
; |
|
|
|
.end |
|
|
|
.end |
|
|
|
|