From b19f1ac2463a84542826f7b6c27b7bc427bb2999 Mon Sep 17 00:00:00 2001 From: Wilfred James Date: Mon, 15 Dec 2025 17:22:38 +1300 Subject: [PATCH] Add Display3in7 update_partial_frame --- src/epd3in7/command.rs | 2 + src/epd3in7/constants.rs | 34 ++++++++++++++- src/epd3in7/mod.rs | 94 +++++++++++++++++++++++++++++++++------- 3 files changed, 112 insertions(+), 18 deletions(-) diff --git a/src/epd3in7/command.rs b/src/epd3in7/command.rs index 13d44a65..0aca0eda 100644 --- a/src/epd3in7/command.rs +++ b/src/epd3in7/command.rs @@ -48,6 +48,8 @@ pub(crate) enum Command { WriteRam = 0x24, /// This command writes VCOM register from MCU interface WriteVcomRegister = 0x2C, + /// This command will transfer its data to R RAM, until another command is written + WriteRamRed = 0x26, /// This command writes LUT register from MCU interface (105 bytes), /// which contains the content of VS [nx-LUT], TP #[nX], RP #[n] WriteLutRegister = 0x32, diff --git a/src/epd3in7/constants.rs b/src/epd3in7/constants.rs index bbfbf0c6..333f7f79 100644 --- a/src/epd3in7/constants.rs +++ b/src/epd3in7/constants.rs @@ -1,4 +1,4 @@ -// This LUT clears the whole display during updates. +#[allow(unused)] pub(crate) const LUT_1GRAY_GC: [u8; 105] = [ 0x2A, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //1 0x05, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //2 @@ -13,7 +13,7 @@ pub(crate) const LUT_1GRAY_GC: [u8; 105] = [ 0x22, 0x22, 0x22, 0x22, 0x22, ]; -// This LUT updates only the pixels that have changed. +#[allow(unused)] pub(crate) const LUT_1GRAY_DU: [u8; 105] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //1 0x01, 0x2A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //2 @@ -27,3 +27,33 @@ pub(crate) const LUT_1GRAY_DU: [u8; 105] = [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //10 0x22, 0x22, 0x22, 0x22, 0x22, ]; + +#[allow(unused)] +pub(crate) const LUT_4GRAY_GC: [u8; 105] = [ + 0x2A, 0x06, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //1 + 0x28, 0x06, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //2 + 0x20, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //3 + 0x14, 0x06, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //5 + 0x00, 0x02, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x08, 0x08, 0x02, //6 + 0x00, 0x02, 0x02, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //10 + 0x22, 0x22, 0x22, 0x22, 0x22, +]; + +#[allow(unused)] +pub(crate) const LUT_1GRAY_A2: [u8; 105] = [ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //1 + 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //2 + 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //3 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //4 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //5 + 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //6 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //7 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //8 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //9 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //10 + 0x22, 0x22, 0x22, 0x22, 0x22, +]; diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c01c49fa..c88b82bf 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -50,6 +50,29 @@ pub struct EPD3in7 { background_color: Color, } +impl EPD3in7 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn reset_ram_start_end_positions(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[0x00, 0x00, 0x17, 0x01], + )?; + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[0x00, 0x00, 0xDF, 0x01], + )?; + Ok(()) + } +} + impl InternalWiAdditions for EPD3in7 where @@ -64,7 +87,7 @@ where self.interface.reset(delay, 30, 10); self.interface.cmd(spi, Command::SwReset)?; - delay.delay_us(300000u32); + delay.delay_us(10000u32); self.interface .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7])?; @@ -101,19 +124,10 @@ where self.interface.cmd_with_data( spi, Command::DisplayOption, - &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF], + &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF], )?; - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[0x00, 0x00, 0x17, 0x01], - )?; - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[0x00, 0x00, 0xDF, 0x01], - )?; + self.reset_ram_start_end_positions(spi)?; self.interface .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF])?; @@ -197,7 +211,6 @@ where Ok(()) } - #[allow(unused)] fn update_partial_frame( &mut self, spi: &mut SPI, @@ -208,12 +221,61 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - todo!() + let x_start = x; + let x_end = x + width - 1; + let y_start = y; + let y_end = y + height - 1; + + self.interface.cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[ + (x_start & 0xFF) as u8, + ((x_start >> 8) & 0x03) as u8, + (x_end & 0xFF) as u8, + ((x_end >> 8) & 0x03) as u8, + ], + )?; + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + (y_start & 0xFF) as u8, + ((y_start >> 8) & 0x03) as u8, + (y_end & 0xFF) as u8, + ((y_end >> 8) & 0x03) as u8, + ], + )?; + + self.interface.cmd_with_data( + spi, + Command::SetRamXAddressCounter, + &[(x_start & 0xFF) as u8, ((x_start >> 8) & 0x03) as u8], + )?; + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[(y_start & 0xFF) as u8, ((y_start >> 8) & 0x03) as u8], + )?; + + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; + + self.set_lut(spi, delay, Some(RefreshLut::Quick))?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF])?; + self.interface.cmd(spi, Command::DisplayUpdateSequence)?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW); + + self.reset_ram_start_end_positions(spi)?; + + Ok(()) } fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - //self.interface - // .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, &LUT_1GRAY_GC)?; + self.set_lut(spi, delay, Some(RefreshLut::Full))?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xC7])?; self.interface.cmd(spi, Command::DisplayUpdateSequence)?; self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(())