READ_ME.TXT for TIME_FNS.ASM and TIME_TST.C

1. Compile/Link/Run

I have compiled on MSVC 1.52 and BC 4.5

Turn off all compiler optimizations.
Turn off all compiler debugging options.
With MSVC linker use /NON.
Exit Windows and run from straight DOS, not from a Windows DOS
box.  It will not run under Windows.  (Windows really does not
want to give up that timer!)

The memory model is set to small with the .model directive.  I
have not tried any other memory model; no changes should be
necessary other than to this one statement.

These function take no arguments so they can be called from C, 
assembler, or any hugh level language.  On entry the functions 
do not save any registers;  but they use only ax and dx.  They 
use no stack space.

There is a conditional assembly identifier NORMAL at the
beginning of TIMER_FNS.ASM.  When NORMAL=1 the program compiles
normally.  When NORMAL=0 the code is omitted that solves the
problems discussed in the article.  Further on in this
read_me.txt are instructions for use of this identifier.

2.  Using TIME_TST.C

Read_time() returns dx=ax=0 if the time interval overflows into
the high word of the doubleword timer interrupt counter.  This
indicates that the time interval exceeded approximately 1 hour.

First generally familiarize yourself with the microsecond timer
concepts, the time_fns.asm functions, the program time_tst.c,
and the sample printouts at the end of this read_me.txt.  Then
on the command line type the program name and an arbitrary long
unsigned int such as:

        time_tst 18929

Observe the output numbers.  The first Process Time should be
different (larger) than all of the others because it times from
start_time() to read_time(), while the others time from
read_time() to read_time().  While the rest of the times
should, theoretically, be all the same, you will see more
variation than we would really like to see.  The latch value
printed has been 2s complimented so it shows the number of
clock cycles that have been subtracted from the initial count,
rather than the remaining count.  The Null Time should be
(mentally) subtracted from the process time to get the actual
correct process time.

Find arbitrary input numbers that will get the value of PIT
LATCH close to 1 and the value of Process Time close to 65536.

A range of about 10 numbers around this point will demonstrate
the technical problem discussed in the article.  On my 386/20
the range is 18929-18936 or 35418-35431 depending on which
compiler I use.  Each is set up in a totally arbitrary way so
this is not a compiler comparison.  To work with your Pentium
200 you will have to use comparatively large arbitrary numbers.

Choose the first and last numbers in the range so that PIC IRR
is always zero; in the middle it will have lots of ones.

You should be able to see the cases where the counter rolled
over after the cli so that an interrupt is pending in the IRR.
These are cases which would cause problems if it were not for
my solution.  There should be some cases where the counter was
clearly latched before it rolled over (it is close to 65536)
and some where it was latched after (it is close to 00001).
Remember that the latch value as printed has been twos
complimented so it shows elapsed time rather than time to go.
Because of the technique used in the program, all of these
cases still have correct Process Times.

After doing the above and being more familiar with what is
going on, is a useful time to set NORMAL=0, recompile, and try
again.  This will permit you to see the actual problems.
Before doing this it would be a good idea to recompile with no
changes to be sure the your compiler settings are OK for this
application.

Here is an edited sample printout with NORMAL=1.  These numbers
do show that the technical problems do exist as I have
described them and that my code does solve the problems.  If
you havn't followed any of this, just note that in spite of the
variations in PIT Latch and PIC IRR, Process Time is always
correct.

Arbitrary number = 18929, Null time = 10, ISR time = 44
Process Time    PIT Latch       PIC IRR
00065516        65516           0x00   Latch has not counted down
00065519        65519           0x00   to 1 (2s comp 65536)
00065523        65523           0x00   after the cli. No interrupt
00065524        65524           0x00   pending (0x00).  Normal
00065523        65523           0x00   situation.
00065524        65524           0x00
00065524        65524           0x00
00065524        65524           0x00
00065523        65523           0x00
00065524        65524           0x00

Arbitrary number = 18930, Null time = 10, ISR time = 44
Process Time    PIT Latch       PIC IRR
00065520        65520           0x00  With the 65529, this
00065529**      65529**         0x01**0x01 indicates that after
00065527        65527           0x00  the cli, and after the count
00065527        65527           0x01  was latched, the counter
00065526        65526           0x00  counted down to 1 and generated
00065527        65527           0x00  an interrupt request. Section
00065527        65527           0x01  6 of read_time() removes this
00065527        65527           0x00  interrupt, else the next
00065526        65526           0x00  read_time() result would be
00065526        65526           0x00  64K cycles too large.
*
*
*
Arbitrary number = 18933, Null time = 9, ISR time = 46
Process Time    PIT Latch       PIC IRR
00065530        65530           0x01
00065533        00043           0x00
00065530        65530           0x01  With the 00001, this 0x01
00065537**      00001**         0x01**indicates that after the cli,
00065537        00001           0x01  but before it was latched,
00065537        00001           0x01  the counter counted down to
00065537        00001           0x01  1 and generated an interrupt
00065538        00002           0x01  request. Without my code
00065538        00002           0x01  result would be 64K too
00065537        00001           0x01  small

Arbitrary number = 18934, Null time = 10, ISR time = 47
Process Time    PIT Latch       PIC IRR
00065534        65534           0x01
00065535**      00046**         0x00**00046 is the time in the
00065534        65534           0x01  interrupt handler. 0x00
00065533        00044           0x00  shows no interrupt is
00065534        65534           0x01  pending. The counter rolled
00065532        00043           0x00  over, generated an interrupt,
00065534        65534           0x01  the interrupt was serviced,
00065532        00043           0x00  then the counter was latched
00065533        65533           0x01  almost immediately.  No
00065533        00044           0x00  problem here.
*
*
*
Arbitrary number = 18936, Null time = 10, ISR time = 46
Process Time    PIT Latch       PIC IRR
00065535        00045*          0x00  Back to normal here. 00045
00065536        00046           0x00  is the time in the interrupt
00065533        00043           0x00  handler. It has been
00065533        00043           0x00  subtracted from the gross
00065534        00044           0x00  to get the correct process
00065534        00044           0x00  time. No problem here.
00065534        00044           0x00
00065533        00043           0x00
00065533        00043           0x00
00065534        00044           0x00



