timer.pas 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. unit timer;
  2. {$r-,s-}
  3. INTERFACE
  4. var
  5. timeractive: boolean;
  6. exacttime, mstime: longint;
  7. function timervalue: longint; {Return time in 10 usec units}
  8. function mstimer: longint; {Return time in ms}
  9. IMPLEMENTATION
  10. uses dos, crt;
  11. var
  12. lowbyte, highbyte, ref: word;
  13. timerid: integer;
  14. saveint, exitsave: pointer;
  15. function inport(x: integer): byte; {Read i/o port}
  16. inline($5a/$eb/$00/$ec);
  17. {$F+}
  18. procedure clock(p: pointer); interrupt;
  19. {$F-}
  20. {Interrupt service routine to update timer reference values}
  21. const
  22. incr = 5493; {Timer increment per interrupt}
  23. begin
  24. port[$43] := $00; {Latch timer 0}
  25. lowbyte := inport($40);
  26. highbyte := inport($40);
  27. ref := (highbyte shl 8) + lowbyte; {Base for subsequent readings
  28. within current clock interval}
  29. exacttime := exacttime + incr; {New 10 usec timer value}
  30. mstime := mstime + 55; {New ms timer value}
  31. inline($9c/$ff/$1e/saveint); {Chain to old interrupt}
  32. end;
  33. function timervalue: longint;
  34. {Get value of 10-usec timer}
  35. var
  36. dif, low, high: word;
  37. t: longint;
  38. begin
  39. inline($fa); {Disable interrupts}
  40. port[$43] := $00; {Latch timer}
  41. low := inport($40); {Timer LSB}
  42. high := inport($40); {MSB}
  43. dif := ref - ((high shl 8) + low); {Delta from last sync}
  44. timervalue := exacttime + (longint(dif)*100 div 1193);
  45. inline($fb); {Re-enable interrupts}
  46. end;
  47. function mstimer: longint;
  48. {Get value of millisecond timer}
  49. var
  50. dif, low, high: word;
  51. t: longint;
  52. begin
  53. inline($fa);
  54. port[$43] := $00;
  55. low := inport($40);
  56. high := inport($40);
  57. inline($fb);
  58. dif := ref - ((high shl 8) + low);
  59. mstimer := mstime + (dif div 1193);
  60. end;
  61. procedure inittimer;
  62. begin
  63. exacttime := 0;
  64. mstime := 0;
  65. if not timeractive then
  66. begin
  67. port[$43] := $34; {Mode 2 - countdown
  68. (approx .84 microsecond ticks)}
  69. port[$40] := $ff; {Initialize timer value}
  70. port[$40] := $ff;
  71. getintvec(8, saveint); {Save old interrupt address}
  72. setintvec(8, @clock); {Install new service routine}
  73. timeractive := true;
  74. delay(60); {Allow for first tick}
  75. end;
  76. end;
  77. {$f+} procedure myexit; {$f-}
  78. {Assure timer interrupt restored before exit}
  79. begin
  80. if timeractive then
  81. setintvec(8, saveint);
  82. exitproc := exitsave; {Restore TP exit chain}
  83. end;
  84. begin {unit initialization}
  85. timeractive := false;
  86. exitsave := exitproc; {Insert exit routine}
  87. exitproc := @myexit;
  88. InitTimer
  89. end.
  90. unit timer;
  91. {$r-,s-}
  92. INTERFACE
  93. var
  94. timeractive: boolean;
  95. exacttime, mstime: longint;
  96. function timervalue: longint; {Return time in 10 usec units}
  97. function mstimer: longint; {Return time in ms}
  98. IMPLEMENTATION
  99. uses dos, crt;
  100. var
  101. lowbyte, highbyte, ref: word;
  102. timerid: integer;
  103. saveint, exitsave: pointer;
  104. function inport(x: integer): byte; {Read i/o port}
  105. inline($5a/$eb/$00/$ec);
  106. {$F+}
  107. procedure clock(p: pointer); interrupt;
  108. {$F-}
  109. {Interrupt service routine to update timer reference values}
  110. const
  111. incr = 5493; {Timer increment per interrupt}
  112. begin
  113. port[$43] := $00; {Latch timer 0}
  114. lowbyte := inport($40);
  115. highbyte := inport($40);
  116. ref := (highbyte shl 8) + lowbyte; {Base for subsequent readings
  117. within current clock interval}
  118. exacttime := exacttime + incr; {New 10 usec timer value}
  119. mstime := mstime + 55; {New ms timer value}
  120. inline($9c/$ff/$1e/saveint); {Chain to old interrupt}
  121. end;
  122. function timervalue: longint;
  123. {Get value of 10-usec timer}
  124. var
  125. dif, low, high: word;
  126. t: longint;
  127. begin
  128. inline($fa); {Disable interrupts}
  129. port[$43] := $00; {Latch timer}
  130. low := inport($40); {Timer LSB}
  131. high := inport($40); {MSB}
  132. dif := ref - ((high shl 8) + low); {Delta from last sync}
  133. timervalue := exacttime + (longint(dif)*100 div 1193);
  134. inline($fb); {Re-enable interrupts}
  135. end;
  136. function mstimer: longint;
  137. {Get value of millisecond timer}
  138. var
  139. dif, low, high: word;
  140. t: longint;
  141. begin
  142. inline($fa);
  143. port[$43] := $00;
  144. low := inport($40);
  145. high := inport($40);
  146. inline($fb);
  147. dif := ref - ((high shl 8) + low);
  148. mstimer := mstime + (dif div 1193);
  149. end;
  150. procedure inittimer;
  151. begin
  152. exacttime := 0;
  153. mstime := 0;
  154. if not timeractive then
  155. begin
  156. port[$43] := $34; {Mode 2 - countdown
  157. (approx .84 microsecond ticks)}
  158. port[$40] := $ff; {Initialize timer value}
  159. port[$40] := $ff;
  160. getintvec(8, saveint); {Save old interrupt address}
  161. setintvec(8, @clock); {Install new service routine}
  162. timeractive := true;
  163. delay(60); {Allow for first tick}
  164. end;
  165. end;
  166. {$f+} procedure myexit; {$f-}
  167. {Assure timer interrupt restored before exit}
  168. begin
  169. if timeractive then
  170. setintvec(8, saveint);
  171. exitproc := exitsave; {Restore TP exit chain}
  172. end;
  173. begin {unit initialization}
  174. timeractive := false;
  175. exitsave := exitproc; {Insert exit routine}
  176. exitproc := @myexit;
  177. InitTimer
  178. end.