inkfish / lander-control

0 stars 0 forks source link

Extension module for timekeeping #12

Open rgov opened 9 months ago

rgov commented 9 months ago

We have two time sources that need to be integrated, the GPS PPS (#3) and RTC SQW (#1).

CircuitPython does not support interrupts except with countio. MicroPython does, with caveats. Either way, Python is not spectacular at timing-sensitive tasks.

The proposal is to have a C extension that handles interrupts on GP10 and GP26 and records some kind of monotonic timestamp: see CircuitPython time.monotonic_ns, implemented with port_get_raw_ticks, using the Pico SDK time_us_64 (though the 32-bit variant is preferable).

The delta between subsequent pulses gives us the number of ticks per 1 second (which will likely shift with temperature); we can take a rolling average. When we want to capture an accurate sub-second timestamp, we should use the current monotonic timestamp divided by the ticks per second.

Upon a GPS PPS, we should program the RTC. This will cause a 500ms offset between the GPS PPS and RTC SQW:

The 1Hz square-wave output, if enabled, transitions high 500ms after the seconds data transfer, provided the oscillator is already running.

Two SQW pulses without an intervening GPS pulse indicates a loss of the GPS signal. In this case we can use the SQW-SQW time deltas rather than GPS-GPS time deltas.

The GPS-SQW time delta can also be measured to try to calibrate the offset.

The MCAP Timestamp data type is a uint64 of the number of nanoseconds since some epoch.

rgov commented 4 months ago

I have a CircuitPython branch up here that simply tracks the monotonic timestamp (relative to the MCU clock) for each pulse: https://github.com/rgov/circuitpython/tree/rzg/pps

CircuitPython does not really let us load external modules. There are native compiled .mpy modules but they're not enabled for the RP2040 port. You also cannot access any functions from the Pico SDK that aren't exposed.