Board index » delphi » Precise (3-4 ms) time control in MS-DOS

Precise (3-4 ms) time control in MS-DOS

Hi!
I am writing experiment-controlling program and need to make measurements
with very regular intervals. So, how can I program delay with error not
more then 3-4 ms or (better) to control, how much time passed since last
measurement -- I want to make some calculations and output in between.

Thanks!

Viatcheslav

 

Re:Precise (3-4 ms) time control in MS-DOS


In article <4pl3q8$...@zeus.rbi.informatik.uni-frankfurt.de>,

Quote
V.V.Nesterov <neste...@em.uni-frankfurt.de> wrote:

:I am writing experiment-controlling program and need to make measurements
:with very regular intervals. So, how can I program delay with error not
:more then 3-4 ms or (better) to control, how much time passed since last
:measurement -- I want to make some calculations and output in between.

-From: ftp://garbo.uwasa.fi/pc/link/tsfaqp.zip Frequently Asked TP Questions
-Subject: Millisecond timing

10. *****
 Q: How is millisecond timing done?

 A: A difficult task, but the facilities are readily available.
TurboPower Software's commercial Turbo Professional (don't confuse
with Borland's Turbo Professional) has a unit for this. (The usual
disclaimer applies). It is called tptimer and is part of the
ftp://garbo.uwasa.fi/pc/turbopas/bonus507.zip package. This one has
been released to the PD. I have also seen a SimTel upload
announcement of a ztimer11.zip for C and ASM, but I have no further
information on that. ftp://garbo.uwasa.fi/pc/turbopas/qwktimer.zip
is another option. It is not quite as accurate as tptimer.
   To test the tptimer unit in bonus507.zip you can use the
following example code
  uses Crt, tptimer;
  var time1, time2 : longint;
  begin
    InitializeTimer;
    time1 := ReadTimer;
    Delay (1356);    (* Or whatever code you wish to benchmark *)
    time2 := ReadTimer;
    RestoreTimer;
    writeln ('Elapsed = ', ElapsedTime (time1, time2)/1000.0 : 0 : 3);
  end.
   It is quite another question when you really need the millisecond
timing. The most common purpose for millisecond timing is testing
the efficiency of alternative procedures and functions, right? The
way I compare mine is simple. I call the procedures or functions I
want to compare for speed, say, a thousand times in a loop.  And
test this for elapsed time. This way the normal resolution (18.2
cycles per second) of the system clock becomes sufficient. This is
accurate enough for the comparisons.
     var elapsed : real; i : word;
     elapsed := TIMERFN;  (* e.g. from /pc/ts/tspa3455.zip *)
     for i := 1 to 1000 do YOURTEST;  (* Try out the alternatives *)
     elapsed := TIMERFN - elapsed;
     writeln ('Elapsed : ', elapsed : 0 : 2);
Incidentally, if you want to make more elaborate evaluations of the
efficiency of your code, Borland's Turbo Profiler is a useful tool.
(The usual disclaimer naturally applies.)
--------------------------------------------------------------------

   All the best, Timo

....................................................................
Prof. Timo Salmi   Co-moderator of news:comp.archives.msdos.announce
Moderating at ftp:// & http://garbo.uwasa.fi archives  193.166.120.5
Department of Accounting and Business Finance  ; University of Vaasa
t...@uwasa.fi http://uwasa.fi/~ts BBS 961-3170972; FIN-65101,  Finland

Re:Precise (3-4 ms) time control in MS-DOS


Quote
"V.V.Nesterov" <neste...@em.uni-frankfurt.de> wrote:
>Hi!
>I am writing experiment-controlling program and need to make measurements
>with very regular intervals. So, how can I program delay with error not
>more then 3-4 ms or (better) to control, how much time passed since last
>measurement -- I want to make some calculations and output in between.

>Thanks!

>Viatcheslav

What you could do is reprogram the PC timer to generate an interrupt at the
required frequency. The PC clock is the highest priority non-processor
interrupt. You then trigger your data acquisition process within an interrupt
service routine (ISR) which is straightforward to write in Turbo Pascal.

The main problem with this method is that you must still call the old timer
interrupt routine 18.2 times per second. For this reason, I created a data
acquisition process running at 200 Hz, since 200/18.2 = 10.989 ~ 11 within
tollerance. The code to reprogram the timer is:-

