From 3b13abf088f8612a468bb99b092e135abb480147 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 08:17:21 +0100 Subject: [PATCH 1/5] add embedded-hal-async --- Cargo.toml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 6eff17ec..2182ccac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,11 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } + embedded-hal = { version = "1.0.0-rc.1" } +embedded-hal-bus = { version = "0.1.0-rc.1", git="https://github.com/rust-embedded/embedded-hal" } +embedded-hal-async = { optional = true, version = "1.0.0-rc.1", git="https://github.com/rust-embedded/embedded-hal" } + bit_field = "0.10.1" [dev-dependencies] @@ -54,12 +58,13 @@ required-features = ["linux-dev"] [features] # Remove the linux-dev feature to build the tests on non unix systems -default = ["graphics", "linux-dev", "epd2in13_v3"] +default = ["async", "epd2in13_v3", "graphics"] #["dep:embedded-hal", "graphics", "linux-dev", "epd2in13_v3"] graphics = ["embedded-graphics-core"] epd2in13_v2 = [] epd2in13_v3 = [] linux-dev = [] +async = ["dep:embedded-hal-async", "embedded-hal-bus/async"] # Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking type_a_alternative_faster_lut = [] From 2c58432aae67021916c7ee37f2e63b34db3beab6 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 08:57:03 +0100 Subject: [PATCH 2/5] disable graphics --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 2182ccac..9d1b5971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ required-features = ["linux-dev"] [features] # Remove the linux-dev feature to build the tests on non unix systems -default = ["async", "epd2in13_v3", "graphics"] #["dep:embedded-hal", "graphics", "linux-dev", "epd2in13_v3"] +default = ["async", "epd2in13_v3"] #["dep:embedded-hal", "graphics", "linux-dev", "epd2in13_v3"] graphics = ["embedded-graphics-core"] epd2in13_v2 = [] From 83878fcca7675b7a6918656fc0f5f05967ff04a9 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 11:37:50 +0100 Subject: [PATCH 3/5] make everything async --- Cargo.toml | 6 +- src/epd1in54/mod.rs | 187 ++++++++++++---------- src/epd1in54_v2/mod.rs | 255 ++++++++++++++++------------- src/epd1in54b/mod.rs | 198 +++++++++++++---------- src/epd1in54c/mod.rs | 134 +++++++++------- src/epd2in13_v2/mod.rs | 262 +++++++++++++++++------------- src/epd2in13bc/mod.rs | 176 ++++++++++++--------- src/epd2in7b/mod.rs | 307 +++++++++++++++++++---------------- src/epd2in9/mod.rs | 176 ++++++++++++--------- src/epd2in9_v2/mod.rs | 243 ++++++++++++++++------------ src/epd2in9bc/mod.rs | 176 ++++++++++++--------- src/epd3in7/mod.rs | 176 ++++++++++++--------- src/epd4in2/mod.rs | 343 +++++++++++++++++++++++----------------- src/epd5in65f/mod.rs | 157 +++++++++--------- src/epd5in83b_v2/mod.rs | 176 +++++++++++---------- src/epd7in5/mod.rs | 132 +++++++++------- src/epd7in5_hd/mod.rs | 137 +++++++++------- src/epd7in5_v2/mod.rs | 132 +++++++++------- src/epd7in5_v3/mod.rs | 169 +++++++++++--------- src/epd7in5b_v2/mod.rs | 155 ++++++++++-------- src/interface.rs | 55 ++++--- src/lib.rs | 3 + src/traits.rs | 50 +++--- 23 files changed, 2167 insertions(+), 1638 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9d1b5971..aafd2b22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,7 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } - embedded-hal = { version = "1.0.0-rc.1" } -embedded-hal-bus = { version = "0.1.0-rc.1", git="https://github.com/rust-embedded/embedded-hal" } embedded-hal-async = { optional = true, version = "1.0.0-rc.1", git="https://github.com/rust-embedded/embedded-hal" } bit_field = "0.10.1" @@ -58,13 +56,13 @@ required-features = ["linux-dev"] [features] # Remove the linux-dev feature to build the tests on non unix systems -default = ["async", "epd2in13_v3"] #["dep:embedded-hal", "graphics", "linux-dev", "epd2in13_v3"] +default = ["async", "graphics", "linux-dev", "epd2in13_v3"] graphics = ["embedded-graphics-core"] epd2in13_v2 = [] epd2in13_v3 = [] linux-dev = [] -async = ["dep:embedded-hal-async", "embedded-hal-bus/async"] +async = ["dep:embedded-hal-async"] # Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking type_a_alternative_faster_lut = [] diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 9bc1b7fe..2cc38e58 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -54,7 +54,8 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -96,19 +97,21 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; // 3 Databytes: // A[7:0] // 0.. A[8] // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) - self.interface.cmd_with_data( - spi, - Command::DriverOutputControl, - &[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00], - )?; + self.interface + .cmd_with_data( + spi, + Command::DriverOutputControl, + &[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00], + ) + .await?; // 3 Databytes: (and default values from datasheet and arduino) // 1 .. A[6:0] = 0xCF | 0xD7 @@ -116,28 +119,33 @@ where // 1 .. C[6:0] = 0x8D | 0x9D //TODO: test self.interface - .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D])?; + .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D]) + .await?; // One Databyte with value 0xA8 for 7V VCOM self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8]) + .await?; // One Databyte with default value 0x1A for 4 dummy lines per gate self.interface - .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?; + .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A]) + .await?; // One Databyte with default value 0x08 for 2us per line self.interface - .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?; + .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08]) + .await?; // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -160,7 +168,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -176,39 +184,41 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 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::DeepSleepMode, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -218,50 +228,54 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, delay, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, delay, x, y, x + width, y + height) + .await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4]) + .await?; - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -273,7 +287,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -283,13 +297,17 @@ where self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE), - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE), + RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + let _ = self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -302,19 +320,20 @@ where RST: OutputPin, DELAY: DelayUs, { - pub(crate) fn use_full_frame( + pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - pub(crate) fn set_ram_area( + pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -323,65 +342,73 @@ where end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + let _ = self.wait_until_idle(spi, delay).await; assert!(start_x < end_x); assert!(start_y < end_y); // 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.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await?; Ok(()) } - pub(crate) fn set_ram_counter( + pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 30); self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; Ok(()) } } diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 0f0399f7..8fce171c 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -11,7 +11,8 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::type_a::command::Command; @@ -46,43 +47,51 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); - self.wait_until_idle(spi, delay)?; - self.interface.cmd(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; + self.wait_until_idle(spi, delay).await?; + self.interface.cmd(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; // 3 Databytes: // A[7:0] // 0.. A[8] // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) - self.interface.cmd_with_data( - spi, - Command::DriverOutputControl, - &[(HEIGHT - 1) as u8, 0x0, 0x00], - )?; + self.interface + .cmd_with_data( + spi, + Command::DriverOutputControl, + &[(HEIGHT - 1) as u8, 0x0, 0x00], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x3])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x3]) + .await?; - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x1])?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x1]) + .await?; - self.interface.cmd_with_data( - spi, - Command::TemperatureSensorSelection, - &[0x80], // 0x80: internal temperature sensor - )?; + self.interface + .cmd_with_data( + spi, + Command::TemperatureSensorSelection, + &[0x80], // 0x80: internal temperature sensor + ) + .await?; self.interface - .cmd_with_data(spi, Command::TemperatureSensorControl, &[0xB1, 0x20])?; + .cmd_with_data(spi, Command::TemperatureSensorControl, &[0xB1, 0x20]) + .await?; - self.set_ram_counter(spi, delay, 0, 0)?; + self.set_ram_counter(spi, delay, 0, 0).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -105,7 +114,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -121,37 +130,39 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -161,56 +172,62 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, delay, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, delay, x, y, x + width, y + height) + .await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; if self.refresh == RefreshLut::Full { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7]) + .await?; } else if self.refresh == RefreshLut::Quick { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xCF])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xCF]) + .await?; } - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - self.interface.cmd(spi, Command::WriteRam2)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; + self.interface.cmd(spi, Command::WriteRam2).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -222,7 +239,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -232,31 +249,39 @@ where self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE), - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE), + RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, }?; // Additional configuration required only for partial updates if self.refresh == RefreshLut::Quick { - self.interface.cmd_with_data( - spi, - Command::WriteOtpSelection, - &[0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0], - )?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data( + spi, + Command::WriteOtpSelection, + &[0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xc0])?; - self.interface.cmd(spi, Command::MasterActivation)?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80]) + .await?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xc0]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; } Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -269,19 +294,20 @@ where RST: OutputPin, DELAY: DelayUs, { - pub(crate) fn use_full_frame( + pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - pub(crate) fn set_ram_area( + pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -290,81 +316,94 @@ where end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(start_x < end_x); assert!(start_y < end_y); // 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.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await?; Ok(()) } - pub(crate) fn set_ram_counter( + pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 159); self.interface - .cmd_with_data(spi, Command::WriteLutRegister, &buffer[0..153])?; + .cmd_with_data(spi, Command::WriteLutRegister, &buffer[0..153]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteLutRegisterEnd, &[buffer[153]])?; + .cmd_with_data(spi, Command::WriteLutRegisterEnd, &[buffer[153]]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::GateDrivingVoltage, &[buffer[154]])?; + .cmd_with_data(spi, Command::GateDrivingVoltage, &[buffer[154]]) + .await?; - self.interface.cmd_with_data( - spi, - Command::SourceDrivingVoltage, - &[buffer[155], buffer[156], buffer[157]], - )?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]])?; + .cmd_with_data( + spi, + Command::SourceDrivingVoltage, + &[buffer[155], buffer[156], buffer[157]], + ) + .await?; + self.interface + .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]]) + .await?; Ok(()) } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 0a477bf4..2146fd8e 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,6 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -52,38 +53,44 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; // set the power settings self.interface - .cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x00, 0x08, 0x00])?; + .cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x00, 0x08, 0x00]) + .await?; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x07])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x07]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0xCF])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xCF]) + .await?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37]) + .await?; // PLL - self.cmd_with_data(spi, Command::PllControl, &[0x39])?; + self.cmd_with_data(spi, Command::PllControl, &[0x39]) + .await?; // set resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; - self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } @@ -98,43 +105,47 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; for b in black { let expanded = expand_bits(*b); - self.interface.data(spi, &expanded)?; + self.interface.data(spi, &expanded).await?; } Ok(()) } - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data(spi, chromatic)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data(spi, chromatic).await?; Ok(()) } } @@ -149,7 +160,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -162,33 +173,36 @@ where let mut epd = Epd1in54b { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) + .await?; //border floating self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // Vcom to 0V + .cmd_with_data(spi, Command::VcmDcSetting, &[0x00]) + .await?; // Vcom to 0V self.interface - .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast + .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00]) + .await?; //VG&VS to 0V fast - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; //NOTE: The example code has a 1s delay here - self.command(spi, Command::PowerOff)?; + self.command(spi, Command::PowerOff).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -207,21 +221,23 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; for b in buffer { // Two bits per pixel let expanded = expand_bits(*b); - self.interface.data(spi, &expanded)?; + self.interface.data(spi, &expanded).await?; } //NOTE: Example code has a delay here @@ -230,15 +246,17 @@ where let color = self.color.get_byte_value(); let nbits = WIDTH * (HEIGHT / 8); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, nbits)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data_x_times(spi, color, nbits).await?; //NOTE: Example code has a delay here Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -251,69 +269,89 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; // Uses 2 bits per pixel self.interface - .data_x_times(spi, color, 2 * (WIDTH * HEIGHT / 8))?; + .data_x_times(spi, color, 2 * (WIDTH * HEIGHT / 8)) + .await?; // Clear the red - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, WIDTH * HEIGHT / 8) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?; + .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0) + .await?; self.interface - .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE)?; + .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE) + .await?; self.interface - .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE)?; - self.interface.cmd_with_data(spi, Command::LutG0, LUT_G1)?; - self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2)?; + .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE) + .await?; self.interface - .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?; + .cmd_with_data(spi, Command::LutG0, LUT_G1) + .await?; self.interface - .cmd_with_data(spi, Command::LutRed0, LUT_RED0)?; + .cmd_with_data(spi, Command::LutG1, LUT_G2) + .await?; self.interface - .cmd_with_data(spi, Command::LutRed1, LUT_RED1)?; + .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM) + .await?; + self.interface + .cmd_with_data(spi, Command::LutRed0, LUT_RED0) + .await?; + self.interface + .cmd_with_data(spi, Command::LutRed1, LUT_RED1) + .await?; Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -326,32 +364,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 341baf7d..006190f4 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,6 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -49,28 +50,31 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Based on Reference Program Code from: // https://www.waveshare.com/w/upload/a/ac/1.54inch_e-Paper_Module_C_Specification.pdf // and: // https://github.com/waveshare/e-Paper/blob/master/STM32/STM32-F103ZET6/User/e-Paper/EPD_1in54c.c - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // start the booster - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0x0f, 0x0d])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0f, 0x0d]) + .await?; // set resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77]) + .await?; Ok(()) } @@ -85,37 +89,39 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission1, black)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission1, black) + .await?; Ok(()) } - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic) + .await?; Ok(()) } @@ -131,7 +137,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -144,23 +150,23 @@ where let mut epd = Epd1in54c { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xa5])?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xa5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -179,25 +185,27 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, buffer)?; + self.update_achromatic_frame(spi, delay, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -210,41 +218,45 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -253,8 +265,12 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -267,40 +283,40 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | // | HRES[7:3] | 0 | 0 | 0 | - self.send_data(spi, &[(w as u8) & 0b1111_1000])?; + self.send_data(spi, &[(w as u8) & 0b1111_1000]).await?; // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | // | - | - | - | - | - | - | - | VRES[8] | - self.send_data(spi, &[(w >> 8) as u8])?; + self.send_data(spi, &[(w >> 8) as u8]).await?; // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | // | VRES[7:0] | // Specification shows C/D is zero while sending the last byte, // but upstream code does not implement it like that. So for now // we follow upstream code. - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 7712835d..ad31e97a 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -15,11 +15,8 @@ //! - [Controller Datasheet SS1780](http://www.e-paper-display.com/download_detail/downloadsId=682.html) //! -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::buffer_len; use crate::color::Color; @@ -89,15 +86,15 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // HW reset - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; if self.refresh == RefreshLut::Quick { - self.set_vcom_register(spi, (-9).vcom())?; - self.wait_until_idle(spi, delay)?; + self.set_vcom_register(spi, (-9).vcom()).await?; + self.wait_until_idle(spi, delay).await?; - self.set_lut(spi, delay, Some(self.refresh))?; + self.set_lut(spi, delay, Some(self.refresh)).await?; // Python code does this, not sure why // self.cmd_with_data(spi, Command::WriteOtpSelection, &[0, 0, 0, 0, 0x40, 0, 0])?; @@ -107,9 +104,10 @@ where self.set_display_update_control_2( spi, DisplayUpdateControl2::new().enable_analog().enable_clock(), - )?; - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + ) + .await?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; self.set_border_waveform( spi, @@ -118,11 +116,12 @@ where fix_level: BorderWaveFormFixLevel::Vss, gs_trans: BorderWaveFormGs::Lut1, }, - )?; + ) + .await?; } else { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; self.set_driver_output( spi, @@ -132,17 +131,19 @@ where scan_dir_incr: true, width: (HEIGHT - 1) as u16, }, - )?; + ) + .await?; // These 2 are the reset values - self.set_dummy_line_period(spi, 0x30)?; - self.set_gate_scan_start_position(spi, 0)?; + self.set_dummy_line_period(spi, 0x30).await?; + self.set_gate_scan_start_position(spi, 0).await?; - self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir)?; + self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir) + .await?; // Use simple X/Y auto increase - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; self.set_border_waveform( spi, @@ -151,24 +152,27 @@ where fix_level: BorderWaveFormFixLevel::Vss, gs_trans: BorderWaveFormGs::Lut3, }, - )?; + ) + .await?; - self.set_vcom_register(spi, (-21).vcom())?; + self.set_vcom_register(spi, (-21).vcom()).await?; - self.set_gate_driving_voltage(spi, 190.gate_driving_decivolt())?; + self.set_gate_driving_voltage(spi, 190.gate_driving_decivolt()) + .await?; self.set_source_driving_voltage( spi, 150.source_driving_decivolt(), 50.source_driving_decivolt(), (-150).source_driving_decivolt(), - )?; + ) + .await?; - self.set_gate_line_width(spi, 10)?; + self.set_gate_line_width(spi, 10).await?; - self.set_lut(spi, delay, Some(self.refresh))?; + self.set_lut(spi, delay, Some(self.refresh)).await?; } - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -183,7 +187,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -198,16 +202,16 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // All sample code enables and disables analog/clocks... self.set_display_update_control_2( @@ -217,31 +221,33 @@ where .enable_clock() .disable_analog() .disable_clock(), - )?; - self.command(spi, Command::MasterActivation)?; + ) + .await?; + self.command(spi, Command::MasterActivation).await?; - self.set_sleep_mode(spi, self.sleep_mode)?; + self.set_sleep_mode(spi, self.sleep_mode).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRam, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equal to current if not doing partial refresh. - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; } Ok(()) } @@ -249,7 +255,7 @@ where /// Updating only a part of the frame is not supported when using the /// partial refresh feature. The function will panic if called when set to /// use partial refresh. - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -269,17 +275,18 @@ where // incorrect. assert!(self.refresh == RefreshLut::Full); - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_address_counters(spi, delay, x, y)?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_address_counters(spi, delay, x, y).await?; - self.cmd_with_data(spi, Command::WriteRam, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equals to current if not doing partial refresh. - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_address_counters(spi, delay, x, y)?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_address_counters(spi, delay, x, y).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; } Ok(()) @@ -287,7 +294,7 @@ where /// Never use directly this function when using partial refresh, or also /// keep the base buffer in syncd using `set_partial_base_buffer` function. - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { if self.refresh == RefreshLut::Full { self.set_display_update_control_2( spi, @@ -297,55 +304,61 @@ where .display() .disable_analog() .disable_clock(), - )?; + ) + .await?; } else { - self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display())?; + self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display()) + .await?; } - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; if self.refresh == RefreshLut::Quick { - self.set_partial_base_buffer(spi, delay, buffer)?; + self.set_partial_base_buffer(spi, delay, buffer).await?; } Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let color = self.background_color.get_byte_value(); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; - - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - color, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - // Always keep the base buffer equals to current if not doing partial refresh. - if self.refresh == RefreshLut::Full { - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; - - self.command(spi, Command::WriteRamRed)?; - self.interface.data_x_times( + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( spi, color, buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + ) + .await?; + + // Always keep the base buffer equals to current if not doing partial refresh. + if self.refresh == RefreshLut::Full { + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; + + self.command(spi, Command::WriteRamRed).await?; + self.interface + .data_x_times( + spi, + color, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } Ok(()) } @@ -366,7 +379,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -378,10 +391,15 @@ where }; self.cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -396,17 +414,18 @@ where { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. - pub fn set_partial_base_buffer( + pub async fn set_partial_base_buffer( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { assert!(buffer_len(WIDTH as usize, HEIGHT as usize) == buffer.len()); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; Ok(()) } @@ -417,7 +436,7 @@ where /// Sets the refresh mode. When changing mode, the screen will be /// re-initialized accordingly. - pub fn set_refresh( + pub async fn set_refresh( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -425,12 +444,12 @@ where ) -> Result<(), SPI::Error> { if self.refresh != refresh { self.refresh = refresh; - self.init(spi, delay)?; + self.init(spi, delay).await?; } Ok(()) } - fn set_gate_scan_start_position( + async fn set_gate_scan_start_position( &mut self, spi: &mut SPI, start: u16, @@ -441,9 +460,10 @@ where Command::GateScanStartPosition, &[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8], ) + .await } - fn set_border_waveform( + async fn set_border_waveform( &mut self, spi: &mut SPI, borderwaveform: BorderWaveForm, @@ -453,35 +473,40 @@ where Command::BorderWaveformControl, &[borderwaveform.to_u8()], ) + .await } - fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { + async fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) + .await } - fn set_gate_driving_voltage( + async fn set_gate_driving_voltage( &mut self, spi: &mut SPI, voltage: GateDrivingVoltage, ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[voltage.0]) + .await } - fn set_dummy_line_period( + async fn set_dummy_line_period( &mut self, spi: &mut SPI, number_of_lines: u8, ) -> Result<(), SPI::Error> { assert!(number_of_lines <= 127); self.cmd_with_data(spi, Command::SetDummyLinePeriod, &[number_of_lines]) + .await } - fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { + async fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F]) + .await } /// Sets the source driving voltage value - fn set_source_driving_voltage( + async fn set_source_driving_voltage( &mut self, spi: &mut SPI, vsh1: SourceDrivingVoltage, @@ -493,30 +518,42 @@ where Command::SourceDrivingVoltageCtrl, &[vsh1.0, vsh2.0, vsl.0], ) + .await } /// Prepare the actions that the next master activation command will /// trigger. - fn set_display_update_control_2( + async fn set_display_update_control_2( &mut self, spi: &mut SPI, value: DisplayUpdateControl2, ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[value.0]) + .await } /// Triggers the deep sleep mode - fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { + async fn set_sleep_mode( + &mut self, + spi: &mut SPI, + mode: DeepSleepMode, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) + .await } - fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> { + async fn set_driver_output( + &mut self, + spi: &mut SPI, + output: DriverOutput, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) + .await } /// Sets the data entry mode (ie. how X and Y positions changes when writing /// data to RAM) - fn set_data_entry_mode( + async fn set_data_entry_mode( &mut self, spi: &mut SPI, counter_incr_mode: DataEntryModeIncr, @@ -524,10 +561,11 @@ where ) -> Result<(), SPI::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) + .await } /// Sets both X and Y pixels ranges - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -539,7 +577,8 @@ where spi, Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + ) + .await?; self.cmd_with_data( spi, @@ -551,38 +590,41 @@ where (end_y >> 8) as u8, ], ) + .await } /// Sets both X and Y pixels counters when writing data to RAM - fn set_ram_address_counters( + async fn set_ram_address_counters( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; self.cmd_with_data( spi, Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], - )?; + ) + .await?; Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 280f47a7..7cf83e24 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -50,7 +50,8 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -106,35 +107,39 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x8F]) + .await?; self.cmd_with_data( spi, Command::VcomAndDataIntervalSetting, &[WHITE_BORDER | VCOM_DATA_INTERVAL], - )?; + ) + .await?; // set resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; - self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } @@ -149,44 +154,48 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } /// Update only the black/white data of the display. /// /// Finish by calling `update_chromatic_frame`. - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, black)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data(spi, black).await?; Ok(()) } /// Update only chromatic data of the display. /// /// This data takes precedence over the black/white data. - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data(spi, chromatic)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -201,7 +210,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -214,30 +223,32 @@ where let mut epd = Epd2in13bc { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Section 8.2 from datasheet - self.interface.cmd_with_data( - spi, - Command::VcomAndDataIntervalSetting, - &[FLOATING_BORDER | VCOM_DATA_INTERVAL], - )?; - - self.command(spi, Command::PowerOff)?; + self.interface + .cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[FLOATING_BORDER | VCOM_DATA_INTERVAL], + ) + .await?; + + self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: TriColor) { @@ -256,28 +267,34 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -290,43 +307,51 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -335,8 +360,12 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -349,36 +378,40 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } /// Set the outer border of the display to the chosen color. - pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> { + pub async fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), SPI::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, @@ -389,5 +422,6 @@ where Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], ) + .await } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 941d0393..83110645 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -2,7 +2,8 @@ //! //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -56,58 +57,67 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set panel settings, 0xbf is bw, 0xaf is multi-color self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0xaf])?; + .cmd_with_data(spi, Command::PanelSetting, &[0xaf]) + .await?; // pll control self.interface - .cmd_with_data(spi, Command::PllControl, &[0x3a])?; + .cmd_with_data(spi, Command::PllControl, &[0x3a]) + .await?; // set the power settings - self.interface.cmd_with_data( - spi, - Command::PowerSetting, - &[0x03, 0x00, 0x2b, 0x2b, 0x09], - )?; + self.interface + .cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x09]) + .await?; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17]) + .await?; // power optimization self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41]) + .await?; self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; self.interface - .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00])?; + .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -122,7 +132,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -135,46 +145,53 @@ where let mut epd = Epd2in7b { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7]) + .await?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], _delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.send_buffer_helper(spi, buffer)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.send_buffer_helper(spi, buffer).await?; // Clear chromatic layer since we won't be using it here - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8) + .await?; - self.interface.cmd(spi, Command::DataStop)?; + self.interface.cmd(spi, Command::DataStop).await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -185,54 +202,61 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; - - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; - - self.send_buffer_helper(spi, buffer)?; - - self.interface.cmd(spi, Command::DataStop) + .cmd(spi, Command::PartialDataStartTransmission1) + .await?; + + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; + + self.send_buffer_helper(spi, buffer).await?; + + self.interface.cmd(spi, Command::DataStop).await } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8) + .await?; - self.interface.cmd(spi, Command::DataStop)?; + self.interface.cmd(spi, Command::DataStop).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DataStop)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8) + .await?; + self.interface.cmd(spi, Command::DataStop).await?; Ok(()) } @@ -252,23 +276,32 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, _refresh_rate: Option, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC)?; - self.cmd_with_data(spi, Command::LutWhiteToWhite, &LUT_WW)?; - self.cmd_with_data(spi, Command::LutBlackToWhite, &LUT_BW)?; - self.cmd_with_data(spi, Command::LutWhiteToBlack, &LUT_WB)?; - self.cmd_with_data(spi, Command::LutBlackToBlack, &LUT_BB)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC) + .await?; + self.cmd_with_data(spi, Command::LutWhiteToWhite, &LUT_WW) + .await?; + self.cmd_with_data(spi, Command::LutBlackToWhite, &LUT_BW) + .await?; + self.cmd_with_data(spi, Command::LutWhiteToBlack, &LUT_WB) + .await?; + self.cmd_with_data(spi, Command::LutBlackToBlack, &LUT_BB) + .await?; Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -282,48 +315,52 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } /// Update only the black/white data of the display. /// /// Finish by calling `update_chromatic_frame`. - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, achromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.send_buffer_helper(spi, achromatic)?; + self.send_buffer_helper(spi, achromatic).await?; - self.interface.cmd(spi, Command::DataStop) + self.interface.cmd(spi, Command::DataStop).await } /// Update only chromatic data of the display. /// /// This data takes precedence over the black/white data. - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; - self.send_buffer_helper(spi, chromatic)?; + self.send_buffer_helper(spi, chromatic).await?; - self.interface.cmd(spi, Command::DataStop)?; - self.wait_until_idle(spi, delay)?; + self.interface.cmd(spi, Command::DataStop).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } @@ -337,34 +374,34 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn send_buffer_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + async fn send_buffer_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { // Based on the waveshare implementation, all data for color values is flipped. This helper // method makes that transmission easier for b in buffer.iter() { - self.send_data(spi, &[!b])?; + self.send_data(spi, &[!b]).await?; } Ok(()) } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } /// Refresh display for partial frame - pub fn display_partial_frame( + pub async fn display_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -373,22 +410,22 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.command(spi, Command::PartialDisplayRefresh)?; - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PartialDisplayRefresh).await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } /// Update black/achromatic frame #[allow(clippy::too_many_arguments)] - pub fn update_partial_achromatic_frame( + pub async fn update_partial_achromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -399,20 +436,21 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; + .cmd(spi, Command::PartialDataStartTransmission1) + .await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; for b in achromatic.iter() { // Flipping based on waveshare implementation - self.send_data(spi, &[!b])?; + self.send_data(spi, &[!b]).await?; } Ok(()) @@ -420,7 +458,7 @@ where /// Update partial chromatic/red frame #[allow(clippy::too_many_arguments)] - pub fn update_partial_chromatic_frame( + pub async fn update_partial_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -431,20 +469,21 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission2)?; - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; + .cmd(spi, Command::PartialDataStartTransmission2) + .await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; for b in chromatic.iter() { // Flipping based on waveshare implementation - self.send_data(spi, &[!b])?; + self.send_data(spi, &[!b]).await?; } Ok(()) diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 6e3e178d..17996fc7 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -50,7 +50,8 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -93,10 +94,10 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 3 Databytes: // A[7:0] @@ -104,7 +105,8 @@ where // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) self.interface - .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; + .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00]) + .await?; // 3 Databytes: (and default values from datasheet and arduino) // 1 .. A[6:0] = 0xCF | 0xD7 @@ -112,26 +114,31 @@ where // 1 .. C[6:0] = 0x8D | 0x9D //TODO: test self.interface - .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D])?; + .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D]) + .await?; // One Databyte with value 0xA8 for 7V VCOM self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8]) + .await?; // One Databyte with default value 0x1A for 4 dummy lines per gate self.interface - .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?; + .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A]) + .await?; // One Databyte with default value 0x08 for 2us per line self.interface - .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?; + .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08]) + .await?; // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) + .await?; - self.set_lut(spi, delay, None) + self.set_lut(spi, delay, None).await } } @@ -153,7 +160,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -169,42 +176,44 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 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::DeepSleepMode, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.init(spi, delay)?; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.init(spi, delay).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -214,50 +223,53 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4]) + .await?; - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -269,7 +281,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -279,13 +291,17 @@ where self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE), - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE), + RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -298,15 +314,15 @@ where RST: OutputPin, DELAY: DelayUs, { - fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -319,58 +335,66 @@ where // 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.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - ) + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await } - fn set_ram_counter( + async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } /// Set your own LUT, this function is also used internally for set_lut - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 30); self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; Ok(()) } } diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 7004a77e..624195c9 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -75,7 +75,8 @@ const LUT_PARTIAL_2IN9: [u8; 159] = [ 0x22, 0x0, 0x0, 0x0, 0x22, 0x17, 0x41, 0xB0, 0x32, 0x36, ]; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::type_a::command::Command; @@ -116,12 +117,12 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 2_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 2_000).await; - self.wait_until_idle(spi, delay)?; - self.interface.cmd(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.interface.cmd(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; // 3 Databytes: // A[7:0] @@ -129,21 +130,24 @@ where // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) self.interface - .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; + .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00]) + .await?; // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) + .await?; - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80])?; + .cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80]) + .await?; - self.set_ram_counter(spi, delay, 0, 0)?; + self.set_ram_counter(spi, delay, 0, 0).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -166,7 +170,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -182,35 +186,38 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay)?; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.interface.cmd_with_data(spi, Command::WriteRam, buffer) + self.wait_until_idle(spi, delay).await?; + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer) + .await } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -221,48 +228,53 @@ where height: u32, ) -> Result<(), SPI::Error> { //TODO This is copied from epd2in9 but it seems not working. Partial refresh supported by version 2? - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } /// actually is the "Turn on Display" sequence - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; + self.interface + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; + self.interface.cmd(spi, Command::WriteRam2).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - self.interface.cmd(spi, Command::WriteRam2)?; - self.interface.data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await } fn set_background_color(&mut self, background_color: Color) { @@ -273,7 +285,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -285,8 +297,12 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -299,15 +315,15 @@ where RST: OutputPin, DELAY: DelayUs, { - fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -320,58 +336,66 @@ where // 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.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - ) + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await } - fn set_ram_counter( + async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 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 - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[x as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[x as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } /// Set your own LUT, this function is also used internally for set_lut - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -386,73 +410,84 @@ where DELAY: DelayUs, { /// To be followed immediately by `update_new_frame`. - fn update_old_frame( + async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.interface .cmd_with_data(spi, Command::WriteRam2, buffer) + .await } /// To be used immediately after `update_old_frame`. - fn update_new_frame( + async fn update_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.interface.reset(delay, 10_000, 2_000); - - self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; - self.interface.cmd_with_data( - spi, - Command::WriteOtpSelection, - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], - )?; + self.wait_until_idle(spi, delay).await?; + self.interface.reset(delay, 10_000, 2_000).await; + + self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9).await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data( + spi, + Command::WriteOtpSelection, + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0])?; - self.interface.cmd(spi, Command::MasterActivation)?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80]) + .await?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay)?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } /// For a quick refresh of the new updated frame. To be used immediately after `update_new_frame` - fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_new_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } /// Updates and displays the new frame. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay)?; - self.display_new_frame(spi, delay)?; + self.update_new_frame(spi, buffer, delay).await?; + self.display_new_frame(spi, delay).await?; Ok(()) } /// Partial quick refresh not supported yet #[allow(unused)] - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -468,7 +503,7 @@ where /// Partial quick refresh not supported yet #[allow(unused)] - fn update_partial_new_frame( + async fn update_partial_new_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -484,7 +519,7 @@ where /// Partial quick refresh not supported yet #[allow(unused)] - fn clear_partial_frame( + async fn clear_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 121c5680..fb1c1732 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -54,7 +54,8 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -110,35 +111,39 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x8F]) + .await?; self.cmd_with_data( spi, Command::VcomAndDataIntervalSetting, &[WHITE_BORDER | VCOM_DATA_INTERVAL], - )?; + ) + .await?; // set resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; - self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } @@ -153,44 +158,48 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } /// Update only the black/white data of the display. /// /// Finish by calling `update_chromatic_frame`. - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, black)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data(spi, black).await?; Ok(()) } /// Update only chromatic data of the display. /// /// This data takes precedence over the black/white data. - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data(spi, chromatic)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -205,7 +214,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -218,30 +227,32 @@ where let mut epd = Epd2in9bc { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Section 8.2 from datasheet - self.interface.cmd_with_data( - spi, - Command::VcomAndDataIntervalSetting, - &[FLOATING_BORDER | VCOM_DATA_INTERVAL], - )?; - - self.command(spi, Command::PowerOff)?; + self.interface + .cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[FLOATING_BORDER | VCOM_DATA_INTERVAL], + ) + .await?; + + self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -260,28 +271,34 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -294,43 +311,51 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -339,8 +364,12 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -353,36 +382,40 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } /// Set the outer border of the display to the chosen color. - pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> { + pub async fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), SPI::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, @@ -393,5 +426,6 @@ where Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], ) + .await } } diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c7f06855..973abb46 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -2,11 +2,8 @@ //! //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; pub(crate) mod command; mod constants; @@ -59,66 +56,84 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 30, 10); + self.interface.reset(delay, 30, 10).await; - self.interface.cmd(spi, Command::SwReset)?; - delay.delay_us(300000u32); + self.interface.cmd(spi, Command::SwReset).await?; + delay.delay_us(300000u32).await; self.interface - .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7])?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7]) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; self.interface - .cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7])?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + .cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7]) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; self.interface - .cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00])?; + .cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::GateVoltage, &[0x00])?; + .cmd_with_data(spi, Command::GateVoltage, &[0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32])?; + .cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32]) + .await?; self.interface - .cmd_with_data(spi, Command::DataEntrySequence, &[0x03])?; + .cmd_with_data(spi, Command::DataEntrySequence, &[0x03]) + .await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x03])?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x03]) + .await?; - self.interface.cmd_with_data( - spi, - Command::BoosterSoftStartControl, - &[0xAE, 0xC7, 0xC3, 0xC0, 0xC0], - )?; + self.interface + .cmd_with_data( + spi, + Command::BoosterSoftStartControl, + &[0xAE, 0xC7, 0xC3, 0xC0, 0xC0], + ) + .await?; + + self.interface + .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80]) + .await?; self.interface - .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44])?; - - self.interface.cmd_with_data( - spi, - Command::DisplayOption, - &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 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], - )?; + .cmd_with_data( + spi, + Command::DisplayOption, + &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF], + ) + .await?; + + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[0x00, 0x00, 0x17, 0x01], + ) + .await?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[0x00, 0x00, 0xDF, 0x01], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF])?; + .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF]) + .await?; - self.set_lut(spi, delay, Some(RefreshLut::Full))?; + self.set_lut(spi, delay, Some(RefreshLut::Full)).await?; Ok(()) } } @@ -134,7 +149,7 @@ where { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -147,19 +162,22 @@ where background_color: DEFAULT_BACKGROUND_COLOR, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, Command::Sleep, &[0xF7])?; - self.interface.cmd(spi, Command::PowerOff)?; + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::Sleep2, &[0xA5])?; + .cmd_with_data(spi, Command::Sleep, &[0xF7]) + .await?; + self.interface.cmd(spi, Command::PowerOff).await?; + self.interface + .cmd_with_data(spi, Command::Sleep2, &[0xA5]) + .await?; Ok(()) } @@ -179,7 +197,7 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -187,18 +205,21 @@ where ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -211,39 +232,45 @@ where todo!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async 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.interface.cmd(spi, Command::DisplayUpdateSequence)?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + self.interface + .cmd(spi, Command::DisplayUpdateSequence) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00]) + .await?; let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; - self.interface.data_x_times(spi, color, WIDTH * HEIGHT)?; + self.interface.cmd(spi, Command::WriteRam).await?; + self.interface + .data_x_times(spi, color, WIDTH * HEIGHT) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -255,12 +282,17 @@ where }; self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index fe43d0ef..8d6b5828 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -49,7 +49,8 @@ //! //! BE CAREFUL! The screen can get ghosting/burn-ins through the Partial Fast Update Drawing. -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; @@ -103,47 +104,50 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // set the power settings - self.interface.cmd_with_data( - spi, - Command::PowerSetting, - &[0x03, 0x00, 0x2b, 0x2b, 0xff], - )?; + self.interface + .cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0xff]) + .await?; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0x3F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x3F]) + .await?; // Set Frequency, 200 Hz didn't work on my board // 150Hz and 171Hz wasn't tested yet // TODO: Test these other frequencies // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz - self.cmd_with_data(spi, Command::PllControl, &[0x3A])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3A]) + .await?; - self.send_resolution(spi)?; + self.send_resolution(spi).await?; self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -158,7 +162,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -175,32 +179,34 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating - self.command(spi, Command::VcmDcSetting)?; // VCOM to 0V - self.command(spi, Command::PanelSetting)?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) + .await?; //border floating + self.command(spi, Command::VcmDcSetting).await?; // VCOM to 0V + self.command(spi, Command::PanelSetting).await?; - self.command(spi, Command::PowerSetting)?; //VG&VS to 0V fast + self.command(spi, Command::PowerSetting).await?; //VG&VS to 0V fast for _ in 0..4 { - self.send_data(spi, &[0x00])?; + self.send_data(spi, &[0x00]).await?; } - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -219,25 +225,29 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -247,77 +257,84 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.command(spi, Command::PartialIn)?; - self.command(spi, Command::PartialWindow)?; - self.send_data(spi, &[(x >> 8) as u8])?; + self.command(spi, Command::PartialIn).await?; + self.command(spi, Command::PartialWindow).await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; let tmp = x & 0xf8; - self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored + self.send_data(spi, &[tmp as u8]).await?; // x should be the multiple of 8, the last 3 bit will always be ignored let tmp = tmp + width - 1; - self.send_data(spi, &[(tmp >> 8) as u8])?; - self.send_data(spi, &[(tmp | 0x07) as u8])?; + self.send_data(spi, &[(tmp >> 8) as u8]).await?; + self.send_data(spi, &[(tmp | 0x07) as u8]).await?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[y as u8])?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[y as u8]).await?; - self.send_data(spi, &[((y + height - 1) >> 8) as u8])?; - self.send_data(spi, &[(y + height - 1) as u8])?; + self.send_data(spi, &[((y + height - 1) >> 8) as u8]) + .await?; + self.send_data(spi, &[(y + height - 1) as u8]).await?; - self.send_data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + self.send_data(spi, &[0x01]).await?; // Gates scan both inside and outside of the partial window. (default) //TODO: handle dtm somehow let is_dtm1 = false; if is_dtm1 { - self.command(spi, Command::DataStartTransmission1)? //TODO: check if data_start transmission 1 also needs "old"/background data here + self.command(spi, Command::DataStartTransmission1).await?; //TODO: check if data_start transmission 1 also needs "old"/background data here } else { - self.command(spi, Command::DataStartTransmission2)? + self.command(spi, Command::DataStartTransmission2).await?; } - self.send_data(spi, buffer)?; + self.send_data(spi, buffer).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -329,21 +346,29 @@ where match self.refresh { RefreshLut::Full => { self.set_lut_helper(spi, delay, &LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB) + .await + } + RefreshLut::Quick => { + self.set_lut_helper( + spi, + delay, + &LUT_VCOM0_QUICK, + &LUT_WW_QUICK, + &LUT_BW_QUICK, + &LUT_WB_QUICK, + &LUT_BB_QUICK, + ) + .await } - RefreshLut::Quick => self.set_lut_helper( - spi, - delay, - &LUT_VCOM0_QUICK, - &LUT_WW_QUICK, - &LUT_BW_QUICK, - &LUT_WB_QUICK, - &LUT_BB_QUICK, - ), } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -356,36 +381,36 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::ResolutionSetting).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } #[allow(clippy::too_many_arguments)] - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -395,27 +420,32 @@ where lut_wb: &[u8], lut_bb: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // LUT VCOM - self.cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; + self.cmd_with_data(spi, Command::LutForVcom, lut_vcom) + .await?; // LUT WHITE to WHITE - self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?; + self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww) + .await?; // LUT BLACK to WHITE - self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?; + self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw) + .await?; // LUT WHITE to BLACK - self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?; + self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb) + .await?; // LUT BLACK to BLACK - self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?; + self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb) + .await?; Ok(()) } /// Helper function. Sets up the display to send pixel data to a custom /// starting point. - pub fn shift_display( + pub async fn shift_display( &mut self, spi: &mut SPI, x: u32, @@ -423,20 +453,21 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.send_data(spi, &[(x >> 8) as u8])?; + self.send_data(spi, &[(x >> 8) as u8]).await?; let tmp = x & 0xf8; - self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored + self.send_data(spi, &[tmp as u8]).await?; // x should be the multiple of 8, the last 3 bit will always be ignored let tmp = tmp + width - 1; - self.send_data(spi, &[(tmp >> 8) as u8])?; - self.send_data(spi, &[(tmp | 0x07) as u8])?; + self.send_data(spi, &[(tmp >> 8) as u8]).await?; + self.send_data(spi, &[(tmp | 0x07) as u8]).await?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[y as u8])?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[y as u8]).await?; - self.send_data(spi, &[((y + height - 1) >> 8) as u8])?; - self.send_data(spi, &[(y + height - 1) as u8])?; + self.send_data(spi, &[((y + height - 1) >> 8) as u8]) + .await?; + self.send_data(spi, &[(y + height - 1) as u8]).await?; - self.send_data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + self.send_data(spi, &[0x01]).await?; // Gates scan both inside and outside of the partial window. (default) Ok(()) } @@ -452,59 +483,67 @@ where DELAY: DelayUs, { /// To be followed immediately after by `update_old_frame`. - fn update_old_frame( + async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// To be used immediately after `update_old_frame`. - fn update_new_frame( + async fn update_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - // self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + // self.send_resolution(spi).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// This is a wrapper around `display_frame` for using this device as a true /// `QuickRefresh` device. - fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.display_frame(spi, delay) + async fn display_new_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.display_frame(spi, delay).await } /// This is wrapper around `update_new_frame` and `display_frame` for using /// this device as a true `QuickRefresh` device. /// /// To be used immediately after `update_old_frame`. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay)?; - self.display_frame(spi, delay) + self.update_new_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await } - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -514,28 +553,30 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.interface.cmd(spi, Command::PartialIn)?; - self.interface.cmd(spi, Command::PartialWindow)?; + self.interface.cmd(spi, Command::PartialIn).await?; + self.interface.cmd(spi, Command::PartialWindow).await?; - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// Always call `update_partial_old_frame` before this, with buffer-updating code /// between the calls. - fn update_partial_new_frame( + async fn update_partial_new_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -545,23 +586,25 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; - self.interface.cmd(spi, Command::PartialOut)?; + self.interface.cmd(spi, Command::PartialOut).await?; Ok(()) } - fn clear_partial_frame( + async fn clear_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -570,25 +613,31 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::PartialIn)?; - self.interface.cmd(spi, Command::PartialWindow)?; + self.interface.cmd(spi, Command::PartialIn).await?; + self.interface.cmd(spi, Command::PartialWindow).await?; - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, width / 8 * height) + .await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, width / 8 * height) + .await?; - self.interface.cmd(spi, Command::PartialOut)?; + self.interface.cmd(spi, Command::PartialOut).await?; Ok(()) } } diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 6233955b..c348dd07 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -6,11 +6,8 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_5in65f.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::OctColor; use crate::interface::DisplayInterface; @@ -57,25 +54,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); - - self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23])?; - self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00])?; - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?; - self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; - self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00])?; - self.update_vcom(spi)?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.send_resolution(spi)?; - - self.cmd_with_data(spi, Command::FlashMode, &[0xAA])?; - - delay.delay_us(100_000); - - self.update_vcom(spi)?; + self.interface.reset(delay, 10_000, 2_000).await; + + self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08]) + .await?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23]) + .await?; + self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00]) + .await?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D]) + .await?; + self.cmd_with_data(spi, Command::PllControl, &[0x3C]) + .await?; + self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00]) + .await?; + self.update_vcom(spi).await?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; + self.send_resolution(spi).await?; + + self.cmd_with_data(spi, Command::FlashMode, &[0xAA]).await?; + + delay.delay_us(100_000).await; + + self.update_vcom(spi).await?; Ok(()) } } @@ -90,7 +94,7 @@ where DELAY: DelayUs, { type DisplayColor = OctColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -103,34 +107,35 @@ where let mut epd = Epd5in65f { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.update_vcom(spi)?; - self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.update_vcom(spi).await?; + self.send_resolution(spi).await?; + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -143,36 +148,38 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_busy_low(delay); + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_busy_low(delay).await; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let bg = OctColor::colors_byte(self.color, self.color); - self.wait_until_idle(spi, delay)?; - self.update_vcom(spi)?; - self.send_resolution(spi)?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; - self.display_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.update_vcom(spi).await?; + self.send_resolution(spi).await?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, bg, WIDTH * HEIGHT / 2) + .await?; + self.display_frame(spi, delay).await?; Ok(()) } @@ -192,7 +199,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -201,8 +208,12 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, true); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, true).await; Ok(()) } } @@ -215,40 +226,42 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn wait_busy_low(&mut self, delay: &mut DELAY) { - self.interface.wait_until_idle(delay, false); + async fn wait_busy_low(&mut self, delay: &mut DELAY) { + self.interface.wait_until_idle(delay, false).await; } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } - fn update_vcom(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn update_vcom(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let bg_color = (self.color.get_nibble() & 0b111) << 5; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17 | bg_color])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17 | bg_color]) + .await?; Ok(()) } } diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index d1df524e..ac1c542b 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -6,11 +6,8 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_5in83b_V2.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -59,37 +56,42 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // Start the booster - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x1e, 0x17])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x1e, 0x17]) + .await?; // Set the power settings: VGH=20V,VGL=-20V,VDH=15V,VDL=-15V - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F]) + .await?; // Power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // Set the panel settings: BWROTP - self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) + .await?; // Set the real resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; // Disable dual SPI - self.cmd_with_data(spi, Command::DualSPI, &[0x00])?; + self.cmd_with_data(spi, Command::DualSPI, &[0x00]).await?; // Set Vcom and data interval - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07]) + .await?; // Set S2G and G2S non-overlap periods to 12 (default) - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -103,37 +105,39 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic)?; + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await?; Ok(()) } - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission1, black)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission1, black) + .await?; Ok(()) } - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic) + .await?; Ok(()) } } @@ -148,7 +152,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -161,21 +165,21 @@ where let mut epd = Epd5in83 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -194,21 +198,23 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.update_achromatic_frame(spi, delay, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.update_achromatic_frame(spi, delay, buffer).await?; let color = self.color.get_byte_value(); - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -218,7 +224,7 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error } @@ -233,61 +239,67 @@ where let vred_lower = (y + height) as u8; let pt_scan = 0x01; // Gates scan both inside and outside of the partial window. (default) - self.command(spi, Command::PartialIn)?; - self.command(spi, Command::PartialWindow)?; + self.command(spi, Command::PartialIn).await?; + self.command(spi, Command::PartialWindow).await?; self.send_data( spi, &[ hrst_upper, hrst_lower, hred_upper, hred_lower, vrst_upper, vrst_lower, vred_upper, vred_lower, pt_scan, ], - )?; - self.command(spi, Command::DataStartTransmission1)?; - self.send_data(spi, buffer)?; + ) + .await?; + self.command(spi, Command::DataStartTransmission1).await?; + self.send_data(spi, buffer).await?; let color = TriColor::Black.get_byte_value(); //We need it black, so red channel will be rendered transparent - self.command(spi, Command::DataStartTransmission2)?; + self.command(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color, width * height / 8)?; + .data_x_times(spi, color, width * height / 8) + .await?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // The Waveshare controllers all implement clear using 0x33 - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0xFF, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0xFF, NUM_DISPLAY_BITS) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -296,8 +308,12 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -310,32 +326,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 5b89e1a1..37fa337c 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -6,11 +6,8 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_7in5.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -57,48 +54,56 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // Set the power settings - self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00]) + .await?; // Set the panel settings: // - 600 x 448 // - Using LUT from external flash - self.cmd_with_data(spi, Command::PanelSetting, &[0xCF, 0x08])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xCF, 0x08]) + .await?; // Start the booster - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xCC, 0x28])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xCC, 0x28]) + .await?; // Power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // Set the clock frequency to 50Hz (default) - self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3C]) + .await?; // Select internal temperature sensor (default) - self.cmd_with_data(spi, Command::TemperatureCalibration, &[0x00])?; + self.cmd_with_data(spi, Command::TemperatureCalibration, &[0x00]) + .await?; // Set Vcom and data interval to 10 (default), border output to white - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77]) + .await?; // Set S2G and G2S non-overlap periods to 12 (default) - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; // Set the real resolution - self.send_resolution(spi)?; + self.send_resolution(spi).await?; // Set VCOM_DC to -1.5V - self.cmd_with_data(spi, Command::VcmDcSetting, &[0x1E])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x1E]) + .await?; // This is in all the Waveshare controllers for Epd7in5 - self.cmd_with_data(spi, Command::FlashMode, &[0x03])?; + self.cmd_with_data(spi, Command::FlashMode, &[0x03]).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -113,7 +118,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,21 +131,21 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -159,14 +164,14 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DataStartTransmission1)?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DataStartTransmission1).await?; for byte in buffer { let mut temp = *byte; for _ in 0..4 { @@ -175,13 +180,13 @@ where temp <<= 1; data |= if temp & 0x80 == 0 { 0x00 } else { 0x03 }; temp <<= 1; - self.send_data(spi, &[data])?; + self.send_data(spi, &[data]).await?; } } Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -194,35 +199,36 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; // The Waveshare controllers all implement clear using 0x33 - self.command(spi, Command::DataStartTransmission1)?; + self.command(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?; + .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -231,8 +237,12 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -245,32 +255,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 5ef9cd47..740eb30d 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -9,11 +9,8 @@ //! - [Datasheet](https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -60,44 +57,55 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // HD procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py // and as per specs: // https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::AutoWriteRed, &[0xF7])?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::AutoWriteBw, &[0xF7])?; - self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::AutoWriteRed, &[0xF7]) + .await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::AutoWriteBw, &[0xF7]) + .await?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::SoftStart, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40])?; + self.cmd_with_data(spi, Command::SoftStart, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40]) + .await?; - self.cmd_with_data(spi, Command::DriverOutputControl, &[0xAF, 0x02, 0x01])?; + self.cmd_with_data(spi, Command::DriverOutputControl, &[0xAF, 0x02, 0x01]) + .await?; - self.cmd_with_data(spi, Command::DataEntry, &[0x01])?; + self.cmd_with_data(spi, Command::DataEntry, &[0x01]).await?; - self.cmd_with_data(spi, Command::SetRamXStartEnd, &[0x00, 0x00, 0x6F, 0x03])?; - self.cmd_with_data(spi, Command::SetRamYStartEnd, &[0xAF, 0x02, 0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamXStartEnd, &[0x00, 0x00, 0x6F, 0x03]) + .await?; + self.cmd_with_data(spi, Command::SetRamYStartEnd, &[0xAF, 0x02, 0x00, 0x00]) + .await?; - self.cmd_with_data(spi, Command::VbdControl, &[0x05])?; + self.cmd_with_data(spi, Command::VbdControl, &[0x05]) + .await?; - self.cmd_with_data(spi, Command::TemperatureSensorControl, &[0x80])?; + self.cmd_with_data(spi, Command::TemperatureSensorControl, &[0x80]) + .await?; - self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xB1])?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xB1]) + .await?; - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::SetRamXAc, &[0x00, 0x00])?; - self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamXAc, &[0x00, 0x00]) + .await?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) + .await?; Ok(()) } @@ -113,7 +121,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,35 +134,37 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0x01]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; - self.cmd_with_data(spi, Command::WriteRamBw, buffer)?; - self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) + .await?; + self.cmd_with_data(spi, Command::WriteRamBw, buffer).await?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -167,39 +177,42 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let pixel_count = WIDTH * HEIGHT / 8; let background_color_byte = self.color.get_byte_value(); - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) + .await?; for cmd in &[Command::WriteRamBw, Command::WriteRamRed] { - self.command(spi, *cmd)?; + self.command(spi, *cmd).await?; self.interface - .data_x_times(spi, background_color_byte, pixel_count)?; + .data_x_times(spi, background_color_byte, pixel_count) + .await?; } - self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) + .await?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } @@ -219,7 +232,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -228,8 +241,12 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } @@ -242,17 +259,17 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index f971bf43..f199cee7 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -10,11 +10,8 @@ //! Revision V2 has been released on 2019.11, the resolution is upgraded to 800×480, from 640×384 of V1. //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -61,26 +58,33 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py // and as per specs: // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F])?; - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; - self.cmd_with_data(spi, Command::PllControl, &[0x06])?; - self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; - self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?; - self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17]) + .await?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F]) + .await?; + self.command(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x1F]) + .await?; + self.cmd_with_data(spi, Command::PllControl, &[0x06]) + .await?; + self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0]) + .await?; + self.cmd_with_data(spi, Command::DualSpi, &[0x00]).await?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07]) + .await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -95,7 +99,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -108,35 +112,36 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -149,34 +154,38 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DisplayRefresh)?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -196,7 +205,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -205,9 +214,14 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn wait_until_idle( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .await } } @@ -219,32 +233,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index 962924af..afa97fd2 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -7,11 +7,8 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5_V2.py) //! -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -65,27 +62,33 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 200_000, 4_000); + self.interface.reset(delay, 200_000, 4_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py // and as per specs: // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf - //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; - //self.cmd_with_data(spi, Command::PllControl, &[0x06])?; - self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; - self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00])?; - self.wait_until_idle(spi, delay)?; + //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17]).await?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F]) + .await?; + self.command(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) + .await?; + //self.cmd_with_data(spi, Command::PllControl, &[0x06]).await?; + self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0]) + .await?; + self.cmd_with_data(spi, Command::DualSpi, &[0x00]).await?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07]) + .await?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; + self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00]) + .await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -99,44 +102,48 @@ where RST: OutputPin, DELAY: DelayUs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) + self.update_achromatic_frame(spi, delay, black).await?; + self.update_chromatic_frame(spi, delay, chromatic).await } /// Update only the black/white data of the display. /// /// Finish by calling `update_chromatic_frame`. - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, black)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data(spi, black).await?; Ok(()) } /// Update only chromatic data of the display. /// /// This data takes precedence over the black/white data. - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data(spi, chromatic)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -151,7 +158,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -164,46 +171,51 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -216,34 +228,38 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DisplayRefresh)?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -263,7 +279,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -272,9 +288,14 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn wait_until_idle( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .await } } @@ -286,32 +307,32 @@ where RST: OutputPin, DELAY: DelayUs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index c71d030c..5d20477c 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -10,11 +10,8 @@ //! Revision V2 has been released on 2019.11, the resolution is upgraded to 800×480, from 640×384 of V1. //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -63,28 +60,31 @@ where RST: OutputPin, DELAY: DelayUs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device // C driver does 200/2 original rust driver does 10/2 - self.interface.reset(delay, 200_000, 2_000); + self.interface.reset(delay, 200_000, 2_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py // and as per specs: // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; - self.command(spi, Command::PowerOn)?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F]) + .await?; + self.command(spi, Command::PowerOn).await?; // C driver adds a static 100ms delay here - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // Done, but this is also the default // 0x1F = B/W mode ? doesnt seem to work - self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) + .await?; // Not done in C driver, this is the default - //self.cmd_with_data(spi, Command::PllControl, &[0x06])?; - self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; + //self.cmd_with_data(spi, Command::PllControl, &[0x06]).await?; + self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0]) + .await?; // Documentation removed in v3 but done in v2 and works in v3 - self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; + self.cmd_with_data(spi, Command::DualSpi, &[0x00]).await?; // 0x10 in BW mode (Work ?) V // 0x12 in BW mode to disable new/old thing // 0x01 -> Black border @@ -93,12 +93,15 @@ where // 0x31 -> don't touch border // the second nibble can change polarity (may be easier for default // display initialization) V - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07]) + .await?; // This is the default - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; + self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00]) + .await?; // Not in C driver - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } @@ -113,7 +116,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,45 +129,47 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // (B) version sends one buffer for black and one for red self.cmd_with_data( spi, Command::DataStartTransmission1, &buffer[..NUM_DISPLAY_BYTES], - )?; + ) + .await?; self.cmd_with_data( spi, Command::DataStartTransmission2, &buffer[NUM_DISPLAY_BYTES..], - )?; + ) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -177,34 +182,38 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0xFF, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0xFF, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH * HEIGHT / 8) + .await?; - self.command(spi, Command::DisplayRefresh)?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -225,7 +234,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -235,9 +244,14 @@ where } /// wait - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn wait_until_idle( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .await } } @@ -251,7 +265,7 @@ where { /// temporary replacement for missing delay in the trait to call wait_until_idle #[allow(clippy::too_many_arguments)] - pub fn update_partial_frame2( + pub async fn update_partial_frame2( &mut self, spi: &mut SPI, buffer: &[u8], @@ -261,7 +275,7 @@ where height: u32, delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error } @@ -276,7 +290,7 @@ where let vred_lower = (y + height - 1) as u8; let pt_scan = 0x01; // Gates scan both inside and outside of the partial window. (default) - self.command(spi, Command::PartialIn)?; + self.command(spi, Command::PartialIn).await?; self.cmd_with_data( spi, Command::PartialWindow, @@ -284,44 +298,47 @@ where hrst_upper, hrst_lower, hred_upper, hred_lower, vrst_upper, vrst_lower, vred_upper, vred_lower, pt_scan, ], - )?; + ) + .await?; let half = buffer.len() / 2; - self.cmd_with_data(spi, Command::DataStartTransmission1, &buffer[..half])?; - self.cmd_with_data(spi, Command::DataStartTransmission2, &buffer[half..])?; + self.cmd_with_data(spi, Command::DataStartTransmission1, &buffer[..half]) + .await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, &buffer[half..]) + .await?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/interface.rs b/src/interface.rs index e53d9186..2470e5fe 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,6 +1,7 @@ use crate::traits::Command; use core::marker::PhantomData; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// @@ -49,28 +50,32 @@ where /// Basic function for sending [Commands](Command). /// /// Enables direct interaction with the device with the help of [data()](DisplayInterface::data()) - pub(crate) fn cmd(&mut self, spi: &mut SPI, command: T) -> Result<(), SPI::Error> { + pub(crate) async fn cmd( + &mut self, + spi: &mut SPI, + command: T, + ) -> Result<(), SPI::Error> { // low for commands let _ = self.dc.set_low(); // Transfer the command over spi - self.write(spi, &[command.address()]) + self.write(spi, &[command.address()]).await } /// Basic function for sending an array of u8-values of data over spi /// /// Enables direct interaction with the device with the help of [command()](Epd4in2::command()) - pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + pub(crate) async fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { // high for data let _ = self.dc.set_high(); if SINGLE_BYTE_WRITE { for val in data.iter().copied() { // Transfer data one u8 at a time over spi - self.write(spi, &[val])?; + self.write(spi, &[val]).await?; } } else { - self.write(spi, data)?; + self.write(spi, data).await?; } Ok(()) @@ -79,20 +84,20 @@ where /// Basic function for sending [Commands](Command) and the data belonging to it. /// /// TODO: directly use ::write? cs wouldn't needed to be changed twice than - pub(crate) fn cmd_with_data( + pub(crate) async fn cmd_with_data( &mut self, spi: &mut SPI, command: T, data: &[u8], ) -> Result<(), SPI::Error> { - self.cmd(spi, command)?; - self.data(spi, data) + self.cmd(spi, command).await?; + self.data(spi, data).await } /// Basic function for sending the same byte of data (one u8) multiple times over spi /// /// Enables direct interaction with the device with the help of [command()](ConnectionInterface::command()) - pub(crate) fn data_x_times( + pub(crate) async fn data_x_times( &mut self, spi: &mut SPI, val: u8, @@ -102,23 +107,23 @@ where let _ = self.dc.set_high(); // Transfer data (u8) over spi for _ in 0..repetitions { - self.write(spi, &[val])?; + self.write(spi, &[val]).await?; } Ok(()) } // spi write helper/abstraction function - fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + async fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { // transfer spi data // Be careful!! Linux has a default limit of 4096 bytes per spi transfer // see https://raspberrypi.stackexchange.com/questions/65595/spi-transfer-fails-with-buffer-size-greater-than-4096 if cfg!(target_os = "linux") { for data_chunk in data.chunks(4096) { - spi.write(data_chunk)?; + spi.write(data_chunk).await?; } Ok(()) } else { - spi.write(data) + spi.write(data).await } } @@ -134,7 +139,7 @@ where /// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?) /// /// Most likely there was a mistake with the 2in9 busy connection - pub(crate) fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) { + pub(crate) async fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) { while self.is_busy(is_busy_low) { // This has been removed and added many time : // - it is faster to not have it @@ -143,27 +148,27 @@ where // - delay waiting enables task switching on realtime OS // -> keep it and leave the decision to the user if self.delay_us > 0 { - delay.delay_us(self.delay_us); + delay.delay_us(self.delay_us).await; } } } /// Same as `wait_until_idle` for device needing a command to probe Busy pin - pub(crate) fn wait_until_idle_with_cmd( + pub(crate) async fn wait_until_idle_with_cmd( &mut self, spi: &mut SPI, delay: &mut DELAY, is_busy_low: bool, status_command: T, ) -> Result<(), SPI::Error> { - self.cmd(spi, status_command)?; + self.cmd(spi, status_command).await?; if self.delay_us > 0 { - delay.delay_us(self.delay_us); + delay.delay_us(self.delay_us).await; } while self.is_busy(is_busy_low) { - self.cmd(spi, status_command)?; + self.cmd(spi, status_command).await?; if self.delay_us > 0 { - delay.delay_us(self.delay_us); + delay.delay_us(self.delay_us).await; } } Ok(()) @@ -194,15 +199,15 @@ where /// The timing of keeping the reset pin low seems to be important and different per device. /// Most displays seem to require keeping it low for 10ms, but the 7in5_v2 only seems to reset /// properly with 2ms - pub(crate) fn reset(&mut self, delay: &mut DELAY, initial_delay: u32, duration: u32) { + pub(crate) async fn reset(&mut self, delay: &mut DELAY, initial_delay: u32, duration: u32) { let _ = self.rst.set_high(); - delay.delay_us(initial_delay); + delay.delay_us(initial_delay).await; let _ = self.rst.set_low(); - delay.delay_us(duration); + delay.delay_us(duration).await; let _ = self.rst.set_high(); //TODO: the upstream libraries always sleep for 200ms here // 10ms works fine with just for the 7in5_v2 but this needs to be validated for other devices - delay.delay_us(200_000); + delay.delay_us(200_000).await; } } diff --git a/src/lib.rs b/src/lib.rs index bdedf055..3174250f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -62,6 +62,9 @@ //! #![no_std] #![deny(missing_docs)] +#![allow(stable_features)] +#![cfg_attr(feature = "async", feature(async_fn_in_trait, impl_trait_projections))] +#![cfg_attr(feature = "async", allow(incomplete_features, async_fn_in_trait))] #[cfg(feature = "graphics")] pub mod graphics; diff --git a/src/traits.rs b/src/traits.rs index 25df34ad..d251949d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,5 +1,6 @@ use core::marker::Sized; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; /// All commands need to have this trait which gives the address of the command /// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode) @@ -36,7 +37,7 @@ where /// This function calls [reset](WaveshareDisplay::reset), /// so you don't need to call reset your self when trying to wake your device up /// after setting it to sleep. - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; } /// Functions to interact with three color panels @@ -52,7 +53,7 @@ where /// Transmit data to the SRAM of the EPD /// /// Updates both the black and the secondary color layers - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -63,7 +64,7 @@ where /// Update only the black/white data of the display. /// /// This must be finished by calling `update_chromatic_frame`. - fn update_achromatic_frame( + async fn update_achromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -74,7 +75,7 @@ where /// /// This should be preceded by a call to `update_achromatic_frame`. /// This data takes precedence over the black/white data. - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -143,7 +144,7 @@ where /// Setting it to None means a default value is used. /// /// This already initialises the device. - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -157,12 +158,12 @@ where /// Let the device enter deep-sleep mode to save power. /// /// The deep sleep mode returns to standby with a hardware reset. - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Wakes the device up from sleep /// /// Also reintialises the device if necessary. - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame) fn set_background_color(&mut self, color: Self::DisplayColor); @@ -177,7 +178,7 @@ where fn height(&self) -> u32; /// Transmit a full frame to the SRAM of the EPD - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -190,7 +191,7 @@ where /// /// BUFFER needs to be of size: width / 8 * height ! #[allow(clippy::too_many_arguments)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -204,10 +205,10 @@ where /// Displays the frame data from SRAM /// /// This function waits until the device isn`t busy anymore - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Provide a combined update&display and save some time (skipping a busy check in between) - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -217,7 +218,7 @@ where /// Clears the frame buffer on the EPD with the declared background color /// /// The background color can be changed with [`WaveshareDisplay::set_background_color`] - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Trait for using various Waveforms from different LUTs /// E.g. for partial refreshes @@ -227,7 +228,7 @@ where /// WARNING: Quick Refresh might lead to ghosting-effects/problems with your display. Especially for the 4.2in Display! /// /// If None is used the old value will be loaded on the LUTs once more - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -237,7 +238,8 @@ where /// Wait until the display has stopped processing data /// /// You can call this to make sure a frame is displayed before goin further - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) + -> Result<(), SPI::Error>; } /// Allows quick refresh support for displays that support it; lets you send both @@ -294,7 +296,7 @@ where DELAY: DelayUs, { /// Updates the old frame. - fn update_old_frame( + async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -302,7 +304,7 @@ where ) -> Result<(), SPI::Error>; /// Updates the new frame. - fn update_new_frame( + async fn update_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -310,10 +312,14 @@ where ) -> Result<(), SPI::Error>; /// Displays the new frame - fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn display_new_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Updates and displays the new frame. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -322,7 +328,7 @@ where /// Updates the old frame for a portion of the display. #[allow(clippy::too_many_arguments)] - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -335,7 +341,7 @@ where /// Updates the new frame for a portion of the display. #[allow(clippy::too_many_arguments)] - fn update_partial_new_frame( + async fn update_partial_new_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -348,7 +354,7 @@ where /// Clears the partial frame buffer on the EPD with the declared background color /// The background color can be changed with [`WaveshareDisplay::set_background_color`] - fn clear_partial_frame( + async fn clear_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, From 2ac5b9f4ec5a408df103f901ab791e2338362ab0 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 14:49:26 +0100 Subject: [PATCH 4/5] do not use polling to wait for idle --- Cargo.toml | 2 +- examples/epd1in54_no_graphics.rs | 6 +++--- src/epd1in54/mod.rs | 8 ++++---- src/epd1in54_v2/mod.rs | 8 ++++---- src/epd1in54b/mod.rs | 10 +++++----- src/epd1in54c/mod.rs | 10 +++++----- src/epd2in13_v2/mod.rs | 8 ++++---- src/epd2in13bc/mod.rs | 10 +++++----- src/epd2in7b/mod.rs | 10 +++++----- src/epd2in9/mod.rs | 8 ++++---- src/epd2in9_v2/mod.rs | 10 +++++----- src/epd2in9bc/mod.rs | 10 +++++----- src/epd3in7/mod.rs | 6 +++--- src/epd4in2/mod.rs | 10 +++++----- src/epd5in65f/mod.rs | 8 ++++---- src/epd5in83b_v2/mod.rs | 10 +++++----- src/epd7in5/mod.rs | 8 ++++---- src/epd7in5_hd/mod.rs | 8 ++++---- src/epd7in5_v2/mod.rs | 8 ++++---- src/epd7in5_v3/mod.rs | 10 +++++----- src/epd7in5b_v2/mod.rs | 8 ++++---- src/interface.rs | 32 +++++++++++++++++--------------- src/traits.rs | 10 +++++----- 23 files changed, 110 insertions(+), 108 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index aafd2b22..2b2816e9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } embedded-hal = { version = "1.0.0-rc.1" } -embedded-hal-async = { optional = true, version = "1.0.0-rc.1", git="https://github.com/rust-embedded/embedded-hal" } +embedded-hal-async = { optional = true, version = "1.0.0-rc.1" } bit_field = "0.10.1" diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 7df04a00..20b26e9c 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -58,11 +58,11 @@ fn main() -> Result<(), SPIError> { // Setup of the needed pins is finished here // Now the "real" usage of the eink-waveshare-rs crate begins - let mut epd = Epd1in54::new(&mut spi, busy, dc, rst, &mut delay, Some(5))?; + let mut epd = Epd1in54::new(&mut spi, busy, dc, rst, &mut delay, Some(5)).await?; // Clear the full screen - epd.clear_frame(&mut spi, &mut delay)?; - epd.display_frame(&mut spi, &mut delay)?; + epd.clear_frame(&mut spi, &mut delay).await?; + epd.display_frame(&mut spi, &mut delay).await?; // Speeddemo epd.set_lut(&mut spi, &mut delay, Some(RefreshLut::Quick))?; diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 2cc38e58..c7e9c050 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -55,7 +55,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -92,7 +92,7 @@ pub struct Epd1in54 { impl Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -154,7 +154,7 @@ impl WaveshareDisplay for Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -315,7 +315,7 @@ where impl Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 8fce171c..35347b0b 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -12,7 +12,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::type_a::command::Command; @@ -42,7 +42,7 @@ pub struct Epd1in54 { impl Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -100,7 +100,7 @@ impl WaveshareDisplay for Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -289,7 +289,7 @@ where impl Epd1in54 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 2146fd8e..c438e15e 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,7 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -48,7 +48,7 @@ impl InternalWiAdditions for Epd1in54b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -100,7 +100,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -154,7 +154,7 @@ impl WaveshareDisplay for Epd1in54b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -359,7 +359,7 @@ where impl Epd1in54b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 006190f4..e6ae0fa7 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,7 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -45,7 +45,7 @@ impl InternalWiAdditions for Epd1in54c where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -84,7 +84,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -131,7 +131,7 @@ impl WaveshareDisplay for Epd1in54c where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -278,7 +278,7 @@ where impl Epd1in54c where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index ad31e97a..8fab7a5f 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,7 +16,7 @@ //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::buffer_len; use crate::color::Color; @@ -81,7 +81,7 @@ impl InternalWiAdditions for Epd2in13 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -181,7 +181,7 @@ impl WaveshareDisplay for Epd2in13 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -407,7 +407,7 @@ where impl Epd2in13 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 7cf83e24..5afdba2e 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -51,7 +51,7 @@ //!# } //!``` use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -102,7 +102,7 @@ impl InternalWiAdditions for Epd2in13bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -149,7 +149,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -204,7 +204,7 @@ impl WaveshareDisplay for Epd2in13bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -373,7 +373,7 @@ where impl Epd2in13bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 83110645..26f6020d 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -3,7 +3,7 @@ //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -52,7 +52,7 @@ impl InternalWiAdditions for Epd2in7b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -126,7 +126,7 @@ impl WaveshareDisplay for Epd2in7b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -310,7 +310,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -369,7 +369,7 @@ where impl Epd2in7b where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 17996fc7..7f742fd6 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -51,7 +51,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -89,7 +89,7 @@ pub struct Epd2in9 { impl Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -146,7 +146,7 @@ impl WaveshareDisplay for Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -309,7 +309,7 @@ where impl Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 624195c9..42e3fba9 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -76,7 +76,7 @@ const LUT_PARTIAL_2IN9: [u8; 159] = [ ]; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::type_a::command::Command; @@ -112,7 +112,7 @@ pub struct Epd2in9 { impl Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -156,7 +156,7 @@ impl WaveshareDisplay for Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -310,7 +310,7 @@ where impl Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -404,7 +404,7 @@ impl QuickRefresh for Epd2in9 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index fb1c1732..f319eaf7 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -55,7 +55,7 @@ //!# } //!``` use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -106,7 +106,7 @@ impl InternalWiAdditions for Epd2in9bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -153,7 +153,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -208,7 +208,7 @@ impl WaveshareDisplay for Epd2in9bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -377,7 +377,7 @@ where impl Epd2in9bc where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index 973abb46..740a2d32 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -3,7 +3,7 @@ //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; pub(crate) mod command; mod constants; @@ -51,7 +51,7 @@ impl InternalWiAdditions for EPD3in7 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -142,7 +142,7 @@ impl WaveshareDisplay for EPD3in7 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 8d6b5828..f9ce7af7 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -50,7 +50,7 @@ //! BE CAREFUL! The screen can get ghosting/burn-ins through the Partial Fast Update Drawing. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; @@ -99,7 +99,7 @@ impl InternalWiAdditions for Epd4in2 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -156,7 +156,7 @@ impl WaveshareDisplay for Epd4in2 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -376,7 +376,7 @@ where impl Epd4in2 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -477,7 +477,7 @@ impl QuickRefresh for Epd4in2 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index c348dd07..443944d1 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::OctColor; use crate::interface::DisplayInterface; @@ -49,7 +49,7 @@ impl InternalWiAdditions for Epd5in65f where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -88,7 +88,7 @@ impl WaveshareDisplay for Epd5in65f where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -221,7 +221,7 @@ where impl Epd5in65f where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index ac1c542b..25f79492 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -51,7 +51,7 @@ impl InternalWiAdditions for Epd5in83 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -100,7 +100,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -146,7 +146,7 @@ impl WaveshareDisplay for Epd5in83 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -321,7 +321,7 @@ where impl Epd5in83 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 37fa337c..282d49e0 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -49,7 +49,7 @@ impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -112,7 +112,7 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -250,7 +250,7 @@ where impl Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 740eb30d..3c56c86e 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -10,7 +10,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -52,7 +52,7 @@ impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -115,7 +115,7 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -254,7 +254,7 @@ where impl Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index f199cee7..183e286c 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -53,7 +53,7 @@ impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -93,7 +93,7 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -228,7 +228,7 @@ where impl Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index afa97fd2..e171614b 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -8,7 +8,7 @@ //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -57,7 +57,7 @@ impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -97,7 +97,7 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -152,7 +152,7 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -302,7 +302,7 @@ where impl Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 5d20477c..16e95bdd 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -55,7 +55,7 @@ impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -110,7 +110,7 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -258,7 +258,7 @@ where impl Epd7in5 where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, diff --git a/src/interface.rs b/src/interface.rs index 2470e5fe..454d9351 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,8 +1,7 @@ use crate::traits::Command; use core::marker::PhantomData; -use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; - +use embedded_hal::digital::{InputPin, OutputPin, ErrorType}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice, digital::Wait}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// /// SINGLE_BYTE_WRITE defines if a data block is written bytewise @@ -26,7 +25,7 @@ impl DisplayInterface where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -139,18 +138,20 @@ where /// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?) /// /// Most likely there was a mistake with the 2in9 busy connection - pub(crate) async fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) { - while self.is_busy(is_busy_low) { - // This has been removed and added many time : - // - it is faster to not have it - // - it is complicated to pass the delay everywhere all the time - // - busy waiting can consume more power that delaying - // - delay waiting enables task switching on realtime OS - // -> keep it and leave the decision to the user - if self.delay_us > 0 { - delay.delay_us(self.delay_us).await; - } + pub(crate) async fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) -> Result<(), BUSY::Error> { + + if is_busy_low { + self.busy.wait_for_high().await?; + } + else { + self.busy.wait_for_low().await?; } + + // TODO: remove + if self.delay_us > 0 { + delay.delay_us(self.delay_us).await; + } + Ok(()) } /// Same as `wait_until_idle` for device needing a command to probe Busy pin @@ -165,6 +166,7 @@ where if self.delay_us > 0 { delay.delay_us(self.delay_us).await; } + while self.is_busy(is_busy_low) { self.cmd(spi, status_command).await?; if self.delay_us > 0 { diff --git a/src/traits.rs b/src/traits.rs index d251949d..7fe7ff77 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,6 +1,6 @@ use core::marker::Sized; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice}; +use embedded_hal_async::{delay::DelayUs, spi::SpiDevice, digital::Wait}; /// All commands need to have this trait which gives the address of the command /// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode) @@ -22,7 +22,7 @@ pub enum RefreshLut { pub(crate) trait InternalWiAdditions where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -45,7 +45,7 @@ pub trait WaveshareThreeColorDisplay: WaveshareDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -130,7 +130,7 @@ where pub trait WaveshareDisplay where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, @@ -290,7 +290,7 @@ where pub trait QuickRefresh where SPI: SpiDevice, - BUSY: InputPin, + BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, DELAY: DelayUs, From d70d1a70f9c7a69142c065af8a6634399f9927e4 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 18:31:55 +0100 Subject: [PATCH 5/5] move delay to spi --- src/epd1in54/mod.rs | 96 ++++++++++++++------------------- src/epd1in54_v2/mod.rs | 95 ++++++++++++++------------------ src/epd1in54b/mod.rs | 81 ++++++++++++---------------- src/epd1in54c/mod.rs | 81 ++++++++++++---------------- src/epd2in13_v2/mod.rs | 92 ++++++++++++++----------------- src/epd2in13bc/mod.rs | 81 ++++++++++++---------------- src/epd2in7b/mod.rs | 93 +++++++++++++------------------- src/epd2in9/mod.rs | 85 +++++++++++++---------------- src/epd2in9_v2/mod.rs | 117 +++++++++++++++++----------------------- src/epd2in9bc/mod.rs | 81 ++++++++++++---------------- src/epd3in7/mod.rs | 56 +++++++++---------- src/epd4in2/mod.rs | 103 +++++++++++++++-------------------- src/epd5in65f/mod.rs | 73 +++++++++++-------------- src/epd5in83b_v2/mod.rs | 89 +++++++++++++----------------- src/epd7in5/mod.rs | 67 ++++++++++------------- src/epd7in5_hd/mod.rs | 73 +++++++++++-------------- src/epd7in5_v2/mod.rs | 63 ++++++++++------------ src/epd7in5_v3/mod.rs | 89 +++++++++++++++--------------- src/epd7in5b_v2/mod.rs | 68 ++++++++++------------- src/interface.rs | 52 ++++++++++-------- src/lib.rs | 2 +- src/traits.rs | 59 +++++++------------- 22 files changed, 729 insertions(+), 967 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index c7e9c050..9c67c9f3 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -17,10 +17,9 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); @@ -35,11 +34,11 @@ //! .draw(&mut display); //! //!// Display updated frame -//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; -//!epd.display_frame(&mut spi, &mut delay)?; +//!epd.update_frame(&mut spi, &display.buffer())?; +//!epd.display_frame(&mut spi)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi, &mut delay)?; +//!epd.sleep(&mut spi)?; //!# Ok(()) //!# } //!``` @@ -55,7 +54,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -80,25 +79,24 @@ pub type Display1in54 = crate::graphics::Display< >; /// Epd1in54 driver -pub struct Epd1in54 { +pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd1in54 +impl Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000).await; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.reset(spi, 10_000, 10_000).await; // 3 Databytes: // A[7:0] @@ -143,21 +141,20 @@ where .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) .await?; - self.set_lut(spi, delay, None).await?; + self.set_lut(spi, None).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd1in54 +impl WaveshareDisplay + for Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -173,7 +170,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -184,17 +180,17 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // 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 @@ -207,10 +203,9 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) .await?; @@ -221,17 +216,16 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.set_ram_area(spi, delay, x, y, x + width, y + height) + self.wait_until_idle(spi).await?; + self.set_ram_area(spi, x, y, x + width, y + height) .await?; - self.set_ram_counter(spi, delay, x, y).await?; + self.set_ram_counter(spi, x, y).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -239,8 +233,8 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // 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 @@ -258,16 +252,15 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); @@ -290,59 +283,54 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, + RefreshLut::Full => self.set_lut_helper(spi, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE).await, } } async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - let _ = self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + let _ = self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd1in54 +impl Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1) .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0).await + self.set_ram_counter(spi, 0, 0).await } pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, - delay: &mut DELAY, start_x: u32, start_y: u32, end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - let _ = self.wait_until_idle(spi, delay).await; + let _ = self.wait_until_idle(spi).await; assert!(start_x < end_x); assert!(start_y < end_y); @@ -375,11 +363,10 @@ where pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 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 @@ -400,10 +387,9 @@ where async fn set_lut_helper( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; assert!(buffer.len() == 30); self.interface diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 35347b0b..83d36e9f 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -12,7 +12,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::type_a::command::Command; @@ -29,9 +29,9 @@ use crate::interface::DisplayInterface; pub use crate::epd1in54::Display1in54; /// Epd1in54 driver -pub struct Epd1in54 { +pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, @@ -39,19 +39,18 @@ pub struct Epd1in54 { refresh: RefreshLut, } -impl Epd1in54 +impl Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000).await; - self.wait_until_idle(spi, delay).await?; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.reset(spi, 10_000, 10_000).await; + self.wait_until_idle(spi).await?; self.interface.cmd(spi, Command::SwReset).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 3 Databytes: // A[7:0] @@ -70,7 +69,7 @@ where .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x3]) .await?; - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1) .await?; self.interface @@ -89,21 +88,20 @@ where .cmd_with_data(spi, Command::TemperatureSensorControl, &[0xB1, 0x20]) .await?; - self.set_ram_counter(spi, delay, 0, 0).await?; + self.set_ram_counter(spi, 0, 0).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd1in54 +impl WaveshareDisplay + for Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -119,7 +117,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -130,17 +127,17 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) .await?; @@ -151,10 +148,9 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) .await?; @@ -165,17 +161,16 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.set_ram_area(spi, delay, x, y, x + width, y + height) + self.wait_until_idle(spi).await?; + self.set_ram_area(spi, x, y, x + width, y + height) .await?; - self.set_ram_counter(spi, delay, x, y).await?; + self.set_ram_counter(spi, x, y).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -183,8 +178,8 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; if self.refresh == RefreshLut::Full { self.interface .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7]) @@ -206,16 +201,15 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); @@ -242,15 +236,14 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, + RefreshLut::Full => self.set_lut_helper(spi, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE).await, }?; // Additional configuration required only for partial updates @@ -278,45 +271,41 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd1in54 +impl Epd1in54 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1) .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0).await + self.set_ram_counter(spi, 0, 0).await } pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, - delay: &mut DELAY, start_x: u32, start_y: u32, end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; assert!(start_x < end_x); assert!(start_y < end_y); @@ -349,11 +338,10 @@ where pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 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 @@ -374,10 +362,9 @@ where async fn set_lut_helper( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; assert!(buffer.len() == 159); self.interface @@ -388,7 +375,7 @@ where .cmd_with_data(spi, Command::WriteLutRegisterEnd, &[buffer[153]]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::GateDrivingVoltage, &[buffer[154]]) diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index c438e15e..e8c73032 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,7 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -39,22 +39,21 @@ pub type Display1in54b = crate::graphics::Display< >; /// Epd1in54b driver -pub struct Epd1in54b { - interface: DisplayInterface, +pub struct Epd1in54b { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd1in54b +impl InternalWiAdditions + for Epd1in54b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000).await; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.reset(spi, 10_000, 10_000).await; // set the power settings self.interface @@ -68,8 +67,8 @@ where // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set the panel settings self.cmd_with_data(spi, Command::PanelSetting, &[0xCF]) @@ -88,41 +87,38 @@ where self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E]) .await?; - self.set_lut(spi, delay, None).await?; + self.set_lut(spi, None).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd1in54b +impl WaveshareThreeColorDisplay + for Epd1in54b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } async fn update_achromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; self.interface @@ -139,7 +135,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -150,14 +145,13 @@ where } } -impl WaveshareDisplay - for Epd1in54b +impl WaveshareDisplay + for Epd1in54b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -165,7 +159,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -173,13 +166,13 @@ where let mut epd = Epd1in54b { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) .await?; //border floating @@ -192,7 +185,7 @@ where .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00]) .await?; //VG&VS to 0V fast - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; //NOTE: The example code has a 1s delay here @@ -201,8 +194,8 @@ where Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -225,9 +218,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; self.interface @@ -259,7 +251,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -269,8 +260,8 @@ where unimplemented!() } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -279,15 +270,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -315,7 +305,6 @@ where async fn set_lut( &mut self, spi: &mut SPI, - _delay: &mut DELAY, _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.interface @@ -348,21 +337,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd1in54b +impl Epd1in54b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index e6ae0fa7..9ebfff2b 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,7 +1,7 @@ //! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -36,26 +36,25 @@ pub type Display1in54c = crate::graphics::Display< >; /// Epd1in54c driver -pub struct Epd1in54c { - interface: DisplayInterface, +pub struct Epd1in54c { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd1in54c +impl InternalWiAdditions + for Epd1in54c where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Based on Reference Program Code from: // https://www.waveshare.com/w/upload/a/ac/1.54inch_e-Paper_Module_C_Specification.pdf // and: // https://github.com/waveshare/e-Paper/blob/master/STM32/STM32-F103ZET6/User/e-Paper/EPD_1in54c.c - self.interface.reset(delay, 10_000, 2_000).await; + self.interface.reset(spi, 10_000, 2_000).await; // start the booster self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) @@ -63,8 +62,8 @@ where // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set the panel settings self.cmd_with_data(spi, Command::PanelSetting, &[0x0f, 0x0d]) @@ -80,33 +79,30 @@ where } } -impl WaveshareThreeColorDisplay - for Epd1in54c +impl WaveshareThreeColorDisplay + for Epd1in54c where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } async fn update_achromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission1, black) .await?; @@ -116,10 +112,9 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic) .await?; @@ -127,14 +122,13 @@ where } } -impl WaveshareDisplay - for Epd1in54c +impl WaveshareDisplay + for Epd1in54c where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -142,7 +136,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -150,23 +143,23 @@ where let mut epd = Epd1in54c { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xa5]).await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -189,9 +182,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, buffer).await?; + self.update_achromatic_frame(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); @@ -208,7 +200,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -218,9 +209,9 @@ where unimplemented!() } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -229,16 +220,15 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black @@ -258,8 +248,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { Ok(()) @@ -267,21 +256,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd1in54c +impl Epd1in54c where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 8fab7a5f..3265e0a4 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,7 +16,7 @@ //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::buffer_len; use crate::color::Color; @@ -66,9 +66,9 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd2in13 (V2 & V3) driver /// /// To use this driver for V2 of the display, feature \"epd2in13_v3\" needs to be disabled and feature \"epd2in13_v2\" enabled. -pub struct Epd2in13 { +pub struct Epd2in13 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, sleep_mode: DeepSleepMode, @@ -77,24 +77,23 @@ pub struct Epd2in13 { refresh: RefreshLut, } -impl InternalWiAdditions - for Epd2in13 +impl InternalWiAdditions + for Epd2in13 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // HW reset - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; if self.refresh == RefreshLut::Quick { self.set_vcom_register(spi, (-9).vcom()).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; - self.set_lut(spi, delay, Some(self.refresh)).await?; + self.set_lut(spi, Some(self.refresh)).await?; // Python code does this, not sure why // self.cmd_with_data(spi, Command::WriteOtpSelection, &[0, 0, 0, 0, 0x40, 0, 0])?; @@ -107,7 +106,7 @@ where ) .await?; self.command(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.set_border_waveform( spi, @@ -119,9 +118,9 @@ where ) .await?; } else { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::SwReset).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.set_driver_output( spi, @@ -143,7 +142,7 @@ where // Use simple X/Y auto increase self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.set_border_waveform( spi, @@ -169,22 +168,21 @@ where self.set_gate_line_width(spi, 10).await?; - self.set_lut(spi, delay, Some(self.refresh)).await?; + self.set_lut(spi, Some(self.refresh)).await?; } - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd2in13 +impl WaveshareDisplay + for Epd2in13 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -192,7 +190,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let mut epd = Epd2in13 { @@ -202,16 +199,16 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // All sample code enables and disables analog/clocks... self.set_display_update_control_2( @@ -233,18 +230,17 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equal to current if not doing partial refresh. self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.cmd_with_data(spi, Command::WriteRamRed, buffer) .await?; @@ -258,7 +254,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -276,14 +271,14 @@ where assert!(self.refresh == RefreshLut::Full); self.set_ram_area(spi, x, y, x + width, y + height).await?; - self.set_ram_address_counters(spi, delay, x, y).await?; + self.set_ram_address_counters(spi, x, y).await?; self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equals to current if not doing partial refresh. self.set_ram_area(spi, x, y, x + width, y + height).await?; - self.set_ram_address_counters(spi, delay, x, y).await?; + self.set_ram_address_counters(spi, x, y).await?; self.cmd_with_data(spi, Command::WriteRamRed, buffer) .await?; @@ -294,7 +289,7 @@ where /// Never use directly this function when using partial refresh, or also /// keep the base buffer in syncd using `set_partial_base_buffer` function. - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { if self.refresh == RefreshLut::Full { self.set_display_update_control_2( spi, @@ -311,7 +306,7 @@ where .await?; } self.command(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -320,22 +315,21 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; if self.refresh == RefreshLut::Quick { - self.set_partial_base_buffer(spi, delay, buffer).await?; + self.set_partial_base_buffer(spi, buffer).await?; } Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let color = self.background_color.get_byte_value(); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.command(spi, Command::WriteRam).await?; self.interface @@ -349,7 +343,7 @@ where // Always keep the base buffer equals to current if not doing partial refresh. if self.refresh == RefreshLut::Full { self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.command(spi, Command::WriteRamRed).await?; self.interface @@ -382,7 +376,6 @@ where async fn set_lut( &mut self, spi: &mut SPI, - _delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { let buffer = match refresh_rate { @@ -396,33 +389,30 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd2in13 +impl Epd2in13 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. pub async fn set_partial_base_buffer( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { assert!(buffer_len(WIDTH as usize, HEIGHT as usize) == buffer.len()); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; - self.set_ram_address_counters(spi, delay, 0, 0).await?; + self.set_ram_address_counters(spi, 0, 0).await?; self.cmd_with_data(spi, Command::WriteRamRed, buffer) .await?; @@ -439,12 +429,11 @@ where pub async fn set_refresh( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh: RefreshLut, ) -> Result<(), SPI::Error> { if self.refresh != refresh { self.refresh = refresh; - self.init(spi, delay).await?; + self.init(spi).await?; } Ok(()) } @@ -597,11 +586,10 @@ where async fn set_ram_address_counters( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) .await?; diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 5afdba2e..ccf69ac0 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -20,7 +20,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in13bc::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in13bc::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white/chromatic pixels @@ -51,7 +51,7 @@ //!# } //!``` use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -93,24 +93,23 @@ pub type Display2in13bc = crate::graphics::Display< >; /// Epd2in13bc driver -pub struct Epd2in13bc { - interface: DisplayInterface, +pub struct Epd2in13bc { + interface: DisplayInterface, color: TriColor, } -impl InternalWiAdditions - for Epd2in13bc +impl InternalWiAdditions + for Epd2in13bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; // start the booster self.interface @@ -119,8 +118,8 @@ where // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set the panel settings self.cmd_with_data(spi, Command::PanelSetting, &[0x8F]) @@ -139,30 +138,28 @@ where self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd2in13bc +impl WaveshareThreeColorDisplay + for Epd2in13bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } /// Update only the black/white data of the display. @@ -171,7 +168,6 @@ where async fn update_achromatic_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -187,7 +183,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -195,19 +190,18 @@ where .await?; self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd2in13bc +impl WaveshareDisplay + for Epd2in13bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = TriColor; async fn new( @@ -215,7 +209,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -223,12 +216,12 @@ where let mut epd = Epd2in13bc { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Section 8.2 from datasheet self.interface .cmd_with_data( @@ -240,15 +233,15 @@ where self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: TriColor) { @@ -271,7 +264,6 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.interface .cmd(spi, Command::DataStartTransmission1) @@ -289,7 +281,7 @@ where .data_x_times(spi, color, NUM_DISPLAY_BITS) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -297,7 +289,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -307,10 +298,10 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -318,14 +309,13 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -347,14 +337,13 @@ where .data_x_times(spi, color, NUM_DISPLAY_BITS) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { Ok(()) @@ -362,21 +351,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd2in13bc +impl Epd2in13bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 26f6020d..fdd88932 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -3,7 +3,7 @@ //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -41,30 +41,29 @@ pub type Display2in7b = crate::graphics::Display< >; /// Epd2in7b driver -pub struct Epd2in7b { +pub struct Epd2in7b { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd2in7b +impl InternalWiAdditions + for Epd2in7b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 2_000).await; + self.interface.reset(spi, 10_000, 2_000).await; // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set panel settings, 0xbf is bw, 0xaf is multi-color self.interface @@ -111,25 +110,24 @@ where .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87]) .await?; - self.set_lut(spi, delay, None).await?; + self.set_lut(spi, None).await?; self.interface .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd2in7b +impl WaveshareDisplay + for Epd2in7b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -137,7 +135,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -145,23 +142,23 @@ where let mut epd = Epd2in7b { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7]) .await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) .await?; @@ -171,9 +168,7 @@ where async fn update_frame( &mut self, spi: &mut SPI, - buffer: &[u8], - _delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + buffer: &[u8] ) -> Result<(), SPI::Error> { self.interface .cmd(spi, Command::DataStartTransmission1) .await?; @@ -194,7 +189,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -213,16 +207,16 @@ where self.send_data(spi, &[(width & 0xf8) as u8]).await?; self.send_data(spi, &[(height >> 8) as u8]).await?; self.send_data(spi, &[(height & 0xff) as u8]).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.send_buffer_helper(spi, buffer).await?; self.interface.cmd(spi, Command::DataStop).await } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -230,15 +224,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; let color_value = self.color.get_byte_value(); self.interface @@ -279,10 +272,9 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, _refresh_rate: Option, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC) .await?; self.cmd_with_data(spi, Command::LutWhiteToWhite, &LUT_WW) @@ -298,32 +290,29 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd2in7b +impl WaveshareThreeColorDisplay + for Epd2in7b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } /// Update only the black/white data of the display. @@ -332,7 +321,6 @@ where async fn update_achromatic_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, achromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -350,7 +338,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -360,19 +347,18 @@ where self.send_buffer_helper(spi, chromatic).await?; self.interface.cmd(spi, Command::DataStop).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl Epd2in7b +impl Epd2in7b where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await @@ -404,7 +390,6 @@ where pub async fn display_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, width: u32, @@ -419,7 +404,7 @@ where self.send_data(spi, &[(width & 0xf8) as u8]).await?; self.send_data(spi, &[(height >> 8) as u8]).await?; self.send_data(spi, &[(height & 0xff) as u8]).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -428,7 +413,6 @@ where pub async fn update_partial_achromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, achromatic: &[u8], x: u32, y: u32, @@ -446,7 +430,7 @@ where self.send_data(spi, &[(width & 0xf8) as u8]).await?; self.send_data(spi, &[(height >> 8) as u8]).await?; self.send_data(spi, &[(height & 0xff) as u8]).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; for b in achromatic.iter() { // Flipping based on waveshare implementation @@ -461,7 +445,6 @@ where pub async fn update_partial_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], x: u32, y: u32, @@ -479,7 +462,7 @@ where self.send_data(spi, &[(width & 0xf8) as u8]).await?; self.send_data(spi, &[(height >> 8) as u8]).await?; self.send_data(spi, &[(height & 0xff) as u8]).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; for b in chromatic.iter() { // Flipping based on waveshare implementation diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 7f742fd6..186b63fc 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -21,7 +21,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display2in9::default(); @@ -51,7 +51,7 @@ const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -77,27 +77,26 @@ pub type Display2in9 = crate::graphics::Display< /// Epd2in9 driver /// -pub struct Epd2in9 { +pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd2in9 +impl Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000).await; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.reset(spi, 10_000, 10_000).await; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 3 Databytes: // A[7:0] @@ -138,18 +137,17 @@ where .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) .await?; - self.set_lut(spi, delay, None).await + self.set_lut(spi, None).await } } -impl WaveshareDisplay - for Epd2in9 +impl WaveshareDisplay + for Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -165,7 +163,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -176,13 +173,13 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) self.interface @@ -191,9 +188,9 @@ where Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.init(spi, delay).await?; + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; + self.init(spi).await?; Ok(()) } @@ -201,10 +198,9 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -216,16 +212,15 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.set_ram_area(spi, x, y, x + width, y + height).await?; - self.set_ram_counter(spi, delay, x, y).await?; + self.set_ram_counter(spi, x, y).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -233,8 +228,8 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // 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 @@ -252,16 +247,15 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; + self.use_full_frame(spi).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); @@ -284,42 +278,39 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE).await, - RefreshLut::Quick => self.set_lut_helper(spi, delay, &LUT_PARTIAL_UPDATE).await, + RefreshLut::Full => self.set_lut_helper(spi, &LUT_FULL_UPDATE).await, + RefreshLut::Quick => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE).await, } } async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd2in9 +impl Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // choose full frame/ram self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0).await + self.set_ram_counter(spi, 0, 0).await } async fn set_ram_area( @@ -361,11 +352,10 @@ where async fn set_ram_counter( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 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 @@ -387,10 +377,9 @@ where async fn set_lut_helper( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; assert!(buffer.len() == 30); self.interface .cmd_with_data(spi, Command::WriteLutRegister, buffer) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 42e3fba9..82a503f0 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -22,7 +22,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display2in9::default(); @@ -76,7 +76,7 @@ const LUT_PARTIAL_2IN9: [u8; 159] = [ ]; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::type_a::command::Command; @@ -100,29 +100,28 @@ pub type Display2in9 = crate::graphics::Display< /// Epd2in9 driver /// -pub struct Epd2in9 { +pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd2in9 +impl Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 2_000).await; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.interface.reset(spi, 10_000, 2_000).await; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface.cmd(spi, Command::SwReset).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 3 Databytes: // A[7:0] @@ -145,21 +144,20 @@ where .cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80]) .await?; - self.set_ram_counter(spi, delay, 0, 0).await?; + self.set_ram_counter(spi, 0, 0).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd2in9 +impl WaveshareDisplay + for Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -175,7 +173,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -186,13 +183,13 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode self.interface .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) @@ -200,8 +197,8 @@ where Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await?; + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await?; Ok(()) } @@ -209,9 +206,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) .await @@ -220,7 +216,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -228,9 +223,9 @@ where height: u32, ) -> Result<(), SPI::Error> { //TODO This is copied from epd2in9 but it seems not working. Partial refresh supported by version 2? - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.set_ram_area(spi, x, y, x + width, y + height).await?; - self.set_ram_counter(spi, delay, x, y).await?; + self.set_ram_counter(spi, x, y).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -239,14 +234,14 @@ where } /// actually is the "Turn on Display" sequence - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) .await?; self.interface.cmd(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -254,15 +249,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); @@ -287,8 +281,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { @@ -299,28 +292,26 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd2in9 +impl Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // choose full frame/ram self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0).await + self.set_ram_counter(spi, 0, 0).await } async fn set_ram_area( @@ -362,11 +353,10 @@ where async fn set_ram_counter( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // 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 @@ -388,35 +378,32 @@ where async fn set_lut_helper( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::WriteLutRegister, buffer) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl QuickRefresh - for Epd2in9 +impl QuickRefresh + for Epd2in9 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// To be followed immediately by `update_new_frame`. async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam2, buffer) .await @@ -427,12 +414,11 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.interface.reset(delay, 10_000, 2_000).await; + self.wait_until_idle(spi).await?; + self.interface.reset(spi, 10_000, 2_000).await; - self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9).await?; + self.set_lut_helper(spi, &LUT_PARTIAL_2IN9).await?; self.interface .cmd_with_data( spi, @@ -448,9 +434,9 @@ where .await?; self.interface.cmd(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; - self.use_full_frame(spi, delay).await?; + self.use_full_frame(spi).await?; self.interface .cmd_with_data(spi, Command::WriteRam, buffer) @@ -462,14 +448,13 @@ where async fn display_new_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F]) .await?; self.interface.cmd(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -478,10 +463,9 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay).await?; - self.display_new_frame(spi, delay).await?; + self.update_new_frame(spi, buffer).await?; + self.display_new_frame(spi).await?; Ok(()) } @@ -490,7 +474,6 @@ where async fn update_partial_old_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -506,7 +489,6 @@ where async fn update_partial_new_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -522,7 +504,6 @@ where async fn clear_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, width: u32, diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index f319eaf7..752e3d54 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -20,7 +20,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9bc::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9bc::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white pixels @@ -55,7 +55,7 @@ //!# } //!``` use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -97,24 +97,23 @@ pub type Display2in9bc = crate::graphics::Display< >; /// Epd2in9bc driver -pub struct Epd2in9bc { - interface: DisplayInterface, +pub struct Epd2in9bc { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd2in9bc +impl InternalWiAdditions + for Epd2in9bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; // start the booster self.interface @@ -123,8 +122,8 @@ where // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set the panel settings self.cmd_with_data(spi, Command::PanelSetting, &[0x8F]) @@ -143,30 +142,28 @@ where self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd2in9bc +impl WaveshareThreeColorDisplay + for Epd2in9bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } /// Update only the black/white data of the display. @@ -175,7 +172,6 @@ where async fn update_achromatic_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -191,7 +187,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -199,19 +194,18 @@ where .await?; self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd2in9bc +impl WaveshareDisplay + for Epd2in9bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -219,7 +213,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -227,12 +220,12 @@ where let mut epd = Epd2in9bc { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Section 8.2 from datasheet self.interface .cmd_with_data( @@ -244,15 +237,15 @@ where self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -275,7 +268,6 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.interface .cmd(spi, Command::DataStartTransmission1) @@ -293,7 +285,7 @@ where .data_x_times(spi, color, NUM_DISPLAY_BITS) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -301,7 +293,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -311,10 +302,10 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -322,14 +313,13 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -351,14 +341,13 @@ where .data_x_times(spi, color, NUM_DISPLAY_BITS) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { Ok(()) @@ -366,21 +355,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd2in9bc +impl Epd2in9bc where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index 740a2d32..e2a74260 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -3,7 +3,7 @@ //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; pub(crate) mod command; mod constants; @@ -40,37 +40,36 @@ pub type Display3in7 = crate::graphics::Display< >; /// EPD3in7 driver -pub struct EPD3in7 { +pub struct EPD3in7 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color background_color: Color, } -impl InternalWiAdditions - for EPD3in7 +impl InternalWiAdditions + for EPD3in7 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 30, 10).await; + self.interface.reset(spi, 30, 10).await; self.interface.cmd(spi, Command::SwReset).await?; - delay.delay_us(300000u32).await; + self.interface.delay(spi, 300000u32).await; self.interface .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7]) .await?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; self.interface .cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7]) .await?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; self.interface .cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00]) @@ -133,19 +132,18 @@ where .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF]) .await?; - self.set_lut(spi, delay, Some(RefreshLut::Full)).await?; + self.set_lut(spi, Some(RefreshLut::Full)).await?; Ok(()) } } -impl WaveshareDisplay - for EPD3in7 +impl WaveshareDisplay + for EPD3in7 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; @@ -154,7 +152,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let mut epd = EPD3in7 { @@ -162,15 +159,15 @@ where background_color: DEFAULT_BACKGROUND_COLOR, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.interface .cmd_with_data(spi, Command::Sleep, &[0xF7]) .await?; @@ -201,7 +198,6 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - _delay: &mut DELAY, ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.interface @@ -222,7 +218,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -232,13 +227,13 @@ where todo!() } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { //self.interface // .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, &LUT_1GRAY_GC)?; self.interface .cmd(spi, Command::DisplayUpdateSequence) .await?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } @@ -246,14 +241,13 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.interface .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00]) .await?; @@ -273,7 +267,6 @@ where async fn set_lut( &mut self, spi: &mut SPI, - _delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { let buffer = match refresh_rate { @@ -289,10 +282,9 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index f9ce7af7..5938ccdf 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -25,7 +25,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display4in2::default(); @@ -50,7 +50,7 @@ //! BE CAREFUL! The screen can get ghosting/burn-ins through the Partial Fast Update Drawing. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; @@ -86,27 +86,26 @@ pub type Display4in2 = crate::graphics::Display< /// Epd4in2 driver /// -pub struct Epd4in2 { +pub struct Epd4in2 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, /// Refresh LUT refresh: RefreshLut, } -impl InternalWiAdditions - for Epd4in2 +impl InternalWiAdditions + for Epd4in2 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; // set the power settings self.interface @@ -120,8 +119,8 @@ where // power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // set the panel settings self.cmd_with_data(spi, Command::PanelSetting, &[0x3F]) @@ -145,21 +144,20 @@ where .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97]) .await?; - self.set_lut(spi, delay, None).await?; + self.set_lut(spi, None).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd4in2 +impl WaveshareDisplay + for Epd4in2 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -167,7 +165,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -179,13 +176,13 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) .await?; //border floating @@ -198,15 +195,15 @@ where } self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) .await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -229,9 +226,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; let color_value = self.color.get_byte_value(); self.interface @@ -250,14 +246,13 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); @@ -295,8 +290,8 @@ where Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -305,15 +300,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); @@ -337,7 +331,6 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { @@ -345,13 +338,12 @@ where } match self.refresh { RefreshLut::Full => { - self.set_lut_helper(spi, delay, &LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB) + self.set_lut_helper(spi, &LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB) .await } RefreshLut::Quick => { self.set_lut_helper( spi, - delay, &LUT_VCOM0_QUICK, &LUT_WW_QUICK, &LUT_BW_QUICK, @@ -365,21 +357,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd4in2 +impl Epd4in2 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await @@ -413,14 +403,13 @@ where async fn set_lut_helper( &mut self, spi: &mut SPI, - delay: &mut DELAY, lut_vcom: &[u8], lut_ww: &[u8], lut_bw: &[u8], lut_wb: &[u8], lut_bb: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // LUT VCOM self.cmd_with_data(spi, Command::LutForVcom, lut_vcom) .await?; @@ -473,23 +462,21 @@ where } } -impl QuickRefresh - for Epd4in2 +impl QuickRefresh + for Epd4in2 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// To be followed immediately after by `update_old_frame`. async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.interface .cmd(spi, Command::DataStartTransmission1) @@ -505,9 +492,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // self.send_resolution(spi).await?; self.interface @@ -524,9 +510,8 @@ where async fn display_new_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.display_frame(spi, delay).await + self.display_frame(spi).await } /// This is wrapper around `update_new_frame` and `display_frame` for using @@ -537,23 +522,21 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await + self.update_new_frame(spi, buffer).await?; + self.display_frame(spi).await } async fn update_partial_old_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that @@ -579,14 +562,13 @@ where async fn update_partial_new_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); @@ -607,13 +589,12 @@ where async fn clear_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 443944d1..81ed7257 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::OctColor; use crate::interface::DisplayInterface; @@ -38,25 +38,24 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd5in65f driver /// -pub struct Epd5in65f { +pub struct Epd5in65f { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: OctColor, } -impl InternalWiAdditions - for Epd5in65f +impl InternalWiAdditions + for Epd5in65f where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000).await; + self.interface.reset(spi, 10_000, 2_000).await; self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08]) .await?; @@ -77,21 +76,20 @@ where self.cmd_with_data(spi, Command::FlashMode, &[0xAA]).await?; - delay.delay_us(100_000).await; + self.interface.delay(spi, 100_000).await; self.update_vcom(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd5in65f +impl WaveshareDisplay + for Epd5in65f where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = OctColor; async fn new( @@ -99,7 +97,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -107,16 +104,16 @@ where let mut epd = Epd5in65f { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } @@ -125,9 +122,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.update_vcom(spi).await?; self.send_resolution(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission1, buffer) @@ -137,8 +133,7 @@ where async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -148,14 +143,14 @@ where unimplemented!(); } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOn).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_busy_low(delay).await; + self.wait_busy_low(spi).await; Ok(()) } @@ -163,23 +158,22 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let bg = OctColor::colors_byte(self.color, self.color); - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.update_vcom(spi).await?; self.send_resolution(spi).await?; self.command(spi, Command::DataStartTransmission1).await?; self.interface .data_x_times(spi, bg, WIDTH * HEIGHT / 2) .await?; - self.display_frame(spi, delay).await?; + self.display_frame(spi).await?; Ok(()) } @@ -201,8 +195,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -210,21 +203,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, true).await; + self.interface.wait_until_idle(spi, true).await; Ok(()) } } -impl Epd5in65f +impl Epd5in65f where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await @@ -243,8 +234,8 @@ where self.interface.cmd_with_data(spi, command, data).await } - async fn wait_busy_low(&mut self, delay: &mut DELAY) { - self.interface.wait_until_idle(delay, false).await; + async fn wait_busy_low(&mut self, spi: &mut SPI) { + self.interface.wait_until_idle(spi, false).await; } async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index 25f79492..330bc8ec 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -40,25 +40,24 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd7in5 driver /// -pub struct Epd5in83 { +pub struct Epd5in83 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd5in83 +impl InternalWiAdditions + for Epd5in83 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; // Start the booster self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x1e, 0x17]) @@ -70,8 +69,8 @@ where // Power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // Set the panel settings: BWROTP self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) @@ -91,39 +90,36 @@ where self.cmd_with_data(spi, Command::TconSetting, &[0x22]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd5in83 +impl WaveshareThreeColorDisplay + for Epd5in83 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await?; + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await?; Ok(()) } async fn update_achromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission1, black) .await?; Ok(()) @@ -132,24 +128,22 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic) .await?; Ok(()) } } -impl WaveshareDisplay - for Epd5in83 +impl WaveshareDisplay + for Epd5in83 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -157,7 +151,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -165,21 +158,21 @@ where let mut epd = Epd5in83 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -202,10 +195,9 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; - self.update_achromatic_frame(spi, delay, buffer).await?; + self.wait_until_idle(spi).await?; + self.update_achromatic_frame(spi, buffer).await?; let color = self.color.get_byte_value(); self.command(spi, Command::DataStartTransmission2).await?; self.interface @@ -217,14 +209,13 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error } @@ -259,15 +250,15 @@ where .await?; self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::PartialOut).await?; Ok(()) } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -275,15 +266,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; // The Waveshare controllers all implement clear using 0x33 self.command(spi, Command::DataStartTransmission1).await?; @@ -301,8 +291,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -310,21 +299,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd5in83 +impl Epd5in83 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 282d49e0..48f8f07c 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -38,25 +38,24 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000).await; + self.interface.reset(spi, 10_000, 10_000).await; // Set the power settings self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00]) @@ -74,8 +73,8 @@ where // Power on self.command(spi, Command::PowerOn).await?; - delay.delay_us(5000).await; - self.wait_until_idle(spi, delay).await?; + self.interface.delay(spi, 5000).await; + self.wait_until_idle(spi).await?; // Set the clock frequency to 50Hz (default) self.cmd_with_data(spi, Command::PllControl, &[0x3C]) @@ -103,19 +102,18 @@ where // This is in all the Waveshare controllers for Epd7in5 self.cmd_with_data(spi, Command::FlashMode, &[0x03]).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -123,7 +121,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -131,21 +128,21 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } fn set_background_color(&mut self, color: Color) { @@ -168,9 +165,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::DataStartTransmission1).await?; for byte in buffer { let mut temp = *byte; @@ -188,8 +184,7 @@ where async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -199,8 +194,8 @@ where unimplemented!(); } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -209,15 +204,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; // The Waveshare controllers all implement clear using 0x33 @@ -230,8 +224,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -239,21 +232,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd7in5 +impl Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 3c56c86e..90cb4132 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -10,7 +10,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -41,41 +41,40 @@ const SINGLE_BYTE_WRITE: bool = false; /// EPD7in5 (HD) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000).await; + self.interface.reset(spi, 10_000, 2_000).await; // HD procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py // and as per specs: // https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::SwReset).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::AutoWriteRed, &[0xF7]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::AutoWriteBw, &[0xF7]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::SoftStart, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40]) .await?; @@ -100,7 +99,7 @@ where .await?; self.command(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::SetRamXAc, &[0x00, 0x00]) .await?; @@ -111,14 +110,13 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -126,7 +124,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -134,17 +131,17 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0x01]).await?; Ok(()) } @@ -153,9 +150,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) .await?; self.cmd_with_data(spi, Command::WriteRamBw, buffer).await?; @@ -166,8 +162,7 @@ where async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -177,9 +172,9 @@ where unimplemented!(); } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.command(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -187,18 +182,17 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; - self.display_frame(spi, delay).await?; + self.update_frame(spi, buffer).await?; + self.display_frame(spi).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let pixel_count = WIDTH * HEIGHT / 8; let background_color_byte = self.color.get_byte_value(); - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) .await?; @@ -212,7 +206,7 @@ where self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) .await?; self.command(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } @@ -234,8 +228,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -243,21 +236,19 @@ where async fn wait_until_idle( &mut self, - _spi: &mut SPI, - delay: &mut DELAY, + spi: &mut SPI, ) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; + self.interface.wait_until_idle(spi, IS_BUSY_LOW).await; Ok(()) } } -impl Epd7in5 +impl Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 183e286c..2a68f55a 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::Color; use crate::interface::DisplayInterface; @@ -42,25 +42,24 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000).await; + self.interface.reset(spi, 10_000, 2_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py @@ -72,7 +71,7 @@ where self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F]) .await?; self.command(spi, Command::PowerOn).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::PanelSetting, &[0x1F]) .await?; self.cmd_with_data(spi, Command::PllControl, &[0x06]) @@ -84,19 +83,18 @@ where .await?; self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07]) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = Color; async fn new( @@ -104,7 +102,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -112,19 +109,19 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } @@ -133,9 +130,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) .await?; Ok(()) @@ -143,8 +139,7 @@ where async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -154,8 +149,8 @@ where unimplemented!(); } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -164,15 +159,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; self.command(spi, Command::DataStartTransmission1).await?; @@ -207,8 +201,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -217,21 +210,19 @@ where async fn wait_until_idle( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.interface - .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .wait_until_idle_with_cmd(spi, IS_BUSY_LOW, Command::GetStatus) .await } } -impl Epd7in5 +impl Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index e171614b..a5384fde 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -8,7 +8,7 @@ //! use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -46,36 +46,42 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V3) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + defmt::info!("initializing Epd7in5"); + // Reset the device - self.interface.reset(delay, 200_000, 4_000).await; + defmt::info!("reset"); + self.interface.reset(spi, 200_000, 4_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py // and as per specs: // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf + defmt::info!("PowerSetting"); //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17]).await?; self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F]) .await?; + defmt::info!("Poweron"); self.command(spi, Command::PowerOn).await?; - self.wait_until_idle(spi, delay).await?; + + defmt::info!("wait for idle"); + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) .await?; //self.cmd_with_data(spi, Command::PllControl, &[0x06]).await?; @@ -88,29 +94,30 @@ where .await?; self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00]) .await?; - self.wait_until_idle(spi, delay).await?; + + defmt::info!("waiting for idle"); + self.wait_until_idle(spi).await?; + defmt::info!("we are idle"); Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd7in5 +impl WaveshareThreeColorDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black).await?; - self.update_chromatic_frame(spi, delay, chromatic).await + self.update_achromatic_frame(spi, black).await?; + self.update_chromatic_frame(spi, chromatic).await } /// Update only the black/white data of the display. @@ -119,7 +126,6 @@ where async fn update_achromatic_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -135,7 +141,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface @@ -143,19 +148,18 @@ where .await?; self.interface.data(spi, chromatic).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = TriColor; async fn new( @@ -163,7 +167,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -171,19 +174,19 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } @@ -192,9 +195,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) .await?; @@ -210,15 +212,14 @@ where .data_x_times(spi, color, NUM_DISPLAY_BITS) .await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -228,8 +229,8 @@ where unimplemented!(); } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -238,15 +239,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; self.command(spi, Command::DataStartTransmission1).await?; @@ -281,8 +281,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -291,21 +290,19 @@ where async fn wait_until_idle( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.interface - .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .wait_until_idle_with_cmd(spi, IS_BUSY_LOW, Command::GetStatus) .await } } -impl Epd7in5 +impl Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command).await diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 16e95bdd..b45ffc4e 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, digital::Wait, spi::SpiDevice}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; use crate::color::TriColor; use crate::interface::DisplayInterface; @@ -44,26 +44,25 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { // Reset the device // C driver does 200/2 original rust driver does 10/2 - self.interface.reset(delay, 200_000, 2_000).await; + self.interface.reset(spi, 200_000, 2_000).await; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py @@ -74,7 +73,7 @@ where .await?; self.command(spi, Command::PowerOn).await?; // C driver adds a static 100ms delay here - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // Done, but this is also the default // 0x1F = B/W mode ? doesnt seem to work self.cmd_with_data(spi, Command::PanelSetting, &[0x0F]) @@ -101,19 +100,18 @@ where self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00]) .await?; // Not in C driver - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; Ok(()) } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { type DisplayColor = TriColor; async fn new( @@ -121,7 +119,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); @@ -129,19 +126,19 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay).await?; + epd.init(spi).await?; Ok(epd) } - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay).await + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.init(spi).await } - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::PowerOff).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } @@ -150,9 +147,8 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; // (B) version sends one buffer for black and one for red self.cmd_with_data( spi, @@ -171,8 +167,7 @@ where async fn update_partial_frame( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _buffer: &[u8], _x: u32, _y: u32, @@ -182,8 +177,8 @@ where unimplemented!() } - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -192,15 +187,14 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay).await?; + self.update_frame(spi, buffer).await?; self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(spi).await?; self.send_resolution(spi).await?; self.command(spi, Command::DataStartTransmission1).await?; @@ -236,8 +230,7 @@ where async fn set_lut( &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, + spi: &mut SPI, _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); @@ -247,21 +240,19 @@ where async fn wait_until_idle( &mut self, spi: &mut SPI, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.interface - .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .wait_until_idle_with_cmd(spi, IS_BUSY_LOW, Command::GetStatus) .await } } -impl Epd7in5 +impl Epd7in5 where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// temporary replacement for missing delay in the trait to call wait_until_idle #[allow(clippy::too_many_arguments)] @@ -273,9 +264,8 @@ where y: u32, width: u32, height: u32, - delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error } @@ -307,7 +297,7 @@ where .await?; self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay).await?; + self.wait_until_idle(spi).await?; self.command(spi, Command::PartialOut).await?; Ok(()) diff --git a/src/interface.rs b/src/interface.rs index 454d9351..326dc632 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,16 +1,17 @@ use crate::traits::Command; use core::marker::PhantomData; -use embedded_hal::digital::{InputPin, OutputPin, ErrorType}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice, digital::Wait}; +use embedded_hal::{ + digital::{ErrorType, InputPin, OutputPin}, + spi::Operation, +}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// /// SINGLE_BYTE_WRITE defines if a data block is written bytewise /// or blockwise to the spi device -pub(crate) struct DisplayInterface { +pub(crate) struct DisplayInterface { /// SPI _spi: PhantomData, - /// DELAY - _delay: PhantomData, /// Low for busy, Wait until display is ready! busy: BUSY, /// Data/Command Control Pin (High for data, Low for command) @@ -21,14 +22,13 @@ pub(crate) struct DisplayInterface - DisplayInterface +impl + DisplayInterface where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// Creates a new `DisplayInterface` struct /// @@ -38,7 +38,6 @@ where let delay_us = delay_us.unwrap_or(10_000); DisplayInterface { _spi: PhantomData, - _delay: PhantomData, busy, dc, rst, @@ -138,18 +137,20 @@ where /// - FALSE for epd2in9, epd1in54 (for all Display Type A ones?) /// /// Most likely there was a mistake with the 2in9 busy connection - pub(crate) async fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) -> Result<(), BUSY::Error> { - + pub(crate) async fn wait_until_idle( + &mut self, + spi: &mut SPI, + is_busy_low: bool, + ) -> Result<(), BUSY::Error> { if is_busy_low { self.busy.wait_for_high().await?; - } - else { + } else { self.busy.wait_for_low().await?; } // TODO: remove if self.delay_us > 0 { - delay.delay_us(self.delay_us).await; + self.delay(spi, self.delay_us).await; } Ok(()) } @@ -158,24 +159,28 @@ where pub(crate) async fn wait_until_idle_with_cmd( &mut self, spi: &mut SPI, - delay: &mut DELAY, is_busy_low: bool, status_command: T, ) -> Result<(), SPI::Error> { self.cmd(spi, status_command).await?; if self.delay_us > 0 { - delay.delay_us(self.delay_us).await; + self.delay(spi, self.delay_us).await?; } + // TODO while self.is_busy(is_busy_low) { self.cmd(spi, status_command).await?; if self.delay_us > 0 { - delay.delay_us(self.delay_us).await; + self.delay(spi, self.delay_us).await?; } } Ok(()) } + pub(crate) async fn delay(&mut self, spi: &mut SPI, duration: u32) -> Result<(), SPI::Error> { + spi.transaction(&mut [Operation::DelayUs(duration)]).await + } + /// Checks if device is still busy /// /// This is normally handled by the more complicated commands themselves, @@ -201,15 +206,20 @@ where /// The timing of keeping the reset pin low seems to be important and different per device. /// Most displays seem to require keeping it low for 10ms, but the 7in5_v2 only seems to reset /// properly with 2ms - pub(crate) async fn reset(&mut self, delay: &mut DELAY, initial_delay: u32, duration: u32) { + pub(crate) async fn reset( + &mut self, + spi: &mut SPI, + initial_delay: u32, + duration: u32, + ) { let _ = self.rst.set_high(); - delay.delay_us(initial_delay).await; + self.delay(spi, initial_delay).await; let _ = self.rst.set_low(); - delay.delay_us(duration).await; + self.delay(spi, duration).await; let _ = self.rst.set_high(); //TODO: the upstream libraries always sleep for 200ms here // 10ms works fine with just for the 7in5_v2 but this needs to be validated for other devices - delay.delay_us(200_000).await; + self.delay(spi, 200_000).await; } } diff --git a/src/lib.rs b/src/lib.rs index 3174250f..e7db51d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); diff --git a/src/traits.rs b/src/traits.rs index 7fe7ff77..028bb00d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,6 +1,6 @@ use core::marker::Sized; use embedded_hal::digital::{InputPin, OutputPin}; -use embedded_hal_async::{delay::DelayUs, spi::SpiDevice, digital::Wait}; +use embedded_hal_async::{digital::Wait, spi::SpiDevice}; /// All commands need to have this trait which gives the address of the command /// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode) @@ -19,13 +19,12 @@ pub enum RefreshLut { Quick, } -pub(crate) trait InternalWiAdditions +pub(crate) trait InternalWiAdditions where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// This initialises the EPD and powers it up /// @@ -37,18 +36,17 @@ where /// This function calls [reset](WaveshareDisplay::reset), /// so you don't need to call reset your self when trying to wake your device up /// after setting it to sleep. - async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn init(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; } /// Functions to interact with three color panels -pub trait WaveshareThreeColorDisplay: - WaveshareDisplay +pub trait WaveshareThreeColorDisplay: + WaveshareDisplay where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// Transmit data to the SRAM of the EPD /// @@ -56,7 +54,6 @@ where async fn update_color_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error>; @@ -67,7 +64,6 @@ where async fn update_achromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, black: &[u8], ) -> Result<(), SPI::Error>; @@ -78,7 +74,6 @@ where async fn update_chromatic_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error>; } @@ -104,10 +99,9 @@ where ///# let busy_in = pin::Mock::new(&expectations); ///# let dc = pin::Mock::new(&expectations); ///# let rst = pin::Mock::new(&expectations); -///# let mut delay = delay::NoopDelay::new(); /// ///// Setup EPD -///let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +///let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, None)?; /// ///// Use display graphics from embedded-graphics ///let mut display = Display4in2::default(); @@ -119,21 +113,20 @@ where /// .draw(&mut display); /// /// // Display updated frame -///epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; -///epd.display_frame(&mut spi, &mut delay)?; +///epd.update_frame(&mut spi, &display.buffer())?; +///epd.display_frame(&mut spi)?; /// ///// Set the EPD to sleep -///epd.sleep(&mut spi, &mut delay)?; +///epd.sleep(&mut spi)?; ///# Ok(()) ///# } ///``` -pub trait WaveshareDisplay +pub trait WaveshareDisplay where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// The Color Type used by the Display type DisplayColor; @@ -149,7 +142,6 @@ where busy: BUSY, dc: DC, rst: RST, - delay: &mut DELAY, delay_us: Option, ) -> Result where @@ -158,12 +150,12 @@ where /// Let the device enter deep-sleep mode to save power. /// /// The deep sleep mode returns to standby with a hardware reset. - async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; /// Wakes the device up from sleep /// /// Also reintialises the device if necessary. - async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn wake_up(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame) fn set_background_color(&mut self, color: Self::DisplayColor); @@ -182,7 +174,6 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Transmits partial data to the SRAM of the EPD @@ -194,7 +185,6 @@ where async fn update_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -205,20 +195,19 @@ where /// Displays the frame data from SRAM /// /// This function waits until the device isn`t busy anymore - async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async 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) async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Clears the frame buffer on the EPD with the declared background color /// /// The background color can be changed with [`WaveshareDisplay::set_background_color`] - async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; /// Trait for using various Waveforms from different LUTs /// E.g. for partial refreshes @@ -231,14 +220,13 @@ where async fn set_lut( &mut self, spi: &mut SPI, - delay: &mut DELAY, refresh_rate: Option, ) -> Result<(), SPI::Error>; /// Wait until the display has stopped processing data /// /// You can call this to make sure a frame is displayed before goin further - async fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) + async fn wait_until_idle(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; } @@ -267,40 +255,37 @@ where ///# let busy_in = pin::Mock::new(&expectations); ///# let dc = pin::Mock::new(&expectations); ///# let rst = pin::Mock::new(&expectations); -///# let mut delay = delay::NoopDelay::new(); ///# ///# // Setup EPD -///# let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; +///# let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, None)?; ///let (x, y, frame_width, frame_height) = (20, 40, 80,80); /// ///let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 80 / 8 * 80]; ///let mut display = VarDisplay::new(frame_width, frame_height, &mut buffer,false).unwrap(); /// -///epd.update_partial_old_frame(&mut spi, &mut delay, display.buffer(), x, y, frame_width, frame_height) +///epd.update_partial_old_frame(&mut spi, display.buffer(), x, y, frame_width, frame_height) /// .ok(); /// ///display.clear(Color::White).ok(); ///// Execute drawing commands here. /// -///epd.update_partial_new_frame(&mut spi, &mut delay, display.buffer(), x, y, frame_width, frame_height) +///epd.update_partial_new_frame(&mut spi, display.buffer(), x, y, frame_width, frame_height) /// .ok(); ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh where SPI: SpiDevice, BUSY: InputPin + Wait, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, { /// Updates the old frame. async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Updates the new frame. @@ -308,14 +293,12 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Displays the new frame async fn display_new_frame( &mut self, spi: &mut SPI, - _delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Updates and displays the new frame. @@ -323,7 +306,6 @@ where &mut self, spi: &mut SPI, buffer: &[u8], - delay: &mut DELAY, ) -> Result<(), SPI::Error>; /// Updates the old frame for a portion of the display. @@ -331,7 +313,6 @@ where async fn update_partial_old_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -344,7 +325,6 @@ where async fn update_partial_new_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, buffer: &[u8], x: u32, y: u32, @@ -357,7 +337,6 @@ where async fn clear_partial_frame( &mut self, spi: &mut SPI, - delay: &mut DELAY, x: u32, y: u32, width: u32,