timer.pas 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  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.