Page 2 of 3

Re: GPS project

Posted: Mon Jun 08, 2020 5:37 pm
by Brutman
I tried to read that post on my laptop and it got really warm and then started emitting smoke. Google Translate also couldn't tell what language that was in. However, that sounds like a really neat project. Is there a Python program or a pre-compiled binary for Windows 10 available?

Re: GPS project

Posted: Mon Jun 08, 2020 6:05 pm
by alanh
What part of 'dead on balls accurate' is hard to understand? :)

The cliff notes version is no local oscillator is 100.00000% accurate to the frequency printed on the can. You know this, hence the problem you are trying to solve with GPS.

So get an oscillator with a +/- fine frequency adjustment. Count the number of ticks between GPS pulses per second. If the tick count is smaller than the desired frequency, turn up the fine adjustment knob. If it's higher, turn down the fine adjustment knob. Create a PID loop to do this automatically every second. Bingo, you have a local oscillator that averages to 100.00000000% accuracy (or however accurate GPS is at least). Let the frequency you choose be 14.318 MHz (the crystal frequency of a 4.77 MHZ 8088 like the PCjr) and use your shinny dead on balls accurate oscillator as the system clock reference. Now you don't have to write any Python, run any Windows 10, or any of that Satan-worshiping software stuff!!!

Re: GPS project

Posted: Mon Jun 08, 2020 6:29 pm
by Brutman
So you causally throw in a control system and you talk about the rest of us being Satan worshippers? :-)

Re: GPS project

Posted: Tue Jun 09, 2020 11:09 am
by alanh
alanh wrote:For example, 5% duty would be 14318181 - (75 * .05) Hz, where a 95% duty would be 14318181 + (75 * .95) Hz.
Just correcting my math:

