timer.pas 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. unit timer;
  2. { NOT PORTED YET, BUT NOT USED BY OTHER LIBS/AND OR DLL AND MOST DEMOES}
  3. {$r-,s-}
  4. INTERFACE
  5. var
  6. timeractive: boolean;
  7. exacttime, mstime: longint;
  8. function timervalue: longint; {Return time in 10 usec units}
  9. function mstimer: longint; {Return time in ms}
  10. IMPLEMENTATION
  11. uses dos, crt;
  12. var
  13. lowbyte, highbyte, ref: word;
  14. timerid: integer;
  15. saveint, exitsave: pointer;
  16. function inport(x: integer): byte; {Read i/o port}
  17. inline($5a/$eb/$00/$ec);
  18. {$F+}
  19. procedure clock(p: pointer); interrupt;
  20. {$F-}
  21. {Interrupt service routine to update timer reference values}
  22. const
  23. incr = 5493; {Timer increment per interrupt}
  24. begin
  25. port[$43] := $00; {Latch timer 0}
  26. lowbyte := inport($40);
  27. highbyte := inport($40);
  28. ref := (highbyte shl 8) + lowbyte; {Base for subsequent readings
  29. within current clock interval}
  30. exacttime := exacttime + incr; {New 10 usec timer value}
  31. mstime := mstime + 55; {New ms timer value}
  32. inline($9c/$ff/$1e/saveint); {Chain to old interrupt}
  33. end;
  34. function timervalue: longint;
  35. {Get value of 10-usec timer}
  36. var
  37. dif, low, high: word;
  38. t: longint;
  39. begin
  40. inline($fa); {Disable interrupts}
  41. port[$43] := $00; {Latch timer}
  42. low := inport($40); {Timer LSB}
  43. high := inport($40); {MSB}
  44. dif := ref - ((high shl 8) + low); {Delta from last sync}
  45. timervalue := exacttime + (longint(dif)*100 div 1193);
  46. inline($fb); {Re-enable interrupts}
  47. end;
  48. function mstimer: longint;
  49. {Get value of millisecond timer}
  50. var
  51. dif, low, high: word;
  52. t: longint;
  53. begin
  54. inline($fa);
  55. port[$43] := $00;
  56. low := inport($40);
  57. high := inport($40);
  58. inline($fb);
  59. dif := ref - ((high shl 8) + low);
  60. mstimer := mstime + (dif div 1193);
  61. end;
  62. procedure inittimer;
  63. begin
  64. exacttime := 0;
  65. mstime := 0;
  66. if not timeractive then
  67. begin
  68. port[$43] := $34; {Mode 2 - countdown
  69. (approx .84 microsecond ticks)}
  70. port[$40] := $ff; {Initialize timer value}
  71. port[$40] := $ff;
  72. getintvec(8, saveint); {Save old interrupt address}
  73. setintvec(8, @clock); {Install new service routine}
  74. timeractive := true;
  75. delay(60); {Allow for first tick}
  76. end;
  77. end;
  78. {$f+} procedure myexit; {$f-}
  79. {Assure timer interrupt restored before exit}
  80. begin
  81. if timeractive then
  82. setintvec(8, saveint);
  83. exitproc := exitsave; {Restore TP exit chain}
  84. end;
  85. begin {unit initialization}
  86. timeractive := false;
  87. exitsave := exitproc; {Insert exit routine}
  88. exitproc := @myexit;
  89. InitTimer
  90. end.