Internals
┌─────────────────────────────────────────────────────┐
│ User Application │
│ C++ / C / Python API Layer │
├───────────────────┬─────────────────────────────────┤
│ IGnssHat │ IRtk / IBase / IRover │
│ (Navigation, │ (RTCM3 corrections) │
│ Timepulse, │ │
│ TimeMark, │ │
│ GPSD) │ │
├───────────────────┴─────────────────────────────────┤
│ UBX Protocol Engine │
│ Parser ←→ Serializer ←→ Message Dispatcher │
├─────────────────────────────────────────────────────┤
│ Transport Layer │
│ SPI Driver (TxReady IRQ) │ UART Driver (epoll) │
├─────────────────────────────────────────────────────┤
│ Hardware (GPIO, SPI, UART) │
└─────────────────────────────────────────────────────┘
The library uses two threads:
- Background reader thread — reads raw bytes from SPI/UART, parses UBX messages, updates the Navigation struct
- User thread(s) — call
waitAndGetFreshNavigation()ornavigation()to read data
Synchronization:
- Mutex protects the Navigation struct — no data races
- Condition variable wakes blocking readers when new data arrives — no busy waiting
- Event-driven I/O — SPI uses TxReady GPIO interrupt, UART uses Linux epoll
The library implements the u-blox UBX binary protocol (not NMEA). Key message classes:
| Class | ID | Message | Description |
|---|---|---|---|
| NAV | 0x07 | NAV-PVT | Position, velocity, time |
| NAV | 0x35 | NAV-SAT | Satellite info |
| NAV | 0x04 | NAV-DOP | Dilution of precision |
| NAV | 0x39 | NAV-GEOFENCE | Geofence status |
| MON | 0x38 | MON-RF | RF/antenna info |
| TIM | 0x03 | TIM-TM2 | Time mark |
| CFG | — | Various | Configuration messages |
At startup, the library reads /proc/device-tree/hat/product to detect which HAT is installed. Based on the product string, it instantiates the correct implementation:
| Product String | Implementation | Transport |
|---|---|---|
| Contains “L1 GNSS HAT” | SPI-based, NEO-M9N | SPI + GPIO 17 TxReady |
| Contains “TIME” | UART-based, NEO-F10T | UART + epoll |
| Contains “RTK” | SPI + UART, NEO-F9P | SPI + UART for RTCM3 |
The GPSD forwarding creates a pseudo-terminal pair (/dev/pts/N) and optionally a symlink at /dev/jimmypaputto/gnss. A background thread converts UBX navigation data to NMEA sentences (GGA, RMC, GSA, GSV, ZDA) and writes them to the PTY slave.