I pulled an all-nighter last night and wrote a first cut of the firmware. It was pretty heavily influenced by the previous work I'd done. It's mostly interrupt driven. There are interrupt handlers for the ICP capture interrupt and an overflow handler used to extend the number of bits of the 20 MHz counter.
The non-interrupt driven portion of the program mostly camps out on the serial port waiting for NEMA sentences. We wait for $GPGSA, and check for whether the fix is 3D or not. If it's not, then the GPS is not locked. The oscillator is allowed to free-run whenever that's the case. Immediately after the GPS becomes locked, we begin acquiring samples. After the sample buffer is full if the total drift within the sample window is below a threshold, we'll indicate a lock. If the drift is within a relatively small window, we'll "nudge" the oscillator by a single trim unit (which is only ~0.2 ppb). If the drift value is larger than that, we'll hit it in proportion to how far out it is, but only up to a maximum value.
Every four hours of running time, we update a location in EEPROM with the trim value, and reload that at startup, hopefully reducing the lock time on restart. Of course, adding a CR1220 battery to the board will allow the GPS to warm-start and obtain a fix much more quickly as well.
At the moment, the firmware is written in the Arduino IDE and it uses digitalWrite(), Serial and delayMicroseconds(), but that's quite wasteful, and that's not counting the timer0 mills() interrupt infrastructure for which we have no use. I'm fairly confident the raw AVR libc equivalents could be used instead, resulting in much more lean and efficient code, and after the initial proof of concept, I hope to do just that.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.