-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathTPTIMER.PAS
159 lines (138 loc) · 5.67 KB
/
TPTIMER.PAS
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
{Unit for high resolution timing (1 microsecond resolution)
Original TPTimer unit was programmed by TurboPower Software and released to the public domain via the SWAG Pascal archive.
Modified by Jan Knipperts for the VGA Benchmark program}
{$S-,R-,I-,V-,B-}
Unit TPTimer;
Interface
Const
TimerResolution = 1193181.667;
Procedure InitializeTimer;
{-ReProgram the timer chip to allow 1 microsecond resolution}
Procedure RestoreTimer;
{-Restore the timer chip to its normal state}
Function ReadTimer : LongInt;
{-Read the timer With 1 microsecond resolution}
Function ElapsedTime(Start, Stop : LongInt) : Real;
{-Calculate time elapsed (in milliseconds) between Start and Stop}
Function ElapsedTimeString(Start, Stop : LongInt) : String;
{-Return time elapsed (in milliseconds) between Start and Stop as a String}
{==========================================================================}
Implementation
Var
SaveExitProc : Pointer;
Delta : LongInt;
Function Cardinal(L : LongInt) : Real;
{-Return the unsigned equivalent of L as a Real}
begin {Cardinal}
if L < 0 then
Cardinal := 4294967296.0+L
else
Cardinal := L;
end; {Cardinal}
Function ElapsedTime(Start, Stop : LongInt) : Real;
{-Calculate time elapsed (in milliseconds) between Start and Stop}
begin {ElapsedTime}
ElapsedTime := 1000.0*Cardinal(Stop-(Start+Delta))/TimerResolution;
end; {ElapsedTime}
Function ElapsedTimeString(Start, Stop : LongInt) : String;
{-Return time elapsed (in milliseconds) between Start and Stop as a String}
Var
R : Real;
S : String;
begin {ElapsedTimeString}
R := ElapsedTime(Start, Stop);
Str(R:0:3, S);
ElapsedTimeString := S;
end; {ElapsedTimeString}
Procedure InitializeTimer;
{-ReProgram the timer chip to allow 1 microsecond resolution}
begin {InitializeTimer}
{select timer mode 2, read/Write channel 0}
Port[$43] := $34; {00110100b}
Inline($EB/$00); {jmp short $+2 ;Delay}
Port[$40] := $00; {LSB = 0}
Inline($EB/$00); {jmp short $+2 ;Delay}
Port[$40] := $00; {MSB = 0}
end; {InitializeTimer}
Procedure RestoreTimer;
{-Restore the timer chip to its normal state}
begin {RestoreTimer}
{select timer mode 3, read/Write channel 0}
Port[$43] := $36; {00110110b}
Inline($EB/$00); {jmp short $+2 ;Delay}
Port[$40] := $00; {LSB = 0}
Inline($EB/$00); {jmp short $+2 ;Delay}
Port[$40] := $00; {MSB = 0}
end; {RestoreTimer}
Function ReadTimer : LongInt;
{-Read the timer With 1 microsecond resolution}
begin {ReadTimer}
Inline(
$FA/ {cli ;Disable interrupts}
$BA/$20/$00/ {mov dx,$20 ;Address PIC ocw3}
$B0/$0A/ {mov al,$0A ;Ask to read irr}
$EE/ {out dx,al}
$B0/$00/ {mov al,$00 ;Latch timer 0}
$E6/$43/ {out $43,al}
$EC/ {in al,dx ;Read irr}
$89/$C7/ {mov di,ax ;Save it in DI}
$E4/$40/ {in al,$40 ;Counter --> bx}
$88/$C3/ {mov bl,al ;LSB in BL}
$E4/$40/ {in al,$40}
$88/$C7/ {mov bh,al ;MSB in BH}
$F7/$D3/ {not bx ;Need ascending counter}
$E4/$21/ {in al,$21 ;Read PIC imr}
$89/$C6/ {mov si,ax ;Save it in SI}
$B0/$FF/ {mov al,$0FF ;Mask all interrupts}
$E6/$21/ {out $21,al}
$B8/$40/$00/ {mov ax,$40 ;read low Word of time}
$8E/$C0/ {mov es,ax ;from BIOS data area}
$26/$8B/$16/$6C/$00/ {mov dx,es:[$6C]}
$89/$F0/ {mov ax,si ;Restore imr from SI}
$E6/$21/ {out $21,al}
$FB/ {sti ;Enable interrupts}
$89/$F8/ {mov ax,di ;Retrieve old irr}
$A8/$01/ {test al,$01 ;Counter hit 0?}
$74/$07/ {jz done ;Jump if not}
$81/$FB/$FF/$00/ {cmp bx,$FF ;Counter > $FF?}
$77/$01/ {ja done ;Done if so}
$42/ {inc dx ;else count int req.}
{done:}
$89/$5E/$FC/ {mov [bp-4],bx ;set Function result}
$89/$56/$FE); {mov [bp-2],dx}
end; {ReadTimer}
Procedure Calibrate;
{-Calibrate the timer}
Const
Reps = 1000;
Var
I : Word;
L1, L2, Diff : LongInt;
begin {Calibrate}
Delta := MaxInt;
For I := 1 to Reps do begin
L1 := ReadTimer;
L2 := ReadTimer;
{use the minimum difference}
Diff := L2-L1;
if Diff < Delta then
Delta := Diff;
end;
end; {Calibrate}
{$F+}
Procedure OurExitProc;
{-Restore timer chip to its original state}
begin {OurExitProc}
ExitProc := SaveExitProc;
RestoreTimer;
end; {OurExitProc}
{$F-}
begin
{set up our Exit handler}
SaveExitProc := ExitProc;
ExitProc := @OurExitProc;
{reProgram the timer chip}
InitializeTimer;
{adjust For speed of machine}
Calibrate;
end.