From 7e9fb38f222e35ffda5700f2649ae6844fcb0ca1 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 11:37:50 +0100 Subject: [PATCH] make everything async --- Cargo.toml | 6 +- src/epd1in54/mod.rs | 119 +++++++++--------- src/epd1in54_v2/mod.rs | 151 +++++++++++----------- src/epd1in54b/mod.rs | 161 ++++++++++++------------ src/epd1in54c/mod.rs | 119 +++++++++--------- src/epd2in13_v2/mod.rs | 225 ++++++++++++++++----------------- src/epd2in13bc/mod.rs | 135 ++++++++++---------- src/epd2in7b/mod.rs | 255 ++++++++++++++++++------------------- src/epd2in9/mod.rs | 119 +++++++++--------- src/epd2in9_v2/mod.rs | 167 ++++++++++++------------ src/epd2in9bc/mod.rs | 135 ++++++++++---------- src/epd3in7/mod.rs | 105 ++++++++-------- src/epd4in2/mod.rs | 273 ++++++++++++++++++++-------------------- src/epd5in65f/mod.rs | 134 ++++++++++---------- src/epd5in83b_v2/mod.rs | 157 ++++++++++++----------- src/epd7in5/mod.rs | 119 +++++++++--------- src/epd7in5_hd/mod.rs | 117 +++++++++-------- src/epd7in5_v2/mod.rs | 117 +++++++++-------- src/epd7in5_v3/mod.rs | 147 +++++++++++----------- src/epd7in5b_v2/mod.rs | 137 ++++++++++---------- src/interface.rs | 51 ++++---- src/lib.rs | 3 + src/traits.rs | 45 +++---- 23 files changed, 1492 insertions(+), 1505 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..164bd049 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,8 +97,8 @@ 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] @@ -108,7 +109,7 @@ where 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 +117,28 @@ 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 +161,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -176,39 +177,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?; // 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 +219,50 @@ 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 +274,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -283,13 +284,13 @@ 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 +303,19 @@ 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,7 +324,7 @@ 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); @@ -333,7 +334,7 @@ where 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( @@ -345,43 +346,43 @@ where 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], - )?; + ).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..6e456106 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,11 +47,11 @@ 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] @@ -61,28 +62,28 @@ where 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 - )?; + ).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 +106,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -121,37 +122,37 @@ 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 +162,56 @@ 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 +223,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -232,8 +233,8 @@ 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 @@ -242,21 +243,21 @@ where spi, Command::WriteOtpSelection, &[0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0], - )?; + ).await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80]).await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xc0])?; - self.interface.cmd(spi, Command::MasterActivation)?; + .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 +270,19 @@ 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,7 +291,7 @@ 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); @@ -300,7 +301,7 @@ where 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( @@ -312,59 +313,59 @@ where 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], - )?; + ).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]], - )?; + ).await?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]]).await?; Ok(()) } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 0a477bf4..d05ce02c 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,38 @@ 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 +99,43 @@ 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 +150,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -162,33 +163,33 @@ 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 +208,21 @@ 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 +231,15 @@ 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 +252,69 @@ 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.cmd(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; + .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::LutG0, LUT_G1).await?; + self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2).await?; self.interface - .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?; + .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM).await?; self.interface - .cmd_with_data(spi, Command::LutRed0, LUT_RED0)?; + .cmd_with_data(spi, Command::LutRed0, LUT_RED0).await?; self.interface - .cmd_with_data(spi, Command::LutRed1, LUT_RED1)?; + .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 +327,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..fc23f930 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,28 @@ 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 +86,37 @@ 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 +132,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -144,23 +145,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 +180,25 @@ 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 +211,41 @@ 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 +254,8 @@ 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 +268,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..8575eff7 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,9 @@ 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 +115,11 @@ 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 +129,17 @@ 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 +148,24 @@ 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 +180,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -198,16 +195,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 +214,31 @@ 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 +246,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 +266,17 @@ 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 +284,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 +294,55 @@ 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.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::WriteRam)?; + 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)?; - 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.command(spi, Command::WriteRamRed)?; + 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 +363,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -377,11 +374,11 @@ where Some(RefreshLut::Quick) => &LUT_PARTIAL_UPDATE, }; - self.cmd_with_data(spi, Command::WriteLutRegister, buffer) + 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 +393,17 @@ 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 +414,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 +422,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, @@ -440,10 +437,10 @@ where spi, 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, @@ -452,36 +449,36 @@ where spi, Command::BorderWaveformControl, &[borderwaveform.to_u8()], - ) + ).await } - fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) + 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]) + 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]) + 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> { - self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F]) + 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, @@ -492,42 +489,42 @@ where spi, 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]) + 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> { - self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) + 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> { - self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) + 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, counter_direction: DataEntryModeDir, ) -> Result<(), SPI::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; - self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) + 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 +536,7 @@ where spi, Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + ).await?; self.cmd_with_data( spi, @@ -550,39 +547,39 @@ where end_y as u8, (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..c54bfe97 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,35 @@ 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 +150,44 @@ 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 +202,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -214,30 +215,30 @@ 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], - )?; + ).await?; - self.command(spi, Command::PowerOff)?; + 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 +257,28 @@ 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 +291,43 @@ 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 +336,8 @@ 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 +350,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.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, @@ -388,6 +389,6 @@ where spi, Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], - ) + ).await } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 941d0393..4eb41640 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,58 @@ 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], - )?; + ).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 +123,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -135,46 +136,46 @@ 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.cmd(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; + .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 +186,54 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; + .cmd(spi, Command::PartialDataStartTransmission1).await?; - 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_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)?; + self.send_buffer_helper(spi, buffer).await?; - self.interface.cmd(spi, Command::DataStop) + 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.cmd(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + .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.cmd(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DataStop)?; + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8).await?; + self.interface.cmd(spi, Command::DataStop).await?; Ok(()) } @@ -252,23 +253,23 @@ 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 +283,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, 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 +338,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 +374,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 +400,20 @@ 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 +421,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 +432,20 @@ 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..4416a6b9 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,7 @@ 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 +113,26 @@ 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 +154,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -169,42 +170,42 @@ 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 +215,50 @@ 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 +270,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -279,13 +280,13 @@ 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 +299,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, @@ -323,7 +324,7 @@ where 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( @@ -335,42 +336,42 @@ where 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], - )?; + ).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..5616a80f 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,21 @@ 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 +167,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -182,35 +183,35 @@ 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 +222,48 @@ 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)?; - 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?; + self.interface.cmd(spi, Command::WriteRam2).await?; + self.interface.data_x_times(spi, color, WIDTH / 8 * HEIGHT).await } fn set_background_color(&mut self, background_color: Color) { @@ -273,7 +274,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -285,8 +286,8 @@ 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 +300,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, @@ -324,7 +325,7 @@ where 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( @@ -336,42 +337,42 @@ where 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], - )?; + ).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 +387,73 @@ 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) + .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.wait_until_idle(spi, delay).await?; + self.interface.reset(delay, 10_000, 2_000).await; - self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; + self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9).await?; self.interface.cmd_with_data( spi, Command::WriteOtpSelection, &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], - )?; + ).await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80]).await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0])?; - self.interface.cmd(spi, Command::MasterActivation)?; + .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 +469,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 +485,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..8adc9739 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,35 @@ 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 +154,44 @@ 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 +206,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -218,30 +219,30 @@ 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], - )?; + ).await?; - self.command(spi, Command::PowerOff)?; + 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 +261,28 @@ 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 +295,43 @@ 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 +340,8 @@ 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 +354,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.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, @@ -392,6 +393,6 @@ where spi, Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], - ) + ).await } } diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c7f06855..b5649769 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,66 @@ 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], - )?; + ).await?; self.interface - .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80])?; + .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80]).await?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44]).await?; self.interface.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 +131,7 @@ where { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -147,19 +144,19 @@ 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::Sleep, &[0xF7]).await?; + self.interface.cmd(spi, Command::PowerOff).await?; self.interface - .cmd_with_data(spi, Command::Sleep2, &[0xA5])?; + .cmd_with_data(spi, Command::Sleep2, &[0xA5]).await?; Ok(()) } @@ -179,7 +176,7 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -187,18 +184,18 @@ 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 +208,39 @@ 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 +252,12 @@ 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..10554eb3 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,47 @@ 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], - )?; + ).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 +159,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -175,32 +176,32 @@ 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 +220,25 @@ 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.cmd(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .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 +248,77 @@ 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.cmd(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .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, @@ -328,7 +329,7 @@ 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, delay, &LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB).await } RefreshLut::Quick => self.set_lut_helper( spi, @@ -338,12 +339,12 @@ where &LUT_BW_QUICK, &LUT_WB_QUICK, &LUT_BB_QUICK, - ), + ).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(()) } } @@ -356,36 +357,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 +396,27 @@ 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 +424,20 @@ 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 +453,59 @@ 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 +515,28 @@ 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 +546,23 @@ 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 +571,25 @@ 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.cmd(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .data_x_times(spi, color_value, width / 8 * height).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .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..f71dc34a 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,25 @@ 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; - 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::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])?; + self.cmd_with_data(spi, Command::FlashMode, &[0xAA]).await?; - delay.delay_us(100_000); + delay.delay_us(100_000).await; - self.update_vcom(spi)?; + self.update_vcom(spi).await?; Ok(()) } } @@ -90,7 +87,7 @@ where DELAY: DelayUs, { type DisplayColor = OctColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -103,34 +100,34 @@ 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 +140,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::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 +189,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -201,8 +198,8 @@ 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 +212,41 @@ 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..a93fa017 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,37 @@ 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 +100,37 @@ 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 +145,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -161,21 +158,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 +191,21 @@ 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 +215,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 +230,61 @@ 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 +293,8 @@ 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 +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/epd7in5/mod.rs b/src/epd7in5/mod.rs index 5b89e1a1..b003d98a 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,48 @@ 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 +110,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,21 +123,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 +156,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 +172,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 +191,35 @@ 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 +228,8 @@ 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 +242,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..6f255758 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,44 @@ 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 +110,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,35 +123,35 @@ 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 +164,39 @@ 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 +216,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -228,8 +225,8 @@ 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 +239,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..e625dc1d 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,26 @@ 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 +92,7 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -108,35 +105,35 @@ 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 +146,34 @@ 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 +193,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -205,9 +202,9 @@ 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) + .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus).await } } @@ -219,32 +216,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..a5f73657 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,27 @@ 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 +96,44 @@ 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 +148,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -164,46 +161,46 @@ 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 +213,34 @@ 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 +260,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -272,9 +269,9 @@ 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) + .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus).await } } @@ -286,32 +283,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..893e56d8 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,28 @@ 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 +90,12 @@ 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 +110,7 @@ where DELAY: DelayUs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,45 +123,45 @@ 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 +174,34 @@ 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 +222,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -235,9 +232,9 @@ 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) + .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus).await } } @@ -251,7 +248,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 +258,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 +273,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 +281,44 @@ 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..b574528f 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,28 @@ 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 +80,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 +103,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 +135,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 +144,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 +195,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..6bf20a6b 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,7 @@ 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 +295,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 +303,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 +311,10 @@ 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 +323,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 +336,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 +349,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,