103 lines
2.6 KiB
Rust
103 lines
2.6 KiB
Rust
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<CriticalSectionRawMutex, ScreenBuffer> = Mutex::new(ScreenBuffer {
|
|
line1: [0; 16],
|
|
line1_ptr: 0,
|
|
line2: [0; 16],
|
|
line2_ptr: 0,
|
|
});
|
|
|
|
static LCD_UPDATE: Signal<CriticalSectionRawMutex, ()> = Signal::new();
|
|
|
|
#[embassy_executor::task]
|
|
pub async fn lcd_display_task(mut lcd: LcdDisplay<Output<'static>, 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(());
|
|
}
|