Millisecond timing without assembly

Posted on 1998-01-29
Medium Priority
Last Modified: 2008-02-01

I am interested in having millisecond timing for
psychology experiments.  The timer...() routines below
were given to me, but dont seem to work properly on
my pentium (200 Mhz).  You will see i have been trying to
test them by timing the vertical refresh, just giving
output every second, or most recently just printing out
timer0count().  Things are generally ok for a little while
but then crazy numbers appear.  (I am making a DOS program
in Borland 5, and then running in a DOS window, or in
DOS mode)

timer0Init() seems to be the critical routine.  I am
hoping one of you can see something obviously wrong with
it, or suggest an alternative source of code.


Mark Chappell

#include <time.h>
#include <process.h>
#include <dos.h>

#include <stdio.h>


/* control register addr of 8253 timer counter chip */
#define CTRL_REG 0x0043
/* word to initialise channel 0 */
#define CTRL_INIT_WORD 0x0036
/* addr of channel 0 */
#define CH2 0x0040
/* number of system clock ticks in a timer tick */

#define CLOCK_DIVISOR 1193
/* #define CLOCK_DIVISOR 1193
       1.193 MHz divided by 1193 gives a timer tick every 1 ms */

/* BIOS interrupt number for tick generated by 8253 channel 0 */
#define TICK_INT_NR 0x1C

/* Below taken from setvect Example.  MC 25/11/97 */
#ifdef __cplusplus
    #define __CPPARGS ...
    #define __CPPARGS

static int initialised = 0;  /* false */
/* static int ch = 0, notstalled = 1 */;
static unsigned long tickCnt = 0 /* , timecount = 0 */ ;
static void interrupt (*origTickHandler)(__CPPARGS); /* arg was empty MC */
static void interrupt newTickHandler(__CPPARGS); /* arg was void MC */

void timer0Init(void), timer0Dispose(void), timer0Reset(void);
unsigned long timer0TickCount(void);

unsigned char ch;
int i, ok, c;
long arr[1000];


for(i = 0; i < 100; i++)
    printf("%u ", timer0TickCount());
/*   while(timer0TickCount() < (i + 1) * 1000)
      if(timer0TickCount() > 30000)
            printf("%d ", timer0TickCount());
   printf("\n%d ", i + 1);      */

for(i = 0; i < 0; i++)
   ok = 0;  ch = 1;
   while(ch != 0)
      ch = inportb(0x3DA)&8;
/*      ok++;
      printf("h1 %X ", ch);
      if(ok > 1000)
            exit(0);              */
  /*    printf("\n");                */

       while(ch == 0)
            ch = inportb(0x3DA)&8;
/*       ok++;
     printf("h2 %X ", ch);
      if(ok > 1000)
            exit(0);            */
/*   printf("\n");                   */

arr[i] = timer0TickCount();

   printf("%u ", timer0TickCount());


for(i = 0; i < 100; i++)
      printf("%ld ", arr[i]);

void timer0Init(void)
      if (!initialised)
            initialised = 1;  /* true */
            /* install new ISR for bios tick interrupt, and save
current one */
            origTickHandler = getvect(TICK_INT_NR);
            setvect(TICK_INT_NR, newTickHandler);
            /* set channel 0 count period */
            outport(CTRL_REG, CTRL_INIT_WORD);
             outportb(CH2, CLOCK_DIVISOR & 0x00FF); /*  LSB     */
            outportb(CH2, CLOCK_DIVISOR >> 8);  /* MSB */
   /*   outportb(CH2, CLOCK_DIVISOR);      */
        /* init tick count */
      tickCnt = 0;

void timer0Dispose(void)
      if (initialised)
            initialised = 0;  /* false */
            /* restore channel 0 count period to 18.203 Hz */
            outport(CTRL_REG, CTRL_INIT_WORD);
            outportb(CH2, 0);
            outportb(CH2, 0);
            /* reinstall original ISR for bios tick */
            setvect(TICK_INT_NR, origTickHandler);

/* the new interrupt handler for the BIOS tick interrupt */
static void interrupt newTickHandler(__CPPARGS)

void timer0Reset(void)
      tickCnt = 0;

unsigned long timer0TickCount(void)
      return (tickCnt);
Question by:markc2
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions

Expert Comment

ID: 1257119
I have a similar piece of code which essently times the vertical retrace which I wrote a while back. Just having a quick look at it, I have at the very end of my interrupt handler the following
This was with BC3.11 and I'm not sure if you'll need it with BC5. Also BC3.11 docs say don't compile with 'Test stack overflow' on, I don't know if you are doing this or it is required with BC5.

Just a few thoughts.

LVL 15

Accepted Solution

Tommy Hui earned 300 total points
ID: 1257120
If this is running on a Pentium, you can use its time counter, using the rdtsc instruction. There's code to do this with Visual C++, you search for pentium counter on the web. There may be code to do this with Borland C++. The counter is maintained by the hardware, so it is very accurate. You might want to search the web for the Zen Timer by Michael Abrash.

Author Comment

ID: 1257121
Thanks, i found ztimer22.zip, after a bit.  I am wondering
if there is a more recent version (it seems to be early
to mid 96); i cant seem to find it.  With this i seem
to be getting sensible timing.

Featured Post

What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Windows programmers of the C/C++ variety, how many of you realise that since Window 9x Microsoft has been lying to you about what constitutes Unicode (http://en.wikipedia.org/wiki/Unicode)? They will have you believe that Unicode requires you to use…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand and use switch statements in the C programming language.

801 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question