Step 38 of 56
GPS: a background service, not a device handle
The one driver here you do not poll through a handle. A task owns the UART, decodes NMEA continuously, and publishes into a protected store that timestamps its own staleness.
A different shape entirely
Every other device driver in this guide hands you a
Device and lets you poll it. This one does not. It is a
singleton background service: a library-level task owns one
UART for its lifetime, continuously reads the
receiver's NMEA-0183 stream, decodes it, and publishes results into a protected
store. The application just reads that store. There is no handle.
That follows from the device: a GPS talks whenever it likes, so something has to be listening the whole time. This is the concrete case for interrupt-driven RX — a receiver that streams asynchronously is exactly what would overflow a polled FIFO.
procedure Setup (...); -- call once at startup; Rx is the only pin needed
function Current_Position return Position_Reading;
function Current_Fix return Fix_Reading;
function Current_Time return Time_Reading;
function Current_Date return Date_Reading;
-- ... plus velocity, signal and PPS readings
Why a fix is one record
Latitude and longitude are a single
Position record updated by one protected action. Split
across two variables, a reader could catch a new latitude with an old longitude
— a coordinate that describes somewhere you have never been, with nothing
to signal it is wrong. Every published value is written and read under the
store's lock, so a reader never sees a half-updated value, and a fix is always a
consistent pair.
Staleness is explicit
Each value group carries the Ada.Real_Time.Time at which it was
last refreshed, and the driver only refreshes a group from a valid
sentence — a lost fix is not written at all.
So a stale group keeps its old timestamp rather than
being cleared, and Current_Position will happily return a position
from twenty minutes ago that reads as perfectly plausible. Compare
Age (R.Updated_At) against your own tolerance before trusting any
reading. The API cannot decide for you how old is too old — that depends on
whether you are tracking a ship or a pedestrian.
type Fix_Quality is (No_Fix, GPS_Fix, DGPS_Fix);
type Fix_Type is (Fix_None, Fix_2D, Fix_3D);
type GNSS_System is (GPS, GLONASS, Galileo, BeiDou, QZSS, Other);
The satellite list and GNSS_System reflect that a modern receiver
tracks several constellations at once. Uses the controlled UART session plus a
task and protected objects, so it is embedded/full only.