1603 ;****************************************************************** ; Millisecond resolution timer ; Parts taken from the PC Timer FAQ ; ; void init_mstimer(void); ; ; void rest_mstimer(void); ; ; unsigned long read_mstimer(void); ; returned value consists of the following: ; high word = ticks << 16 ; low word = latched timer count (ascending) ; ; void ms_delay(unsigned int ms); ;****************************************************************** OPTION PROC:PRIVATE .MODEL SMALL .386 .DATA mstimer_ticks word 0 .CODE PUBLIC _init_mstimer, _rest_mstimer, _read_mstimer, _ms_delay mstimer_isr PROC FAR ASSUME CS:_TEXT, DS:@data push ds push @data pop ds inc mstimer_ticks ;Update tick value pop ds db 0eah ;Jump to old int8 vector old_int8_offs dw 0 old_int8_seg dw 0 mstimer_isr ENDP _init_mstimer PROC push si push es mov ax, 3508h ;Get INT8 vector int 21h mov old_int8_offs, bx ;Save old INT8 vector mov old_int8_seg, es push ds mov ax, 2508h ;Install new ISR push cs pop ds mov dx, offset mstimer_isr int 21h pop ds mov dx, mstimer_ticks ;Synchronize wait_tick1: cmp mstimer_ticks, dx jz short wait_tick1 cli mov al, 34h ;Set Mode 2 out 43h, al xor ax,ax ;Same count as before jmp SHORT $+2 out 40h, al ;(65536) jmp SHORT $+2 out 40h, al sti pop es pop si ret _init_mstimer ENDP _rest_mstimer PROC push si push es mov dx, mstimer_ticks ;Synchronize wait_tick2: cmp mstimer_ticks, dx jz short wait_tick2 cli mov al, 36h ;Back to mode 3 out 43h, al xor ax, ax ;Load count jmp SHORT $+2 out 40h, al jmp SHORT $+2 out 40h, al push ds ;Restore old INT 8 mov ax, 2508h mov dx, old_int8_offs mov ds, old_int8_seg int 21h pop ds sti pop es pop si ret _rest_mstimer ENDP _read_mstimer PROC ; Taken from PCTIM003 Func: Return absolute timestamp (32-bit) in ; Modified by MP units of 0.83809534452us since midnight ; in the current day (range 00000000h ; to 0ffffffffh) using "mstimer_ticks" ; variable and PIT channel zero count in ; progress, assuming PIT channel 0 is ; operating in mode 2 with a reload value ; of 0 (65536 divisor). ; In: None ; Out: AX = Count loword (b0..15) (0000-FFFF) ; DX = Count hiword (b16..31) (0000-FFFF) push si push di cli mov si, mstimer_ticks ; Get tick count (18.2065 Hz) mov al, 0 ; Latch count for PIT channel 0 out 43h, al ; Send it jmp SHORT $+2 ; Delay in al, 40h ; Get lobyte of count mov ah, al ; Save in AH jmp SHORT $+2 ; Delay in al, 40h ; Get hibyte of count sti ; Make sure interrupts are enabled now xchg al, ah ; Get bytes the right way round nop ; Sniff for interrupt neg ax ; Convert to ascending count cli ; No interrupts again for reading count mov dx, mstimer_ticks ; Get tick count again sti cmp dx, si ; Did tick count change? jz GotTimestamp ; If not, just return second tick count test ax, ax ; Is tick count low or high? jns GotTimestamp ; If low, read was just past interrupt mov dx, si ; If high, previous tick count is right GotTimestamp: pop di ; Restore working registers pop si ret _read_mstimer ENDP _ms_delay PROC push bp mov bp, sp push cx push si xor eax, eax mov ax, [bp + 4] ;Calculate count delay mov esi, eax mov ebx, 1193 ;(ms * 1193 + mul ebx ; ms * 180 / 1000) mov ecx, eax mov eax, esi mov ebx, 181 mul ebx xor edx, edx mov ebx, 1000 div ebx add ecx, eax call _read_mstimer ror eax, 16 mov ax, dx rol eax, 16 mov ebx, eax delay_lp: call _read_mstimer ror eax, 16 mov ax, dx rol eax, 16 sub eax, ebx cmp eax, ecx jb delay_lp pop si pop cx pop bp ret _ms_delay ENDP COMMENT # ;----------------------------------------------------------------------- ; Old version of _read_mstimer based on the MSEQ_12 package. ; Replaced by the PCTIM version, because that one is apparently faster. ;----------------------------------------------------------------------- _read_mstimer_old PROC push bx push si push di push es cli ;Disable interrupts mov dx, 020h ;Address PIC OCW3 mov al, 00Ah ;Ask to read IRR out dx, al mov al, 00h ;Latch timer 0 out 043h, al in al, dx ;Read IRR mov di, ax ;Save it in DI in al, 040h ;Counter --> bx mov bl, al ;LSB in BL in al, 040h mov bh, al ;MSB in BH not bx ;Need ascending counter in al, 021h ;Read interrupt mask mov si, ax ;Save it in SI mov al, 0ffh ;Mask all interrupts out 021h, al mov dx, mstimer_ticks ;get timerticks mov ax, si ;Restore imr from SI out 021h, al sti ;Enable interrupts mov ax, di ;Retrieve old IRR test al, 1 ;Counter hit 0? jz done ;Jump if not cmp bx, 0ffh ;Counter > 0x0FF? ja done ;Done if so inc dx ;Else count int request done: mov ax, bx ;Set function result pop es pop di pop si pop bx ret _read_mstimer_old ENDP # END . 0