From 05e927d0a8ff47f2ae43045d03034c1426cc3d23 Mon Sep 17 00:00:00 2001 From: Zac Wilson Date: Thu, 18 Dec 2025 10:24:33 +0000 Subject: [PATCH] Added support for partial window tracking --- src/lib.rs | 141 +++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 132 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ef014a2..1682658 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] //! This library is an embedded-hal based driver implementation for the GDEQ031T10 e-paper display. -//! +//! //! **Note**: 9-bit SPI mode (where the data/command is designated with an extra bit for each byte) //! is not supported by this driver. Only the mode with a dedicated data/command line is supported. @@ -27,7 +27,7 @@ pub struct EPaperDisplay { /// An error that may occur during display initialisation. pub enum InitError { /// This variant is for any error with setting the level of the reset pin. - /// + /// /// This variant may be uninhabited if the `ResetPin` type parameter for [EPaperDisplay] is one that /// doesn't produce errors. ResetError(ResetError), @@ -38,7 +38,7 @@ pub enum InitError { /// An error when trying to communicate with the display controller. pub enum WriteError { /// This variant is for any error with setting the level of the DC (Data/Command) pin. - /// + /// /// This variant may be uninhabited if the `DcPin` type parameter for [EPaperDisplay] is one that /// doesn't produce errors. DcError(DcError), @@ -58,9 +58,10 @@ impl Frame { } } -pub struct DoubleFrame { +pub struct DoubleFrame { old: Frame, new: Frame, + partial_window: PartialWindow, } pub enum PixelColour { @@ -68,13 +69,126 @@ pub enum PixelColour { White = 1, } -impl DoubleFrame { +pub trait ApplyParitalWindow: private::Sealed { + fn apply< + BusyPin: InputPin, + ResetPin: OutputPin, + DcPin: OutputPin, + Spi: SpiDevice, + Delay: DelayNs, + >( + &self, + display: &mut EPaperDisplay, + ); + + fn update_partial_window(&mut self, min_x: u16, max_x: u16, min_y: u16, max_y: u16); + + fn reset_partial_window(&mut self); +} + +mod private { + pub(super) trait Sealed {} + + impl Sealed for super::NoPartialWindow {} + + impl Sealed for super::AutomaticPartialWindow {} +} + +pub struct NoPartialWindow; + +impl ApplyParitalWindow for NoPartialWindow { + fn apply< + BusyPin: InputPin, + ResetPin: OutputPin, + DcPin: OutputPin, + Spi: SpiDevice, + Delay: DelayNs, + >( + &self, + _display: &mut EPaperDisplay, + ) { + } + + fn update_partial_window(&mut self, _min_x: u16, _max_x: u16, _min_y: u16, _max_y: u16) {} + + fn reset_partial_window(&mut self) {} +} + +pub struct AutomaticPartialWindow { + min_x: u16, + max_x: u16, + min_y: u16, + max_y: u16, +} + +impl ApplyParitalWindow for AutomaticPartialWindow { + fn apply< + BusyPin: InputPin, + ResetPin: OutputPin, + DcPin: OutputPin, + Spi: SpiDevice, + Delay: DelayNs, + >( + &self, + display: &mut EPaperDisplay, + ) { + let hrst = self.min_x as u8 & 0b11111000; + let hred = self.max_x as u8 | 0b111; + let vrst = self.min_y & 0x1FF; + let vred = self.max_y & 0x1FF; + display.write_command(0x90); + display.write_data(hrst); + display.write_data(hred); + display.write_data((vrst >> 8) as u8); + display.write_data((vrst & 0xFF) as u8); + display.write_data((vred >> 8) as u8); + display.write_data((vred & 0xFF) as u8); + display.write_data(0x00); + } + + fn update_partial_window(&mut self, min_x: u16, max_x: u16, min_y: u16, max_y: u16) { + self.min_x = core::cmp::min(self.min_x, min_x); + self.max_x = core::cmp::max(self.max_x, max_x); + self.min_y = core::cmp::min(self.min_y, min_y); + self.max_y = core::cmp::max(self.max_y, max_y); + } + + fn reset_partial_window(&mut self) { + *self = AutomaticPartialWindow { + min_x: EPD_WIDTH as u16, + max_x: 0, + min_y: EPD_HEIGHT as u16, + max_y: 0, + } + } +} + +impl DoubleFrame { pub fn new(old: Frame, new: Frame) -> Self { - Self { old, new } + Self { + old, + new, + partial_window: NoPartialWindow, + } } pub fn draw_pixel(&mut self, x: usize, y: usize, colour: PixelColour) { + todo!() + } +} +impl DoubleFrame { + pub fn new_with_automatic_partial_window(old: Frame, new: Frame) -> Self { + Self { + old, + new, + partial_window: AutomaticPartialWindow { + min_x: EPD_WIDTH as u16, + max_x: 0, + min_y: EPD_HEIGHT as u16, + max_y: 0, + }, + } } } @@ -158,7 +272,8 @@ impl(&mut self, double_frame: &mut DoubleFrame) { + double_frame.partial_window.apply(self); self.write_command(0x10); for byte in double_frame.old.0 { self.write_data(byte); @@ -175,12 +290,20 @@ impl