From 8aa7a40fa5f6c0affd2c08259b89130c0d39fabe Mon Sep 17 00:00:00 2001 From: sawyer bristol Date: Wed, 25 Jun 2025 19:22:37 -0600 Subject: [PATCH] half display resolution --- src/display.rs | 77 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/src/display.rs b/src/display.rs index f994927..fe3f2b0 100644 --- a/src/display.rs +++ b/src/display.rs @@ -5,10 +5,10 @@ use embassy_rp::{ }; use embassy_time::{Delay, Timer}; use embedded_graphics::{ - Drawable, - pixelcolor::{BinaryColor, Rgb555, Rgb565}, - prelude::{Point, Primitive, RgbColor, Size}, - primitives::{PrimitiveStyle, Rectangle, Triangle}, + Drawable, Pixel, + pixelcolor::{Rgb565, raw::RawU16}, + prelude::{DrawTarget, OriginDimensions, Point, Primitive, RawData, RgbColor, Size}, + primitives::{PrimitiveStyle, Rectangle}, }; use embedded_hal_bus::spi::ExclusiveDevice; use st7365p_lcd::{Orientation, ST7365P}; @@ -32,15 +32,82 @@ pub async fn display_task( ); display.init(&mut Delay).unwrap(); display.set_orientation(&Orientation::Landscape).unwrap(); + let mut virtual_display = VirtualDisplay::new(display, 320 / 2, 320 / 2); let thin_stroke = PrimitiveStyle::with_stroke(Rgb565::RED, 20); Rectangle::new(Point::new(10, 10), Size::new(100, 100)) .into_styled(thin_stroke) - .draw(&mut display) + .draw(&mut virtual_display) .unwrap(); loop { Timer::after_millis(500).await; } } + +/// simple abstraction over real display & resolution to reduce frame buffer size +/// by cutting the resolution by 1/4 +struct VirtualDisplay { + display: ST7365P< + ExclusiveDevice, Output<'static>, Delay>, + Output<'static>, + Output<'static>, + >, + width: u32, + height: u32, +} + +impl VirtualDisplay { + pub fn new( + display: ST7365P< + ExclusiveDevice, Output<'static>, Delay>, + Output<'static>, + Output<'static>, + >, + new_width: u32, + new_height: u32, + ) -> Self { + Self { + display, + width: new_width, + height: new_height, + } + } +} + +impl DrawTarget for VirtualDisplay { + type Color = Rgb565; + type Error = (); + + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for Pixel(coord, color) in pixels.into_iter() { + // Check bounds on the *virtual* (already reduced) resolution + if coord.x >= 0 + && coord.y >= 0 + && coord.x < self.width as i32 + && coord.y < self.height as i32 + { + let px = coord.x as u16 * 2; + let py = coord.y as u16 * 2; + let raw_color = RawU16::from(color).into_inner(); + + // Draw the 2x2 block on the underlying hardware + self.display.set_pixel(px, py, raw_color)?; + self.display.set_pixel(px + 1, py, raw_color)?; + self.display.set_pixel(px, py + 1, raw_color)?; + self.display.set_pixel(px + 1, py + 1, raw_color)?; + } + } + Ok(()) + } +} + +impl OriginDimensions for VirtualDisplay { + fn size(&self) -> Size { + Size::new(self.width, self.height) + } +}