diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..e8e7140 --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,85 @@ + +use rp2040_hal::uart::{Enabled, UartDevice, UartPeripheral, ValidUartPinout}; +use embedded_hal::serial::Write; +use heapless::spsc::Queue; + +#[derive(Debug)] +pub enum LoggerError { + OutOfMemory, + WriteError +} + +pub struct Logger +where + D: UartDevice, + P: ValidUartPinout +{ + uart: UartPeripheral, + queue: Queue, +} + +impl Logger +where + D: UartDevice, + P: ValidUartPinout +{ + pub fn new( + uart: UartPeripheral + ) -> Self + { + Logger:: { + uart, + queue: Queue::new() + } + } + + pub fn log(&mut self, msg: &[u8]) -> Result<(), LoggerError> + { + for c in msg.iter() { + match self.queue.enqueue(*c) { + Ok(_) => {}, + Err(_c) => return Err(LoggerError::OutOfMemory) + } + } + + self.process().map(|_| ()) + } + + pub fn log_fatal(&mut self, msg: &[u8]) + { + // first flush all data in the queue + self.flush(); + + // enqueue the message + let _ = self.log(msg); + + // block until it is actually handed over to the hardware + self.flush(); + } + + pub fn flush(&mut self) + { + // call process() until no more data remains in the queue + loop { + match self.process() { + Ok(more_data) => if !more_data { + break; + }, + Err(_) => break + } + } + } + + // returns whether data remains in the queue + pub fn process(&mut self) -> Result + { + while !self.queue.is_empty() && self.uart.uart_is_writable() { + match self.uart.write(self.queue.dequeue().unwrap()) { + Ok(_) => {}, + Err(_) => return Err(LoggerError::WriteError) + } + } + + Ok(!self.queue.is_empty()) + } +}