home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast2.iso
/
ddjmag
/
ddj9209.zip
/
HRT.ASC
< prev
next >
Wrap
Text File
|
1992-08-10
|
5KB
|
176 lines
_HIGH-RESOLUTION TIMING_
by Thomas Roden
[LISTING ONE]
; hrtime.asm - Hi Resolution TIMEr for dos. Copyright (c) 1991 Thomas A. Roden
; All Rights Reserved (with one exception). The right to freely distribute this
; source and any executable code it creates is granted, provided that this
; copyright notice is included in the source. It is requested that the author's
; name (Thomas A. Roden) be included in the acknowledgements of any product
; including this code, but this request is in no way legally binding.
IO_DELAY_NEEDED equ 0 ; doesn't seem to need recovery time here
PRVT_TICKS_USED equ 1 ; if a private tick count is to be used
IRET_IF_RESTORE equ 0 ; if the flag is to be restored with an IRET,
; or with the windows suggested method
; io_delay - delay just a bit
io_delay macro
if IO_DELAY_NEEDED
jmp short $+2
endif ; IO_DELAY_NEEDED
endm
PIC0_ADDR equ 020h ; I/O address of PIC 0
TIMER0 equ 040h ; I/O address of Timer 0
TIMER_STAT equ 043h ; I/O address for status/control of timers 0-2
PIC_RIRR equ 00Ah ; Read Interrupt Request Register of a PIC
T0_R_S_C equ 0C2h ; Timer 0 Read Status and Count
DOS_GLOBALS equ 040h ; segment for 40:xx variables
SYS_TIMER_CNT equ 06Ch ; offset for system count
.model large
.code
assume ds:nothing, es:nothing
if PRVT_TICKS_USED
hrt_ticks dd 0
old_int8 dd 0
; hrt_isr - interrupt routine for private tick counting for hi-res timer
public _hrt_isr
_hrt_isr proc far
add word ptr cs:[hrt_ticks], 1
adc word ptr cs:[hrt_ticks+2], 0
jmp dword ptr cs:[old_int8]
_hrt_isr endp
endif ; PRVT_TICKS_USED
; hrt_open - the init function for the hi-res timer
public _hrt_open
_hrt_open proc far
push ds ; save this stuff to avoid bad crashes
push es ; save this stuff just to be paranoid
push bx
push cx
push dx
if PRVT_TICKS_USED
xor ax, ax
mov word ptr cs:[hrt_ticks], ax
mov word ptr cs:[hrt_ticks+2], ax
mov ax, 03508h ; get int vector for int8 (irq0)
int 21h
mov word ptr cs:[old_int8], bx
mov ax, es
mov word ptr cs:[old_int8+2], ax
mov dx, seg _hrt_isr
mov ds, dx
mov dx, offset _hrt_isr
mov ax, 02508h ; set int vector for int8 (irq0)
int 21h
endif ; PRVT_TICKS_USED
pop dx
pop cx
pop bx
pop es
pop ds
xor ax, ax
ret
_hrt_open endp
; hrt_close - the un-init function for the hi-res timer
public _hrt_close
_hrt_close proc far
push ds ; save this stuff to avoid bad crashes
push es ; save this stuff just to be paranoid
push bx
push cx
push dx
if PRVT_TICKS_USED
mov dx, word ptr cs:[old_int8+2]
mov ds, dx
mov dx, word ptr cs:[old_int8]
mov ax, 02508h ; set int vector for int8 (irq0)
int 21h
endif ; PRVT_TICKS_USED
pop dx
pop cx
pop bx
pop es
pop ds
xor ax, ax
ret
_hrt_close endp
; hrtime - the hi-res time reader
public _hrtime
_hrtime proc far
if IRET_IF_RESTORE
pop bx ; return ip - to make iret return frame
pop ax ; return cs
pushf ; flags
push ax ; cs
push bx ; ip
else ; IRET_IF_RESTORE
pushf ; store flags on stack to check at end
endif ; IRET_IF_RESTORE
cli ; freeze ticker while checking
hrt_readhw:
mov al, T0_R_S_C ; timer 0 read stat and count
out TIMER_STAT, al
io_delay
in al, TIMER0 ; store stat in ch
mov ch, al
io_delay
in al, TIMER0 ; store count in bx
mov bl, al
io_delay
in al, TIMER0
mov bh, al
io_delay ; delay between timer and pic access
mov al, PIC_RIRR
out PIC0_ADDR, al
io_delay
in al, PIC0_ADDR
test al, 001h ; check if system time is stale
jz short hrt_timegood
mov ax, 0ffffh ; force max in lower part
jmp short hrt_gotlo
hrt_timegood:
test ch, 040h
jnz short hrt_readhw ; timer invalid, retry
mov ax, bx ; move count to more convenient reg
neg ax ; convert to count up
shl ch, 1 ; bash ch to get high bit of status
; (output state) into high bit of
; count via carry
cmc ; invert carry to match count negation
rcr ax, 1 ; mode 3 counts down twice by twos,
; first with output high, then low
hrt_gotlo:
; This would be the place to shift ax down if less resolution but greater range
; were needed. The merging with system ticks or parallel ticks would have to
; involve the same shifting.
if PRVT_TICKS_USED ; if a parallel tick count is to be used
mov dx, word ptr cs:[hrt_ticks]
else ; PRVT_TICKS_USED
mov dx, DOS_GLOBALS
mov es, dx
mov dx, es:[SYS_TIMER_CNT] ; add system time
endif ; PRVT_TICKS_USED
if IRET_IF_RESTORE
iret
else ; IRET_IF_RESTORE
pop bx ; get flags down to restore interrupt flag
test bx, 0200h ; was IF set? (jump if no)
jz short hrt_if_done
sti ; restore interrupts to ON
hrt_if_done:
ret
endif ; IRET_IF_RESTORE
_hrtime endp
end