5% duty would be 14318181 - (75 * 14.31 * .95) Hz (, where a 95% duty would be 14318181 + (75 * 14.31 * .95) Hz.

So 14317161 MHz (5%) to 14319212 MHz (95%)

Re: GPS project

Posted: Sun Jul 05, 2020 12:34 pm
by Brutman
So I got back to this project and I decided to try mode 2 of the 8253 timer out. Short story, it works ...

This code is better because it doesn't change the interrupt interval from the 8253 like the previous code, so that interrupt is firing back at the normal 18.2 times per second. I had it firing 64x faster before which is slightly noticeable on the machine, and also raises the chances than an interrupt will be missed. The biggest challenge was doing the math correctly without doing floating point. I'm using 32 bit integers to keep things faster than using emulated floating point, and it is slightly sloppy but it works.

I think my timing resolution is comfortably under 1ms now where before it was in the 1 to 2ms range. When the GPS 1PPS causes an interrupt I increment my own "seconds since the epoch" counter, the BIOS ticks and the 8253 counter are read and squirreled away. The interrupt gets handled, my code resumes, and it sees that the interrupt has recently fired. It then snapshots the BIOS ticks and 8253 counter again, does the math, and computes the current timestamp. This is taking on the order of 600 to 700 microseconds to do. (Screen access time is not counted; it's just the time to finish the interrupt handler, get back to the main program loop, figure out the time needs to be displayed, and then compute the current time.)

Assuming 650 microseconds and machine running at 4.77Mhz that works out to 3100 clock cycles. I actually have a V20 which is slightly better than the stock 8088 but the machine is running C code that isn't highly optimized and it's still doing integer division on the math. This doesn't seem unreasonable, and if I can knock off a few division instructions I can save a lot of clock cycles. (Shifting 10 bits right instead of dividing by 1000 would save a lot of cycles at the expense of some accuracy.)


Mike

Re: GPS project

Posted: Sun Aug 15, 2021 5:34 pm
by Brutman
Another project update, and some shade to throw at the PCjr ...

To recap there are two basic approaches to improve the timer resolution on a PC:
  • Keep the 8253 ticking at the same rate, but try to read its internal counters too.
  • Speed up the 8253 timer to tick more often.
The first option preserves the standard 55ms BIOS tick, but it allows you to read the time in between ticks. There is a counter in the 8253 that you read, and based on the value of the counter you can tell how far into the 55ms time period you are. It also doesn't really work because it requires you to snapshot both the BIOS time and the 8253 counter simultaneously, and there is no way to do that. There is always a small window of error, and that error can result in a 55ms glitch. It is a great technique for measuring code that runs in less than 55ms .. just disable interrupts, snapshot the 8253 counter, run your code, get another snapshot, and compute the difference. You can get microsecond accuracy from it. You just can't measure things larger than 55ms.

The second option makes the 8253 tick faster. You add your own interrupt handler to count the faster ticks, and every so often you call the BIOS handler to update the BIOS time. This gives you faster ticks while still keeping the BIOS/DOS time accurate. You can speed up the tick rate by 64x to get to 1ms timing accuracy. My mTCP Ping code uses this technique.

Well, that approach doesn't work great on a PCjr because even when just sitting around doing nothing, the machine loses interrupts when ticking at the faster rate. Over a 15 minute period it might only lose 100 to 200ms, and that is pretty sad. The machine is fine with a normal 55ms tick, but ticking 16x faster or more causes interrupts to be lost. And if you use the keyboard the situation is worse because the PCjr uses the non-maskable interrupt line to decode the keyboard. In contrast, my 386-40 has no problems even with a 128x faster tick rate.

So what does this mean?

I'm going with the second approach, even though timer ticks are being lost. While that is sad, it is not too much of a problem because the GPS fires an interrupt every second, so I only have to worry about how many timer ticks are lost in a second. (The 15 minute period I measured over is 900x longer than I need to worry about, which is extreme.) Running the 8253 64x faster gives 0.85ms resolution, or 1165 ticks per second. Every tick that gets lost throws away 0.85ms, but I doubt more than 2 ticks per second are getting lost. So on a PCjr I'll have to settle for times that are within 5ms of the GPS. That is acceptable for DOS. ;-0

Faster machines should not have any problems with lost interrupts. My 386-40 has been running 30 minutes and the time has not drifted by a measurable amount yet, and that is running the 8253 128x faster. (That gives it better than 0.5ms of timing resolution.)

The GPS part of the code is done. Next I need to turn it into an SNTP (Simple NTP) server. Stay tuned ...

Re: GPS project

Posted: Sun Aug 29, 2021 8:46 pm
by Trixter
How are you detecting that the PCjr is losing ticks just sitting idle?

Re: GPS project

Posted: Sun Aug 29, 2021 10:48 pm
by Brutman
Basically using a stopwatch ...
  • Synchronize DOS time to GPS time. DOS time measures down to two decimal places, but the BIOS timer tick is still 55ms so DOS time can be off by as much as 0.05 seconds.
  • Let the machine sit. While it is sitting it takes an interrupt from the GPS once a second and the timer interrupt hook gets hit 64 or 128 times faster than the regular timer interrupt.
  • Measure the drift on the DOS time vs. the GPS time after 10 minutes. Up to 0.11 seconds is assumed normal because of the BIOS tick is 55ms. I'm seeing much more than that amount of time being lost - DOS time is slower by up to .3 or .5 seconds. (There is some variability to it.)
When I don't hook the timer interrupt and make it tick faster things are fine. Or even if I do, making the interrupt tick up to 16x faster is generally fine. But at 32x faster or more the time starts to drift quite a bit. I'm not touching the keyboard or doing anything else, so the lost interrupts are probably just the timer ticks getting missed. If I touch the keyboard I can really cause the time to drift, but that's not fair on a PCjr.

A 386 with the same code is solid, even when ticking 128x faster than the normal 18 times a second.

Re: GPS project

Posted: Tue Aug 31, 2021 5:04 pm
by Trixter
The lost time is likely due to extended time spent in an interrupt handler and/or with interrupts disabled.

The BIOS updates the value in the BDA at 40:6C; a quick look at the PCjr BIOS source doesn't show anything egregious in either 08h or 1ch, so maybe DOS is doing something stupid or costly. DOS runs in the slower 128K, so anything dumb gets amplified on a PCjr.

Re: GPS project

Posted: Tue Aug 31, 2021 5:39 pm
by Brutman
I scrubbed the code pretty hard and limited the times when I disabled interrupts.

While DOS generally is resident in the first 128K of memory (which is slow), my program was active and not really doing anything that required DOS. Interrupt handling and things that touch low memory will be slow, but the machine was not primarily running from that region of memory.

When I dust off an XT I'll see if it has this problem too. It will be interesting to see if this is a "PCjr is slow" issue or "slow machines are slow" issue.


Mike