PROCEDURE InitTimer;
{Initialise PC timer chan 0 to generate 5 msec interrupts}
BEGIN
  OldTimerMode := port[$43];
  Inline($EB/$00);                          {Delay}
  Port[$43] := $34;                         {chan 0, mode 2}
  Inline($EB/$00);                          {Delay}
  OldTimerLSB := Port[$40];
  Inline($EB/$00);                          {Delay}
  Port[$40] := lo(5958);                    {LSB 1.19MHz/5958 = 200.2Hz}
  Inline($EB/$00);                          {Delay}
  OldTimerMSB := Port[$40];
  Inline($EB/$00);                          {Delay}
  Port[$40] := hi(5958);                    {MSB = 4}
END;

{---------------------------------------------------------------------------}

PROCEDURE StartIRQ;
{Start the interrupts}
BEGIN
  INLINE ($FA);    {Disables interrupts}
  IF IRQRunning = false
    THEN
      BEGIN
        GetIntVec($08,Int0DSave);                  {fetch interupt vector 1CH
                                                     - PC ch0}
        SetIntVec($08,@Data_Int);                  {set interrupt vector for
                                                     Data Int}
        SetIntVec(SavedInt, Int0DSave);
        {Set original Ch0 int vect to saved int(78)}
        IrqRunning := true;
      END;
  INLINE ($FB);   {Enables interrupts}
END;

{---------------------------------------------------------------------------}

{$F+}   (* Compile with FAR calls*)

PROCEDURE Data_Int;  Interrupt;
{Timer Interrupt handler routine}

LABEL Here;
BEGIN

  {Calls the DOS real-time clock interrupt handler once every 11 cycles}
  Inc(NumberOfTimesTried);
  IF CycleMyOldInt < 11
    THEN GOTO here;
  CASE cycleMyOldInt OF
    -10..10: GOTO Here;
    11..25:
            BEGIN
              Intr(SavedInt, Regs);
              CycleMyOldInt := 0;
              Inc(numberoftimesthro);
              GOTO Here;
            END;
  END;
  Here:
        Inc(CycleMyOldInt);

  INLINE ($FA);    {Disables interrupts}

  {Do your data acquisition stuff here}

  INLINE ($FB);   {Enables interrupts}

  Port[$20] := $20;     {Flag irq controller for EOI}
END;
{$F-}

{---------------------------------------------------------------------------}

