Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

I Need a millesecond Timer under DOS ?

1,193 views
Skip to first unread message

Lester Masher

unread,
Oct 14, 1998, 3:00:00 AM10/14/98
to
Hi

Is it at all possible to implement a timer at a millescond resolution under
DOS.
I need to interrupt every 15 millesconds.
The BIOS clock tick function has a resolution of 55 ms i.e an interrupt is
generated 18.2 times per second. But this is not good enough for what I need
to do.

Is three any other way in assembler ?

Thank You.

device

unread,
Oct 14, 1998, 3:00:00 AM10/14/98
to
I think there are ways to reprogram the clock to generate more higher
resolution tics.

Dave

Oliver Kreylos

unread,
Oct 14, 1998, 3:00:00 AM10/14/98
to

Yes, there are. I am using a custom timer resolution in my game, here's
what you have to do to
a) set the timer to 1ms resolution
b) keep the DOS clock going correctly nonetheless

Just reprogramming the timer chip without some book-keeping would let
the DOS clock run 18 times as fast. We don't want that...

--8<------------------------------------------------------------

typedef void (__interrupt __far* INTFUNCPTR)(void);

INTFUNCPTR oldTimerInterrupt; // Original interrupt handler

volatile long int milliseconds; // Elapsed time in milliseconds

void __interrupt __far timerHandler(void)
{
static unsigned long count=0; // To keep track of original timer ticks
++milliseconds;
count+=1103;
if(count>=65536) // It is now time to call the original handler
{
count-=65536;
_chain_intr(oldTimerInterrupt);
}
else
outp(0x20,0x20); // Acknowledge interrupt
}

void installInterrupt(void)
{
union REGS r;
struct SREGS s;
_disable();
segread(&s);
/* Save old interrupt vector: */
r.h.al=0x08;
r.h.ah=0x35;
int386x(0x21,&r,&r,&s);
oldTimerInterrupt=(INTFUNCPTR)MK_FP(s.es,r.x.ebx);
/* Install new interrupt handler: */
milliseconds=0;
r.h.al=0x08;
r.h.ah=0x25;
s.ds=FP_SEG(timerHandler);
r.x.edx=FP_OFF(timerHandler);
int386x(0x21,&r,&r,&s);
/* Set resolution of timer chip to 1ms: */
outp(0x43,0x36);
outp(0x40,(unsigned char)(1103&0xff));
outp(0x40,(unsigned char)((1103>>8)&0xff));
_enable();
}

void removeInterrupt(void)
{
union REGS r;
struct SREGS s;
_disable();
segread(&s);
/* Re-install original interrupt handler: */
r.h.al=0x08;
r.h.ah=0x25;
s.ds=FP_SEG(oldTimerInterrupt);
r.x.edx=FP_OFF(oldTimerInterrupt);
int386x(0x21,&r,&r,&s);
/* Reset timer chip resolution to 18.2...ms: */
outp(0x43,0x36);
outp(0x40,0x00);
outp(0x40,0x00);
_enable();
}

--8<------------------------------------------------------------

To query the elapsed time in ms, just read the variable milliseconds.

A note: This program is for Watcom C. For other compilers, some
structures and functions (like _enable) might have different names.
Refer to your compiler's manual.

A second note: This program is for Protected Mode using DOS/4G. To
compile it for real mode, just replace all int386 by int86, and all wide
registers (like edx) with their short counterparts (like dx). The
program should work fine then.

I hope this helps a bit,
Oliver

David Lindauer

unread,
Oct 15, 1998, 3:00:00 AM10/15/98
to

Lester Masher wrote:

um, how accurate do your numbers need to be? For audio work it used to be
fairly common to jump the int 8 clock up to 27.8 hz, which gives an interval of
about 13.8ms. Is that close enough? If not we can get you a little closer, I
forget what the tolerance is but by using the RTC clock you can get somewhere
close to a millisecond interrupt, probably on a 15ms interval you can do between
14.5 and 15ms using it.

