• Please review our updated Terms and Rules here

Is it safe to mess with the PIT timer modes?

PgrAm

Experienced Member
Joined
Sep 28, 2011
Messages
276
Location
Toronto, Canada
I'm messing with different ways to get high resolution timing in DOS, only now did I just realize you can simply read the counter from the PIT (good example here). However I don't need THAT much resolution (ticks at approximately 1.19 MHz), so I figure I'll just read the high byte from the timer giving me a rate of 4661 ticks per second which is good enough for me. The PIT allows you to change the mode to allow reading the high byte only as per this article, which leads to my question.

Is it safe to change the timer mode to read the high byte only and then re-enable interrupts while this change is in place? Does DOS assume that the timer is in access mode 3 (Highbyte/lowbyte) and that no program changes this? You know cause if I changed the read mode and then DOS code expecting the read mode to be different ran inside an interrupt there's no telling what would happen.

So does anybody know if DOS cares what read mode the timer is in and if so what mode does it set/expect it to be?
 
Not DOS per se, but the BIOS does maintain a 55 msec. "tick" for controlling the time of day and floppy motor control (i.e. inactivity).

One of the means for getting a finer "tick" was to increase the interrupt frequency, say by 4 times and chain your own ISR in place of the original and call the original only every 4th interrupt. Very simple and employed very often.
 
Thanks,

I know there is a 18.2 Hz tick that is supposed to be maintained, and my current interrupt manages to fake that by chaining.

I suppose I wasn't very clear, what I'm trying to do is simply read ticks at a higher resolution then the interrupt rate, this can be done with interrupts disabled even. You basically read the internal 16-bit counter which increments at a rate of 1.19 MHz regardless of the interrupt frequency, you can do this in 3 different modes, reading just the high byte, just the low byte by using "in al, 0x40" or both by latching then doing two reads. What I was wondering is if DOS or the BIOS care if you change the read mode, I suppose if they don't even bother to read the counter then I could just do whatever I want.

Using this in combination with my interrupt gives me a pretty high resolution timer that I can use to measure elapsed time (the counter resets when the interrupt is triggered so I simply just add the timer divisor to my elapsed time every time that occurs).
 
Last edited:
Sure, you can directly read the PIT counter without fouling things up. I don't think that DOS itself cares how you do it; perusing the MSDOS source doesn't show anything. There have been utilities that do just this.
 
As Chuck said, safe to read the timer at any time. It latches when you issue the read command, so if you need to read both the low and high bytes, they'll be correct at the time of the latch.

I'm curious what you hope to gain by only reading the lower resolution though. It takes almost no time to do this:

Code:
;  iMC_OpMode0=0;                       Interrupt on terminal count
;  iMC_OpMode1=2;                       Hardware-retriggerable one-shot
;  iMC_OpMode2=4;                       Rate generator
;  iMC_OpMode3=iMC_OpMode1+iMC_OpMode2; Square wave generator
;  iMC_OpMode4=8;                       Software-triggered strobe
;  iMC_OpMode5=iMC_OpMode4+iMC_OpMode1; Hardware-triggered strobe

        mov     al,(iMC_Chan0 + iMC_LatchCounter + iMC_OpMode2 + iMC_BinaryMode)
        out     43h,al          ;Tell timer about it
        in      al,40h          ;Get LSB of timer counter
        xchg    al,ah           ;Save it in ah
        in      al,40h          ;Get MSB of timer counter
        xchg    al,ah           ;Put things in the right order; AX:=starting timer

...giving you a nice 16-bit result.
 
I'm curious what you hope to gain by only reading the lower resolution though. It takes almost no time to do this:

It just has to do with the timescales I'm working on, and wanting to keep everything in a 16 bit number when these add up, because I'm going to be accumulating these timer numbers, otherwise they would overflow every ~54 ms. It makes the math I have to do later on with these timestamps easier. I suppose I may as well grab both bytes in case I need it though.

If your curious what I'm using this for is to try doing a decoupled physics/game logic loop for a game idea I had similar to what modern games do.
 
a decoupled physics/game logic loop for a game idea I had similar to what modern games do.

Ah, so you calibrate physics calcs for time unit N and then, to figure out how to keep the calcs accurate across time regardless of framerate, calc for N*M?

Is this for Chuck Jones?
 
Yeah, you got the idea. I'm using Chuck Jones to test the idea out, although it's not strictly necessary for that game but it will at least makes things a bit more playable on slow hardware. Really this is for a blades of steel style hockey game which I may make in the future.
 
Well it all seems to work.

After trying it with reduced precision, I ended up going with the full timer precision and keeping my timestamps as 32 bit values which is not that much more expensive in this case (a couple of extra adc and sbb instructions per frame). This means I need to handle overflow roughly every hour. Now Chuck Jones plays at the same speed regardless of what the frame rate is.
 
Back
Top