#![no_std]
mod double_buf;
use core::fmt::{Debug, Display};
use double_buf::DoubleBuf;
use embedded_hal::{nb, serial};
use heapless::Vec;
pub const STANDARD_MAX_NMEA_LEN: usize = 82;
pub struct Gps<Serial, const MAX_NMEA_LEN: usize> {
serial: Serial,
bufs: DoubleBuf<u8, MAX_NMEA_LEN>,
has_nmea: bool,
}
#[derive(Debug)]
pub enum Error<SerialError> {
Serial(SerialError),
Overflow(u8),
}
impl<SerialError> From<SerialError> for Error<SerialError> {
fn from(value: SerialError) -> Self {
Self::Serial(value)
}
}
#[cfg(feature = "defmt")]
impl<SerialError> defmt::Format for Error<SerialError>
where
SerialError: Display,
{
fn format(&self, fmt: defmt::Formatter) {
use defmt::{write, Display2Format};
match self {
Self::Serial(e) => write!(fmt, "Serial error: {}", Display2Format(&e)),
Self::Overflow(e) => write!(fmt, "Buffer overflow: {}", e),
}
}
}
impl<Serial, const MAX_NMEA_LEN: usize> Gps<Serial, MAX_NMEA_LEN> {
pub fn new(serial: Serial) -> Self {
Self {
serial,
bufs: Default::default(),
has_nmea: false,
}
}
pub fn last_nmea(&self) -> Option<Vec<u8, MAX_NMEA_LEN>> {
self.has_nmea.then(|| self.bufs.read().clone())
}
}
impl<Serial, const MAX_NMEA_LEN: usize> Gps<Serial, MAX_NMEA_LEN>
where
Serial: serial::nb::Read,
{
pub fn read_serial(&mut self) -> Result<(u8, bool), Error<Serial::Error>> {
let b = nb::block!(self.serial.read())?;
let write_buf = self.bufs.write();
write_buf.push(b).map_err(Error::Overflow)?;
let is_terminated = write_buf.ends_with(b"\r\n");
if is_terminated {
self.bufs.swap();
self.bufs.write().clear();
self.has_nmea = true;
}
Ok((b, is_terminated))
}
}
impl<Serial, const MAX_NMEA_LEN: usize> Gps<Serial, MAX_NMEA_LEN>
where
Serial: serial::nb::Write,
{
pub fn send(&mut self, input: &[u8]) -> Result<(), Error<Serial::Error>> {
for &b in input {
nb::block!(self.serial.write(b))?;
}
Ok(())
}
}