diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 95ed53b..2927730 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -175,21 +175,19 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here or would 0x01 be even more efficient? self.interface .cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?; - - self.wait_until_idle(); Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.use_full_frame(spi)?; self.interface .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; - - self.wait_until_idle(); Ok(()) } @@ -203,17 +201,17 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_counter(spi, x, y)?; self.interface .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; - - self.wait_until_idle(); Ok(()) } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface @@ -223,12 +221,17 @@ where // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send self.interface.cmd(spi, Command::NOP)?; + Ok(()) + } - self.wait_until_idle(); + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.use_full_frame(spi)?; // clear the ram with the background color @@ -237,8 +240,6 @@ where self.interface.cmd(spi, Command::WRITE_RAM)?; self.interface .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - - self.wait_until_idle(); Ok(()) } @@ -297,6 +298,7 @@ where end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { + self.wait_until_idle(); assert!(start_x < end_x); assert!(start_y < end_y); @@ -319,8 +321,6 @@ where (end_y >> 8) as u8, ], )?; - - self.wait_until_idle(); Ok(()) } @@ -330,6 +330,7 @@ where x: u32, y: u32, ) -> Result<(), SPI::Error> { + self.wait_until_idle(); // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface @@ -341,18 +342,15 @@ where Command::SET_RAM_Y_ADDRESS_COUNTER, &[y as u8, (y >> 8) as u8], )?; - - self.wait_until_idle(); Ok(()) } fn set_lut_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); assert!(buffer.len() == 30); self.interface .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?; - - self.wait_until_idle(); Ok(()) } } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 75bd987..52d402f 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -100,6 +100,7 @@ where black: &[u8], red: &[u8], ) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; self.interface @@ -113,8 +114,6 @@ where self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface.data(spi, red)?; - - self.wait_until_idle(); Ok(()) } } @@ -147,6 +146,7 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating @@ -190,6 +190,7 @@ where } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; self.interface @@ -212,8 +213,6 @@ where self.interface.data_x_times(spi, color, nbits)?; //NOTE: Example code has a delay here - - self.wait_until_idle(); Ok(()) } @@ -227,17 +226,23 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - Ok(()) + unimplemented!() } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; + Ok(()) + } - self.wait_until_idle(); + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -255,8 +260,6 @@ where .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; - - self.wait_until_idle(); Ok(()) } diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 3bd61db..28c283b 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -87,6 +87,8 @@ where ) -> Result<(), SPI::Error> { self.interface.reset(delay); + self.wait_until_idle(); + // 3 Databytes: // A[7:0] // 0.. A[8] @@ -166,12 +168,11 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) self.interface .cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?; - - self.wait_until_idle(); Ok(()) } @@ -180,19 +181,17 @@ where spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.init(spi, delay)?; - self.wait_until_idle(); + self.init(spi, delay)?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.use_full_frame(spi)?; self.interface .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; - - self.wait_until_idle(); Ok(()) } @@ -206,17 +205,17 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_counter(spi, x, y)?; self.interface .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; - - self.wait_until_idle(); Ok(()) } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface @@ -226,12 +225,17 @@ where // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send self.interface.cmd(spi, Command::NOP)?; + Ok(()) + } - self.wait_until_idle(); + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.use_full_frame(spi)?; // clear the ram with the background color @@ -240,8 +244,6 @@ where self.interface.cmd(spi, Command::WRITE_RAM)?; self.interface .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - - self.wait_until_idle(); Ok(()) } @@ -325,6 +327,7 @@ where } fn set_ram_counter(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + self.wait_until_idle(); // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface @@ -336,17 +339,15 @@ where Command::SET_RAM_Y_ADDRESS_COUNTER, &[y as u8, (y >> 8) as u8], )?; - - self.wait_until_idle(); Ok(()) } /// Set your own LUT, this function is also used internally for set_lut fn set_lut_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); assert!(buffer.len() == 30); self.interface .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?; - self.wait_until_idle(); Ok(()) } } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index f983083..7772ad4 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -188,6 +188,7 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating self.command(spi, Command::VCM_DC_SETTING)?; // VCOM to 0V @@ -202,12 +203,11 @@ where self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; - - self.wait_until_idle(); Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); let color_value = self.color.get_byte_value(); self.send_resolution(spi)?; @@ -226,8 +226,6 @@ where self.interface .cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?; - - self.wait_until_idle(); Ok(()) } @@ -240,6 +238,7 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { + self.wait_until_idle(); if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); @@ -273,19 +272,23 @@ where self.send_data(spi, buffer)?; self.command(spi, Command::PARTIAL_OUT)?; - - self.wait_until_idle(); Ok(()) } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; + Ok(()) + } - self.wait_until_idle(); + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; let color_value = self.color.get_byte_value(); @@ -299,8 +302,6 @@ where .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; - - self.wait_until_idle(); Ok(()) } @@ -397,6 +398,7 @@ where lut_wb: &[u8], lut_bb: &[u8], ) -> Result<(), SPI::Error> { + self.wait_until_idle(); // LUT VCOM self.cmd_with_data(spi, Command::LUT_FOR_VCOM, lut_vcom)?; @@ -411,8 +413,6 @@ where // LUT BLACK to BLACK self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, lut_bb)?; - - self.wait_until_idle(); Ok(()) } } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 42711d8..f30c396 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -150,15 +150,15 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::POWER_OFF)?; self.wait_until_idle(); self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; - - self.wait_until_idle(); Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::DATA_START_TRANSMISSION_1)?; for byte in buffer { let mut temp = *byte; @@ -171,8 +171,6 @@ where self.send_data(spi, &[data])?; } } - - self.wait_until_idle(); Ok(()) } @@ -189,21 +187,25 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; + Ok(()) + } - self.wait_until_idle(); + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; // The Waveshare controllers all implement clear using 0x33 self.command(spi, Command::DATA_START_TRANSMISSION_1)?; self.interface .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?; - - self.wait_until_idle(); Ok(()) } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index e1d95ca..68c9a46 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -17,7 +17,7 @@ use embedded_hal::{ use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareDisplayExt}; +use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -132,6 +132,7 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.command(spi, Command::POWER_OFF)?; self.wait_until_idle(); self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; @@ -139,9 +140,8 @@ where } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.command(spi, Command::DATA_START_TRANSMISSION_2)?; - self.send_data(spi, buffer)?; self.wait_until_idle(); + self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?; Ok(()) } @@ -158,12 +158,19 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.command(spi, Command::DISPLAY_REFRESH)?; self.wait_until_idle(); + self.command(spi, Command::DISPLAY_REFRESH)?; + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); self.send_resolution(spi)?; self.command(spi, Command::DATA_START_TRANSMISSION_1)?; @@ -173,7 +180,6 @@ where self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; self.command(spi, Command::DISPLAY_REFRESH)?; - self.wait_until_idle(); Ok(()) } @@ -206,26 +212,6 @@ where } } -impl WaveshareDisplayExt - for EPD7in5 -where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, -{ - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.command(spi, Command::DATA_START_TRANSMISSION_2)?; - for b in buffer { - self.send_data(spi, &[255 - b])?; - } - self.command(spi, Command::DISPLAY_REFRESH)?; - self.wait_until_idle(); - Ok(()) - } -} - impl EPD7in5 where SPI: Write, diff --git a/src/lib.rs b/src/lib.rs index 88e54b0..5d8c9d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,8 +76,6 @@ pub mod prelude { pub use crate::color::Color; pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay}; - pub use crate::traits::WaveshareDisplayExt; - pub use crate::SPI_MODE; #[cfg(feature = "graphics")] diff --git a/src/traits.rs b/src/traits.rs index 9f83da5..91352ee 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -148,6 +148,9 @@ where /// This function waits until the device isn`t busy anymore fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; + /// Provide a combined update&display and save some time (skipping a busy check in between) + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + /// Clears the frame buffer on the EPD with the declared background color /// /// The background color can be changed with [`set_background_color`] @@ -174,15 +177,3 @@ where /// if the device is still busy fn is_busy(&self) -> bool; } -/// Tiny optional extension trait -pub trait WaveshareDisplayExt -where - SPI: Write, - CS: OutputPin, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, -{ - // provide a combined update&display and save some time (skipping a busy check in between) - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; -}