diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0c06d2f5..fcfe6a40 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -27,6 +27,8 @@ jobs: run: cargo build --examples --all-targets --verbose - name: Run tests run: cargo test --verbose + - name: Run tests (async) + run: cargo test --verbose --lib --tests --benches --features async - name: Build docs run: cargo doc - name: Clippy diff --git a/Cargo.toml b/Cargo.toml index 73c33370..172c7cb3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,9 @@ rust-version = "1.62" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } embedded-hal = "1.0.0" +embedded-hal-async = { version = "1.0.0", optional = true } bit_field = "0.10.1" +maybe-async = { git = "https://github.com/XLPhere/maybe-async-rs.git", branch = "default_sync", features = ["default_sync"] } [dev-dependencies] embedded-graphics = "0.8" @@ -47,11 +49,16 @@ required-features = ["linux-dev"] name = "epd4in2" required-features = ["linux-dev"] +[[example]] +name = "epd7in5_v2" +required-features = ["linux-dev"] + [features] # Remove the linux-dev feature to build the tests on non unix systems default = ["graphics", "linux-dev", "epd2in13_v3"] graphics = ["embedded-graphics-core"] +async = ["embedded-hal-async", "maybe-async/is_async"] epd2in13_v2 = [] epd2in13_v3 = [] linux-dev = [] diff --git a/src/epd12in48b_v2/mod.rs b/src/epd12in48b_v2/mod.rs index c802286e..8df93202 100644 --- a/src/epd12in48b_v2/mod.rs +++ b/src/epd12in48b_v2/mod.rs @@ -11,12 +11,9 @@ mod command; mod config; -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin, PinState}, - spi::SpiBus, -}; +use embedded_hal::digital::{InputPin, OutputPin, PinState}; +use crate::interface::{DelayNs, SpiBus}; pub use crate::rect::Rect; use command::Command; pub use config::*; @@ -133,6 +130,7 @@ where control_state: CS, } +#[maybe_async::maybe_async] impl EpdDriver where INPUT: InputPin, @@ -161,7 +159,7 @@ where /// Reset the display, potentially waking it up from deep sleep. /// Normally should be followed by a call to [`init()`](EpdDriver::init). - pub fn reset(&mut self) -> Result<(), OUTPUT::Error> { + pub async fn reset(&mut self) -> Result<(), OUTPUT::Error> { drop(self.peris.m1_cs.set_high()); drop(self.peris.s1_cs.set_high()); drop(self.peris.m2_cs.set_high()); @@ -172,25 +170,26 @@ where self.peris.m1s1_rst.set_high()?; self.peris.m2s2_rst.set_high()?; - self.delay.delay_ms(1); + self.delay.delay_ms(1).await; self.peris.m1s1_rst.set_low()?; - self.delay.delay_us(100); // min RST low = 50us + self.delay.delay_us(100).await; // min RST low = 50us self.peris.m1s1_rst.set_high()?; - self.delay.delay_ms(100); // min wait after RST = 10ms + self.delay.delay_ms(100).await; // min wait after RST = 10ms self.peris.m2s2_rst.set_low()?; - self.delay.delay_us(100); + self.delay.delay_us(100).await; self.peris.m2s2_rst.set_high()?; - self.delay.delay_ms(100); + self.delay.delay_ms(100).await; Ok(()) } /// Initialize display registers. - pub fn init(&mut self, config: &Config) -> Result<(), SPI::Error> { + pub async fn init(&mut self, config: &Config) -> Result<(), SPI::Error> { // booster soft start - self.cmd_with_data(CS_ALL, Command::BoosterSoftStart, &[0x17, 0x17, 0x39, 0x17])?; + self.cmd_with_data(CS_ALL, Command::BoosterSoftStart, &[0x17, 0x17, 0x39, 0x17]) + .await?; // resolution setting fn resolution_data(rect: Rect) -> [u8; 4] { @@ -201,24 +200,33 @@ where (rect.h % 256) as u8, ] } - self.cmd_with_data(CS_M1, Command::TconResolution, &resolution_data(M1_RECT))?; - self.cmd_with_data(CS_S1, Command::TconResolution, &resolution_data(S1_RECT))?; - self.cmd_with_data(CS_M2, Command::TconResolution, &resolution_data(M2_RECT))?; - self.cmd_with_data(CS_S2, Command::TconResolution, &resolution_data(S2_RECT))?; - - self.cmd_with_data(CS_ALL, Command::DualSPI, &[0x20])?; - self.cmd_with_data(CS_ALL, Command::TconSetting, &[0x22])?; - self.cmd_with_data(CS_ALL, Command::PowerSaving, &[0x00])?; - self.cmd_with_data(CS_ALL, Command::CascadeSetting, &[0x03])?; - self.cmd_with_data(CS_ALL, Command::ForceTemperature, &[25])?; - - self.set_mode(config)?; - - self.flush() + self.cmd_with_data(CS_M1, Command::TconResolution, &resolution_data(M1_RECT)) + .await?; + self.cmd_with_data(CS_S1, Command::TconResolution, &resolution_data(S1_RECT)) + .await?; + self.cmd_with_data(CS_M2, Command::TconResolution, &resolution_data(M2_RECT)) + .await?; + self.cmd_with_data(CS_S2, Command::TconResolution, &resolution_data(S2_RECT)) + .await?; + + self.cmd_with_data(CS_ALL, Command::DualSPI, &[0x20]) + .await?; + self.cmd_with_data(CS_ALL, Command::TconSetting, &[0x22]) + .await?; + self.cmd_with_data(CS_ALL, Command::PowerSaving, &[0x00]) + .await?; + self.cmd_with_data(CS_ALL, Command::CascadeSetting, &[0x03]) + .await?; + self.cmd_with_data(CS_ALL, Command::ForceTemperature, &[25]) + .await?; + + self.set_mode(config).await?; + + self.flush().await } /// Set data "polarity", waveform lookup table mode, etc, without re-initializing anything else. - pub fn set_mode(&mut self, config: &Config) -> Result<(), SPI::Error> { + pub async fn set_mode(&mut self, config: &Config) -> Result<(), SPI::Error> { let ddx = match (config.inverted_r, config.inverted_kw) { (false, true) => 0b00, (false, false) => 0b01, @@ -238,19 +246,24 @@ where }; let reg = (config.external_lut as u8) << 5; - self.cmd_with_data(CS_M1, Command::PanelSetting, &[reg | 0x0F])?; - self.cmd_with_data(CS_S1, Command::PanelSetting, &[reg | 0x0F])?; - self.cmd_with_data(CS_M2, Command::PanelSetting, &[reg | 0x03])?; - self.cmd_with_data(CS_S2, Command::PanelSetting, &[reg | 0x03])?; + self.cmd_with_data(CS_M1, Command::PanelSetting, &[reg | 0x0F]) + .await?; + self.cmd_with_data(CS_S1, Command::PanelSetting, &[reg | 0x0F]) + .await?; + self.cmd_with_data(CS_M2, Command::PanelSetting, &[reg | 0x03]) + .await?; + self.cmd_with_data(CS_S2, Command::PanelSetting, &[reg | 0x03]) + .await?; let bdv = bdv << 4; self.cmd_with_data( CS_ALL, Command::VcomAndDataIntervalSetting, &[bdv | ddx, 0x07], - )?; + ) + .await?; - self.flush() + self.flush().await } /// Fill data1 buffer with pixels: @@ -259,30 +272,42 @@ where /// /// `pixels` may contain a lesser number of rows than the window being written, /// in which case it will be treated as circular. - pub fn write_data1(&mut self, pixels: &[u8]) -> Result<(), SPI::Error> { - self.write_window_data(Command::DataStartTransmission1, FULL_RECT, pixels)?; - self.flush() + pub async fn write_data1(&mut self, pixels: &[u8]) -> Result<(), SPI::Error> { + self.write_window_data(Command::DataStartTransmission1, FULL_RECT, pixels) + .await?; + self.flush().await } /// Fill data2 buffer with pixels. /// See also [`write_data1`](EpdDriver::write_data1). - pub fn write_data2(&mut self, pixels: &[u8]) -> Result<(), SPI::Error> { - self.write_window_data(Command::DataStartTransmission2, FULL_RECT, pixels)?; - self.flush() + pub async fn write_data2(&mut self, pixels: &[u8]) -> Result<(), SPI::Error> { + self.write_window_data(Command::DataStartTransmission2, FULL_RECT, pixels) + .await?; + self.flush().await } /// Fill a window in the data1 buffer with pixels. /// See also [`write_data1`](EpdDriver::write_data1). - pub fn write_data1_partial(&mut self, window: Rect, pixels: &[u8]) -> Result<(), SPI::Error> { - self.write_partial(Command::DataStartTransmission1, window, pixels)?; - self.flush() + pub async fn write_data1_partial( + &mut self, + window: Rect, + pixels: &[u8], + ) -> Result<(), SPI::Error> { + self.write_partial(Command::DataStartTransmission1, window, pixels) + .await?; + self.flush().await } /// Fill a window in the data2 buffer with pixels. /// See also [`write_data1`](EpdDriver::write_data1). - pub fn write_data2_partial(&mut self, window: Rect, pixels: &[u8]) -> Result<(), SPI::Error> { - self.write_partial(Command::DataStartTransmission2, window, pixels)?; - self.flush() + pub async fn write_data2_partial( + &mut self, + window: Rect, + pixels: &[u8], + ) -> Result<(), SPI::Error> { + self.write_partial(Command::DataStartTransmission2, window, pixels) + .await?; + self.flush().await } /// Store VCOM Look-Up Table. @@ -290,116 +315,123 @@ where /// If LUT data is shorter than expected, the rest is filled with zeroes.
/// Note that stored lookup tables need to be activated by setting /// [`Config::external_lut`](config::Config::external_lut)`=true`. - pub fn set_lutc(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutC, data, 60) + pub async fn set_lutc(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutC, data, 60).await } /// Store White-to-White Look-Up Table. /// See also [`write_data1`](EpdDriver::set_lutc). - pub fn set_lutww(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutWW, data, 42) + pub async fn set_lutww(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutWW, data, 42).await } /// Store Black-to-White (KW mode) / Red (KWR mode) Look-Up Table. /// See also [`write_data1`](EpdDriver::set_lutc). - pub fn set_lutkw_lutr(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutKW_LutR, data, 60) + pub async fn set_lutkw_lutr(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutKW_LutR, data, 60).await } /// Store White-to-Black (KW mode) / White (KWR mode) Look-Up Table. /// See also [`write_data1`](EpdDriver::set_lutc). - pub fn set_lutwk_lutw(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutWK_LutW, data, 60) + pub async fn set_lutwk_lutw(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutWK_LutW, data, 60).await } /// Store Black-to-Black (KW mode) / Black (KWR mode) Look-Up Table. /// See also [`write_data1`](EpdDriver::set_lutc). - pub fn set_lutkk_lutk(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutKK_LutK, data, 60) + pub async fn set_lutkk_lutk(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutKK_LutK, data, 60).await } /// Store Border Look-Up Table. /// See also [`write_data1`](EpdDriver::set_lutc). - pub fn set_lutbd(&mut self, data: &[u8]) -> Result<(), SPI::Error> { - self.set_lut(Command::LutBD, data, 42) + pub async fn set_lutbd(&mut self, data: &[u8]) -> Result<(), SPI::Error> { + self.set_lut(Command::LutBD, data, 42).await } - fn set_lut(&mut self, cmd: Command, data: &[u8], reqd_len: usize) -> Result<(), SPI::Error> { - self.cmd_with_data(CS_ALL, cmd, data)?; + async fn set_lut( + &mut self, + cmd: Command, + data: &[u8], + reqd_len: usize, + ) -> Result<(), SPI::Error> { + self.cmd_with_data(CS_ALL, cmd, data).await?; if data.len() < reqd_len { let zeroes = [0; 60]; - self.spi_write(CS_ALL | CS_DATA, &zeroes[..reqd_len - data.len()])?; + self.spi_write(CS_ALL | CS_DATA, &zeroes[..reqd_len - data.len()]) + .await?; } - self.flush() + self.flush().await } /// Refresh the entire display. - pub fn refresh_display(&mut self) -> Result<(), SPI::Error> { - self.begin_refresh_display()?; - drop(self.wait_ready(CS_ALL)); + pub async fn refresh_display(&mut self) -> Result<(), SPI::Error> { + self.begin_refresh_display().await?; + drop(self.wait_ready(CS_ALL).await); Ok(()) } /// Asynchronous version of [`refresh_display`](EpdDriver::refresh_display). /// Use [`is_busy`](EpdDriver::is_busy) to poll for completion. - pub fn begin_refresh_display(&mut self) -> Result<(), SPI::Error> { - self.cmd(CS_ALL, Command::PowerOn)?; - drop(self.wait_ready(CS_ALL)); + pub async fn begin_refresh_display(&mut self) -> Result<(), SPI::Error> { + self.cmd(CS_ALL, Command::PowerOn).await?; + drop(self.wait_ready(CS_ALL).await); // Appears to be required to reliably trigger display refresh after a power-on. - self.delay.delay_ms(100); + self.delay.delay_ms(100).await; - self.cmd(CS_ALL, Command::DisplayRefresh)?; + self.cmd(CS_ALL, Command::DisplayRefresh).await?; - self.flush() + self.flush().await } /// Refresh the specified sub-window of the display. /// /// Technically, this works, however, after 2+ partial updates, the rest of the displayed image becomes visibly degraded. - pub fn refresh_display_partial(&mut self, window: Rect) -> Result<(), SPI::Error> { - self.begin_refresh_display_partial(window)?; + pub async fn refresh_display_partial(&mut self, window: Rect) -> Result<(), SPI::Error> { + self.begin_refresh_display_partial(window).await?; - drop(self.wait_ready(CS_ALL)); + drop(self.wait_ready(CS_ALL).await); Ok(()) } /// Asynchronous version of [`refresh_display_partial`](EpdDriver::refresh_display_partial). /// Use [`is_busy`](EpdDriver::is_busy) to poll for completion. - pub fn begin_refresh_display_partial(&mut self, window: Rect) -> Result<(), SPI::Error> { - self.setup_partial_windows(window)?; + pub async fn begin_refresh_display_partial(&mut self, window: Rect) -> Result<(), SPI::Error> { + self.setup_partial_windows(window).await?; - self.cmd(CS_ALL, Command::PowerOn)?; - drop(self.wait_ready(CS_ALL)); - self.delay.delay_ms(100); + self.cmd(CS_ALL, Command::PowerOn).await?; + drop(self.wait_ready(CS_ALL).await); + self.delay.delay_ms(100).await; - self.cmd(CS_ALL, Command::PartialIn)?; - self.cmd(CS_ALL, Command::DisplayRefresh)?; - self.cmd(CS_ALL, Command::PartialOut)?; + self.cmd(CS_ALL, Command::PartialIn).await?; + self.cmd(CS_ALL, Command::DisplayRefresh).await?; + self.cmd(CS_ALL, Command::PartialOut).await?; - self.flush() + self.flush().await } /// Turn off booster, controller, source driver, gate driver, VCOM, and temperature sensor. /// However, the contents of the data memory buffers will be retained. - pub fn power_off(&mut self) -> Result<(), SPI::Error> { - self.cmd(CS_ALL, Command::PowerOff)?; - drop(self.wait_ready(CS_ALL)); + pub async fn power_off(&mut self) -> Result<(), SPI::Error> { + self.cmd(CS_ALL, Command::PowerOff).await?; + drop(self.wait_ready(CS_ALL).await); - self.flush() + self.flush().await } /// Put display into deep sleep. Only [`reset()`](EpdDriver::reset) can bring it out of this state. /// The contents of the data memory buffers will be lost. - pub fn hibernate(&mut self) -> Result<(), SPI::Error> { - self.cmd(CS_ALL, Command::PowerOff)?; - drop(self.wait_ready(CS_ALL)); + pub async fn hibernate(&mut self) -> Result<(), SPI::Error> { + self.cmd(CS_ALL, Command::PowerOff).await?; + drop(self.wait_ready(CS_ALL).await); - self.cmd_with_data(CS_ALL, Command::DeepSleep, &[0xA5])?; + self.cmd_with_data(CS_ALL, Command::DeepSleep, &[0xA5]) + .await?; - self.flush() + self.flush().await } - fn setup_partial_windows(&mut self, window: Rect) -> Result<(), SPI::Error> { + async fn setup_partial_windows(&mut self, window: Rect) -> Result<(), SPI::Error> { let s2_part = window.intersect(S2_RECT).sub_offset(S2_RECT.x, S2_RECT.y); let m2_part = window.intersect(M2_RECT).sub_offset(M2_RECT.x, M2_RECT.y); let m1_part = window.intersect(M1_RECT).sub_offset(M1_RECT.x, M1_RECT.y); @@ -434,27 +466,31 @@ where CS_S2, Command::PartialWindow, &partial_window_data(s2_part, Some(S2_RECT.w)), - )?; + ) + .await?; self.cmd_with_data( CS_M2, Command::PartialWindow, &partial_window_data(m2_part, Some(M2_RECT.w)), - )?; + ) + .await?; self.cmd_with_data( CS_M1, Command::PartialWindow, &partial_window_data(m1_part, None), - )?; + ) + .await?; self.cmd_with_data( CS_S1, Command::PartialWindow, &partial_window_data(s1_part, None), - )?; + ) + .await?; Ok(()) } - fn write_partial( + async fn write_partial( &mut self, transmission_cmd: Command, window: Rect, @@ -464,16 +500,17 @@ where panic!("Window is not 8-aligned horizontally"); } - self.cmd(CS_ALL, Command::PartialIn)?; + self.cmd(CS_ALL, Command::PartialIn).await?; - self.setup_partial_windows(window)?; - self.write_window_data(transmission_cmd, window, pixels)?; + self.setup_partial_windows(window).await?; + self.write_window_data(transmission_cmd, window, pixels) + .await?; - self.cmd(CS_ALL, Command::PartialOut) + self.cmd(CS_ALL, Command::PartialOut).await } // Send data to each sub-display for the window area that overlaps with it. - fn write_window_data( + async fn write_window_data( &mut self, transmission_cmd: Command, window: Rect, @@ -501,40 +538,40 @@ where if top_rows > 0 { if left_bytes > 0 { - self.cmd(CS_S2, transmission_cmd)?; + self.cmd(CS_S2, transmission_cmd).await?; for y in 0..top_rows { let begin = row_offset(y); let end = begin + left_bytes; - self.spi_write(CS_S2 | CS_DATA, &pixels[begin..end])?; + self.spi_write(CS_S2 | CS_DATA, &pixels[begin..end]).await?; } } if right_bytes > 0 { - self.cmd(CS_M2, transmission_cmd)?; + self.cmd(CS_M2, transmission_cmd).await?; for y in 0..top_rows { let begin = row_offset(y) + left_bytes; let end = begin + right_bytes; - self.spi_write(CS_M2 | CS_DATA, &pixels[begin..end])?; + self.spi_write(CS_M2 | CS_DATA, &pixels[begin..end]).await?; } } } if bottom_rows > 0 { if left_bytes > 0 { - self.cmd(CS_M1, transmission_cmd)?; + self.cmd(CS_M1, transmission_cmd).await?; for y in 0..bottom_rows { let begin = row_offset(top_rows + y); let end = begin + left_bytes; - self.spi_write(CS_M1 | CS_DATA, &pixels[begin..end])?; + self.spi_write(CS_M1 | CS_DATA, &pixels[begin..end]).await?; } } if right_bytes > 0 { - self.cmd(CS_S1, transmission_cmd)?; + self.cmd(CS_S1, transmission_cmd).await?; for y in 0..bottom_rows { let begin = row_offset(top_rows + y) + left_bytes; let end = begin + right_bytes; - self.spi_write(CS_S1 | CS_DATA, &pixels[begin..end])?; + self.spi_write(CS_S1 | CS_DATA, &pixels[begin..end]).await?; } } } @@ -542,22 +579,22 @@ where Ok(()) } - fn cmd(&mut self, chips: CS, command: Command) -> Result<(), SPI::Error> { - self.spi_write(chips, &[command as u8]) + async fn cmd(&mut self, chips: CS, command: Command) -> Result<(), SPI::Error> { + self.spi_write(chips, &[command as u8]).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, chips: CS, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.spi_write(chips, &[command as u8])?; - self.spi_write(chips | CS_DATA, data) + self.spi_write(chips, &[command as u8]).await?; + self.spi_write(chips | CS_DATA, data).await } // Set control pins to the specified state, then send data via SPI. - fn spi_write(&mut self, control: CS, data: &[u8]) -> Result<(), SPI::Error> { + async fn spi_write(&mut self, control: CS, data: &[u8]) -> Result<(), SPI::Error> { if self.control_state != control { fn pin_state(high: bool) -> PinState { if high { @@ -567,8 +604,8 @@ where } } - self.peris.spi.flush()?; - self.delay.delay_ns(100); // Tscc = 20ns, Tchw = 40ns + self.peris.spi.flush().await?; + self.delay.delay_ns(100).await; // Tscc = 20ns, Tchw = 40ns // CS is active low drop(self.peris.m1_cs.set_state(pin_state(control & CS_M1 == 0))); @@ -581,16 +618,16 @@ where drop(self.peris.m1s1_dc.set_state(dc)); drop(self.peris.m2s2_dc.set_state(dc)); - self.delay.delay_ns(100); // Tcss = 60ns, Tsds = 30ns + self.delay.delay_ns(100).await; // Tcss = 60ns, Tsds = 30ns self.control_state = control; } - self.peris.spi.write(data) + self.peris.spi.write(data).await } // Flush SPI, reset control pins to the default state. - fn flush(&mut self) -> Result<(), SPI::Error> { - self.peris.spi.flush()?; + async fn flush(&mut self) -> Result<(), SPI::Error> { + self.peris.spi.flush().await?; drop(self.peris.m1_cs.set_high()); drop(self.peris.s1_cs.set_high()); drop(self.peris.m2_cs.set_high()); @@ -601,9 +638,9 @@ where Ok(()) } - fn wait_ready(&mut self, chips: CS) -> Result<(), INPUT::Error> { + async fn wait_ready(&mut self, chips: CS) -> Result<(), INPUT::Error> { while self.busy_chips(chips)? != 0 { - self.delay.delay_ms(200); + self.delay.delay_ms(200).await; } Ok(()) } @@ -637,7 +674,7 @@ where /// Query and return the status byte of each sub-display. /// Order: \[M1, S1, M2, S2\]. - pub fn get_status(&mut self) -> Result<[u8; 4], SPI::Error> { + pub async fn get_status(&mut self) -> Result<[u8; 4], SPI::Error> { self.control_state = 0xFF; let mut status = [0u8; 4]; for i in 0..4 { @@ -650,20 +687,20 @@ where // Request status drop(cs.set_low()); drop(dc.set_low()); - self.delay.delay_ns(100); // Tcss = 60ns - self.peris.spi.write(&[Command::GetStatus as u8])?; - self.peris.spi.flush()?; - self.delay.delay_ns(100); // Tsds = 30ns + self.delay.delay_ns(100).await; // Tcss = 60ns + self.peris.spi.write(&[Command::GetStatus as u8]).await?; + self.peris.spi.flush().await?; + self.delay.delay_ns(100).await; // Tsds = 30ns // Read status drop(dc.set_high()); - self.delay.delay_ns(100); // Tsdh = 30ns - self.peris.spi.read(&mut status[i..i + 1])?; - self.delay.delay_ns(100); // Tscc = 20ns + self.delay.delay_ns(100).await; // Tsdh = 30ns + self.peris.spi.read(&mut status[i..i + 1]).await?; + self.delay.delay_ns(100).await; // Tscc = 20ns drop(dc.set_low()); drop(cs.set_high()); - self.delay.delay_ns(100); // Tchw = 40ns + self.delay.delay_ns(100).await; // Tchw = 40ns } self.control_state = 0; Ok(status) diff --git a/src/epd1in02/mod.rs b/src/epd1in02/mod.rs index 6eafea13..b4585790 100644 --- a/src/epd1in02/mod.rs +++ b/src/epd1in02/mod.rs @@ -4,14 +4,10 @@ //! //! The display controller IC is UC8175 -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::prelude::WaveshareDisplay; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut}; @@ -58,6 +54,7 @@ pub struct Epd1in02 { refresh_mode: RefreshLut, } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd1in02 where @@ -69,7 +66,7 @@ where { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -87,15 +84,15 @@ where refresh_mode: 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)?; - self.turn_off(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.turn_off(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; // display registers are set to default value self.refresh_mode = RefreshLut::Full; @@ -103,8 +100,8 @@ where 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) { @@ -123,29 +120,31 @@ 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?; - self.set_full_mode(spi, delay)?; + self.set_full_mode(spi, delay).await?; let color_value = self.background_color().get_byte_value(); - self.command(spi, Command::DataStartTransmission1)?; + self.command(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, color_value, NUMBER_OF_BYTES)?; + .data_x_times(spi, color_value, NUMBER_OF_BYTES) + .await?; - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } // Implemented as quick partial update // as it requires old frame update - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -158,44 +157,46 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.turn_on_if_turned_off(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.turn_on_if_turned_off(spi, delay).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?; 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.set_full_mode(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.set_full_mode(spi, delay).await?; let color_value = self.background_color().get_byte_value(); - self.command(spi, Command::DataStartTransmission1)?; + self.command(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, !color_value, NUMBER_OF_BYTES)?; + .data_x_times(spi, !color_value, NUMBER_OF_BYTES) + .await?; - self.command(spi, Command::DataStartTransmission2)?; + self.command(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color_value, NUMBER_OF_BYTES)?; + .data_x_times(spi, color_value, NUMBER_OF_BYTES) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -207,17 +208,24 @@ where None => return Ok(()), }; - self.cmd_with_data(spi, Command::SetWhiteLut, white_lut)?; - self.cmd_with_data(spi, Command::SetBlackLut, black_lut)?; + self.cmd_with_data(spi, Command::SetWhiteLut, white_lut) + .await?; + self.cmd_with_data(spi, Command::SetBlackLut, black_lut) + .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(()) } } +#[maybe_async::maybe_async(AFIT)] impl QuickRefresh for Epd1in02 where @@ -228,35 +236,42 @@ where DELAY: DelayNs, { /// 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.set_partial_mode(spi, delay)?; - self.set_partial_window(spi, delay, 0, 0, WIDTH, HEIGHT)?; + self.set_partial_mode(spi, delay).await?; + self.set_partial_window(spi, delay, 0, 0, WIDTH, HEIGHT) + .await?; - self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission1, 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.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - 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> { unimplemented!() } - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, _spi: &mut SPI, _buffer: &[u8], @@ -267,7 +282,7 @@ where /// To be followed immediately by update_partial_new_frame /// isn't faster then full update - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -281,15 +296,17 @@ where panic!("Image buffer size is not correct") } - self.set_partial_mode(spi, delay)?; - self.set_partial_window(spi, delay, x, y, width, height)?; + self.set_partial_mode(spi, delay).await?; + self.set_partial_window(spi, delay, x, y, width, height) + .await?; - self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer) + .await?; Ok(()) } /// To be used immediately after update_partial_old_frame - fn update_partial_new_frame( + async fn update_partial_new_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -303,12 +320,13 @@ where panic!("Image buffer size is not correct") } - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } /// Isn't faster then full clear - fn clear_partial_frame( + async fn clear_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -317,29 +335,33 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // set full LUT as quick LUT requires old image - self.set_full_mode(spi, delay)?; - self.command(spi, Command::PartialIn)?; - self.set_partial_window(spi, delay, x, y, width, height)?; + self.set_full_mode(spi, delay).await?; + self.command(spi, Command::PartialIn).await?; + self.set_partial_window(spi, delay, x, y, width, height) + .await?; let color_value = self.background_color().get_byte_value(); let number_of_bytes = buffer_len(width as usize, height as usize) as u32; - self.command(spi, Command::DataStartTransmission1)?; + self.command(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, !color_value, number_of_bytes)?; + .data_x_times(spi, !color_value, number_of_bytes) + .await?; - self.command(spi, Command::DataStartTransmission2)?; + self.command(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color_value, number_of_bytes)?; + .data_x_times(spi, color_value, number_of_bytes) + .await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd1in02 where @@ -349,24 +371,29 @@ where RST: OutputPin, DELAY: DelayNs, { - 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, 20_000, 2000); + self.interface.reset(delay, 20_000, 2000).await; // Set the panel settings: LUT from register - self.cmd_with_data(spi, Command::PanelSetting, &[0x6F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x6F]) + .await?; // Set the power settings: VGH=16V, VGL=-16V, VDH=11V, VDL=-11V - self.cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b]) + .await?; // Set the charge pump settings: 50ms, Strength 4, 8kHz - self.cmd_with_data(spi, Command::ChargePumpSetting, &[0x3F])?; + self.cmd_with_data(spi, Command::ChargePumpSetting, &[0x3F]) + .await?; // Set LUT option: no All-Gate-ON - self.cmd_with_data(spi, Command::LutOption, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::LutOption, &[0x00, 0x00]) + .await?; // Set the clock frequency: 50 Hz - self.cmd_with_data(spi, Command::PllControl, &[0x17])?; + self.cmd_with_data(spi, Command::PllControl, &[0x17]) + .await?; // Set Vcom and data interval: default // set the border color the same as background color @@ -374,27 +401,32 @@ where Color::Black => 0x57, Color::White => 0x97, }; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[value])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[value]) + .await?; // Set the non-overlapping period of Gate and Source: 24us - 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 value: -1 V - self.cmd_with_data(spi, Command::VcomDcSetting, &[0x12])?; + self.cmd_with_data(spi, Command::VcomDcSetting, &[0x12]) + .await?; // Set pover saving settings - self.cmd_with_data(spi, Command::PowerSaving, &[0x33])?; + self.cmd_with_data(spi, Command::PowerSaving, &[0x33]) + .await?; - self.set_lut(spi, delay, Some(self.refresh_mode))?; + self.set_lut(spi, delay, Some(self.refresh_mode)).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async] impl Epd1in02 where SPI: SpiDevice, @@ -403,72 +435,76 @@ where RST: OutputPin, DELAY: DelayNs, { - 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, &[h as u8])?; - self.send_data(spi, &[w as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[h as u8]).await?; + self.send_data(spi, &[w as u8]).await } /// PowerOn command - fn turn_on_if_turned_off( + async fn turn_on_if_turned_off( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { if !self.is_turned_on { - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; self.is_turned_on = true; } Ok(()) } - fn turn_off(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; + async fn turn_off(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; self.is_turned_on = false; Ok(()) } - fn set_full_mode(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn set_full_mode(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { if self.refresh_mode != RefreshLut::Full { - self.command(spi, Command::PartialOut)?; - self.set_lut(spi, delay, Some(RefreshLut::Full))?; + self.command(spi, Command::PartialOut).await?; + self.set_lut(spi, delay, Some(RefreshLut::Full)).await?; self.refresh_mode = RefreshLut::Full; } Ok(()) } - fn set_partial_mode(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn set_partial_mode( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { if self.refresh_mode != RefreshLut::Quick { - self.command(spi, Command::PartialIn)?; - self.set_lut(spi, delay, Some(RefreshLut::Quick))?; + self.command(spi, Command::PartialIn).await?; + self.set_lut(spi, delay, Some(RefreshLut::Quick)).await?; self.refresh_mode = RefreshLut::Quick; } Ok(()) } - fn set_partial_window( + async fn set_partial_window( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -491,7 +527,8 @@ where (y + height - 1) as u8, 0x00, ], - )?; + ) + .await?; Ok(()) } diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index b598693e..8dd7e324 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -54,7 +54,7 @@ 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::*; use crate::type_a::{ command::Command, @@ -66,7 +66,7 @@ use crate::color::Color; use crate::traits::{RefreshLut, WaveshareDisplay}; use crate::buffer_len; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; /// Full size buffer for use with the 1in54b EPD #[cfg(feature = "graphics")] @@ -88,6 +88,7 @@ pub struct Epd1in54 { refresh: RefreshLut, } +#[maybe_async::maybe_async] impl Epd1in54 where SPI: SpiDevice, @@ -96,19 +97,21 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; // 3 Databytes: // A[7:0] // 0.. A[8] // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) - self.interface.cmd_with_data( - spi, - Command::DriverOutputControl, - &[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00], - )?; + self.interface + .cmd_with_data( + spi, + Command::DriverOutputControl, + &[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00], + ) + .await?; // 3 Databytes: (and default values from datasheet and arduino) // 1 .. A[6:0] = 0xCF | 0xD7 @@ -116,32 +119,38 @@ 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd1in54 where @@ -160,7 +169,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -176,39 +185,41 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here or would 0x01 be even more efficient? self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -218,50 +229,54 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, delay, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, delay, x, y, x + width, y + height) + .await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4]) + .await?; - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -273,7 +288,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -283,17 +298,22 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd1in54 where SPI: SpiDevice, @@ -302,19 +322,20 @@ where RST: OutputPin, DELAY: DelayNs, { - pub(crate) fn use_full_frame( + pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - pub(crate) fn set_ram_area( + pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -323,65 +344,73 @@ where end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(start_x < end_x); assert!(start_y < end_y); // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await?; Ok(()) } - pub(crate) fn set_ram_counter( + pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 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 80bf5849..0fcc3f09 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -11,7 +11,7 @@ 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::*; use crate::type_a::command::Command; @@ -22,7 +22,7 @@ use crate::color::Color; use crate::traits::{RefreshLut, WaveshareDisplay}; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; #[cfg(feature = "graphics")] pub use crate::epd1in54::Display1in54; @@ -38,6 +38,7 @@ pub struct Epd1in54 { refresh: RefreshLut, } +#[maybe_async::maybe_async] impl Epd1in54 where SPI: SpiDevice, @@ -46,47 +47,55 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); - self.wait_until_idle(spi, delay)?; - self.interface.cmd(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; + self.wait_until_idle(spi, delay).await?; + self.interface.cmd(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; // 3 Databytes: // A[7:0] // 0.. A[8] // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) - self.interface.cmd_with_data( - spi, - Command::DriverOutputControl, - &[(HEIGHT - 1) as u8, 0x0, 0x00], - )?; + self.interface + .cmd_with_data( + spi, + Command::DriverOutputControl, + &[(HEIGHT - 1) as u8, 0x0, 0x00], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x3])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x3]) + .await?; - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; - self.interface.cmd_with_data( - spi, - Command::TemperatureSensorSelection, - &[0x80], // 0x80: internal temperature sensor - )?; + self.interface + .cmd_with_data( + spi, + Command::TemperatureSensorSelection, + &[0x80], // 0x80: internal temperature sensor + ) + .await?; self.interface - .cmd_with_data(spi, Command::TemperatureSensorControl, &[0xB1, 0x20])?; + .cmd_with_data(spi, Command::TemperatureSensorControl, &[0xB1, 0x20]) + .await?; - self.set_ram_counter(spi, delay, 0, 0)?; + self.set_ram_counter(spi, delay, 0, 0).await?; //Initialize the lookup table with a refresh waveform - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd1in54 where @@ -105,7 +114,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -121,37 +130,39 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -161,56 +172,62 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, delay, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, delay, x, y, x + width, y + height) + .await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; if self.refresh == RefreshLut::Full { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7]) + .await?; } else if self.refresh == RefreshLut::Quick { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xCF])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xCF]) + .await?; } - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - self.interface.cmd(spi, Command::WriteRam2)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; + self.interface.cmd(spi, Command::WriteRam2).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -222,7 +239,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -234,33 +251,43 @@ where 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), - }?; + } + .await?; // Additional configuration required only for partial updates if self.refresh == RefreshLut::Quick { - self.interface.cmd_with_data( - spi, - Command::WriteOtpSelection, - &[0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0], - )?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data( + spi, + Command::WriteOtpSelection, + &[0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x0], + ) + .await?; + self.interface + .cmd_with_data(spi, Command::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(()) } } +#[maybe_async::maybe_async] impl Epd1in54 where SPI: SpiDevice, @@ -269,19 +296,20 @@ where RST: OutputPin, DELAY: DelayNs, { - pub(crate) fn use_full_frame( + pub(crate) async fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - pub(crate) fn set_ram_area( + pub(crate) async fn set_ram_area( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -290,81 +318,94 @@ where end_x: u32, end_y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(start_x < end_x); assert!(start_y < end_y); // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await?; Ok(()) } - pub(crate) fn set_ram_counter( + pub(crate) async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 159); self.interface - .cmd_with_data(spi, Command::WriteLutRegister, &buffer[0..153])?; + .cmd_with_data(spi, Command::WriteLutRegister, &buffer[0..153]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteLutRegisterEnd, &[buffer[153]])?; + .cmd_with_data(spi, Command::WriteLutRegisterEnd, &[buffer[153]]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::GateDrivingVoltage, &[buffer[154]])?; + .cmd_with_data(spi, Command::GateDrivingVoltage, &[buffer[154]]) + .await?; - self.interface.cmd_with_data( - spi, - Command::SourceDrivingVoltage, - &[buffer[155], buffer[156], buffer[157]], - )?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]])?; + .cmd_with_data( + spi, + Command::SourceDrivingVoltage, + &[buffer[155], buffer[156], buffer[157]], + ) + .await?; + self.interface + .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]]) + .await?; Ok(()) } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 08aae37c..f476060e 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,8 +1,8 @@ //! 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::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -43,6 +43,7 @@ pub struct Epd1in54b { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd1in54b where @@ -52,43 +53,50 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd1in54b where @@ -98,47 +106,52 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd1in54b where @@ -149,7 +162,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -162,33 +175,36 @@ where let mut epd = Epd1in54b { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) + .await?; //border floating self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // Vcom to 0V + .cmd_with_data(spi, Command::VcmDcSetting, &[0x00]) + .await?; // Vcom to 0V self.interface - .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast + .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00]) + .await?; //VG&VS to 0V fast - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; //NOTE: The example code has a 1s delay here - self.command(spi, Command::PowerOff)?; + self.command(spi, Command::PowerOff).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -207,21 +223,23 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; for b in buffer { // Two bits per pixel let expanded = expand_bits(*b); - self.interface.data(spi, &expanded)?; + self.interface.data(spi, &expanded).await?; } //NOTE: Example code has a delay here @@ -230,15 +248,17 @@ where let color = self.color.get_byte_value(); let nbits = WIDTH * (HEIGHT / 8); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, nbits)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data_x_times(spi, color, nbits).await?; //NOTE: Example code has a delay here Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -251,73 +271,94 @@ 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 / 8 * HEIGHT))?; + .data_x_times(spi, color, 2 * (WIDTH / 8 * HEIGHT)) + .await?; // Clear the red - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?; + .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0) + .await?; self.interface - .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE)?; + .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE) + .await?; self.interface - .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE)?; - self.interface.cmd_with_data(spi, Command::LutG0, LUT_G1)?; - self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2)?; + .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE) + .await?; self.interface - .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?; + .cmd_with_data(spi, Command::LutG0, LUT_G1) + .await?; self.interface - .cmd_with_data(spi, Command::LutRed0, LUT_RED0)?; + .cmd_with_data(spi, Command::LutG1, LUT_G2) + .await?; self.interface - .cmd_with_data(spi, Command::LutRed1, LUT_RED1)?; + .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM) + .await?; + self.interface + .cmd_with_data(spi, Command::LutRed0, LUT_RED0) + .await?; + self.interface + .cmd_with_data(spi, Command::LutRed1, LUT_RED1) + .await?; Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } +#[maybe_async::maybe_async] impl Epd1in54b where SPI: SpiDevice, @@ -326,32 +367,32 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 bbe27302..899123ee 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,8 +1,8 @@ //! 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::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -40,6 +40,7 @@ pub struct Epd1in54c { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd1in54c where @@ -49,33 +50,37 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd1in54c where @@ -85,42 +90,45 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd1in54c where @@ -131,7 +139,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -144,23 +152,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 +187,27 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, buffer)?; + self.update_achromatic_frame(spi, delay, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -210,41 +220,45 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -253,12 +267,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd1in54c where SPI: SpiDevice, @@ -267,40 +286,40 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 5d8d4e0b..49a7cc39 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -15,15 +15,11 @@ //! - [Controller Datasheet SS1780](http://www.e-paper-display.com/download_detail/downloadsId=682.html) //! -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::buffer_len; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; @@ -80,6 +76,7 @@ pub struct Epd2in13 { refresh: RefreshLut, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in13 where @@ -89,27 +86,28 @@ where RST: OutputPin, DELAY: DelayNs, { - 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])?; + // self.cmd_with_data(spi, Command::WriteOtpSelection, &[0, 0, 0, 0, 0x40, 0, 0]).await?; // During partial update, clock/analog are not disabled between 2 // updates. self.set_display_update_control_2( spi, DisplayUpdateControl2::new().enable_analog().enable_clock(), - )?; - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + ) + .await?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; self.set_border_waveform( spi, @@ -118,11 +116,12 @@ where fix_level: BorderWaveFormFixLevel::Vss, gs_trans: BorderWaveFormGs::Lut1, }, - )?; + ) + .await?; } else { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::SwReset)?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::SwReset).await?; + self.wait_until_idle(spi, delay).await?; self.set_driver_output( spi, @@ -132,17 +131,19 @@ where scan_dir_incr: true, width: (HEIGHT - 1) as u16, }, - )?; + ) + .await?; // These 2 are the reset values - self.set_dummy_line_period(spi, 0x30)?; - self.set_gate_scan_start_position(spi, 0)?; + self.set_dummy_line_period(spi, 0x30).await?; + self.set_gate_scan_start_position(spi, 0).await?; - self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir)?; + self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir) + .await?; // Use simple X/Y auto increase - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; self.set_border_waveform( spi, @@ -151,28 +152,32 @@ 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in13 where @@ -183,7 +188,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -198,16 +203,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 +222,33 @@ where .enable_clock() .disable_analog() .disable_clock(), - )?; - self.command(spi, Command::MasterActivation)?; + ) + .await?; + self.command(spi, Command::MasterActivation).await?; - self.set_sleep_mode(spi, self.sleep_mode)?; + self.set_sleep_mode(spi, self.sleep_mode).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRam, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equal to current if not doing partial refresh. - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; } Ok(()) } @@ -249,7 +256,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 +276,18 @@ where // incorrect. assert!(self.refresh == RefreshLut::Full); - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_address_counters(spi, delay, x, y)?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_address_counters(spi, delay, x, y).await?; - self.cmd_with_data(spi, Command::WriteRam, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer).await?; if self.refresh == RefreshLut::Full { // Always keep the base buffer equals to current if not doing partial refresh. - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_address_counters(spi, delay, x, y)?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_address_counters(spi, delay, x, y).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; } Ok(()) @@ -287,7 +295,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 +305,61 @@ where .display() .disable_analog() .disable_clock(), - )?; + ) + .await?; } else { - self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display())?; + self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display()) + .await?; } - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; if self.refresh == RefreshLut::Quick { - self.set_partial_base_buffer(spi, delay, buffer)?; + self.set_partial_base_buffer(spi, delay, buffer).await?; } Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let color = self.background_color.get_byte_value(); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; - - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - color, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - // Always keep the base buffer equals to current if not doing partial refresh. - if self.refresh == RefreshLut::Full { - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; - - self.command(spi, Command::WriteRamRed)?; - self.interface.data_x_times( + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( spi, color, buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + ) + .await?; + + // Always keep the base buffer equals to current if not doing partial refresh. + if self.refresh == RefreshLut::Full { + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; + + self.command(spi, Command::WriteRamRed).await?; + self.interface + .data_x_times( + spi, + color, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } Ok(()) } @@ -366,7 +380,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -378,14 +392,20 @@ where }; self.cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } +#[maybe_async::maybe_async] impl Epd2in13 where SPI: SpiDevice, @@ -396,17 +416,18 @@ where { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. - pub fn set_partial_base_buffer( + pub async fn set_partial_base_buffer( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { assert!(buffer_len(WIDTH as usize, HEIGHT as usize) == buffer.len()); - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.set_ram_address_counters(spi, delay, 0, 0)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; + self.set_ram_address_counters(spi, delay, 0, 0).await?; - self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer) + .await?; Ok(()) } @@ -417,7 +438,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 +446,12 @@ where ) -> Result<(), SPI::Error> { if self.refresh != refresh { self.refresh = refresh; - self.init(spi, delay)?; + self.init(spi, delay).await?; } Ok(()) } - fn set_gate_scan_start_position( + async fn set_gate_scan_start_position( &mut self, spi: &mut SPI, start: u16, @@ -441,9 +462,10 @@ where Command::GateScanStartPosition, &[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8], ) + .await } - fn set_border_waveform( + async fn set_border_waveform( &mut self, spi: &mut SPI, borderwaveform: BorderWaveForm, @@ -453,35 +475,40 @@ where Command::BorderWaveformControl, &[borderwaveform.to_u8()], ) + .await } - fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { + async fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) + .await } - fn set_gate_driving_voltage( + async fn set_gate_driving_voltage( &mut self, spi: &mut SPI, voltage: GateDrivingVoltage, ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[voltage.0]) + .await } - fn set_dummy_line_period( + async fn set_dummy_line_period( &mut self, spi: &mut SPI, number_of_lines: u8, ) -> Result<(), SPI::Error> { assert!(number_of_lines <= 127); self.cmd_with_data(spi, Command::SetDummyLinePeriod, &[number_of_lines]) + .await } - fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { + async fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F]) + .await } /// Sets the source driving voltage value - fn set_source_driving_voltage( + async fn set_source_driving_voltage( &mut self, spi: &mut SPI, vsh1: SourceDrivingVoltage, @@ -493,30 +520,42 @@ where Command::SourceDrivingVoltageCtrl, &[vsh1.0, vsh2.0, vsl.0], ) + .await } /// Prepare the actions that the next master activation command will /// trigger. - fn set_display_update_control_2( + async fn set_display_update_control_2( &mut self, spi: &mut SPI, value: DisplayUpdateControl2, ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[value.0]) + .await } /// Triggers the deep sleep mode - fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { + async fn set_sleep_mode( + &mut self, + spi: &mut SPI, + mode: DeepSleepMode, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) + .await } - fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> { + async fn set_driver_output( + &mut self, + spi: &mut SPI, + output: DriverOutput, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) + .await } /// Sets the data entry mode (ie. how X and Y positions changes when writing /// data to RAM) - fn set_data_entry_mode( + async fn set_data_entry_mode( &mut self, spi: &mut SPI, counter_incr_mode: DataEntryModeIncr, @@ -524,10 +563,11 @@ where ) -> Result<(), SPI::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) + .await } /// Sets both X and Y pixels ranges - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -539,7 +579,8 @@ where spi, Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + ) + .await?; self.cmd_with_data( spi, @@ -551,38 +592,41 @@ where (end_y >> 8) as u8, ], ) + .await } /// Sets both X and Y pixels counters when writing data to RAM - fn set_ram_address_counters( + async fn set_ram_address_counters( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; self.cmd_with_data( spi, Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], - )?; + ) + .await?; Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } } diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs index 5bedea9a..c7a24059 100644 --- a/src/epd2in13b_v4/mod.rs +++ b/src/epd2in13b_v4/mod.rs @@ -51,15 +51,11 @@ //!# } //!``` // Original Waveforms from Waveshare -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::buffer_len; use crate::color::TriColor; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -102,6 +98,7 @@ pub struct Epd2in13b { background_color: TriColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in13b where @@ -111,13 +108,13 @@ where RST: OutputPin, DELAY: DelayNs, { - 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; - 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?; self.set_driver_output( spi, @@ -127,13 +124,15 @@ where scan_dir_incr: true, width: (HEIGHT - 1) as u16, }, - )?; + ) + .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, @@ -142,11 +141,15 @@ where fix_level: BorderWaveFormFixLevel::Vss, gs_trans: BorderWaveFormGs::Lut3, }, - )?; + ) + .await?; - self.cmd_with_data(spi, Command::WriteVcomRegister, &[0x36])?; - self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[0x17])?; - self.cmd_with_data(spi, Command::SourceDrivingVoltageCtrl, &[0x41, 0x00, 0x32])?; + self.cmd_with_data(spi, Command::WriteVcomRegister, &[0x36]) + .await?; + self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[0x17]) + .await?; + self.cmd_with_data(spi, Command::SourceDrivingVoltageCtrl, &[0x41, 0x00, 0x32]) + .await?; self.set_display_update_control( spi, @@ -155,14 +158,16 @@ where bw_ram_option: RamOption::Normal, source_output_mode: true, }, - )?; + ) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in13b where @@ -172,40 +177,41 @@ where RST: OutputPin, DELAY: DelayNs, { - 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.interface.cmd(spi, Command::WriteRam)?; - self.interface.data(spi, black)?; + self.interface.cmd(spi, Command::WriteRam).await?; + self.interface.data(spi, 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.interface.cmd(spi, Command::WriteRamRed)?; - self.interface.data(spi, chromatic)?; + self.interface.cmd(spi, Command::WriteRamRed).await?; + self.interface.data(spi, chromatic).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in13b where @@ -216,7 +222,7 @@ where DELAY: DelayNs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -229,38 +235,40 @@ 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.set_sleep_mode(spi, DeepSleepMode::Normal)?; + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.set_sleep_mode(spi, DeepSleepMode::Normal).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.cmd_with_data(spi, Command::WriteRam, buffer)?; - - self.command(spi, Command::WriteRamRed)?; - self.interface.data_x_times( - spi, - TriColor::Black.get_byte_value(), - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.cmd_with_data(spi, Command::WriteRam, buffer).await?; + + self.command(spi, Command::WriteRamRed).await?; + self.interface + .data_x_times( + spi, + TriColor::Black.get_byte_value(), + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -273,27 +281,27 @@ 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> { - self.clear_achromatic_frame(spi)?; - self.clear_chromatic_frame(spi) + async fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.clear_achromatic_frame(spi).await?; + self.clear_chromatic_frame(spi).await } fn set_background_color(&mut self, background_color: TriColor) { @@ -312,7 +320,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -321,12 +329,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in13b where SPI: SpiDevice, @@ -335,7 +348,7 @@ where RST: OutputPin, DELAY: DelayNs, { - fn set_display_update_control( + async fn set_display_update_control( &mut self, spi: &mut SPI, display_update_control: DisplayUpdateControl, @@ -345,9 +358,10 @@ where Command::DisplayUpdateControl1, &display_update_control.to_bytes(), ) + .await } - fn set_border_waveform( + async fn set_border_waveform( &mut self, spi: &mut SPI, borderwaveform: BorderWaveForm, @@ -357,20 +371,31 @@ where Command::BorderWaveformControl, &[borderwaveform.to_u8()], ) + .await } /// Triggers the deep sleep mode - fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { + async fn set_sleep_mode( + &mut self, + spi: &mut SPI, + mode: DeepSleepMode, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) + .await } - fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> { + async fn set_driver_output( + &mut self, + spi: &mut SPI, + output: DriverOutput, + ) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) + .await } /// Sets the data entry mode (ie. how X and Y positions changes when writing /// data to RAM) - fn set_data_entry_mode( + async fn set_data_entry_mode( &mut self, spi: &mut SPI, counter_incr_mode: DataEntryModeIncr, @@ -378,10 +403,11 @@ where ) -> Result<(), SPI::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) + .await } /// Sets both X and Y pixels ranges - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -393,7 +419,8 @@ where spi, Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + ) + .await?; self.cmd_with_data( spi, @@ -405,96 +432,111 @@ where (end_y >> 8) as u8, ], ) + .await } /// Sets both X and Y pixels counters when writing data to RAM - fn set_ram_address_counters( + async fn set_ram_address_counters( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; self.cmd_with_data( spi, Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], - )?; + ) + .await?; Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn clear_achromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn clear_achromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { match self.background_color { TriColor::White => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0xFF, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } TriColor::Chromatic => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0xFF, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } TriColor::Black => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0x00, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } } Ok(()) } - fn clear_chromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn clear_chromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { match self.background_color { TriColor::White => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0x00, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } TriColor::Chromatic => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0xFF, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } TriColor::Black => { - self.command(spi, Command::WriteRam)?; - self.interface.data_x_times( - spi, - 0x00, - buffer_len(WIDTH as usize, HEIGHT as usize) as u32, - )?; + self.command(spi, Command::WriteRam).await?; + self.interface + .data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + ) + .await?; } } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index d1256c4c..dbc0f3fc 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -50,9 +50,9 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -97,6 +97,7 @@ pub struct Epd2in13bc { color: TriColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in13bc where @@ -106,40 +107,45 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in13bc where @@ -149,48 +155,53 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in13bc where @@ -201,7 +212,7 @@ where DELAY: DelayNs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -214,30 +225,32 @@ where let mut epd = Epd2in13bc { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Section 8.2 from datasheet - self.interface.cmd_with_data( - spi, - Command::VcomAndDataIntervalSetting, - &[FLOATING_BORDER | VCOM_DATA_INTERVAL], - )?; - - self.command(spi, Command::PowerOff)?; + self.interface + .cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[FLOATING_BORDER | VCOM_DATA_INTERVAL], + ) + .await?; + + self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: TriColor) { @@ -256,28 +269,34 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -290,43 +309,51 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -335,12 +362,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in13bc where SPI: SpiDevice, @@ -349,36 +381,40 @@ where RST: OutputPin, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } /// Set the outer border of the display to the chosen color. - pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> { + pub async fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), SPI::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, @@ -389,5 +425,6 @@ where Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], ) + .await } } diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 092fce3f..9fd419ee 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -166,14 +166,10 @@ //!} //!``` -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::TriColor; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -208,6 +204,7 @@ pub struct Epd2in66b { background: TriColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in66b where @@ -217,24 +214,28 @@ where RST: OutputPin, DELAY: DelayNs, { - 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> { // We follow the sequence of the Pi-Pico hat example code. - self.hw_reset(delay)?; - self.sw_reset(spi, delay)?; - self.data_entry_mode(spi, DataEntryRow::XMinor, DataEntrySign::IncYIncX)?; - self.set_display_window(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.hw_reset(delay).await?; + self.sw_reset(spi, delay).await?; + self.data_entry_mode(spi, DataEntryRow::XMinor, DataEntrySign::IncYIncX) + .await?; + self.set_display_window(spi, 0, 0, WIDTH - 1, HEIGHT - 1) + .await?; self.update_control1( spi, WriteMode::Normal, WriteMode::Normal, OutputSource::S8ToS167, - )?; - self.set_cursor(spi, 0, 0)?; + ) + .await?; + self.set_cursor(spi, 0, 0).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in66b where @@ -244,40 +245,41 @@ where RST: OutputPin, DELAY: DelayNs, { - 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.set_cursor(spi, 0, 0)?; - self.interface.cmd(spi, Command::WriteBlackWhiteRAM)?; - self.interface.data(spi, black) + self.set_cursor(spi, 0, 0).await?; + self.interface.cmd(spi, Command::WriteBlackWhiteRAM).await?; + self.interface.data(spi, black).await } - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.set_cursor(spi, 0, 0)?; - self.interface.cmd(spi, Command::WriteRedRAM)?; - self.interface.data(spi, chromatic) + self.set_cursor(spi, 0, 0).await?; + self.interface.cmd(spi, Command::WriteRedRAM).await?; + self.interface.data(spi, chromatic).await } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in66b where @@ -289,7 +291,7 @@ where { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -304,20 +306,22 @@ where interface: DisplayInterface::new(busy, dc, rst, delay_us), background: DEFAULT_BACKGROUND_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.interface.cmd_with_data( - spi, - Command::DeepSleepMode, - &[DeepSleep::SleepLosingRAM as u8], - ) + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface + .cmd_with_data( + spi, + Command::DeepSleepMode, + &[DeepSleep::SleepLosingRAM as u8], + ) + .await } - 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: Self::DisplayColor) { @@ -336,18 +340,19 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.set_cursor(spi, 0, 0)?; - self.update_achromatic_frame(spi, delay, buffer)?; - self.red_pattern(spi, delay, PatW::W160, PatH::H296, StartWith::Zero) // do NOT consider background here since red overrides other colors + self.set_cursor(spi, 0, 0).await?; + self.update_achromatic_frame(spi, delay, buffer).await?; + self.red_pattern(spi, delay, PatW::W160, PatH::H296, StartWith::Zero) + .await // do NOT consider background here since red overrides other colors } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -357,38 +362,41 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.set_display_window(spi, x, y, x + width, y + height)?; - self.set_cursor(spi, x, y)?; - self.update_achromatic_frame(spi, delay, buffer)?; - self.set_display_window(spi, 0, 0, WIDTH, HEIGHT) + self.set_display_window(spi, x, y, x + width, y + height) + .await?; + self.set_cursor(spi, x, y).await?; + self.update_achromatic_frame(spi, delay, buffer).await?; + self.set_display_window(spi, 0, 0, WIDTH, HEIGHT).await } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(delay) + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::MasterActivation).await?; + self.wait_until_idle(delay).await } - 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 } - 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 (white, red) = match self.background { TriColor::Black => (StartWith::Zero, StartWith::Zero), TriColor::White => (StartWith::One, StartWith::Zero), TriColor::Chromatic => (StartWith::Zero, StartWith::One), }; - self.black_white_pattern(spi, delay, PatW::W160, PatH::H296, white)?; + self.black_white_pattern(spi, delay, PatW::W160, PatH::H296, white) + .await?; self.red_pattern(spi, delay, PatW::W160, PatH::H296, red) + .await } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -397,12 +405,17 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(delay) + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(delay).await } } // Helper functions that enforce some type and value constraints. Meant to help with code readability. They caught some of my silly errors -> yay rust!. +#[maybe_async::maybe_async] impl Epd2in66b where SPI: SpiDevice, @@ -411,20 +424,20 @@ where RST: OutputPin, DELAY: DelayNs, { - fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, false); + async fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, false).await; Ok(()) } - fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { // The initial delay is taken from other code here, the 2 ms comes from the SSD1675B datasheet. - self.interface.reset(delay, 20_000, 2_000); - self.wait_until_idle(delay) + self.interface.reset(delay, 20_000, 2_000).await; + self.wait_until_idle(delay).await } - fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::Reset)?; - self.wait_until_idle(delay) + async fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::Reset).await?; + self.wait_until_idle(delay).await } - fn data_entry_mode( + async fn data_entry_mode( &mut self, spi: &mut SPI, row: DataEntryRow, @@ -432,8 +445,9 @@ where ) -> Result<(), SPI::Error> { self.interface .cmd_with_data(spi, Command::DataEntryMode, &[row as u8 | sign as u8]) + .await } - fn set_display_window( + async fn set_display_window( &mut self, spi: &mut SPI, xstart: u32, @@ -441,50 +455,56 @@ where xend: u32, yend: u32, ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data( - spi, - Command::SetXAddressRange, - &[(((xstart >> 3) & 0x1f) as u8), (((xend >> 3) & 0x1f) as u8)], - )?; - self.interface.cmd_with_data( - spi, - Command::SetYAddressRange, - &[ - ((ystart & 0xff) as u8), - (((ystart >> 8) & 0x01) as u8), - ((yend & 0xff) as u8), - (((yend >> 8) & 0x01) as u8), - ], - ) + self.interface + .cmd_with_data( + spi, + Command::SetXAddressRange, + &[(((xstart >> 3) & 0x1f) as u8), (((xend >> 3) & 0x1f) as u8)], + ) + .await?; + self.interface + .cmd_with_data( + spi, + Command::SetYAddressRange, + &[ + ((ystart & 0xff) as u8), + (((ystart >> 8) & 0x01) as u8), + ((yend & 0xff) as u8), + (((yend >> 8) & 0x01) as u8), + ], + ) + .await } - fn update_control1( + async fn update_control1( &mut self, spi: &mut SPI, red_mode: WriteMode, bw_mode: WriteMode, source: OutputSource, ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data( - spi, - Command::DisplayUpdateControl1, - &[((red_mode as u8) << 4 | bw_mode as u8), (source as u8)], - ) + self.interface + .cmd_with_data( + spi, + Command::DisplayUpdateControl1, + &[((red_mode as u8) << 4 | bw_mode as u8), (source as u8)], + ) + .await } - fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { - self.interface.cmd_with_data( - spi, - Command::SetXAddressCounter, - &[((x >> 3) & 0x1f) as u8], - )?; - self.interface.cmd_with_data( - spi, - Command::SetYAddressCounter, - &[((y & 0xff) as u8), (((y >> 8) & 0x01) as u8)], - ) + async fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + self.interface + .cmd_with_data(spi, Command::SetXAddressCounter, &[((x >> 3) & 0x1f) as u8]) + .await?; + self.interface + .cmd_with_data( + spi, + Command::SetYAddressCounter, + &[((y & 0xff) as u8), (((y >> 8) & 0x01) as u8)], + ) + .await } - fn black_white_pattern( + async fn black_white_pattern( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -492,14 +512,16 @@ where h: PatH, phase: StartWith, ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data( - spi, - Command::BlackWhiteRAMTestPattern, - &[phase as u8 | h as u8 | w as u8], - )?; - self.wait_until_idle(delay) + self.interface + .cmd_with_data( + spi, + Command::BlackWhiteRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + ) + .await?; + self.wait_until_idle(delay).await } - fn red_pattern( + async fn red_pattern( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -507,11 +529,13 @@ where h: PatH, phase: StartWith, ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data( - spi, - Command::RedRAMTestPattern, - &[phase as u8 | h as u8 | w as u8], - )?; - self.wait_until_idle(delay) + self.interface + .cmd_with_data( + spi, + Command::RedRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + ) + .await?; + self.wait_until_idle(delay).await } } diff --git a/src/epd2in7/mod.rs b/src/epd2in7/mod.rs index 77cccca0..50b0a36d 100644 --- a/src/epd2in7/mod.rs +++ b/src/epd2in7/mod.rs @@ -2,13 +2,9 @@ //! //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT) -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; // The Lookup Tables for the Display @@ -48,6 +44,7 @@ pub struct Epd2in7 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in7 where @@ -57,42 +54,57 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 setting - self.cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x09])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x09]) + .await?; // booster soft start - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17]) + .await?; // power optimization - self.cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0xa0, 0xa5])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0xa1, 0x00])?; - self.cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41])?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0xa0, 0xa5]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0xa1, 0x00]) + .await?; + self.cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41]) + .await?; // partial display refresh - self.cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00])?; + self.cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00]) + .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?; // panel setting - self.cmd_with_data(spi, Command::PanelSetting, &[0xaf])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xaf]) + .await?; // pll control - self.cmd_with_data(spi, Command::PllControl, &[0x3a])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3a]) + .await?; // vcom and data interval setting - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x57])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x57]) + .await?; // cvm dc setting register - self.cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; - self.set_lut(spi, delay, None)?; - self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; + self.set_lut(spi, delay, None).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in7 where @@ -103,7 +115,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -116,42 +128,49 @@ where let mut epd = Epd2in7 { 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.interface - .data_x_times(spi, self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.send_data(spi, buffer)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, self.color.get_byte_value(), WIDTH * HEIGHT / 8) + .await?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.send_data(spi, buffer).await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -162,47 +181,54 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; - - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; - self.send_data(spi, buffer) + .cmd(spi, Command::PartialDataStartTransmission1) + .await?; + + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; + self.send_data(spi, buffer).await } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8) + .await?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8) + .await?; Ok(()) } @@ -222,27 +248,37 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in7 where SPI: SpiDevice, @@ -251,21 +287,21 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 } } diff --git a/src/epd2in7_v2/mod.rs b/src/epd2in7_v2/mod.rs index b1687326..6d193e84 100644 --- a/src/epd2in7_v2/mod.rs +++ b/src/epd2in7_v2/mod.rs @@ -8,16 +8,12 @@ //! - [Waveshare C driver](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7_V2.c) //! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in7_V2.py) -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::{ buffer_len, color::Color, - interface::DisplayInterface, + interface::{DelayNs, DisplayInterface, SpiDevice}, traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}, type_a::command::Command, }; @@ -52,6 +48,7 @@ pub struct Epd2in7 { refresh: RefreshLut, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in7 where @@ -61,23 +58,25 @@ where RST: OutputPin, DELAY: DelayNs, { - 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, 2_000); + self.interface.reset(delay, 200_000, 2_000).await; - 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.use_full_frame(spi, delay)?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03]) + .await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in7 where @@ -88,7 +87,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -105,36 +104,38 @@ 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(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -144,51 +145,55 @@ 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?; if self.refresh == RefreshLut::Full { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) + .await?; } else if self.refresh == RefreshLut::Quick { self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7]) + .await?; } - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + 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)?; - 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?; let color = self.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(()) } @@ -209,7 +214,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -221,12 +226,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in7 where SPI: SpiDevice, @@ -235,11 +245,11 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -250,50 +260,57 @@ where assert!(start_x < end_x); assert!(start_y < end_y); - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; - - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - (start_y & 0xFF) as u8, - ((start_y >> 8) & 0x01) as u8, - (end_y & 0xFF) as u8, - ((end_y >> 8) & 0x01) as u8, - ], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; + + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + (start_y & 0xFF) as u8, + ((start_y >> 8) & 0x01) as u8, + (end_y & 0xFF) as u8, + ((end_y >> 8) & 0x01) as u8, + ], + ) + .await?; Ok(()) } - 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?; self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x & 0xFF) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x & 0xFF) as u8]) + .await?; - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[(y & 0xFF) as u8, ((y >> 8) & 0x01) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[(y & 0xFF) as u8, ((y >> 8) & 0x01) as u8], + ) + .await?; Ok(()) } - 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 } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 42f25f19..2bd73632 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -2,9 +2,9 @@ //! //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -47,6 +47,7 @@ pub struct Epd2in7b { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in7b where @@ -56,62 +57,72 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set panel settings, 0xbf is bw, 0xaf is multi-color self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0xaf])?; + .cmd_with_data(spi, Command::PanelSetting, &[0xaf]) + .await?; // pll control self.interface - .cmd_with_data(spi, Command::PllControl, &[0x3a])?; + .cmd_with_data(spi, Command::PllControl, &[0x3a]) + .await?; // set the power settings - self.interface.cmd_with_data( - spi, - Command::PowerSetting, - &[0x03, 0x00, 0x2b, 0x2b, 0x09], - )?; + self.interface + .cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x09]) + .await?; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17]) + .await?; // power optimization self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a]) + .await?; self.interface - .cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41]) + .await?; self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; self.interface - .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00])?; + .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00]) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in7b where @@ -122,7 +133,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -135,46 +146,53 @@ where let mut epd = Epd2in7b { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7]) + .await?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + .await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], _delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.send_buffer_helper(spi, buffer)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.send_buffer_helper(spi, buffer).await?; // Clear chromatic layer since we won't be using it here - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, !self.color.get_byte_value(), WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, !self.color.get_byte_value(), WIDTH / 8 * HEIGHT) + .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 +203,61 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; - - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; - - self.send_buffer_helper(spi, buffer)?; - - self.interface.cmd(spi, Command::DataStop) + .cmd(spi, Command::PartialDataStartTransmission1) + .await?; + + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; + + self.send_buffer_helper(spi, buffer).await?; + + self.interface.cmd(spi, Command::DataStop).await } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; - self.interface.cmd(spi, Command::DataStop)?; + self.interface.cmd(spi, Command::DataStop).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; - self.interface.cmd(spi, Command::DataStop)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; + self.interface.cmd(spi, Command::DataStop).await?; Ok(()) } @@ -252,27 +277,37 @@ 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in7b where @@ -282,53 +317,58 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async] impl Epd2in7b where SPI: SpiDevice, @@ -337,34 +377,34 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 +413,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 +439,21 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission1)?; - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; + .cmd(spi, Command::PartialDataStartTransmission1) + .await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; for b in achromatic.iter() { // Flipping based on waveshare implementation - self.send_data(spi, &[!b])?; + self.send_data(spi, &[!b]).await?; } Ok(()) @@ -420,7 +461,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 +472,21 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PartialDataStartTransmission2)?; - self.send_data(spi, &[(x >> 8) as u8])?; - self.send_data(spi, &[(x & 0xf8) as u8])?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[(y & 0xff) as u8])?; - self.send_data(spi, &[(width >> 8) as u8])?; - self.send_data(spi, &[(width & 0xf8) as u8])?; - self.send_data(spi, &[(height >> 8) as u8])?; - self.send_data(spi, &[(height & 0xff) as u8])?; - self.wait_until_idle(spi, delay)?; + .cmd(spi, Command::PartialDataStartTransmission2) + .await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; + self.send_data(spi, &[(x & 0xf8) as u8]).await?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[(y & 0xff) as u8]).await?; + self.send_data(spi, &[(width >> 8) as u8]).await?; + self.send_data(spi, &[(width & 0xf8) as u8]).await?; + self.send_data(spi, &[(height >> 8) as u8]).await?; + self.send_data(spi, &[(height & 0xff) as u8]).await?; + self.wait_until_idle(spi, delay).await?; for b in chromatic.iter() { // Flipping based on waveshare implementation - self.send_data(spi, &[!b])?; + self.send_data(spi, &[!b]).await?; } Ok(()) diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 0ad3d771..8cb3ae35 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -50,7 +50,7 @@ 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::*; use crate::type_a::{ command::Command, @@ -62,7 +62,7 @@ use crate::color::Color; use crate::traits::*; use crate::buffer_len; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; /// Display with Fullsize buffer for use with the 2in9 EPD #[cfg(feature = "graphics")] @@ -85,6 +85,7 @@ pub struct Epd2in9 { refresh: RefreshLut, } +#[maybe_async::maybe_async] impl Epd2in9 where SPI: SpiDevice, @@ -93,10 +94,10 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 10_000, 10_000).await; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // 3 Databytes: // A[7:0] @@ -104,7 +105,8 @@ where // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) self.interface - .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; + .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00]) + .await?; // 3 Databytes: (and default values from datasheet and arduino) // 1 .. A[6:0] = 0xCF | 0xD7 @@ -112,29 +114,35 @@ 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 } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in9 where @@ -153,7 +161,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -169,42 +177,44 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.init(spi, delay)?; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.init(spi, delay).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } //TODO: update description: last 3 bits will be ignored for width and x_pos - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -214,50 +224,53 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4]) + .await?; - self.interface.cmd(spi, Command::MasterActivation)?; + self.interface.cmd(spi, Command::MasterActivation).await?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; + self.interface.cmd(spi, Command::Nop).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.use_full_frame(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.use_full_frame(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } @@ -269,7 +282,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -282,14 +295,20 @@ where RefreshLut::Full => self.set_lut_helper(spi, delay, &LUT_FULL_UPDATE), 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(()) } } +#[maybe_async::maybe_async] impl Epd2in9 where SPI: SpiDevice, @@ -298,15 +317,15 @@ where RST: OutputPin, DELAY: DelayNs, { - fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram - self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1).await?; // start from the beginning - self.set_ram_counter(spi, delay, 0, 0) + self.set_ram_counter(spi, delay, 0, 0).await } - fn set_ram_area( + async fn set_ram_area( &mut self, spi: &mut SPI, start_x: u32, @@ -319,58 +338,66 @@ where // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - ) + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await } - fn set_ram_counter( + async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } /// Set your own LUT, this function is also used internally for set_lut - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; assert!(buffer.len() == 30); self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; Ok(()) } } diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index df466cba..f92ba742 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -87,7 +87,7 @@ const WS_20_30: [u8; 159] = [ 0x44, 0x44, 0x0, 0x0, 0x0, 0x22, 0x17, 0x41, 0x0, 0x32, 0x36, ]; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; use crate::type_a::command::Command; @@ -96,7 +96,7 @@ use crate::color::Color; use crate::traits::*; use crate::buffer_len; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::QuickRefresh; /// Display with Fullsize buffer for use with the 2in9 EPD V2 @@ -120,6 +120,7 @@ pub struct Epd2in9 { refresh: RefreshLut, } +#[maybe_async::maybe_async] impl Epd2in9 where SPI: SpiDevice, @@ -128,12 +129,12 @@ where RST: OutputPin, DELAY: DelayNs, { - 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] @@ -141,37 +142,45 @@ 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?; // set LUT by host - self.set_lut_helper(spi, delay, &WS_20_30[0..153])?; + self.set_lut_helper(spi, delay, &WS_20_30[0..153]).await?; self.interface - .cmd_with_data(spi, Command::WriteLutRegisterEnd, &WS_20_30[153..154])?; + .cmd_with_data(spi, Command::WriteLutRegisterEnd, &WS_20_30[153..154]) + .await?; self.interface - .cmd_with_data(spi, Command::GateDrivingVoltage, &WS_20_30[154..155])?; + .cmd_with_data(spi, Command::GateDrivingVoltage, &WS_20_30[154..155]) + .await?; self.interface - .cmd_with_data(spi, Command::SourceDrivingVoltage, &WS_20_30[155..158])?; + .cmd_with_data(spi, Command::SourceDrivingVoltage, &WS_20_30[155..158]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &WS_20_30[158..159])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &WS_20_30[158..159]) + .await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in9 where @@ -190,7 +199,7 @@ where HEIGHT } - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -206,35 +215,38 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode self.interface - .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay)?; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.interface.cmd_with_data(spi, Command::WriteRam, buffer) + self.wait_until_idle(spi, delay).await?; + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer) + .await } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -245,48 +257,53 @@ where height: u32, ) -> Result<(), SPI::Error> { //TODO This is copied from epd2in9 but it seems not working. Partial refresh supported by version 2? - self.wait_until_idle(spi, delay)?; - self.set_ram_area(spi, x, y, x + width, y + height)?; - self.set_ram_counter(spi, delay, x, y)?; + self.wait_until_idle(spi, delay).await?; + self.set_ram_area(spi, x, y, x + width, y + height).await?; + self.set_ram_counter(spi, delay, x, y).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } /// actually is the "Turn on Display" sequence - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; + self.interface.cmd(spi, Command::WriteRam).await?; + self.interface + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await?; + self.interface.cmd(spi, Command::WriteRam2).await?; self.interface - .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; - self.interface.cmd(spi, Command::WriteRam2)?; - self.interface.data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .data_x_times(spi, color, WIDTH / 8 * HEIGHT) + .await } fn set_background_color(&mut self, background_color: Color) { @@ -297,7 +314,7 @@ where &self.background_color } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -309,12 +326,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in9 where SPI: SpiDevice, @@ -323,15 +345,15 @@ where RST: OutputPin, DELAY: DelayNs, { - 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, @@ -344,62 +366,71 @@ where // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[(start_x >> 3) as u8, (end_x >> 3) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + ) + .await?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[ - start_y as u8, - (start_y >> 8) as u8, - end_y as u8, - (end_y >> 8) as u8, - ], - ) + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + .await } - fn set_ram_counter( + async fn set_ram_counter( &mut self, spi: &mut SPI, delay: &mut DELAY, x: u32, y: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[x as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[x as u8]) + .await?; // 2 Databytes: A[7:0] & 0..A[8] - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressCounter, - &[y as u8, (y >> 8) as u8], - )?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + ) + .await?; Ok(()) } /// Set your own LUT, this function is also used internally for set_lut - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl QuickRefresh for Epd2in9 where @@ -410,75 +441,87 @@ where DELAY: DelayNs, { /// 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::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; self.interface .cmd_with_data(spi, Command::WriteRam2, buffer) + .await } /// To be used immediately after `update_old_frame`. - fn update_new_frame( + async fn update_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.interface.reset(delay, 10_000, 2_000); - - self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; - self.interface.cmd_with_data( - spi, - Command::WriteOtpSelection, - &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], - )?; + self.wait_until_idle(spi, delay).await?; + self.interface.reset(delay, 10_000, 2_000).await; + + self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9).await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; + .cmd_with_data( + spi, + Command::WriteOtpSelection, + &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0])?; - self.interface.cmd(spi, Command::MasterActivation)?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80]) + .await?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.use_full_frame(spi, delay)?; + self.use_full_frame(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } /// For a quick refresh of the new updated frame. To be used immediately after `update_new_frame` - fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn display_new_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; - self.interface.cmd(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F]) + .await?; + self.interface.cmd(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } /// Updates and displays the new frame. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay)?; - self.display_new_frame(spi, delay)?; + self.update_new_frame(spi, buffer, delay).await?; + self.display_new_frame(spi, delay).await?; Ok(()) } /// Partial quick refresh not supported yet #[allow(unused)] - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -494,7 +537,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, @@ -510,7 +553,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/epd2in9b_v4/mod.rs b/src/epd2in9b_v4/mod.rs index 12cfdd90..bda98bcd 100644 --- a/src/epd2in9b_v4/mod.rs +++ b/src/epd2in9b_v4/mod.rs @@ -7,14 +7,10 @@ use crate::{ buffer_len, color::TriColor, - interface::DisplayInterface, + interface::{DelayNs, DisplayInterface, SpiDevice}, traits::{InternalWiAdditions, WaveshareDisplay, WaveshareThreeColorDisplay}, }; -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; pub(crate) mod command; use self::command::Command; @@ -56,6 +52,7 @@ enum DisplayMode { Base, } +#[maybe_async::maybe_async] impl Epd2in9b where SPI: SpiDevice, @@ -67,22 +64,22 @@ where /// set the base image before partially update /// /// - pub fn update_and_display_frame_base( + pub async fn update_and_display_frame_base( &mut self, spi: &mut SPI, black: &[u8], chromatic: Option<&[u8]>, delay: &mut DELAY, ) -> Result<(), ::Error> { - self.update_frame(spi, black, delay)?; + self.update_frame(spi, black, delay).await?; if let Some(chromatic) = chromatic { - self.update_chromatic_frame(spi, delay, chromatic)?; + self.update_chromatic_frame(spi, delay, chromatic).await?; } - self.turn_on_display(spi, delay, DisplayMode::Base)?; + self.turn_on_display(spi, delay, DisplayMode::Base).await?; - self.command(spi, Command::WriteRedData)?; - self.send_data(spi, black)?; + self.command(spi, Command::WriteRedData).await?; + self.send_data(spi, black).await?; Ok(()) } @@ -91,30 +88,31 @@ where /// /// To perform partial update, it need to call update_and_display_frame_base /// than call update_partial_frame before call display_frame_partial - pub fn display_frame_partial( + pub async fn display_frame_partial( &mut self, spi: &mut SPI, delay: &mut DELAY, ) -> Result<(), ::Error> { - self.turn_on_display(spi, delay, DisplayMode::Partial)?; + self.turn_on_display(spi, delay, DisplayMode::Partial) + .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 turn_on_display( + async fn turn_on_display( &mut self, spi: &mut SPI, delay: &mut DELAY, mode: DisplayMode, ) -> Result<(), SPI::Error> { - self.command(spi, Command::TurnOnDisplay)?; + self.command(spi, Command::TurnOnDisplay).await?; let data = match mode { DisplayMode::Default => 0xf7, @@ -123,13 +121,15 @@ where DisplayMode::Base => 0xf4, }; - self.send_data(spi, &[data])?; - self.command(spi, Command::ActivateDisplayUpdateSequence)?; - self.wait_until_idle(spi, delay)?; + self.send_data(spi, &[data]).await?; + self.command(spi, Command::ActivateDisplayUpdateSequence) + .await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in9b where @@ -139,56 +139,58 @@ where RST: OutputPin, DELAY: DelayNs, { - 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> { let w = self.width(); let h = self.height(); - self.interface.reset(delay, 200_000, 2_000); + self.interface.reset(delay, 200_000, 2_000).await; - 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.command(spi, Command::DriverOutputControl)?; - self.send_data(spi, &[((h - 1) % 256) as u8])?; - self.send_data(spi, &[((h - 1) / 256) as u8])?; - self.send_data(spi, &[0])?; + self.command(spi, Command::DriverOutputControl).await?; + self.send_data(spi, &[((h - 1) % 256) as u8]).await?; + self.send_data(spi, &[((h - 1) / 256) as u8]).await?; + self.send_data(spi, &[0]).await?; - self.command(spi, Command::DataEntryMode)?; - self.send_data(spi, &[0x03])?; + self.command(spi, Command::DataEntryMode).await?; + self.send_data(spi, &[0x03]).await?; - self.command(spi, Command::RamXPosition)?; - self.send_data(spi, &[0])?; - self.send_data(spi, &[(w / 8 - 1) as u8])?; + self.command(spi, Command::RamXPosition).await?; + self.send_data(spi, &[0]).await?; + self.send_data(spi, &[(w / 8 - 1) as u8]).await?; - self.command(spi, Command::RamYPosition)?; - self.send_data(spi, &[0])?; - self.send_data(spi, &[0])?; - self.send_data(spi, &[((h - 1) % 256) as u8])?; - self.send_data(spi, &[((h - 1) / 256) as u8])?; + self.command(spi, Command::RamYPosition).await?; + self.send_data(spi, &[0]).await?; + self.send_data(spi, &[0]).await?; + self.send_data(spi, &[((h - 1) % 256) as u8]).await?; + self.send_data(spi, &[((h - 1) / 256) as u8]).await?; - self.command(spi, Command::BorderWavefrom)?; - self.send_data(spi, &[0x05])?; + self.command(spi, Command::BorderWavefrom).await?; + self.send_data(spi, &[0x05]).await?; - self.command(spi, Command::DisplayUpdateControl)?; - self.send_data(spi, &[0x00])?; - self.send_data(spi, &[0x80])?; + self.command(spi, Command::DisplayUpdateControl).await?; + self.send_data(spi, &[0x00]).await?; + self.send_data(spi, &[0x80]).await?; - self.command(spi, Command::ReadBuiltInTemperatureSensor)?; - self.send_data(spi, &[0x80])?; + self.command(spi, Command::ReadBuiltInTemperatureSensor) + .await?; + self.send_data(spi, &[0x80]).await?; - self.command(spi, Command::RamXAddressCount)?; - self.send_data(spi, &[0x00])?; // set RAM x address count to 0 - self.command(spi, Command::RamYAddressCount)?; // set RAM y address count to 0X199 - self.send_data(spi, &[0x00])?; - self.send_data(spi, &[0x00])?; + self.command(spi, Command::RamXAddressCount).await?; + self.send_data(spi, &[0x00]).await?; // set RAM x address count to 0 + self.command(spi, Command::RamYAddressCount).await?; // set RAM y address count to 0X199 + self.send_data(spi, &[0x00]).await?; + self.send_data(spi, &[0x00]).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in9b where @@ -198,41 +200,42 @@ where RST: OutputPin, DELAY: DelayNs, { - fn update_color_frame( + async fn update_color_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, black: &[u8], chromatic: &[u8], ) -> Result<(), ::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<(), ::Error> { - self.command(spi, Command::WriteBlackData)?; - self.send_data(spi, black)?; + self.command(spi, Command::WriteBlackData).await?; + self.send_data(spi, black).await?; Ok(()) } - fn update_chromatic_frame( + async fn update_chromatic_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, chromatic: &[u8], ) -> Result<(), ::Error> { - self.command(spi, Command::WriteRedData)?; - self.send_data(spi, chromatic)?; + self.command(spi, Command::WriteRedData).await?; + self.send_data(spi, chromatic).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in9b where @@ -244,7 +247,7 @@ where { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -263,21 +266,21 @@ where background_color, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.command(spi, Command::DeepSleep)?; - self.send_data(spi, &[1])?; - delay.delay_ms(100); + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.command(spi, Command::DeepSleep).await?; + self.send_data(spi, &[1]).await?; + delay.delay_ms(100).await; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.init(spi, delay)?; + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.init(spi, delay).await?; Ok(()) } @@ -297,21 +300,23 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], _delay: &mut DELAY, ) -> Result<(), ::Error> { - self.command(spi, Command::WriteBlackData)?; - self.send_data(spi, buffer)?; + self.command(spi, Command::WriteBlackData).await?; + self.send_data(spi, buffer).await?; - self.command(spi, Command::WriteRedData)?; - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + self.command(spi, Command::WriteRedData).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -355,55 +360,60 @@ where let y_end_1 = y_end as u8; let y_end_2 = (y_end >> 8) as u8; - self.command(spi, Command::RamXPosition)?; - self.send_data(spi, &[x_start, x_end])?; - self.command(spi, Command::RamYPosition)?; - self.send_data(spi, &[y_start_1, y_start_2])?; - self.send_data(spi, &[y_end_1, y_end_2])?; + self.command(spi, Command::RamXPosition).await?; + self.send_data(spi, &[x_start, x_end]).await?; + self.command(spi, Command::RamYPosition).await?; + self.send_data(spi, &[y_start_1, y_start_2]).await?; + self.send_data(spi, &[y_end_1, y_end_2]).await?; - self.command(spi, Command::RamXAddressCount)?; - self.send_data(spi, &[x_start])?; - self.command(spi, Command::RamYAddressCount)?; - self.send_data(spi, &[y_start_1, y_start_2])?; + self.command(spi, Command::RamXAddressCount).await?; + self.send_data(spi, &[x_start]).await?; + self.command(spi, Command::RamYAddressCount).await?; + self.send_data(spi, &[y_start_1, y_start_2]).await?; - self.command(spi, Command::WriteBlackData)?; - self.send_data(spi, buffer)?; + self.command(spi, Command::WriteBlackData).await?; + self.send_data(spi, buffer).await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.turn_on_display(spi, delay, DisplayMode::Default)?; + async fn display_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.turn_on_display(spi, delay, DisplayMode::Default) + .await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), ::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<(), ::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { const SIZE: u32 = WIDTH / 8 * HEIGHT; - self.command(spi, Command::WriteBlackData)?; - self.interface.data_x_times(spi, 0xff, SIZE)?; + self.command(spi, Command::WriteBlackData).await?; + self.interface.data_x_times(spi, 0xff, SIZE).await?; - self.command(spi, Command::WriteRedData)?; - self.interface.data_x_times(spi, 0, SIZE)?; + self.command(spi, Command::WriteRedData).await?; + self.interface.data_x_times(spi, 0, SIZE).await?; - self.display_frame(spi, delay)?; + self.display_frame(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -412,8 +422,12 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 7a4ba92c..5c5439f1 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -54,9 +54,9 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -101,6 +101,7 @@ pub struct Epd2in9bc { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in9bc where @@ -110,40 +111,45 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd2in9bc where @@ -153,48 +159,53 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in9bc where @@ -205,7 +216,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -218,30 +229,32 @@ where let mut epd = Epd2in9bc { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Section 8.2 from datasheet - self.interface.cmd_with_data( - spi, - Command::VcomAndDataIntervalSetting, - &[FLOATING_BORDER | VCOM_DATA_INTERVAL], - )?; - - self.command(spi, Command::PowerOff)?; + self.interface + .cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[FLOATING_BORDER | VCOM_DATA_INTERVAL], + ) + .await?; + + self.command(spi, Command::PowerOff).await?; // The example STM code from Github has a wait after PowerOff - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -260,28 +273,34 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -294,43 +313,51 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.send_resolution(spi).await?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; // Clear the chromatic - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -339,12 +366,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd2in9bc where SPI: SpiDevice, @@ -353,36 +385,40 @@ where RST: OutputPin, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::ResolutionSetting)?; + self.command(spi, Command::ResolutionSetting).await?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } /// Set the outer border of the display to the chosen color. - pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> { + pub async fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), SPI::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, @@ -393,5 +429,6 @@ where Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], ) + .await } } diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index 50619060..7e4b2440 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -7,13 +7,9 @@ use core::slice::from_raw_parts; -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; //The Lookup Tables for the Display @@ -64,6 +60,7 @@ pub struct Epd2in9d<'a, SPI, BUSY, DC, RST, DELAY> { is_partial_refresh: bool, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where @@ -73,29 +70,33 @@ where RST: OutputPin, DELAY: DelayNs, { - 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; //panel setting //LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0x1f, 0x0D])?; + .cmd_with_data(spi, Command::PanelSetting, &[0x1f, 0x0D]) + .await?; //resolution setting self.interface - .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28]) + .await?; - self.interface.cmd(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; + self.interface.cmd(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; //VCOM AND DATA INTERVAL SETTING self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97]) + .await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where @@ -106,7 +107,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -127,26 +128,28 @@ where is_partial_refresh, }; - 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> { self.is_partial_refresh = false; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; - self.interface.cmd(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - delay.delay_us(100_000); + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7]) + .await?; + self.interface.cmd(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + delay.delay_us(100_000).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?; Ok(()) } @@ -168,7 +171,7 @@ where // Corresponds to the Display function. // Used to write the data to be displayed to the screen SRAM. - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -178,20 +181,23 @@ where // Modify local refresh status if full refresh is performed. self.is_partial_refresh = false; } - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0xFF, EPD_ARRAY)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data_x_times(spi, 0xFF, EPD_ARRAY).await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; self.old_data = unsafe { from_raw_parts(buffer.as_ptr(), buffer.len()) }; Ok(()) } // 这个是DisplayPart // Partial refresh write address and data - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -203,65 +209,74 @@ where ) -> Result<(), SPI::Error> { if !self.is_partial_refresh { // Initialize only on first call - self.set_part_reg(spi, delay)?; + self.set_part_reg(spi, delay).await?; self.is_partial_refresh = true; } - self.interface.cmd(spi, Command::PartialIn)?; + self.interface.cmd(spi, Command::PartialIn).await?; - self.interface.cmd(spi, Command::PartialWindow)?; - self.interface.data(spi, &[(x - x % 8) as u8])?; + self.interface.cmd(spi, Command::PartialWindow).await?; + self.interface.data(spi, &[(x - x % 8) as u8]).await?; self.interface - .data(spi, &[(((x - x % 8) + width - 1) - 1) as u8])?; - self.interface.data(spi, &[(y / 256) as u8])?; - self.interface.data(spi, &[(y % 256) as u8])?; + .data(spi, &[(((x - x % 8) + width - 1) - 1) as u8]) + .await?; + self.interface.data(spi, &[(y / 256) as u8]).await?; + self.interface.data(spi, &[(y % 256) as u8]).await?; self.interface - .data(spi, &[((y + height - 1) / 256) as u8])?; + .data(spi, &[((y + height - 1) / 256) as u8]) + .await?; self.interface - .data(spi, &[((y + height - 1) % 256 - 1) as u8])?; - self.interface.data(spi, &[0x28])?; + .data(spi, &[((y + height - 1) % 256 - 1) as u8]) + .await?; + self.interface.data(spi, &[0x28]).await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission1, self.old_data)?; + .cmd_with_data(spi, Command::DataStartTransmission1, self.old_data) + .await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; self.old_data = unsafe { from_raw_parts(buffer.as_ptr(), buffer.len()) }; Ok(()) } /// actually is the "Turn on Display" sequence - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DisplayRefresh)?; - delay.delay_us(1_000); - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::DisplayRefresh).await?; + delay.delay_us(1_000).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.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, EPD_ARRAY)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data_x_times(spi, 0x00, EPD_ARRAY).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0xFF, EPD_ARRAY)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data_x_times(spi, 0xFF, EPD_ARRAY).await?; - self.display_frame(spi, delay)?; + self.display_frame(spi, delay).await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -272,17 +287,23 @@ where } self.set_lut_helper( spi, delay, &LUT_VCOM1, &LUT_WW1, &LUT_BW1, &LUT_WB1, &LUT_BB1, - )?; + ) + .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(()) } } +#[maybe_async::maybe_async] impl Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where SPI: SpiDevice, @@ -297,8 +318,8 @@ where // /// Wake the screen. // fn awaken(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // // reset the device - // self.interface.reset(delay, 20_000, 2_000); - // self.wait_until_idle(spi, delay)?; + // self.interface.reset(delay, 20_000, 2_000).await; + // self.wait_until_idle(spi, delay).await?; // // panel setting // // LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f @@ -315,42 +336,45 @@ where // Ok(()) // } - fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the EPD driver circuit //TODO: 这里在微雪的例程中反复刷新了3次,后面有显示问题再进行修改 - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000).await; // Power settings //TODO: The data in the document is [0x03,0x00,0x2b,0x2b,0x09]. - self.interface.cmd_with_data( - spi, - Command::PowerSetting, - &[0x03, 0x00, 0x2b, 0x2b, 0x03], - )?; + self.interface + .cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x03]) + .await?; // Soft start self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // Panel settings self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0xbf, 0x0D])?; + .cmd_with_data(spi, Command::PanelSetting, &[0xbf, 0x0D]) + .await?; // Setting the refresh rate // 3a 100HZ | 29 150Hz | 39 200HZ | 31 171HZ // 3a is used in the example self.interface - .cmd_with_data(spi, Command::PllControl, &[0x3C])?; + .cmd_with_data(spi, Command::PllControl, &[0x3C]) + .await?; // Resolution Settings self.interface - .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28]) + .await?; // vcom_DC settings self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; // Power on // self.interface.cmd_with_data( @@ -358,11 +382,11 @@ where // Command::PowerOn, // &[0x04], // ); - self.interface.cmd(spi, Command::PowerOn)?; + self.interface.cmd(spi, Command::PowerOn).await?; // Get the BUSY level, high to continue, low to wait for the screen to respond. //TODO: This is the recommended step in the documentation, but I've ignored it since I've seen other screens that don't wait. - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // vcom and data interval settings // self.interface @@ -372,7 +396,7 @@ where } #[allow(clippy::too_many_arguments)] - fn set_lut_helper( + async fn set_lut_helper( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -385,23 +409,28 @@ where let _ = delay; // LUT VCOM self.interface - .cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; + .cmd_with_data(spi, Command::LutForVcom, lut_vcom) + .await?; // LUT WHITE to WHITE self.interface - .cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?; + .cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww) + .await?; // LUT BLACK to WHITE self.interface - .cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?; + .cmd_with_data(spi, Command::LutBlackToWhite, lut_bw) + .await?; // LUT WHITE to BLACK self.interface - .cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?; + .cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb) + .await?; // LUT BLACK to BLACK self.interface - .cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?; + .cmd_with_data(spi, Command::LutBlackToBlack, lut_bb) + .await?; Ok(()) } } diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c01c49fa..00155d76 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -2,11 +2,7 @@ //! //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; pub(crate) mod command; mod constants; @@ -16,7 +12,7 @@ use self::constants::*; use crate::buffer_len; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; /// Width of the display. @@ -50,6 +46,7 @@ pub struct EPD3in7 { background_color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for EPD3in7 where @@ -59,70 +56,89 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 30, 10); + self.interface.reset(delay, 30, 10).await; - self.interface.cmd(spi, Command::SwReset)?; - delay.delay_us(300000u32); + self.interface.cmd(spi, Command::SwReset).await?; + delay.delay_us(300000u32).await; self.interface - .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7])?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + .cmd_with_data(spi, Command::AutoWriteRedRamRegularPattern, &[0xF7]) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; self.interface - .cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7])?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + .cmd_with_data(spi, Command::AutoWriteBwRamRegularPattern, &[0xF7]) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; self.interface - .cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00])?; + .cmd_with_data(spi, Command::GateSetting, &[0xDF, 0x01, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::GateVoltage, &[0x00])?; + .cmd_with_data(spi, Command::GateVoltage, &[0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32])?; + .cmd_with_data(spi, Command::GateVoltageSource, &[0x41, 0xA8, 0x32]) + .await?; self.interface - .cmd_with_data(spi, Command::DataEntrySequence, &[0x03])?; + .cmd_with_data(spi, Command::DataEntrySequence, &[0x03]) + .await?; self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x03])?; + .cmd_with_data(spi, Command::BorderWaveformControl, &[0x03]) + .await?; - self.interface.cmd_with_data( - spi, - Command::BoosterSoftStartControl, - &[0xAE, 0xC7, 0xC3, 0xC0, 0xC0], - )?; + self.interface + .cmd_with_data( + spi, + Command::BoosterSoftStartControl, + &[0xAE, 0xC7, 0xC3, 0xC0, 0xC0], + ) + .await?; + + self.interface + .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80]) + .await?; self.interface - .cmd_with_data(spi, Command::TemperatureSensorSelection, &[0x80])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[0x44])?; - - self.interface.cmd_with_data( - spi, - Command::DisplayOption, - &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF], - )?; - - self.interface.cmd_with_data( - spi, - Command::SetRamXAddressStartEndPosition, - &[0x00, 0x00, 0x17, 0x01], - )?; - self.interface.cmd_with_data( - spi, - Command::SetRamYAddressStartEndPosition, - &[0x00, 0x00, 0xDF, 0x01], - )?; + .cmd_with_data( + spi, + Command::DisplayOption, + &[0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x4F, 0xFF, 0xFF, 0xFF, 0xFF], + ) + .await?; + + self.interface + .cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[0x00, 0x00, 0x17, 0x01], + ) + .await?; + self.interface + .cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[0x00, 0x00, 0xDF, 0x01], + ) + .await?; self.interface - .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF])?; + .cmd_with_data(spi, Command::DisplayUpdateSequenceSetting, &[0xCF]) + .await?; - self.set_lut(spi, delay, Some(RefreshLut::Full))?; + self.set_lut(spi, delay, Some(RefreshLut::Full)).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for EPD3in7 where @@ -134,7 +150,7 @@ where { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -147,19 +163,22 @@ where background_color: DEFAULT_BACKGROUND_COLOR, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, Command::Sleep, &[0xF7])?; - self.interface.cmd(spi, Command::PowerOff)?; + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::Sleep2, &[0xA5])?; + .cmd_with_data(spi, Command::Sleep, &[0xF7]) + .await?; + self.interface.cmd(spi, Command::PowerOff).await?; + self.interface + .cmd_with_data(spi, Command::Sleep2, &[0xA5]) + .await?; Ok(()) } @@ -179,7 +198,7 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -187,18 +206,21 @@ where ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::WriteRam, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer) + .await?; Ok(()) } #[allow(unused)] - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -211,39 +233,45 @@ where todo!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { //self.interface // .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, &LUT_1GRAY_GC)?; - self.interface.cmd(spi, Command::DisplayUpdateSequence)?; - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + self.interface + .cmd(spi, Command::DisplayUpdateSequence) + .await?; + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00]) + .await?; self.interface - .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00])?; + .cmd_with_data(spi, Command::SetRamYAddressCounter, &[0x00, 0x00]) + .await?; let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WriteRam)?; - self.interface.data_x_times(spi, color, WIDTH * HEIGHT)?; + self.interface.cmd(spi, Command::WriteRam).await?; + self.interface + .data_x_times(spi, color, WIDTH * HEIGHT) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, _delay: &mut DELAY, @@ -255,12 +283,17 @@ where }; self.interface - .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer) + .await?; Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle(delay, IS_BUSY_LOW); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW).await; Ok(()) } } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 6de676e6..cf6d8e73 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -49,9 +49,9 @@ //! //! 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::*; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; //The Lookup Tables for the Display @@ -94,6 +94,7 @@ pub struct Epd4in2 { refresh: RefreshLut, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd4in2 where @@ -103,51 +104,55 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000).await; // set the power settings - self.interface.cmd_with_data( - spi, - Command::PowerSetting, - &[0x03, 0x00, 0x2b, 0x2b, 0xff], - )?; + self.interface + .cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0xff]) + .await?; // start the booster self.interface - .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17]) + .await?; // power on - self.command(spi, Command::PowerOn)?; - delay.delay_us(5000); - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOn).await?; + delay.delay_us(5000).await; + self.wait_until_idle(spi, delay).await?; // set the panel settings - self.cmd_with_data(spi, Command::PanelSetting, &[0x3F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x3F]) + .await?; // Set Frequency, 200 Hz didn't work on my board // 150Hz and 171Hz wasn't tested yet // TODO: Test these other frequencies // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz - self.cmd_with_data(spi, Command::PllControl, &[0x3A])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3A]) + .await?; - self.send_resolution(spi)?; + self.send_resolution(spi).await?; self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12]) + .await?; //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97]) + .await?; - self.set_lut(spi, delay, None)?; + self.set_lut(spi, delay, None).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd4in2 where @@ -158,7 +163,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -175,32 +180,34 @@ where refresh: RefreshLut::Full, }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating - self.command(spi, Command::VcmDcSetting)?; // VCOM to 0V - self.command(spi, Command::PanelSetting)?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17]) + .await?; //border floating + self.command(spi, Command::VcmDcSetting).await?; // VCOM to 0V + self.command(spi, Command::PanelSetting).await?; - self.command(spi, Command::PowerSetting)?; //VG&VS to 0V fast + self.command(spi, Command::PowerSetting).await?; //VG&VS to 0V fast for _ in 0..4 { - self.send_data(spi, &[0x00])?; + self.send_data(spi, &[0x00]).await?; } - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; self.interface - .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + .await?; Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Color) { @@ -219,25 +226,29 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -247,77 +258,84 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.command(spi, Command::PartialIn)?; - self.command(spi, Command::PartialWindow)?; - self.send_data(spi, &[(x >> 8) as u8])?; + self.command(spi, Command::PartialIn).await?; + self.command(spi, Command::PartialWindow).await?; + self.send_data(spi, &[(x >> 8) as u8]).await?; let tmp = x & 0xf8; - self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored + self.send_data(spi, &[tmp as u8]).await?; // x should be the multiple of 8, the last 3 bit will always be ignored let tmp = tmp + width - 1; - self.send_data(spi, &[(tmp >> 8) as u8])?; - self.send_data(spi, &[(tmp | 0x07) as u8])?; + self.send_data(spi, &[(tmp >> 8) as u8]).await?; + self.send_data(spi, &[(tmp | 0x07) as u8]).await?; - self.send_data(spi, &[(y >> 8) as u8])?; - self.send_data(spi, &[y as u8])?; + self.send_data(spi, &[(y >> 8) as u8]).await?; + self.send_data(spi, &[y as u8]).await?; - self.send_data(spi, &[((y + height - 1) >> 8) as u8])?; - self.send_data(spi, &[(y + height - 1) as u8])?; + self.send_data(spi, &[((y + height - 1) >> 8) as u8]) + .await?; + self.send_data(spi, &[(y + height - 1) as u8]).await?; - self.send_data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + self.send_data(spi, &[0x01]).await?; // Gates scan both inside and outside of the partial window. (default) //TODO: handle dtm somehow let is_dtm1 = false; if is_dtm1 { - self.command(spi, Command::DataStartTransmission1)? //TODO: check if data_start transmission 1 also needs "old"/background data here + self.command(spi, Command::DataStartTransmission1).await? //TODO: check if data_start transmission 1 also needs "old"/background data here } else { - self.command(spi, Command::DataStartTransmission2)? + self.command(spi, Command::DataStartTransmission2).await? } - self.send_data(spi, buffer)?; + self.send_data(spi, buffer).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -340,14 +358,20 @@ where &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(()) } } +#[maybe_async::maybe_async] impl Epd4in2 where SPI: SpiDevice, @@ -356,36 +380,36 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 +419,32 @@ where lut_wb: &[u8], lut_bb: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; // LUT VCOM - self.cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; + self.cmd_with_data(spi, Command::LutForVcom, lut_vcom) + .await?; // LUT WHITE to WHITE - self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?; + self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww) + .await?; // LUT BLACK to WHITE - self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?; + self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw) + .await?; // LUT WHITE to BLACK - self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?; + self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb) + .await?; // LUT BLACK to BLACK - self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?; + self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb) + .await?; Ok(()) } /// Helper function. Sets up the display to send pixel data to a custom /// starting point. - pub fn shift_display( + pub async fn shift_display( &mut self, spi: &mut SPI, x: u32, @@ -423,25 +452,27 @@ 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl QuickRefresh for Epd4in2 where @@ -452,59 +483,67 @@ where DELAY: DelayNs, { /// To be followed immediately after by `update_old_frame`. - fn update_old_frame( + async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// To be used immediately after `update_old_frame`. - fn update_new_frame( + async fn update_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - // self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + // self.send_resolution(spi).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// This is a wrapper around `display_frame` for using this device as a true /// `QuickRefresh` device. - fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.display_frame(spi, delay) + async fn display_new_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.display_frame(spi, delay).await } /// This is wrapper around `update_new_frame` and `display_frame` for using /// this device as a true `QuickRefresh` device. /// /// To be used immediately after `update_old_frame`. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_new_frame(spi, buffer, delay)?; - self.display_frame(spi, delay) + self.update_new_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await } - fn update_partial_old_frame( + async fn update_partial_old_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -514,28 +553,30 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.interface.cmd(spi, Command::PartialIn)?; - self.interface.cmd(spi, Command::PartialWindow)?; + self.interface.cmd(spi, Command::PartialIn).await?; + self.interface.cmd(spi, Command::PartialWindow).await?; - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; Ok(()) } /// Always call `update_partial_old_frame` before this, with buffer-updating code /// between the calls. - fn update_partial_new_frame( + async fn update_partial_new_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -545,23 +586,25 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); } - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; - self.interface.data(spi, buffer)?; + self.interface.data(spi, buffer).await?; - self.interface.cmd(spi, Command::PartialOut)?; + self.interface.cmd(spi, Command::PartialOut).await?; Ok(()) } - fn clear_partial_frame( + async fn clear_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -570,25 +613,31 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::PartialIn)?; - self.interface.cmd(spi, Command::PartialWindow)?; + self.interface.cmd(spi, Command::PartialIn).await?; + self.interface.cmd(spi, Command::PartialWindow).await?; - self.shift_display(spi, x, y, width, height)?; + self.shift_display(spi, x, y, width, height).await?; - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, width / 8 * height) + .await?; - self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, width / 8 * height)?; + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface + .data_x_times(spi, color_value, width / 8 * height) + .await?; - self.interface.cmd(spi, Command::PartialOut)?; + self.interface.cmd(spi, Command::PartialOut).await?; Ok(()) } } diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 1a70b78a..9dafa513 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -6,14 +6,10 @@ //! - [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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::OctColor; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; @@ -48,6 +44,7 @@ pub struct Epd5in65f { color: OctColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd5in65f where @@ -57,29 +54,37 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); - - self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23])?; - self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00])?; - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?; - self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; - self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00])?; - self.update_vcom(spi)?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.send_resolution(spi)?; - - self.cmd_with_data(spi, Command::FlashMode, &[0xAA])?; - - delay.delay_us(100_000); - - self.update_vcom(spi)?; + self.interface.reset(delay, 10_000, 2_000).await; + + self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08]) + .await?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23]) + .await?; + self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00]) + .await?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D]) + .await?; + self.cmd_with_data(spi, Command::PllControl, &[0x3C]) + .await?; + self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00]) + .await?; + self.update_vcom(spi).await?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; + self.send_resolution(spi).await?; + + self.cmd_with_data(spi, Command::FlashMode, &[0xAA]).await?; + + delay.delay_us(100_000).await; + + self.update_vcom(spi).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd5in65f where @@ -90,7 +95,7 @@ where DELAY: DelayNs, { type DisplayColor = OctColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -103,34 +108,35 @@ where let mut epd = Epd5in65f { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.update_vcom(spi)?; - self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.update_vcom(spi).await?; + self.send_resolution(spi).await?; + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -143,36 +149,38 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_busy_low(delay); + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOn).await?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_busy_low(delay).await; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let bg = OctColor::colors_byte(self.color, self.color); - self.wait_until_idle(spi, delay)?; - self.update_vcom(spi)?; - self.send_resolution(spi)?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; - self.display_frame(spi, delay)?; + self.wait_until_idle(spi, delay).await?; + self.update_vcom(spi).await?; + self.send_resolution(spi).await?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, bg, WIDTH * HEIGHT / 2) + .await?; + self.display_frame(spi, delay).await?; Ok(()) } @@ -192,7 +200,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -201,12 +209,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd5in65f where SPI: SpiDevice, @@ -215,40 +228,41 @@ where RST: OutputPin, DELAY: DelayNs, { - 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/epd5in83_v2/mod.rs b/src/epd5in83_v2/mod.rs index 58909b2c..28caad3c 100644 --- a/src/epd5in83_v2/mod.rs +++ b/src/epd5in83_v2/mod.rs @@ -6,14 +6,10 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_5in83_V2.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83_V2.py) -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::prelude::WaveshareDisplay; use crate::traits::{InternalWiAdditions, RefreshLut}; @@ -50,6 +46,7 @@ pub struct Epd5in83 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd5in83 where @@ -59,38 +56,43 @@ where RST: OutputPin, DELAY: DelayNs, { - 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, 2000, 50); + self.interface.reset(delay, 2000, 50).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: BWOTP - self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x1F]) + .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, &[0x10, 0x07])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd5in83 where @@ -101,7 +103,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -114,21 +116,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) { @@ -147,25 +149,29 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT) + .await?; self.interface - .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -178,36 +184,40 @@ 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?; - 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, @@ -216,12 +226,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd5in83 where SPI: SpiDevice, @@ -230,32 +245,32 @@ where RST: OutputPin, DELAY: DelayNs, { - 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/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index 625b1e7c..7138018f 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -6,14 +6,10 @@ //! - [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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::prelude::{TriColor, WaveshareDisplay, WaveshareThreeColorDisplay}; use crate::traits::{InternalWiAdditions, RefreshLut}; @@ -50,6 +46,7 @@ pub struct Epd5in83 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd5in83 where @@ -59,41 +56,47 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd5in83 where @@ -103,41 +106,44 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd5in83 where @@ -148,7 +154,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -161,21 +167,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 +200,23 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.update_achromatic_frame(spi, delay, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.update_achromatic_frame(spi, delay, buffer).await?; let color = self.color.get_byte_value(); - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, color, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -218,7 +226,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 +241,67 @@ where let vred_lower = (y + height) as u8; let pt_scan = 0x01; // Gates scan both inside and outside of the partial window. (default) - self.command(spi, Command::PartialIn)?; - self.command(spi, Command::PartialWindow)?; + self.command(spi, Command::PartialIn).await?; + self.command(spi, Command::PartialWindow).await?; self.send_data( spi, &[ hrst_upper, hrst_lower, hred_upper, hred_lower, vrst_upper, vrst_lower, vred_upper, vred_lower, pt_scan, ], - )?; - self.command(spi, Command::DataStartTransmission1)?; - self.send_data(spi, buffer)?; + ) + .await?; + self.command(spi, Command::DataStartTransmission1).await?; + self.send_data(spi, buffer).await?; let color = TriColor::Black.get_byte_value(); //We need it black, so red channel will be rendered transparent - self.command(spi, Command::DataStartTransmission2)?; + self.command(spi, Command::DataStartTransmission2).await?; self.interface - .data_x_times(spi, color, width * height / 8)?; + .data_x_times(spi, color, width * height / 8) + .await?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; // The Waveshare controllers all implement clear using 0x33 - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0xFF, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0xFF, NUM_DISPLAY_BITS) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, NUM_DISPLAY_BITS)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, NUM_DISPLAY_BITS) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -296,12 +310,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd5in83 where SPI: SpiDevice, @@ -310,32 +329,32 @@ where RST: OutputPin, DELAY: DelayNs, { - 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/epd7in3f/mod.rs b/src/epd7in3f/mod.rs index 11a733df..98f6c2d5 100644 --- a/src/epd7in3f/mod.rs +++ b/src/epd7in3f/mod.rs @@ -6,16 +6,12 @@ //! - [Waveshare C driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_7in3f.c) //! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in3f.py) -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::{ buffer_len, color::OctColor, - interface::DisplayInterface, + interface::{DelayNs, DisplayInterface, SpiDevice}, traits::{InternalWiAdditions, WaveshareDisplay}, }; @@ -50,6 +46,7 @@ pub struct Epd7in3f { color: OctColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd7in3f where @@ -59,33 +56,43 @@ where RST: OutputPin, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.interface.reset(delay, 20_000, 2_000); - self.wait_busy_low(delay); - delay.delay_ms(30); - - self.cmd_with_data(spi, Command::CMDH, &[0x49, 0x55, 0x20, 0x08, 0x09, 0x18])?; - self.cmd_with_data(spi, Command::Ox01, &[0x3F, 0x00, 0x32, 0x2A, 0x0E, 0x2A])?; - self.cmd_with_data(spi, Command::Ox00, &[0x5F, 0x69])?; - self.cmd_with_data(spi, Command::Ox03, &[0x00, 0x54, 0x00, 0x44])?; - self.cmd_with_data(spi, Command::Ox05, &[0x40, 0x1F, 0x1F, 0x2C])?; - self.cmd_with_data(spi, Command::Ox06, &[0x6F, 0x1F, 0x1F, 0x22])?; - self.cmd_with_data(spi, Command::Ox08, &[0x6F, 0x1F, 0x1F, 0x22])?; - self.cmd_with_data(spi, Command::IPC, &[0x00, 0x04])?; - self.cmd_with_data(spi, Command::Ox30, &[0x3C])?; - self.cmd_with_data(spi, Command::TSE, &[0x00])?; - self.cmd_with_data(spi, Command::Ox50, &[0x3F])?; - self.cmd_with_data(spi, Command::Ox60, &[0x02, 0x00])?; - self.cmd_with_data(spi, Command::Ox61, &[0x03, 0x20, 0x01, 0xE0])?; - self.cmd_with_data(spi, Command::Ox82, &[0x1E])?; - self.cmd_with_data(spi, Command::Ox84, &[0x00])?; - self.cmd_with_data(spi, Command::AGID, &[0x00])?; - self.cmd_with_data(spi, Command::OxE3, &[0x2F])?; - self.cmd_with_data(spi, Command::CCSET, &[0x00])?; - self.cmd_with_data(spi, Command::TSSET, &[0x00]) + async fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.interface.reset(delay, 20_000, 2_000).await; + self.wait_busy_low(delay).await; + delay.delay_ms(30).await; + + self.cmd_with_data(spi, Command::CMDH, &[0x49, 0x55, 0x20, 0x08, 0x09, 0x18]) + .await?; + self.cmd_with_data(spi, Command::Ox01, &[0x3F, 0x00, 0x32, 0x2A, 0x0E, 0x2A]) + .await?; + self.cmd_with_data(spi, Command::Ox00, &[0x5F, 0x69]) + .await?; + self.cmd_with_data(spi, Command::Ox03, &[0x00, 0x54, 0x00, 0x44]) + .await?; + self.cmd_with_data(spi, Command::Ox05, &[0x40, 0x1F, 0x1F, 0x2C]) + .await?; + self.cmd_with_data(spi, Command::Ox06, &[0x6F, 0x1F, 0x1F, 0x22]) + .await?; + self.cmd_with_data(spi, Command::Ox08, &[0x6F, 0x1F, 0x1F, 0x22]) + .await?; + self.cmd_with_data(spi, Command::IPC, &[0x00, 0x04]).await?; + self.cmd_with_data(spi, Command::Ox30, &[0x3C]).await?; + self.cmd_with_data(spi, Command::TSE, &[0x00]).await?; + self.cmd_with_data(spi, Command::Ox50, &[0x3F]).await?; + self.cmd_with_data(spi, Command::Ox60, &[0x02, 0x00]) + .await?; + self.cmd_with_data(spi, Command::Ox61, &[0x03, 0x20, 0x01, 0xE0]) + .await?; + self.cmd_with_data(spi, Command::Ox82, &[0x1E]).await?; + self.cmd_with_data(spi, Command::Ox84, &[0x00]).await?; + self.cmd_with_data(spi, Command::AGID, &[0x00]).await?; + self.cmd_with_data(spi, Command::OxE3, &[0x2F]).await?; + self.cmd_with_data(spi, Command::CCSET, &[0x00]).await?; + self.cmd_with_data(spi, Command::TSSET, &[0x00]).await } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd7in3f where @@ -97,7 +104,7 @@ where { type DisplayColor = OctColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -113,17 +120,17 @@ where let mut epd = Epd7in3f { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), ::Error> { - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + async fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), ::Error> { + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.init(spi, delay).await } fn set_background_color(&mut self, color: Self::DisplayColor) { @@ -142,17 +149,18 @@ where HEIGHT } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), ::Error> { - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; self.cmd_with_data(spi, Command::DataStartTransmission, buffer) + .await } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -165,40 +173,46 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.command(spi, Command::PowerOn)?; - self.wait_busy_low(delay); + async fn display_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.command(spi, Command::PowerOn).await?; + self.wait_busy_low(delay).await; - self.cmd_with_data(spi, Command::DataFresh, &[0x00])?; - self.wait_busy_low(delay); + self.cmd_with_data(spi, Command::DataFresh, &[0x00]).await?; + self.wait_busy_low(delay).await; - self.cmd_with_data(spi, Command::PowerOff, &[0x00])?; - self.wait_busy_low(delay); + self.cmd_with_data(spi, Command::PowerOff, &[0x00]).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<(), ::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 } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { let bg = OctColor::colors_byte(self.color, self.color); - self.wait_busy_low(delay); - self.command(spi, Command::DataStartTransmission)?; - self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; + self.wait_busy_low(delay).await; + self.command(spi, Command::DataStartTransmission).await?; + self.interface + .data_x_times(spi, bg, WIDTH * HEIGHT / 2) + .await?; - self.display_frame(spi, delay) + self.display_frame(spi, delay).await } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -207,12 +221,17 @@ where unimplemented!() } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.wait_busy_low(delay); + async fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.wait_busy_low(delay).await; Ok(()) } } +#[maybe_async::maybe_async] impl Epd7in3f where SPI: SpiDevice, @@ -221,25 +240,29 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 } - fn wait_busy_low(&mut self, delay: &mut DELAY) { - self.interface.wait_until_idle(delay, true); + async fn wait_busy_low(&mut self, delay: &mut DELAY) { + self.interface.wait_until_idle(delay, true).await; } /// Show 7 blocks of color, used for quick testing - pub fn show_7block(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + pub async fn show_7block( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { let color_7 = [ OctColor::Black, OctColor::White, @@ -251,12 +274,13 @@ where OctColor::White, ]; - self.command(spi, Command::DataStartTransmission)?; + self.command(spi, Command::DataStartTransmission).await?; for _ in 0..240 { for color in color_7.iter().take(4) { for _ in 0..100 { self.interface - .data(spi, &[OctColor::colors_byte(*color, *color)])?; + .data(spi, &[OctColor::colors_byte(*color, *color)]) + .await?; } } } @@ -265,11 +289,12 @@ where for color in color_7.iter().skip(4) { for _ in 0..100 { self.interface - .data(spi, &[OctColor::colors_byte(*color, *color)])?; + .data(spi, &[OctColor::colors_byte(*color, *color)]) + .await?; } } } - self.display_frame(spi, delay) + self.display_frame(spi, delay).await } } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 121b780d..6c7efd85 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -6,14 +6,10 @@ //! - [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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; @@ -48,6 +44,7 @@ pub struct Epd7in5 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd7in5 where @@ -57,52 +54,61 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd7in5 where @@ -113,7 +119,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,21 +132,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 +165,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 +181,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 +200,36 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; // The Waveshare controllers all implement clear using 0x33 - self.command(spi, Command::DataStartTransmission1)?; + self.command(spi, Command::DataStartTransmission1).await?; self.interface - .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?; + .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4) + .await?; Ok(()) } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -231,12 +238,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd7in5 where SPI: SpiDevice, @@ -245,32 +257,32 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 f78df1f2..9d2c7ca9 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -9,14 +9,10 @@ //! - [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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; @@ -51,6 +47,7 @@ pub struct Epd7in5 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd7in5 where @@ -60,49 +57,61 @@ where RST: OutputPin, DELAY: DelayNs, { - 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd7in5 where @@ -113,7 +122,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -126,35 +135,37 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0x01]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; - self.cmd_with_data(spi, Command::WriteRamBw, buffer)?; - self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00]) + .await?; + self.cmd_with_data(spi, Command::WriteRamBw, buffer).await?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7]) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -167,39 +178,42 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.command(spi, Command::MasterActivation)?; - self.wait_until_idle(spi, delay)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::MasterActivation).await?; + self.wait_until_idle(spi, delay).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.display_frame(spi, delay)?; + self.update_frame(spi, buffer, delay).await?; + self.display_frame(spi, delay).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let pixel_count = WIDTH / 8 * HEIGHT; 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 +233,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -228,12 +242,17 @@ 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(()) } } +#[maybe_async::maybe_async] impl Epd7in5 where SPI: SpiDevice, @@ -242,17 +261,17 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 8d0d45f3..ba60fde9 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -10,14 +10,10 @@ //! 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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::Color; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; @@ -52,6 +48,7 @@ pub struct Epd7in5 { color: Color, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd7in5 where @@ -61,29 +58,36 @@ where RST: OutputPin, DELAY: DelayNs, { - 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::PowerSetting, &[0x07, 0x07, 0x3f, 0x3f])?; - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x28, 0x17])?; - self.command(spi, Command::PowerOn)?; - delay.delay_ms(100); - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; - 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, &[0x10, 0x07])?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3f, 0x3f]) + .await?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x28, 0x17]) + .await?; + self.command(spi, Command::PowerOn).await?; + delay.delay_ms(100).await; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x1F]) + .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, &[0x10, 0x07]) + .await?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22]) + .await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd7in5 where @@ -94,7 +98,7 @@ where DELAY: DelayNs, { type DisplayColor = Color; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -107,35 +111,36 @@ where let mut epd = Epd7in5 { interface, color }; - epd.init(spi, delay)?; + epd.init(spi, delay).await?; Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) + async fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay).await } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + async fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::PowerOff).await?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]).await?; Ok(()) } - fn update_frame( + async fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.wait_until_idle(spi, delay).await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer) + .await?; Ok(()) } - fn update_partial_frame( + async fn update_partial_frame( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -148,34 +153,38 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + async fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn update_and_display_frame( + async fn update_and_display_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.update_frame(spi, buffer, delay).await?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; + async fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay).await?; + self.send_resolution(spi).await?; - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT) + .await?; - self.command(spi, Command::DisplayRefresh)?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -195,7 +204,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -204,12 +213,18 @@ where unimplemented!(); } - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn wait_until_idle( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .await } } +#[maybe_async::maybe_async] impl Epd7in5 where SPI: SpiDevice, @@ -218,32 +233,32 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 69963c57..d0f074a8 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -10,14 +10,10 @@ //! 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::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::digital::{InputPin, OutputPin}; use crate::color::TriColor; -use crate::interface::DisplayInterface; +use crate::interface::{DelayNs, DisplayInterface, SpiDevice}; use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; @@ -57,6 +53,7 @@ pub struct Epd7in5 { color: TriColor, } +#[maybe_async::maybe_async(AFIT)] impl InternalWiAdditions for Epd7in5 where @@ -66,28 +63,31 @@ where RST: OutputPin, DELAY: DelayNs, { - 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 @@ -96,16 +96,20 @@ 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(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareThreeColorDisplay for Epd7in5 where @@ -115,50 +119,55 @@ where RST: OutputPin, DELAY: DelayNs, { - 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::DataStop)?; + self.interface + .cmd(spi, Command::DataStartTransmission1) + .await?; + self.interface.data(spi, black).await?; + self.interface.cmd(spi, Command::DataStop).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::DataStop)?; + self.interface + .cmd(spi, Command::DataStartTransmission2) + .await?; + self.interface.data(spi, chromatic).await?; + self.interface.cmd(spi, Command::DataStop).await?; - self.wait_until_idle(spi, delay)?; + self.wait_until_idle(spi, delay).await?; Ok(()) } } +#[maybe_async::maybe_async(AFIT)] impl WaveshareDisplay for Epd7in5 where @@ -169,7 +178,7 @@ where DELAY: DelayNs, { type DisplayColor = TriColor; - fn new( + async fn new( spi: &mut SPI, busy: BUSY, dc: DC, @@ -182,46 +191,48 @@ 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_BITS], - )?; + ) + .await?; self.cmd_with_data( spi, Command::DataStartTransmission2, &buffer[NUM_DISPLAY_BITS..], - )?; - self.interface.cmd(spi, Command::DataStop)?; + ) + .await?; + 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, @@ -234,36 +245,40 @@ 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 / 8 * HEIGHT)?; + self.command(spi, Command::DataStartTransmission1).await?; + self.interface + .data_x_times(spi, 0xFF, WIDTH / 8 * HEIGHT) + .await?; - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + self.command(spi, Command::DataStartTransmission2).await?; + self.interface + .data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT) + .await?; - self.interface.cmd(spi, Command::DataStop)?; + self.interface.cmd(spi, Command::DataStop).await?; - self.command(spi, Command::DisplayRefresh)?; + self.command(spi, Command::DisplayRefresh).await?; Ok(()) } @@ -284,7 +299,7 @@ where HEIGHT } - fn set_lut( + async fn set_lut( &mut self, _spi: &mut SPI, _delay: &mut DELAY, @@ -294,12 +309,18 @@ where } /// wait - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + async fn wait_until_idle( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) + .await } } +#[maybe_async::maybe_async] impl Epd7in5 where SPI: SpiDevice, @@ -310,7 +331,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], @@ -320,7 +341,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 } @@ -335,7 +356,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, @@ -343,44 +364,47 @@ where hrst_upper, hrst_lower, hred_upper, hred_lower, vrst_upper, vrst_lower, vred_upper, vred_lower, pt_scan, ], - )?; + ) + .await?; let half = buffer.len() / 2; - self.cmd_with_data(spi, Command::DataStartTransmission1, &buffer[..half])?; - self.cmd_with_data(spi, Command::DataStartTransmission2, &buffer[half..])?; + self.cmd_with_data(spi, Command::DataStartTransmission1, &buffer[..half]) + .await?; + self.cmd_with_data(spi, Command::DataStartTransmission2, &buffer[half..]) + .await?; - self.command(spi, Command::DisplayRefresh)?; - self.wait_until_idle(spi, delay)?; + self.command(spi, Command::DisplayRefresh).await?; + self.wait_until_idle(spi, delay).await?; - self.command(spi, Command::PartialOut)?; + self.command(spi, Command::PartialOut).await?; Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) + async fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command).await } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) + async fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data).await } - fn cmd_with_data( + async fn cmd_with_data( &mut self, spi: &mut SPI, command: Command, data: &[u8], ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) + self.interface.cmd_with_data(spi, command, data).await } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + async fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) + self.command(spi, Command::TconResolution).await?; + self.send_data(spi, &[(w >> 8) as u8]).await?; + self.send_data(spi, &[w as u8]).await?; + self.send_data(spi, &[(h >> 8) as u8]).await?; + self.send_data(spi, &[h as u8]).await } } diff --git a/src/interface.rs b/src/interface.rs index f3a9a3d7..14d52dde 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,6 +1,18 @@ use crate::traits::Command; use core::marker::PhantomData; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; + +#[cfg(not(feature = "async"))] +pub use embedded_hal::{ + delay::DelayNs, + spi::{SpiBus, SpiDevice}, +}; + +#[cfg(feature = "async")] +pub use embedded_hal_async::{ + delay::DelayNs, + spi::{SpiBus, SpiDevice}, +}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// @@ -21,6 +33,8 @@ pub(crate) struct DisplayInterface DisplayInterface where @@ -49,28 +63,32 @@ where /// Basic function for sending [Commands](Command). /// /// Enables direct interaction with the device with the help of [data()](DisplayInterface::data()) - pub(crate) fn cmd(&mut self, spi: &mut SPI, command: T) -> Result<(), SPI::Error> { + pub(crate) async fn cmd( + &mut self, + spi: &mut SPI, + command: T, + ) -> Result<(), SPI::Error> { // low for commands let _ = self.dc.set_low(); // Transfer the command over spi - self.write(spi, &[command.address()]) + self.write(spi, &[command.address()]).await } /// Basic function for sending an array of u8-values of data over spi /// /// Enables direct interaction with the device with the help of [command()](Epd4in2::command()) - pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + pub(crate) async fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { // high for data let _ = self.dc.set_high(); if SINGLE_BYTE_WRITE { for val in data.iter().copied() { // Transfer data one u8 at a time over spi - self.write(spi, &[val])?; + self.write(spi, &[val]).await?; } } else { - self.write(spi, data)?; + self.write(spi, data).await?; } Ok(()) @@ -79,20 +97,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 +120,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,8 +152,8 @@ 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) { - while self.is_busy(is_busy_low) { + pub(crate) async fn wait_until_idle(&mut self, delay: &mut DELAY, is_busy_low: bool) { + while self.is_busy(is_busy_low).await { // This has been removed and added many time : // - it is faster to not have it // - it is complicated to pass the delay everywhere all the time @@ -143,27 +161,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)?; + while self.is_busy(is_busy_low).await { + 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(()) @@ -182,7 +200,7 @@ where /// /// Most likely there was a mistake with the 2in9 busy connection /// //TODO: use the #cfg feature to make this compile the right way for the certain types - pub(crate) fn is_busy(&mut self, is_busy_low: bool) -> bool { + pub(crate) async fn is_busy(&mut self, is_busy_low: bool) -> bool { (is_busy_low && self.busy.is_low().unwrap_or(false)) || (!is_busy_low && self.busy.is_high().unwrap_or(false)) } @@ -194,15 +212,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 3ef7291a..f0e257c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,14 @@ //!# } //!``` //! +//! # Async Support +//! +//! Enabling the `async` feature will switch all relevant functions in the API to async functions. +//! +//! Additionally the Delay and Spi traits from [`embedded-hal-async`] will be used. +//! +//! [`embedded-hal-async`]: https://docs.rs/embedded-hal-async +//! //! # Other information and requirements //! //! - Buffersize: Wherever a buffer is used it always needs to be of the size: `width / 8 * length`, diff --git a/src/traits.rs b/src/traits.rs index abd2b3f9..8f4fcc2b 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,5 +1,6 @@ +use crate::interface::{DelayNs, SpiDevice}; use core::marker::Sized; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::digital::*; /// 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) @@ -18,6 +19,7 @@ pub enum RefreshLut { Quick, } +#[maybe_async::maybe_async(AFIT)] pub(crate) trait InternalWiAdditions where SPI: SpiDevice, @@ -36,10 +38,12 @@ 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 +#[maybe_async::maybe_async(AFIT)] +#[allow(async_fn_in_trait)] pub trait WaveshareThreeColorDisplay: WaveshareDisplay where @@ -52,7 +56,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 +67,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 +78,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, @@ -144,6 +148,8 @@ where /// .into_styled(PrimitiveStyle::with_stroke(Color::Black, 1)) /// .draw(&mut *display); ///``` +#[maybe_async::maybe_async(AFIT)] +#[allow(async_fn_in_trait)] pub trait WaveshareDisplay where SPI: SpiDevice, @@ -161,7 +167,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, @@ -175,12 +181,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); @@ -195,7 +201,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], @@ -208,7 +214,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, @@ -222,10 +228,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], @@ -235,7 +241,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 @@ -245,7 +251,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, @@ -255,7 +261,8 @@ where /// Wait until the display has stopped processing data /// /// You can call this to make sure a frame is displayed before goin further - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) + -> Result<(), SPI::Error>; } /// Allows quick refresh support for displays that support it; lets you send both @@ -303,6 +310,8 @@ where ///# Ok(()) ///# } ///``` +#[maybe_async::maybe_async(AFIT)] +#[allow(async_fn_in_trait)] pub trait QuickRefresh where SPI: SpiDevice, @@ -312,7 +321,7 @@ where DELAY: DelayNs, { /// Updates the old frame. - fn update_old_frame( + async fn update_old_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -320,7 +329,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], @@ -328,10 +337,14 @@ where ) -> Result<(), SPI::Error>; /// Displays the new frame - fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error>; + async fn display_new_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Updates and displays the new frame. - fn update_and_display_new_frame( + async fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], @@ -340,7 +353,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, @@ -353,7 +366,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, @@ -366,7 +379,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,