home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast2.iso / ddjmag / ddj9209.zip / HRT.ASC < prev    next >
Text File  |  1992-08-10  |  5KB  |  176 lines

  1. _HIGH-RESOLUTION TIMING_
  2. by Thomas Roden
  3.  
  4. [LISTING ONE]
  5.  
  6. ; hrtime.asm - Hi Resolution TIMEr for dos. Copyright (c) 1991 Thomas A. Roden
  7. ; All Rights Reserved (with one exception). The right to freely distribute this
  8. ; source and any executable code it creates is granted, provided that this 
  9. ; copyright notice is included in the source. It is requested that the author's
  10. ; name (Thomas A. Roden) be included in the acknowledgements of any product 
  11. ; including this code, but this request is in no way legally binding.
  12.  
  13. IO_DELAY_NEEDED equ 0   ; doesn't seem to need recovery time here
  14. PRVT_TICKS_USED equ 1   ; if a private tick count is to be used
  15. IRET_IF_RESTORE equ 0   ; if the flag is to be restored with an IRET,
  16.                 ; or with the windows suggested method
  17. ; io_delay - delay just a bit
  18. io_delay    macro
  19. if IO_DELAY_NEEDED
  20.     jmp short $+2
  21. endif   ; IO_DELAY_NEEDED
  22. endm
  23.  
  24. PIC0_ADDR   equ 020h    ; I/O address of PIC 0
  25. TIMER0      equ 040h    ; I/O address of Timer 0 
  26. TIMER_STAT  equ 043h    ; I/O address for status/control of timers 0-2
  27.  
  28. PIC_RIRR    equ 00Ah    ; Read Interrupt Request Register of a PIC
  29. T0_R_S_C    equ 0C2h    ; Timer 0 Read Status and Count
  30.  
  31. DOS_GLOBALS equ 040h    ; segment for 40:xx variables
  32. SYS_TIMER_CNT   equ 06Ch    ; offset for system count
  33.  .model large
  34.  .code
  35. assume  ds:nothing, es:nothing
  36.  
  37. if PRVT_TICKS_USED
  38. hrt_ticks   dd  0
  39. old_int8    dd  0
  40.  
  41. ; hrt_isr - interrupt routine for private tick counting for hi-res timer
  42.     public  _hrt_isr
  43. _hrt_isr    proc    far
  44.     add word ptr cs:[hrt_ticks], 1
  45.     adc word ptr cs:[hrt_ticks+2], 0
  46.  
  47.     jmp dword ptr cs:[old_int8]
  48. _hrt_isr    endp
  49. endif   ; PRVT_TICKS_USED
  50.  
  51. ; hrt_open - the init function for the hi-res timer
  52.     public  _hrt_open
  53. _hrt_open   proc    far
  54.     push    ds      ; save this stuff to avoid bad crashes
  55.     push    es      ; save this stuff just to be paranoid
  56.     push    bx
  57.     push    cx
  58.     push    dx
  59. if PRVT_TICKS_USED
  60.     xor ax, ax
  61.     mov word ptr cs:[hrt_ticks], ax
  62.     mov word ptr cs:[hrt_ticks+2], ax
  63.     mov ax, 03508h  ; get int vector for int8 (irq0)
  64.     int 21h
  65.     mov word ptr cs:[old_int8], bx
  66.     mov ax, es
  67.     mov word ptr cs:[old_int8+2], ax
  68.     mov dx, seg _hrt_isr
  69.     mov ds, dx
  70.     mov dx, offset _hrt_isr
  71.     mov ax, 02508h  ; set int vector for int8 (irq0)
  72.     int 21h
  73. endif   ; PRVT_TICKS_USED
  74.     pop dx
  75.     pop cx
  76.     pop bx
  77.     pop es
  78.     pop ds
  79.     xor ax, ax
  80.     ret
  81. _hrt_open   endp
  82. ; hrt_close - the un-init function for the hi-res timer
  83.     public  _hrt_close
  84. _hrt_close  proc    far
  85.     push    ds      ; save this stuff to avoid bad crashes
  86.     push    es      ; save this stuff just to be paranoid
  87.     push    bx
  88.     push    cx
  89.     push    dx
  90. if PRVT_TICKS_USED
  91.     mov dx, word ptr cs:[old_int8+2]
  92.     mov ds, dx
  93.     mov dx, word ptr cs:[old_int8]
  94.     mov ax, 02508h  ; set int vector for int8 (irq0)
  95.     int 21h
  96. endif   ; PRVT_TICKS_USED
  97.     pop dx
  98.     pop cx
  99.     pop bx
  100.     pop es
  101.     pop ds
  102.     xor ax, ax
  103.     ret
  104. _hrt_close  endp
  105. ; hrtime - the hi-res time reader
  106.     public  _hrtime
  107. _hrtime proc    far
  108. if IRET_IF_RESTORE
  109.     pop bx      ; return ip - to make iret return frame
  110.     pop ax      ; return cs
  111.     pushf           ; flags
  112.     push    ax      ; cs
  113.     push    bx      ; ip
  114. else    ; IRET_IF_RESTORE
  115.     pushf           ; store flags on stack to check at end
  116. endif   ; IRET_IF_RESTORE
  117.     cli             ; freeze ticker while checking
  118. hrt_readhw:
  119.     mov al, T0_R_S_C        ; timer 0 read stat and count
  120.     out TIMER_STAT, al
  121.     io_delay
  122.     in  al, TIMER0      ; store stat in ch
  123.     mov ch, al
  124.     io_delay
  125.     in  al, TIMER0      ; store count in bx
  126.     mov bl, al
  127.     io_delay
  128.     in  al, TIMER0
  129.     mov bh, al
  130.     io_delay            ; delay between timer and pic access
  131.     mov al, PIC_RIRR
  132.     out PIC0_ADDR, al
  133.     io_delay
  134.     in  al, PIC0_ADDR
  135.     test    al, 001h        ; check if system time is stale
  136.     jz  short hrt_timegood
  137.     mov ax, 0ffffh      ; force max in lower part
  138.     jmp short hrt_gotlo
  139. hrt_timegood:
  140.     test    ch, 040h
  141.     jnz short hrt_readhw    ; timer invalid, retry
  142.     mov ax, bx          ; move count to more convenient reg
  143.     neg ax          ; convert to count up
  144.     shl ch, 1           ; bash ch to get high bit of status
  145.                     ; (output state) into high bit of 
  146.                     ; count via carry
  147.     cmc             ; invert carry to match count negation
  148.     rcr ax, 1           ; mode 3 counts down twice by twos, 
  149.                     ; first with output high, then low
  150. hrt_gotlo:
  151. ; This would be the place to shift ax down if less resolution but greater range
  152. ; were needed. The merging with system ticks or parallel ticks would have to 
  153. ; involve the same shifting.
  154. if PRVT_TICKS_USED  ; if a parallel tick count is to be used
  155.     mov dx, word ptr cs:[hrt_ticks]
  156. else    ; PRVT_TICKS_USED
  157.     mov dx, DOS_GLOBALS
  158.     mov es, dx
  159.     mov dx, es:[SYS_TIMER_CNT]  ; add system time
  160. endif   ; PRVT_TICKS_USED
  161. if IRET_IF_RESTORE
  162.     iret
  163. else    ; IRET_IF_RESTORE
  164.     pop bx          ; get flags down to restore interrupt flag
  165.     test    bx, 0200h       ; was IF set? (jump if no)
  166.     jz  short hrt_if_done
  167.     sti             ; restore interrupts to ON
  168. hrt_if_done:
  169.     ret
  170. endif   ; IRET_IF_RESTORE
  171. _hrtime endp
  172.  
  173. end
  174.  
  175.  
  176.