Prior to the actual doomsday, we plan to use DOOMSDAY as a race timer for mountain bike races. To that end we need precision time keeping. We have a 1 ms accuracy goal relative to an absolute GPS time reference. The GPS module provides time data in NEMA format as well as a one pulse per second (1pps) reference signal. When the GPS signal goes out of view, a real time clock chip keeps track of time and provides its own 1 Hertz signal: a 1 Hertz square wave.
In order to sync the 1pps signals to the real time clock square wave, I made some modifications to two libraries: Time, and TinyGPS (by Mikal Hart). Precision timing is made possible by adding a 1Hz reference to the existing library. Millisecond accuracy is obtained by keeping track of the last 1 Hz transistion and the 1 Hz duration. So in addition to the standard year(), month(), day(), hour(), minute(), and second() functions, I added millisecond() which returns an integer between 0 and 999.
Some other functions were added to support the 1Hz reference:
/* TJS: one Hertz interrupt to be called on rising edge of one Hz square wave. * Used to sync with GPS clock or other 1Hz source to get millisecond time accuracy * trigger is one of LOW, CHANGE, RISING, or FALLING */ void set_1Hz_ref(time_t current_time, int interrupt_pin, void(*cb_ptr)(), int trigger); /* * TJS: stop counting ticks. Used to sync with absolute time. */ void pause_1Hz(); /* * TJS: start counting ticks. Used to sync with absolute time. */ void unpause_1Hz();
The TinyGPS library also needed to be modified to support precision time synchronization. The key enabler is a fix notification scheme. At the heart is a user provided function that gets called when a new fix message arrives. This function was added to support this:
/* * TJS: Add a callback routine to be called when a new fix arrives. */ void TinyGPS::add_callback(fix_cb_t fct_ptr); // Example fix callback signature void grab_datetime(unsigned long _date, unsigned long _time, long lat, long lon, long alt, unsigned long speed, unsigned long course);