home *** CD-ROM | disk | FTP | other *** search
- ;*****************************************************************************
- ;
- ; A GetTickCount() that is accurate to the millisecond
- ;
- ; Copyright (C) 1988-1991 Datametrics Systems Corporation
- ;
- ; Notes:
- ;
- ; - Proc directly accesses the 8254 timer chip (does port I/O).
- ; - Proc issues sti/cli instructions.
- ; - Assumes timer interrupt frequency has not been changed.
- ; - There is a dramatic performance degradation if this proc
- ; is executed on a 386 w/ I/O port trapping enabled for the
- ; timer chip.
- ; - Time will wrap after 49.7 days (1ms) or 4.97 days (100us).
- ; - TIMERRES is 54925, the interrupt period in microseconds.
- ;
- ;*****************************************************************************
-
- TENTHTICK EQU 0
-
- if (TENTHTICK)
- TR1 EQU 16384 ;; (WORD)((TIMERRES*10*65536)/1000)
- TR2 EQU 549 ;; (TIMERRES*10/1000)
- TR3 EQU 8788 ;; (TIMERRES*10*16)/1000
- else
- TR1 EQU 60620 ;; (WORD)((TIMERRES*65536)/1000)
- TR2 EQU 54 ;; (TIMERRES/1000)
- TR3 EQU 56243 ;; (TIMERRES*256*4)/1000
- endif
-
- .MODEL SMALL,PASCAL
- .DATA
- dwLowTickCount dd 0
- .CODE
- GetLowTickCount PROC FAR USES SI DI
- LOCAL wFrac:WORD
-
- ; /*--- Disable interrupts; Issue read-back command for counter 0 ---*/
- start: mov al, 0C2h ;; read back command
- cli
- out 43h, al ;; send command to 8254
- jmp short $+2 ;; I/O wait
-
- ; /*--- Set carry flag to counter 0 OUT pin status ---*/
- in al, 40h ;; OUT status is in bit 7
- jmp short $+2 ;; I/O wait
- shl al, 1 ;; carry = OUT status
-
- ; /*--- Set CX to where in interval we are ---*/
- in al, 40h ;; read counter low
- jmp short $+2 ;; I/O wait
- mov cl, al ;; save counter low
- in al, 40h ;; read counter high
- jmp short $+2 ;; I/O wait
- mov ch, al ;; save counter high
- jcxz restart ;; restart if counter is zero
- rcr cx, 1 ;; combine OUT status w/ counter
- not cx ;; change high->low to low->high
-
- ; /*--- Convert BIOS ticks to milliseconds (into DI:SI) ---*/
- if (?WIN EQ 1)
- extrn __0040H:ABS
- mov bx, __0040H ;; Windows requires external absolute
- else
- mov bx, 040h ;; ROM BIOS data area segment
- endif
- mov es, bx
- mov bx, 06Ch ;; offset to timer info
- mov ax, TR1
- mul WORD PTR es:[bx]
- mov wFrac, ax ;; fraction
- mov si, dx
- mov ax, TR1
- mul WORD PTR es:[bx+2]
- mov di, dx
- add si, ax
- adc di, 0
- mov ax, TR2
- mul WORD PTR es:[bx]
- add si, ax
- adc di, dx
- mov ax, TR2
- mul WORD PTR es:[bx+2]
- add di, ax
-
- if (TENTHTICK)
- ; /*--- Get tick count accurate to 1/10000 second ---*/
- mov ax, TR3
- shr cx, 1
- shr cx, 1
- shr cx, 1
- shr cx, 1
- mul cx ;; where in interval
- add ax, WORD PTR [wFrac] ;; add fraction
- mov ax, si ;; ax = tick count low
- adc ax, dx
- mov dx, di ;; dx = tick count high
- adc dx, 0 ;;
- else
- ; /*--- Get tick count accurate to 1/1000 second ---*/
- mov ax, TR3
- shr cx, 1
- shr cx, 1
- mul cx ;; where in interval
- add ah, BYTE PTR [wFrac] ;; add fraction low/high
- adc dl, BYTE PTR [wFrac+1] ;; ..to get carry
- mov ax, si ;; ax = tick count low
- adc al, dh ;;
- adc ah, 0 ;;
- mov dx, di ;; dx = tick count high
- adc dx, 0 ;;
- endif
-
- ; /*--- Assure tick count is equal or advancing ---*/
- cmp dx, WORD PTR [dwLowTickCount+2]
- ja done
- cmp ax, WORD PTR [dwLowTickCount]
- jb restart
-
- ; /*--- Save last tick count obtained ---*/
- done: mov WORD PTR [dwLowTickCount], ax
- mov WORD PTR [dwLowTickCount+2], dx
- sti
- ret
-
- ; /*--- Restart procedure ---*/
- restart: sti
- jmp start
-
- GetLowTickCount ENDP
-
- END