Newsgroups: comp.lang.pascal
Subject: Re: High speed clock
From: phys169@csc.canterbury.ac.nz
Date: Thu, 17 Dec 1992 01:51:05 GMT
 <peter.422.723796479@psychnet.psychol.utas.edu.au> <Bz47zL.5sH@news.cso.uiuc.edu> <peter.430.724488284@psychnet.psychol.utas.edu.au>
Organization: University of Canterbury, Christchurch, New Zealand

In article <peter.430.724488284@psychnet.psychol.utas.edu.au>, peter@psychnet.psychol.utas.edu.au (Peter R. Tattam) writes:
> In article <Bz47zL.5sH@news.cso.uiuc.edu> amead@s.psych.uiuc.edu (Alan Mead) writes:
>>From: amead@s.psych.uiuc.edu (Alan Mead)
>>>Does anyone out there know how to do high-speed timing?
>>>The internal clock ticks with 18.2 ticks per second, and
>>>sometimes this is too slow. I want a resolution of about
>>>one millisecond.
> 
> Basically the idea is to reprogram the timer chip to tick at a different rate. 
> ...What you have to do is change the divisor to some other number.  To 
> get 1000 Hz (1 millisecond) you will need a divisor of 1193.

There is another way, avoiding reprogramming the timer. 

You can read the value of the counter out while it is counting, and use it
in conjunction with the longint count of 18.2..Hz ticks at $40:$6C (probably
ignore the least significant byte - you should still read it from the port
though). Remember to disable interrupts for the few instructions, and read the
two halves of the counter twice if you want toi take notice of the least
significant byte.

The following program has two functions - one that returns the time as a real
number of seconds (accurate to about 0.0005 sec on a 10Mhz AT), and one giving 
the time in microticks (4770000/4 of them per second), accurate to about 90
microticks (sometimes more due to the PC's timer interrupt service routine) on
a 10MHz AT. Notice the lack of floating point arithmetic helps the speed.

If you have a slow PC/XT with a CMOS clock card, you may prefer to use the
internal timer in that, which can give a resolution down to 1/1000th of a
second if you find the correct I/O port to read, by the way.

----snip----
program HighResClock; {example program by M.Aitchison@csc.canterbury.ac.nz}

uses DOS;

function RealTime : real;
const f1 = -$40000/4.77e6; f2 = f1/256;
var TickCount : longint absolute $40:$6C; {approx. 18.1961 ticks per second}
    TicksTimes256 : longint absolute $40:$6B;
    result        : longint;
    CounterHi     : byte;
    CounterLo     : byte;
begin
inline($FC);             {DisableInterrupts}
result:=TickCount;       {number of times counter has ticked over since boot}
CounterLo:=port[$40];    {have to read it, even though we don't use it}
CounterHi:=port[$40];
inline($FB);             {EnableInterrupts}
RealTime:=Result*f1 + CounterHi*f2;
end;

function ExactTime : longint;
var TickCount  : word absolute $40:$6C; {approx. 18.1961 ticks per second}
    Part       : record LoByte,HiByte : byte;
                        HighestWord   : word;
                        end;
    result     : longint absolute Part;
    CounterHi,
    CounterLo  : byte;
begin
DisableInterrupts;
Part.HighestWord:=TickCount;
CounterLo:=port[$40];
CounterHi:=port[$40];    {over-write the first byte from 46Bh}
Part.LoByte:=Port[$40];
Part.HiByte:=Port[$40];  {read twice, in case Hi byte changed}
EnableInterrupts;
if CounterHi<>Part.HiByte
   then Part.LoByte:=200;
ExactTime:=result;       {result is units of 0.838574423 microseconds}
end;

begin
writeln('Takes ',RealTime-RealTime:9:6,' sec to call the RealTime function');
writeln('Takes ',-(ExactTime-ExactTime):16,' microticks in ExactTime');
end.