// src/display/api.rs //! Public API for the display feature. //! //! Other parts of the system use this module to send commands to the display. //! The actual rendering happens in `task.rs`. use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::channel::{Channel, Receiver, TrySendError}; use heapless::String as HString; use crate::contracts::{DisplayCommand, ImuReading}; /// Queue size for display commands. /// Moderate size to handle bursts without dropping. const QUEUE_SIZE: usize = 8; /// Channel for sending commands to the display task. pub(crate) static DISPLAY_CHANNEL: Channel = Channel::new(); /// Send a command to the display. /// /// This is async and will wait if the queue is full. /// For fire-and-forget, use `try_send`. /// /// # Example /// ```ignore /// display::api::send(DisplayCommand::SetStatus("Hello".try_into().unwrap())).await; /// ``` pub async fn send(cmd: DisplayCommand) { DISPLAY_CHANNEL.send(cmd).await; } /// Try to send a command without waiting. /// /// Returns `Err(cmd)` if the queue is full. pub fn try_send(cmd: DisplayCommand) -> Result<(), DisplayCommand> { DISPLAY_CHANNEL.try_send(cmd).map_err(|e| match e { TrySendError::Full(command) => command, }) } /// Get a receiver for display commands (internal use). /// /// Used by the display task to receive commands. pub(crate) fn receiver() -> Receiver<'static, CriticalSectionRawMutex, DisplayCommand, QUEUE_SIZE> { DISPLAY_CHANNEL.receiver() } // ───────────────────────────────────────────────────────────────────────────── // Convenience functions for common commands // ───────────────────────────────────────────────────────────────────────────── /// Send IMU data to the display. pub async fn show_imu(reading: ImuReading) { send(DisplayCommand::SetImu(reading)).await; } /// Set the status line. pub async fn set_status(text: &str) { let mut s = HString::<32>::new(); let _ = s.push_str(&text[..text.len().min(32)]); send(DisplayCommand::SetStatus(s)).await; } /// Show an error message. pub async fn show_error(text: &str) { let mut s = HString::<64>::new(); let _ = s.push_str(&text[..text.len().min(64)]); send(DisplayCommand::ShowError(s)).await; } /// Update MQTT status indicator. pub async fn set_mqtt_status(connected: bool, msg_count: u32) { send(DisplayCommand::SetMqttStatus { connected, msg_count }).await; } /// Clear the display. pub async fn clear() { send(DisplayCommand::Clear).await; }