PROCEDURE ReInitialise;
BEGIN
  INLINE ($FA);    {Disables interrupts}
  Port[$43] := $36;{OldTimerMode;                {original mode}
  Inline($EB/$00);                          {Delay}
  Port[$40] := $00;{OldTimerLSB;                 {LSB = 0}
  Inline($EB/$00);                          {Delay}
  Port[$40] := $00;{OldTimerMSB;                 {MSB = 0}

  port[BASE + 9] := 0;
  INLINE ($FB);   {Enables interrupts}
END;

{---------------------------------------------------------------------------}

PROCEDURE StopIRQ;
{Stops the interrupts}
BEGIN
  INLINE ($FA);    {Disables interrupts}
  IF IRQRunning = true
    THEN
      SetIntVec($08,Int0DSave);           {reset interrupt vector 1CH, timer}
  IRQRunning := false;
  INLINE ($FB);   {Enables interrupts}
END;

{---------------------------------------------------------------------------}

----------------------
THINGS TO BEAR IN MIND
----------------------

To get accurate timing, you must remember several things.

1. EMM386 should be disabled. Not just set to NOEMS, but completely disabled.
It intercepts every interrupt call made, so reducing the accuracy and      
responsiveness of the interrupt handler.

2. No disk activity. DOS does funny things and can really{*word*222}accurate
timing. Don't write to a disk is you need accuracy. Some data acquisition
boards can use buffered memory writing and DMA techniques with on-board
timing sources, thus allowing data logging, but if your main concern is
responsiveness, don't read or write files.

3. Disable other interrupts. This is left up ot you, but you can mask other
interrupts such as the keyboard handler, disk controller and others. See how
you get on. Remember, the PC timer is IRQ 0, so this has highest priority
anyway, so can interrupt lower-level interrupts.

4. Write your interrupt handler efficiently. Make sure you don't overload the
processor - toggle a digital output to see how long your routine takes and
make sure there is a lot of spare time.

5. Call the origianl timer ISR at the appropriate rate. If you don't, the PC
will stop dead, I think because it calls a memory refresh routine. Anyway,
the DOS clock must be updated 18.2 times per second.

That's it. See how you get on.

Regards,
Richard

--
_______________________________________________________________________
Richard C A Cullen                  |  Postgraduate Student
EMail : I...@SIRIUS.TN.RL.AC.UK      |  Imperial College,
at Rutherford Appleton Laboratory   |  Dept of Electrical Engineering,
____________________________________|__________________________________

Re:Precise (3-4 ms) time control in MS-DOS


In article <4pl3q8$...@zeus.rbi.informatik.uni-frankfurt.de> of Wed, 12
Jun 1996 00:42:48 in comp.lang.pascal.borland, "V.V.Nesterov"

Quote
<neste...@em.uni-frankfurt.de> wrote:

>I am writing experiment-controlling program and need to make measurements
>with very regular intervals. So, how can I program delay with error not
>more then 3-4 ms or (better) to control, how much time passed since last
>measurement -- I want to make some calculations and output in between.

From my unavailable incomplete draft Web pages -

<p> PCTIM003.ZIP timing FAQ  : "The file's URL at SimTel is
  ftp://ftp.coast.net/SimTel/msdos/info/pctim*.zip."  

(it's by Kris Heidenstrom of NZ)

--
John Stockton, Surrey, UK.  J...@merlyn.demon.co.uk  Turnpike v1.12  MIME
    Home Page under construction.

Re:Precise (3-4 ms) time control in MS-DOS


Quote
"V.V.Nesterov" <neste...@em.uni-frankfurt.de> wrote:
>Hi!
>I am writing experiment-controlling program and need to make measurements
>with very regular intervals. So, how can I program delay with error not
>more then 3-4 ms or (better) to control, how much time passed since last
>measurement -- I want to make some calculations and output in between.

>Thanks!

>Viatcheslav

What's about using the periodic interrupt feature of the RTC?
Periodic interrupt can be programmed from 500ms down to
approx. 30.?? us (2Hz .. ~32kHz). If you don't have a
description of the RTC-chip or need more information, please
feel free to e-mail me.

Many greetings
 --Hermann
--
------------------------------------------------------
Hermann Tauber                     Siemens EZM Villach
mailto:Hermann.Tau...@ezmvi.siemens.co.at        Austria (CE)
------------------------------------------------------

Re:Precise (3-4 ms) time control in MS-DOS


In article <31BFB6CB.3F54B...@ezmvi.HL.Siemens.de>,
Hermann Tauber  <Hermann.Tau...@ezmvi.HL.Siemens.de> wrote:

Quote
>"V.V.Nesterov" <neste...@em.uni-frankfurt.de> wrote:
>>Hi!
>>I am writing experiment-controlling program and need to make measurements
>>with very regular intervals. So, how can I program delay with error not

>>Viatcheslav

>What's about using the periodic interrupt feature of the RTC?
>Periodic interrupt can be programmed from 500ms down to
>approx. 30.?? us (2Hz .. ~32kHz). If you don't have a
>description of the RTC-chip or need more information, please

How about posting some more info? Anyone got some xample code?

Thanks,

Ben
--
****************************************************************
**      ... So he sat, alone in his world of so many...       **
****************************************************************

Re:Precise (3-4 ms) time control in MS-DOS


In article <5ZtngNAYS0vxE...@merlyn.demon.co.uk>, Dr John Stockton <j...@merlyn.demon.co.uk> writes:

Quote
>In article <4pl3q8$...@zeus.rbi.informatik.uni-frankfurt.de> of Wed, 12
>Jun 1996 00:42:48 in comp.lang.pascal.borland, "V.V.Nesterov"
><neste...@em.uni-frankfurt.de> wrote:

>>I am writing experiment-controlling program and need to make measurements
>>with very regular intervals. So, how can I program delay with error not
>>more then 3-4 ms or (better) to control, how much time passed since last
>>measurement -- I want to make some calculations and output in between.

>From my unavailable incomplete draft Web pages -

><p> PCTIM003.ZIP timing FAQ  : "The file's URL at SimTel is
>  ftp://ftp.coast.net/SimTel/msdos/info/pctim*.zip."  

Or something like that (for AT compatible only, but today...)

procedure  delay_mus ( delt : longint ) ;
{ Delay of  delt  microseconds  ( for AT compatibles only ! ) }
const  maxword = 65536 ;
var  Regs : Registers ;
begin  if delt > 0  then  begin
   Regs.CX := delt div maxword ;  Regs.DX := delt mod maxword ;
   Regs.AH := $86 ;  Intr ( $15, Regs ) ;  { Pour AT compatibles seulement ! }
end ;  end  { delay_mus } ;

The granularity is certainly more than 1 microsecond, and there is some
overhead, depending on the CPU speed. But I use this since many years.

Regards
                                            D. LOVY

  _____   Dominique LOVY, Dept. de Chimie-Physique, Universite  de  GENEVE
   /  /   30 Quai Ansermet, CH-1211 GENEVE 4 (Suisse)  l...@scsun.unige.ch
__/__/___ Tel: ++41 22 7026525  Fax: ++41 22 7026518

Other Threads