use core::convert::Infallible; use ag_lcd::LcdDisplay; use embassy_rp::gpio::Output; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex, signal::Signal}; use embassy_time::{Delay, Timer}; use ufmt::uWrite; pub struct ScreenBuffer { line1: [u8; 16], line2: [u8; 16], line1_ptr: u8, line2_ptr: u8, } impl ScreenBuffer { pub fn clear(&mut self) { self.line1.fill(0); self.line2.fill(0); self.line1_ptr = 0; self.line2_ptr = 0; } pub fn line1(&mut self) -> ScreenBufferWriter<'_> { ScreenBufferWriter { buf: self, line: 0 } } pub fn line2(&mut self) -> ScreenBufferWriter<'_> { ScreenBufferWriter { buf: self, line: 1 } } } pub struct ScreenBufferWriter<'a> { buf: &'a mut ScreenBuffer, line: u8, } impl<'a> uWrite for ScreenBufferWriter<'a> { type Error = Infallible; fn write_char(&mut self, c: char) -> Result<(), Self::Error> { if self.line == 0 { let ptr = self.buf.line1_ptr as usize; self.buf.line1[ptr] = c as u8; self.buf.line1_ptr = (self.buf.line1_ptr + 1) % 16; } else { let ptr = self.buf.line2_ptr as usize; self.buf.line2[ptr] = c as u8; self.buf.line2_ptr = (self.buf.line2_ptr + 1) % 16; } Ok(()) } fn write_str(&mut self, s: &str) -> Result<(), Self::Error> { for c in s.chars() { self.write_char(c)?; } Ok(()) } } impl Drop for ScreenBufferWriter<'_> { fn drop(&mut self) { LCD_UPDATE.signal(()); } } pub static SCREEN_BUFFER: Mutex = Mutex::new(ScreenBuffer { line1: [0; 16], line1_ptr: 0, line2: [0; 16], line2_ptr: 0, }); static LCD_UPDATE: Signal = Signal::new(); #[embassy_executor::task] pub async fn lcd_display_task(mut lcd: LcdDisplay, Delay>) { loop { LCD_UPDATE.wait().await; let buffer = SCREEN_BUFFER.lock().await; lcd.clear(); for byte in &buffer.line1 { lcd.write(*byte); } lcd.set_position(0, 1); for byte in &buffer.line2 { lcd.write(*byte); } Timer::after_millis(20).await; } } pub async fn overwrite_lcd(line1: &str, line2: &str) { let mut buffer = SCREEN_BUFFER.lock().await; buffer.line1_ptr = 0; buffer.line2_ptr = 0; buffer.line1.fill(0); buffer.line2.fill(0); buffer.line1[..line1.len()].copy_from_slice(line1.as_bytes()); buffer.line2[..line2.len()].copy_from_slice(line2.as_bytes()); LCD_UPDATE.signal(()); }