If you HAVE to be right on 15 Ms, there is probably a value to get fairly close
to it using the int 8 clock, however, unless you want to do complex coding you
will NOT be able to keep the MSDOS time running right. But it doesn't anyway...
it loses several minutes a day I think because they rounded that 18.2 off to
18...

David

David

> Thank You.

--
---------------------------------------------------------------
David Lindauer mailto:cam...@bluegrass.net ICQ: 8699592

http://www.geocities.com/Area51/Station/5196/index.html (home page)
http://www.geocities.com/Area51/Station/5196/ttc.html (tao te ching)
http://www.geocities.com/Area51/Station/5196/treasure.html (computer page)

Martijn Lievaart

unread,
Oct 15, 1998, 3:00:00 AM10/15/98
to
Oliver Kreylos wrote in message
<362576...@gallagher.cipic.ucdavis.edu>...

>device wrote:
>>
>> I think there are ways to reprogram the clock to generate more higher
>> resolution tics.
>>
>> Dave
>
>Yes, there are. I am using a custom timer resolution in my game, here's
>what you have to do to
>a) set the timer to 1ms resolution
>b) keep the DOS clock going correctly nonetheless
>
>Just reprogramming the timer chip without some book-keeping would let
>the DOS clock run 18 times as fast. We don't want that...
>

(snip)

>To query the elapsed time in ms, just read the variable milliseconds.
>
>A note: This program is for Watcom C. For other compilers, some
>structures and functions (like _enable) might have different names.
>Refer to your compiler's manual.
>
>A second note: This program is for Protected Mode using DOS/4G. To
>compile it for real mode, just replace all int386 by int86, and all wide
>registers (like edx) with their short counterparts (like dx). The
>program should work fine then.
>


And a third note, to make it reliable under real mode you have to hook the
program termination vector to unhook this interrupt if your program dies on
you (critical error, Ctrl-break, divide by zero etc). You may be able to
circumvent most of these but it is easier to circumvent them all. Mail me if
you need a program snippet (see sig for real address, replies go to
/dev/null).

Martijn
--
Microsoft logic. Add signature under dash-dash-space.
Then strip all trailing spaces (Outlook Express 4.71)
My email address is intentionally invalid against spam
reply to mlievaart at orion in nl


BobGardner

unread,
Oct 15, 1998, 3:00:00 AM10/15/98
to
>Is it at all possible to implement a timer at a millescond resolution under
>DOS.
>I need to interrupt every 15 millesconds.
>The BIOS clock tick function has a resolution of 55 ms i.e an interrupt is
>generated 18.2 times per second. But this is not good enough for what I need
>to do.
>
>Is three any other way in assembler?
No, four is the way in assembler (haha)

Timer channel 0 has a time constant of 0, so it generates its interrupt every
65536 ticks of the 1.19 MHz clock it is counting. If you change the time
constant to 6553 it will interrupt 10x faster or every 5.5ms. Then you must
call the old clock handler every 10th interrupt to keep the clock at the right
time. If you dont care about the clock running 10x faster, ok.

Joe Hagen

unread,
Oct 16, 1998, 3:00:00 AM10/16/98
to
I used a technique similar to this in a 16 bit real-mode program.

There's another note: the 32 bit access won't be coherent in
16 bits unless 386 opcodes are being used to access the variable.

Using 16 bit instructions, the compiler typically generates two MOV
instructions using AX and DX, but these instructions could be interrupted.

If you're not using 386 opcodes, which can do a MOV EAX,milliseconds
then the access needs to be protected with a CLI/STI sequence.

Joe
jdh...@itis.com

Kris Heidenstrom

unread,
Oct 17, 1998, 3:00:00 AM10/17/98
to Lester Masher
Lester Masher wrote:

> Is it at all possible to implement a timer at a millescond resolution
> under DOS. I need to interrupt every 15 millesconds.
> The BIOS clock tick function has a resolution of 55 ms i.e an
> interrupt is generated 18.2 times per second. But this is not good
> enough for what I need to do.

