The Jr warped my brain a little bit today ...
The project is to create a highly accurate time server using a GPS directly connected to the machine. The GPS I've chosen is a Garmin 18X LVC, which is a weather-tight puck shaped receiver that communicates using a serial data stream. These are often mounted on trucks or boats, and this particular model also has an extra wire for "1PPS" (one pulse per second) which allows you to accurately detect the start of each new second. The 1PPS line can be configured to generate a pulse ranging in duration from 20 to 980ms, although 20ms works fine.
Problem #1: Com1 and Com2 are at non-standard addresses and IRQs. We use comswap or an option on jrconfig to fix this, but I was reminded of it again today. Grr.
Problem #2: The baud rate divisor number for the Jr is not the same as on any other PC. It's close but not perfect, so any software that does not use the BIOS to open the serial port is probably doing it wrong on the PCjr. The Jr starts with a 1.7895Mhz clock while the PC starts with a 1.8432Mhz clock. On the PC you take the clock and divide by 16 to get 115200. That gets divided by 24 to generate a 4800bps setting for the UART. On the Jr if you assume the source clock is the same you wind up with 4660 bps, which is quite a bit off. Adjust for the Jr and dividing by 23 instead gives you 4862, which is close enough to work but still off.
Problem #3: The machine's timer ticks ever 55ms, which is just slow. This can be reprogrammed to get millisecond accuracy, but it involves making the timer interrupt fire 64x faster. I'm don't think it crushes the machine to do that, but taken to an extreme it will make reading the UART more difficult.
Problem #4: The machine is just slow. Screen writes using the BIOS are painful. Screen scrolling is glacial.
At the moment I've got the 1PPS line hooked up to the carrier detect line on the serial port, and I have an interrupt handler that can detect when the pulse comes in. (It actually fires the interrupt twice - once when the pulse starts and once when it ends. You can tell which is which by examining the carrier detect pin.) I've also got the system timer re-programmed to be more accurate, and I can measure the duration of the pulse to within 2 milliseconds or so. (The measurements are variable, probably because of other things going on in the system.) I can read the time data from the GPS using polled I/O, and usually I get everything. You definitely have to compute the checksum though as once in a while a byte or two get dropped.
I thought I was going to be able to create a stratum-1 time server. It's not going to be that accurate, but it will still be pretty cool. (I think I can get the accuracy of the system time to within 2 milliseconds of the GPS time.)