GPS clock

Due to my workplace's lack of enthusiasm for precision time keeping (and also the fact that the clock is directly behind me when I'm at my desk), I decided to construct my own timekeeping device.

Such a device needed to be hopelessly over-engineered, of course, and so I elected to build a GPS based clock that is, according to the GPS module datasheet, accurate to 200ns.

It currently exists in a breadboard incarnation, but I plan to put it inside a sturdy diecast Aluminium box with panel mount connectors for power, GPS, and serial communication. Or maybe even THIS!

The source code is available on GitHub. Requires CCS C compiler to compile, but much of the code should be portable without too much effort.

The hardware itself is fairly simple. I have a PIC18F26K80 as the brains, an Adafruit Ultimate GPS Breakout as my GPS receiver, and a couple of 20mm OpenSegment 4 digit 7 segment displays, in red, of course.

The PIC is clocked with a 16MHz crystal, run through the 4x PLL multiplier, for a 64MHz clock speed. The PIC receives both AT+ commands through the first hardware UART, and standard NMEA strings from the GPS module through the second hardware UART. The first UART is also used to reprogram the device with the tinybld PIC bootloader. It interfaces with the displays via an SPI bus clocked at 250kHz. The SPI clock has to be run off timer2, rather than the main clock, as there is no suitable main clock scalar.

The GPS module is configured at startup to communicate at 115200 baud, and to output only GPGGA and GPZDA NMEA strings, as those are the only strings we are interested in. GPGGA provides the time, and the number of satellites, whilst GPZDA provides the date. GPZDA should also provide the timezone, but this functionality isn't included in this particular GPS module.

Finally, the displays have two different modes, one displaying the date in the format YYYY.MM.DD, and the other showing the time as . The digit separators are toggled every second whilst the clock is displaying the time, but remain on whilst displaying the date, to aid readability.

In order to enable truly accurate timekeeping, the PPS output of the GPS unit is connected to an external interrupt pin on the PIC. This allows the PIC to immediately update it's own internal timekeeping variables as soon as a new UTC second begins. However, PPS is only available with a fix of 4 or more satellites, so the PIC keeps track of the number of satellites. If there isn't a good enough quality fix for PPS, it will revert to using the NMEA strings for time to the nearest second, and it's own internal clock to more accurately track time down to hundredths of second.

Other bells and whistles include setting timezone via the AT+TIMEZONE command, and set the display brightness via the AT+BRIGHT command.