// Uses too much RAM to be useful ): // 320 * 240 * 2 * 2 bytes/pixel = 307KB of RAM use core::convert::Infallible; use embedded_graphics::{ draw_target::DrawTarget, geometry::{Dimensions, Point, Size}, pixelcolor::{raw::ToBytes, Rgb565}, primitives::Rectangle, Pixel, }; use crate::{ app::{HEIGHT, WIDTH}, drivers::st7789::St7789, }; pub struct BufferedDisplay { target: St7789, cur: Option<&'static mut [u8; WIDTH * HEIGHT * 2]>, } impl BufferedDisplay { pub fn new(target: St7789, cur: &'static mut [u8; WIDTH * HEIGHT * 2]) -> Self { Self { target, cur: Some(cur), } } pub fn flush(&mut self) { let buf = self.target.write_framebuffer(self.cur.take().unwrap()); self.cur = Some(buf); } } impl Dimensions for BufferedDisplay { fn bounding_box(&self) -> Rectangle { Rectangle { top_left: Point::zero(), size: Size::new(WIDTH.try_into().unwrap(), HEIGHT.try_into().unwrap()), } } } impl DrawTarget for BufferedDisplay { type Color = Rgb565; type Error = Infallible; fn draw_iter<I>(&mut self, pixels: I) -> Result<(), Self::Error> where I: IntoIterator<Item = embedded_graphics::prelude::Pixel<Self::Color>>, { for Pixel(p, c) in pixels { if let Some(idx) = index(p.x, p.y) { let bytes = c.to_be_bytes(); self.cur.as_mut().unwrap()[idx] = bytes[0]; self.cur.as_mut().unwrap()[idx + 1] = bytes[1]; } } Ok(()) } } #[inline(always)] fn index<X: TryInto<usize>, Y: TryInto<usize>>(x: X, y: Y) -> Option<usize> { let x: usize = x.try_into().ok()?; let y: usize = y.try_into().ok()?; if y >= HEIGHT || x >= WIDTH { return None; } Some((x * HEIGHT + y) * 2) }