Yes, as several others have said, you can do this by hooking int 8 and
running the timer at a higher rate.

I have a few things to add. First, the timer's input clock runs at
14.31818/12 MHz which doesn't divide exactly into 15 ms, but you
can get the interrupt at intervals of exactly 15 ms by alternating
between two divisors. You do this by reprogramming the count value
when necessary, within the interrupt handler. Don't rewrite the
mode word, since this stops and restarts the counter. You just write
the new divisor value (lobyte then hibyte) to the counter register.
This gives you zero cumulative error in your timekeeping, if that is
important. Of course you still have the error caused by the
inaccuracy of the 14.31818 MHz crystal!

Second, speeding up the timer tick can have implications for the
performance of the program. A faster tick rate increases the
overhead, though a tick rate of 67 Hz is still very slow and won't
cause a problem. Also various bits of software disable interrupts
for various lengths of time; the faster you run the tick interrupt,
the more noticeable the latency and interrupt timing jitter, caused
by interrupts being disabled by foreground code, will become. Again
this is unlikely to be a problem at 67 Hz, but could be a problem
in future if you want to increase the interrupt rate.

All the techniques and warnings (including the others mentioned
in this thread - at least those that I've seen) are covered in detail
in my PC Timing FAQ document which you can get as:

ftp://ftp.simtel.net/pub/simtelnet/msdos/info/pctim003.zip
or ftp://ftp.cdrom.com/pub/simtelnet/msdos/info/pctim003.zip

Good luck

Kris
--
Kris Heidenstrom Electronic designer and programmer
khei...@clear.net.nz http://home.clear.net.nz/pages/kheidens/
Work: kr...@abbey.co.nz Wellington, New Zealand

ra...@telerama.lm.com.xxx.us

unread,
Oct 19, 1998, 3:00:00 AM10/19/98
to
In article <3625809D...@bluegrass.net>,

David Lindauer <cam...@bluegrass.net> wrote:
}to it using the int 8 clock, however, unless you want to do complex coding you
}will NOT be able to keep the MSDOS time running right. But it doesn't anyway...
}it loses several minutes a day I think because they rounded that 18.2 off to
}18...

If it loses several minutes a day you have a REALLY bad crystal oscillator
in your system. MS has made boneheaded moves aplenty, but in this case, the
time is computed to better accuracy than most crystals support (even 18.2 is
a very lame approximation compared to the value that MS-DOS's clock driver
actually uses).

BTW, the difference between 18.0 and 18.2 ticks per second amounts to over
17 minutes per day.

--
-=- mailto:ralf%pobox.com%solicitations-c...@127.0.0.1 -=-
"The Internet is like a freight train roaring along while people are laying
tracks in front of it. It's not just gaining on those laying tracks; it's
gaining on the steel mills." -- Matt Mathis -=- #include <disclaimer> -=-


Game Corner Playthroughs

unread,
Dec 21, 2021, 3:08:45 PM12/21/21
to
On Wednesday, October 14, 1998 at 3:00:00 AM UTC-4, Oliver Kreylos wrote:
> device wrote:
> >
> > I think there are ways to reprogram the clock to generate more higher
> > resolution tics.
> >
> > Dave
> Yes, there are. I am using a custom timer resolution in my game, here's
> what you have to do to
> a) set the timer to 1ms resolution
> b) keep the DOS clock going correctly nonetheless
> Just reprogramming the timer chip without some book-keeping would let
> the DOS clock run 18 times as fast. We don't want that...
> To query the elapsed time in ms, just read the variable milliseconds.
> A note: This program is for Watcom C. For other compilers, some
> structures and functions (like _enable) might have different names.
> Refer to your compiler's manual.
> A second note: This program is for Protected Mode using DOS/4G. To
> compile it for real mode, just replace all int386 by int86, and all wide
> registers (like edx) with their short counterparts (like dx). The
> program should work fine then.
0 new messages