diff --git a/Cargo.toml b/Cargo.toml index 55d682a7..fb2a6390 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ embedded-graphics = "0.8" embedded-hal-mock = { version = "=0.10.0", default-features = false, features = [ "eh1", ] } +anyhow = { version = "1.0", default-features = false} [target.'cfg(unix)'.dev-dependencies] linux-embedded-hal = "0.4.0" diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 4baac378..73a56ad3 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -1,21 +1,22 @@ #![deny(warnings)] +use anyhow; use embedded_hal::delay::DelayNs; use epd_waveshare::{epd1in54::Epd1in54, prelude::*}; use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, SpidevDevice, SysfsPin, + Delay, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config // needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems // see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues -fn main() -> Result<(), SPIError> { +fn main() -> Result<(), anyhow::Error> { // Configure SPI // SPI settings are from eink-waveshare-rs documenation - let mut spi = SpidevDevice::open("/dev/spidev0.0")?; + let mut spi = SpidevDevice::open("/dev/spidev0.0").map_err(anyhow::Error::msg)?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) @@ -58,14 +59,18 @@ fn main() -> Result<(), SPIError> { // Setup of the needed pins is finished here // Now the "real" usage of the eink-waveshare-rs crate begins - let mut epd = Epd1in54::new(&mut spi, busy, dc, rst, &mut delay, Some(5))?; + let mut epd = + Epd1in54::new(&mut spi, busy, dc, rst, &mut delay, Some(5)).map_err(anyhow::Error::msg)?; // Clear the full screen - epd.clear_frame(&mut spi, &mut delay)?; - epd.display_frame(&mut spi, &mut delay)?; + epd.clear_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; + epd.display_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; // Speeddemo - epd.set_lut(&mut spi, &mut delay, Some(RefreshLut::Quick))?; + epd.set_lut(&mut spi, &mut delay, Some(RefreshLut::Quick)) + .map_err(anyhow::Error::msg)?; let small_buffer = [Color::Black.get_byte_value(); 32]; //16x16 let number_of_runs = 1; for i in 0..number_of_runs { @@ -78,30 +83,39 @@ fn main() -> Result<(), SPIError> { 25 + offset, 16, 16, - )?; - epd.display_frame(&mut spi, &mut delay)?; + ) + .map_err(anyhow::Error::msg)?; + epd.display_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; } // Clear the full screen - epd.clear_frame(&mut spi, &mut delay)?; - epd.display_frame(&mut spi, &mut delay)?; + epd.clear_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; + epd.display_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; // Draw some squares let small_buffer = [Color::Black.get_byte_value(); 3200]; //160x160 - epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 20, 20, 160, 160)?; + epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 20, 20, 160, 160) + .map_err(anyhow::Error::msg)?; let small_buffer = [Color::White.get_byte_value(); 800]; //80x80 - epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 60, 60, 80, 80)?; + epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 60, 60, 80, 80) + .map_err(anyhow::Error::msg)?; let small_buffer = [Color::Black.get_byte_value(); 8]; //8x8 - epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 96, 96, 8, 8)?; + epd.update_partial_frame(&mut spi, &mut delay, &small_buffer, 96, 96, 8, 8) + .map_err(anyhow::Error::msg)?; // Display updated frame - epd.display_frame(&mut spi, &mut delay)?; + epd.display_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; delay.delay_ms(5000); // Set the EPD to sleep - epd.sleep(&mut spi, &mut delay)?; + epd.sleep(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; Ok(()) } diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index b3cb64eb..2a3d48cc 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -1,5 +1,6 @@ #![deny(warnings)] +use anyhow; use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, @@ -16,7 +17,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, SpidevDevice, SysfsPin, + Delay, SpidevDevice, SysfsPin, }; // The pins in this example are for the Universal e-Paper Raw Panel Driver HAT @@ -24,7 +25,7 @@ use linux_embedded_hal::{ // needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems // see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues -fn main() -> Result<(), SPIError> { +fn main() -> Result<(), anyhow::Error> { // Configure SPI // Settings are taken from let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); @@ -80,7 +81,9 @@ fn main() -> Result<(), SPIError> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd2in13.update_frame(&mut spi, display.buffer(), &mut delay)?; + epd2in13 + .update_frame(&mut spi, display.buffer(), &mut delay) + .map_err(anyhow::Error::msg)?; epd2in13 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); @@ -156,7 +159,9 @@ fn main() -> Result<(), SPIError> { } println!("Finished tests - going to sleep"); - epd2in13.sleep(&mut spi, &mut delay) + epd2in13 + .sleep(&mut spi, &mut delay) + .map_err(anyhow::Error::msg) } fn draw_text(display: &mut Display2in13, text: &str, x: i32, y: i32) { diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 8007acf3..e8cc84fb 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -1,5 +1,6 @@ #![deny(warnings)] +use anyhow; use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, @@ -16,7 +17,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, SpidevDevice, SysfsPin, + Delay, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -34,7 +35,7 @@ use linux_embedded_hal::{ // // after finishing, put the display to sleep -fn main() -> Result<(), SPIError> { +fn main() -> Result<(), anyhow::Error> { let busy = SysfsPin::new(24); // GPIO 24, board J-18 busy.export().expect("busy export"); while !busy.is_exported() {} @@ -137,12 +138,14 @@ fn main() -> Result<(), SPIError> { // we used three colors, so we need to update both bw-buffer and chromatic-buffer - epd2in13.update_color_frame( - &mut spi, - &mut delay, - display.bw_buffer(), - display.chromatic_buffer(), - )?; + epd2in13 + .update_color_frame( + &mut spi, + &mut delay, + display.bw_buffer(), + display.chromatic_buffer(), + ) + .map_err(anyhow::Error::msg)?; epd2in13 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); @@ -152,16 +155,22 @@ fn main() -> Result<(), SPIError> { // clear both bw buffer and chromatic buffer display.clear(TriColor::White).ok(); - epd2in13.update_color_frame( - &mut spi, - &mut delay, - display.bw_buffer(), - display.chromatic_buffer(), - )?; - epd2in13.display_frame(&mut spi, &mut delay)?; + epd2in13 + .update_color_frame( + &mut spi, + &mut delay, + display.bw_buffer(), + display.chromatic_buffer(), + ) + .map_err(anyhow::Error::msg)?; + epd2in13 + .display_frame(&mut spi, &mut delay) + .map_err(anyhow::Error::msg)?; println!("Finished tests - going to sleep"); - epd2in13.sleep(&mut spi, &mut delay) + epd2in13 + .sleep(&mut spi, &mut delay) + .map_err(anyhow::Error::msg) } fn draw_text(display: &mut Display2in13bc, text: &str, x: i32, y: i32) { diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 10576124..9f9a90e0 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -1,5 +1,6 @@ #![deny(warnings)] +use anyhow; use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, @@ -16,14 +17,14 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, SpidevDevice, SysfsPin, + Delay, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config // needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems // see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues -fn main() -> Result<(), SPIError> { +fn main() -> Result<(), anyhow::Error> { // Configure SPI // Settings are taken from let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); @@ -79,7 +80,9 @@ fn main() -> Result<(), SPIError> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd4in2.update_frame(&mut spi, display.buffer(), &mut delay)?; + epd4in2 + .update_frame(&mut spi, display.buffer(), &mut delay) + .map_err(anyhow::Error::msg)?; epd4in2 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); @@ -147,7 +150,9 @@ fn main() -> Result<(), SPIError> { } println!("Finished tests - going to sleep"); - epd4in2.sleep(&mut spi, &mut delay) + epd4in2 + .sleep(&mut spi, &mut delay) + .map_err(anyhow::Error::msg) } fn draw_text(display: &mut Display4in2, text: &str, x: i32, y: i32) { diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 8ff8259d..bc6cfe5c 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -1,6 +1,7 @@ #![deny(warnings)] #![deny(warnings)] +use anyhow; use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, @@ -17,14 +18,14 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, SpidevDevice, SysfsPin, + Delay, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config // needs to be run with sudo because of some sysfs_gpio permission problems and follow-up timing problems // see https://github.com/rust-embedded/rust-sysfs-gpio/issues/5 and follow-up issues -fn main() -> Result<(), SPIError> { +fn main() -> Result<(), anyhow::Error> { // Configure SPI // Settings are taken from let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); @@ -150,7 +151,9 @@ fn main() -> Result<(), SPIError> { } println!("Finished tests - going to sleep"); - epd4in2.sleep(&mut spi, &mut delay) + epd4in2 + .sleep(&mut spi, &mut delay) + .map_err(anyhow::Error::msg) } fn draw_text(display: &mut impl DrawTarget, text: &str, x: i32, y: i32) { diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 4a4514ed..73266a6b 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -54,19 +54,26 @@ 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 crate::type_a::{ - command::Command, - constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}, +use core::fmt::{Debug, Display}; +use embedded_hal::{ + delay::*, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; -use crate::color::Color; - -use crate::traits::{RefreshLut, WaveshareDisplay}; +use crate::{ + traits::{ErrorType, InternalWiAdditions}, + type_a::{ + command::Command, + constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}, + }, +}; use crate::buffer_len; +use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; +use crate::traits::{RefreshLut, WaveshareDisplay}; /// Full size buffer for use with the 1in54b EPD #[cfg(feature = "graphics")] @@ -88,16 +95,37 @@ pub struct Epd1in54 { refresh: RefreshLut, } -impl Epd1in54 +impl ErrorType + for Epd1in54 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + +impl InternalWiAdditions + for Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 10_000, 10_000)?; // 3 Databytes: // A[7:0] @@ -146,9 +174,13 @@ impl WaveshareDisplay for Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -167,7 +199,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd1in54 { @@ -181,11 +213,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here or would 0x01 be even more efficient? @@ -199,7 +231,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; self.interface @@ -217,7 +249,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -227,7 +259,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // 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) @@ -246,13 +278,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; @@ -278,7 +310,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } @@ -288,7 +320,7 @@ where } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -297,16 +329,20 @@ where impl Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { // choose full frame/ram self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -322,7 +358,7 @@ where start_y: u32, end_x: u32, end_y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; assert!(start_x < end_x); assert!(start_y < end_y); @@ -355,7 +391,7 @@ where delay: &mut DELAY, x: u32, y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant @@ -376,7 +412,7 @@ where spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; assert!(buffer.len() == 30); diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 80bf5849..85cd3d7c 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -2,6 +2,8 @@ //! //! GDEH0154D67 +mod constants; + /// Width of the display pub const WIDTH: u32 = 200; /// Height of the display @@ -11,16 +13,22 @@ 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 crate::type_a::command::Command; - -mod constants; -use crate::epd1in54_v2::constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}; - -use crate::color::Color; - -use crate::traits::{RefreshLut, WaveshareDisplay}; +use core::fmt::{Debug, Display}; +use embedded_hal::{ + delay::*, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +use crate::{ + color::Color, + error::ErrorKind, + traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}, + type_a::{ + command::Command, + constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}, + }, +}; use crate::interface::DisplayInterface; @@ -38,16 +46,37 @@ pub struct Epd1in54 { refresh: RefreshLut, } -impl Epd1in54 +impl ErrorType + for Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + type Error = ErrorKind; +} + +impl InternalWiAdditions + for Epd1in54 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::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)?; @@ -91,9 +120,13 @@ impl WaveshareDisplay for Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -112,7 +145,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd1in54 { @@ -126,11 +159,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; @@ -142,7 +175,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; self.interface @@ -160,7 +193,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -170,7 +203,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; if self.refresh == RefreshLut::Full { self.interface @@ -183,8 +216,7 @@ where self.interface.cmd(spi, Command::MasterActivation)?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::Nop)?; - Ok(()) + self.interface.cmd(spi, Command::Nop) } fn update_and_display_frame( @@ -192,13 +224,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; @@ -209,9 +241,7 @@ where 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)?; - Ok(()) + self.interface.data_x_times(spi, color, WIDTH / 8 * HEIGHT) } fn set_background_color(&mut self, background_color: Color) { @@ -227,7 +257,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } @@ -255,7 +285,7 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -264,16 +294,20 @@ where impl Epd1in54 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, spi: &mut SPI, delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { // choose full frame/ram self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -289,7 +323,7 @@ where start_y: u32, end_x: u32, end_y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; assert!(start_x < end_x); assert!(start_y < end_y); @@ -322,7 +356,7 @@ where delay: &mut DELAY, x: u32, y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant @@ -334,8 +368,7 @@ where spi, Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], - )?; - Ok(()) + ) } fn set_lut_helper( @@ -343,7 +376,7 @@ where spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; assert!(buffer.len() == 159); @@ -364,9 +397,7 @@ where &[buffer[155], buffer[156], buffer[157]], )?; self.interface - .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]])?; - - Ok(()) + .cmd_with_data(spi, Command::WriteVcomRegister, &[buffer[158]]) } } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 08aae37c..d3e07268 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,10 +1,16 @@ //! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use core::fmt::{Debug, Display}; +use embedded_hal::{ + delay::*, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; //The Lookup Tables for the Display @@ -43,17 +49,37 @@ pub struct Epd1in54b { color: Color, } +impl ErrorType + for Epd1in54b +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd1in54b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 10_000, 10_000)?; // set the power settings self.interface @@ -93,9 +119,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -104,7 +134,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -114,7 +144,7 @@ where spi: &mut SPI, delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -132,7 +162,7 @@ where spi: &mut SPI, _delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; Ok(()) @@ -143,9 +173,13 @@ impl WaveshareDisplay for Epd1in54b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -156,7 +190,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -167,7 +201,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating @@ -187,7 +221,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -212,7 +246,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -231,10 +265,9 @@ where let nbits = WIDTH * (HEIGHT / 8); self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, nbits)?; + self.interface.data_x_times(spi, color, nbits) //NOTE: Example code has a delay here - Ok(()) } #[allow(unused)] @@ -247,11 +280,11 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) @@ -262,13 +295,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -293,7 +326,7 @@ where spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?; self.interface @@ -312,7 +345,7 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -321,16 +354,28 @@ where impl Epd1in54b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -339,11 +384,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index bbe27302..273606b8 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,10 +1,15 @@ //! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI +use core::fmt::{Debug, Display}; +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; - +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; /// Width of epd1in54 in pixels @@ -40,21 +45,40 @@ pub struct Epd1in54c { color: Color, } +impl ErrorType + for Epd1in54c +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd1in54c where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::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)?; // start the booster self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; @@ -80,9 +104,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -91,7 +119,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -101,7 +129,7 @@ where spi: &mut SPI, delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission1, black)?; @@ -113,7 +141,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?; @@ -125,9 +153,13 @@ impl WaveshareDisplay for Epd1in54c where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -138,7 +170,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -149,7 +181,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; @@ -159,7 +191,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -184,7 +216,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, buffer)?; // Clear the chromatic layer @@ -206,11 +238,11 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; @@ -222,14 +254,14 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -249,11 +281,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -262,16 +294,28 @@ where impl Epd1in54c where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -280,11 +324,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 5d8d4e0b..fdacd761 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -15,6 +15,7 @@ //! - [Controller Datasheet SS1780](http://www.e-paper-display.com/download_detail/downloadsId=682.html) //! +use core::fmt::{Debug, Display}; use embedded_hal::{ delay::DelayNs, digital::{InputPin, OutputPin}, @@ -23,8 +24,9 @@ use embedded_hal::{ use crate::buffer_len; use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::{ @@ -80,18 +82,38 @@ pub struct Epd2in13 { refresh: RefreshLut, } +impl ErrorType + for Epd2in13 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in13 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // HW reset - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; if self.refresh == RefreshLut::Quick { self.set_vcom_register(spi, (-9).vcom())?; @@ -177,9 +199,13 @@ impl WaveshareDisplay for Epd2in13 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -190,7 +216,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let mut epd = Epd2in13 { interface: DisplayInterface::new(busy, dc, rst, delay_us), sleep_mode: DeepSleepMode::Mode1, @@ -202,11 +228,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // All sample code enables and disables analog/clocks... @@ -229,7 +255,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -258,7 +284,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { assert!((width * height / 8) as usize == buffer.len()); // This should not be used when doing partial refresh. The RAM_RED must @@ -287,7 +313,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> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { if self.refresh == RefreshLut::Full { self.set_display_update_control_2( spi, @@ -312,7 +338,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; @@ -322,7 +348,7 @@ where Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { let color = self.background_color.get_byte_value(); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -371,7 +397,7 @@ where spi: &mut SPI, _delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { let buffer = match refresh_rate { Some(RefreshLut::Full) | None => &LUT_FULL_UPDATE, Some(RefreshLut::Quick) => &LUT_PARTIAL_UPDATE, @@ -380,7 +406,7 @@ where self.cmd_with_data(spi, Command::WriteLutRegister, buffer) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -389,9 +415,13 @@ where impl Epd2in13 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// When using partial refresh, the controller uses the provided buffer for @@ -401,7 +431,7 @@ where spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::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)?; @@ -422,7 +452,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh: RefreshLut, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { if self.refresh != refresh { self.refresh = refresh; self.init(spi, delay)?; @@ -434,7 +464,7 @@ where &mut self, spi: &mut SPI, start: u16, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { assert!(start <= 295); self.cmd_with_data( spi, @@ -447,7 +477,7 @@ where &mut self, spi: &mut SPI, borderwaveform: BorderWaveForm, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.cmd_with_data( spi, Command::BorderWaveformControl, @@ -455,7 +485,11 @@ where ) } - fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { + fn set_vcom_register( + &mut self, + spi: &mut SPI, + vcom: Vcom, + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) } @@ -463,7 +497,7 @@ where &mut self, spi: &mut SPI, voltage: GateDrivingVoltage, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[voltage.0]) } @@ -471,12 +505,16 @@ where &mut self, spi: &mut SPI, number_of_lines: u8, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { assert!(number_of_lines <= 127); self.cmd_with_data(spi, Command::SetDummyLinePeriod, &[number_of_lines]) } - fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { + fn set_gate_line_width( + &mut self, + spi: &mut SPI, + width: u8, + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F]) } @@ -487,7 +525,7 @@ where vsh1: SourceDrivingVoltage, vsh2: SourceDrivingVoltage, vsl: SourceDrivingVoltage, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.cmd_with_data( spi, Command::SourceDrivingVoltageCtrl, @@ -501,16 +539,24 @@ where &mut self, spi: &mut SPI, value: DisplayUpdateControl2, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[value.0]) } /// Triggers the deep sleep mode - fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { + fn set_sleep_mode( + &mut self, + spi: &mut SPI, + mode: DeepSleepMode, + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) } - fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> { + fn set_driver_output( + &mut self, + spi: &mut SPI, + output: DriverOutput, + ) -> Result<(), >::Error> { self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) } @@ -521,7 +567,7 @@ where spi: &mut SPI, counter_incr_mode: DataEntryModeIncr, counter_direction: DataEntryModeDir, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) } @@ -534,7 +580,7 @@ where start_y: u32, end_x: u32, end_y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.cmd_with_data( spi, Command::SetRamXAddressStartEndPosition, @@ -560,7 +606,7 @@ where delay: &mut DELAY, x: u32, y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; @@ -572,7 +618,11 @@ where Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } @@ -581,7 +631,7 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 9d1f0d88..1bb93eef 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -50,11 +50,15 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; /// Width of epd2in13bc in pixels @@ -97,19 +101,39 @@ pub struct Epd2in13bc { color: TriColor, } +impl ErrorType + for Epd2in13bc +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in13bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; // start the booster self.interface @@ -144,9 +168,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -155,7 +183,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -168,7 +196,7 @@ where spi: &mut SPI, _delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, black)?; Ok(()) @@ -182,7 +210,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; @@ -195,9 +223,13 @@ impl WaveshareDisplay for Epd2in13bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = TriColor; @@ -208,7 +240,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -219,7 +251,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Section 8.2 from datasheet self.interface.cmd_with_data( spi, @@ -236,7 +268,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -261,7 +293,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -286,11 +318,11 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; @@ -302,13 +334,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.send_resolution(spi)?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -331,11 +363,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -344,16 +376,28 @@ where impl Epd2in13bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -362,11 +406,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); @@ -378,7 +425,11 @@ where } /// 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 fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), >::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 092fce3f..a8a355f3 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -165,6 +165,7 @@ //! loop {} //!} //!``` +use core::fmt::{Debug, Display}; use embedded_hal::{ delay::DelayNs, @@ -174,8 +175,9 @@ use embedded_hal::{ use crate::color::TriColor; use crate::interface::DisplayInterface; +use crate::prelude::ErrorKind; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; pub(crate) mod command; @@ -208,16 +210,36 @@ pub struct Epd2in66b { background: TriColor, } +impl ErrorType + for Epd2in66b +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in66b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // We follow the sequence of the Pi-Pico hat example code. self.hw_reset(delay)?; self.sw_reset(spi, delay)?; @@ -239,9 +261,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -250,7 +276,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -260,7 +286,7 @@ where spi: &mut SPI, _delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.set_cursor(spi, 0, 0)?; self.interface.cmd(spi, Command::WriteBlackWhiteRAM)?; self.interface.data(spi, black) @@ -271,7 +297,7 @@ where spi: &mut SPI, _delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.set_cursor(spi, 0, 0)?; self.interface.cmd(spi, Command::WriteRedRAM)?; self.interface.data(spi, chromatic) @@ -282,9 +308,13 @@ impl WaveshareDisplay for Epd2in66b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = TriColor; @@ -296,7 +326,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result + ) -> Result where Self: Sized, { @@ -308,7 +338,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.cmd_with_data( spi, Command::DeepSleepMode, @@ -316,7 +346,7 @@ where ) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -341,7 +371,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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 @@ -356,14 +386,14 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::MasterActivation)?; self.wait_until_idle(delay) } @@ -373,12 +403,12 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { let (white, red) = match self.background { TriColor::Black => (StartWith::Zero, StartWith::Zero), TriColor::White => (StartWith::One, StartWith::Zero), @@ -393,11 +423,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(delay) } } @@ -406,21 +436,35 @@ where impl Epd2in66b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle( + &mut self, + delay: &mut DELAY, + ) -> Result<(), >::Error> { self.interface.wait_until_idle(delay, false); Ok(()) } - fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn hw_reset( + &mut self, + delay: &mut DELAY, + ) -> Result<(), >::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.interface.reset(delay, 20_000, 2_000)?; self.wait_until_idle(delay) } - fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sw_reset( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { self.interface.cmd(spi, Command::Reset)?; self.wait_until_idle(delay) } @@ -429,7 +473,7 @@ where spi: &mut SPI, row: DataEntryRow, sign: DataEntrySign, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface .cmd_with_data(spi, Command::DataEntryMode, &[row as u8 | sign as u8]) } @@ -440,7 +484,7 @@ where ystart: u32, xend: u32, yend: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data( spi, Command::SetXAddressRange, @@ -463,7 +507,7 @@ where red_mode: WriteMode, bw_mode: WriteMode, source: OutputSource, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data( spi, Command::DisplayUpdateControl1, @@ -471,7 +515,12 @@ where ) } - fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + fn set_cursor( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + ) -> Result<(), >::Error> { self.interface.cmd_with_data( spi, Command::SetXAddressCounter, @@ -491,7 +540,7 @@ where w: PatW, h: PatH, phase: StartWith, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data( spi, Command::BlackWhiteRAMTestPattern, @@ -506,7 +555,7 @@ where w: PatW, h: PatH, phase: StartWith, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data( spi, Command::RedRAMTestPattern, diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 42f25f19..e3d37cfb 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -1,12 +1,15 @@ //! A simple Driver for the Waveshare 2.7" B Tri-Color E-Ink Display via SPI //! //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) +use core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; - +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; // The Lookup Tables for the Display @@ -47,18 +50,38 @@ pub struct Epd2in7b { color: Color, } +impl ErrorType + for Epd2in7b +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in7b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000)?; // power on self.command(spi, Command::PowerOn)?; @@ -116,9 +139,13 @@ impl WaveshareDisplay for Epd2in7b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -129,7 +156,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -140,11 +167,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; @@ -161,7 +188,7 @@ where spi: &mut SPI, buffer: &[u8], _delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, buffer)?; @@ -183,7 +210,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface .cmd(spi, Command::PartialDataStartTransmission1)?; @@ -202,7 +229,7 @@ where self.interface.cmd(spi, Command::DataStop) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; Ok(()) @@ -213,13 +240,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; let color_value = self.color.get_byte_value(); @@ -257,7 +284,7 @@ where spi: &mut SPI, delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -267,7 +294,7 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -277,9 +304,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -288,7 +319,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -301,7 +332,7 @@ where spi: &mut SPI, _delay: &mut DELAY, achromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, achromatic)?; @@ -317,7 +348,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission2)?; self.send_buffer_helper(spi, chromatic)?; @@ -332,20 +363,36 @@ where impl Epd2in7b where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } - fn send_buffer_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn send_buffer_helper( + &mut self, + spi: &mut SPI, + buffer: &[u8], + ) -> Result<(), >::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() { @@ -359,7 +406,7 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } @@ -372,7 +419,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.command(spi, Command::PartialDisplayRefresh)?; self.send_data(spi, &[(x >> 8) as u8])?; self.send_data(spi, &[(x & 0xf8) as u8])?; @@ -397,7 +444,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface .cmd(spi, Command::PartialDataStartTransmission1)?; self.send_data(spi, &[(x >> 8) as u8])?; @@ -429,7 +476,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface .cmd(spi, Command::PartialDataStartTransmission2)?; self.send_data(spi, &[(x >> 8) as u8])?; diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 48c5bdcc..ed825919 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -50,18 +50,22 @@ 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 crate::type_a::{ - command::Command, - constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}, +use core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; + +use crate::{ + traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}, + type_a::{ + command::Command, + constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}, + }, }; -use crate::color::Color; - -use crate::traits::*; - use crate::buffer_len; +use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; /// Display with Fullsize buffer for use with the 2in9 EPD @@ -85,16 +89,36 @@ pub struct Epd2in9 { refresh: RefreshLut, } -impl Epd2in9 +impl ErrorType for Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 10_000); + type Error = ErrorKind; +} + +impl InternalWiAdditions + for Epd2in9 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 10_000, 10_000)?; self.wait_until_idle(spi, delay)?; @@ -139,9 +163,13 @@ impl WaveshareDisplay for Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -160,7 +188,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd2in9 { @@ -174,7 +202,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) @@ -183,7 +211,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.init(spi, delay)?; Ok(()) @@ -194,7 +222,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; @@ -213,7 +241,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -223,7 +251,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // 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) @@ -242,13 +270,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.use_full_frame(spi, delay)?; @@ -274,7 +302,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } @@ -284,7 +312,7 @@ where } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -293,12 +321,20 @@ where impl Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn use_full_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { // choose full frame/ram self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -313,7 +349,7 @@ where start_y: u32, end_x: u32, end_y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { assert!(start_x < end_x); assert!(start_y < end_y); @@ -344,7 +380,7 @@ where delay: &mut DELAY, x: u32, y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant @@ -366,7 +402,7 @@ where spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; assert!(buffer.len() == 30); self.interface diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 3a36fdf7..1017e022 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -87,17 +87,19 @@ 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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; -use crate::type_a::command::Command; - -use crate::color::Color; +use crate::error::ErrorKind; +use crate::interface::DisplayInterface; +use crate::traits::{ErrorType, InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; -use crate::traits::*; +use crate::type_a::command::Command; use crate::buffer_len; -use crate::interface::DisplayInterface; -use crate::traits::QuickRefresh; +use crate::color::Color; /// Display with Fullsize buffer for use with the 2in9 EPD V2 #[cfg(feature = "graphics")] @@ -120,16 +122,36 @@ pub struct Epd2in9 { refresh: RefreshLut, } -impl Epd2in9 +impl ErrorType for Epd2in9 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + +impl InternalWiAdditions + for Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 2_000); + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 10_000, 2_000)?; self.wait_until_idle(spi, delay)?; self.interface.cmd(spi, Command::SwReset)?; @@ -176,9 +198,13 @@ impl WaveshareDisplay for Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -197,7 +223,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd2in9 { @@ -211,7 +237,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode self.interface @@ -219,7 +245,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay)?; Ok(()) } @@ -229,7 +255,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface.cmd_with_data(spi, Command::WriteRam, buffer) } @@ -243,7 +269,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::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)?; @@ -255,7 +281,7 @@ where } /// actually is the "Turn on Display" sequence - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface @@ -270,13 +296,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // clear the ram with the background color @@ -302,14 +328,14 @@ where _spi: &mut SPI, _delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -318,12 +344,20 @@ where impl Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn use_full_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { // choose full frame/ram self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -338,7 +372,7 @@ where start_y: u32, end_x: u32, end_y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { assert!(start_x < end_x); assert!(start_y < end_y); @@ -369,7 +403,7 @@ where delay: &mut DELAY, x: u32, y: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant @@ -391,7 +425,7 @@ where spi: &mut SPI, delay: &mut DELAY, buffer: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; @@ -404,9 +438,13 @@ impl QuickRefresh for Epd2in9 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// To be followed immediately by `update_new_frame`. @@ -415,7 +453,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::WriteRam2, buffer) @@ -427,9 +465,9 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000)?; self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; self.interface.cmd_with_data( @@ -453,7 +491,11 @@ where } /// 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> { + fn display_new_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; @@ -468,7 +510,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.update_new_frame(spi, buffer, delay)?; self.display_new_frame(spi, delay)?; Ok(()) @@ -485,7 +527,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { //TODO supported by display? unimplemented!() } @@ -501,7 +543,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { //TODO supported by display? unimplemented!() } @@ -516,7 +558,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { //TODO supported by display? unimplemented!() } diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 0f6d52b2..9031b307 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -54,11 +54,15 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; /// Width of epd2in9bc in pixels @@ -101,19 +105,39 @@ pub struct Epd2in9bc { color: Color, } +impl ErrorType + for Epd2in9bc +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in9bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Values taken from datasheet and sample code - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; // start the booster self.interface @@ -148,9 +172,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -159,7 +187,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -172,7 +200,7 @@ where spi: &mut SPI, _delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, black)?; Ok(()) @@ -186,7 +214,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; @@ -199,9 +227,13 @@ impl WaveshareDisplay for Epd2in9bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -212,7 +244,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -223,7 +255,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Section 8.2 from datasheet self.interface.cmd_with_data( spi, @@ -240,7 +272,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -265,7 +297,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -290,11 +322,11 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; @@ -306,13 +338,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.send_resolution(spi)?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -335,11 +367,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -348,16 +380,28 @@ where impl Epd2in9bc where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -366,11 +410,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); @@ -382,7 +429,11 @@ where } /// 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 fn set_border_color( + &mut self, + spi: &mut SPI, + color: TriColor, + ) -> Result<(), >::Error> { let border = match color { TriColor::Black => BLACK_BORDER, TriColor::White => WHITE_BORDER, diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index 95d72398..17c86c07 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -5,16 +5,15 @@ //! //! Specification: https://www.waveshare.net/w/upload/b/b5/2.9inch_e-Paper_%28D%29_Specification.pdf +use core::fmt::{Debug, Display}; use core::slice::from_raw_parts; -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; -use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::{interface::DisplayInterface, prelude::ErrorKind, traits::ErrorType}; //The Lookup Tables for the Display mod constants; @@ -64,17 +63,37 @@ pub struct Epd2in9d<'a, SPI, BUSY, DC, RST, DELAY> { is_partial_refresh: bool, } +impl<'a, SPI, BUSY, DC, RST, DELAY> ErrorType + for Epd2in9d<'a, SPI, BUSY, DC, RST, DELAY> +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 10_000, 2_000); + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 10_000, 2_000)?; //panel setting //LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f @@ -100,9 +119,13 @@ impl WaveshareDisplay for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -113,7 +136,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let old_data: &[u8] = &[]; @@ -132,7 +155,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.is_partial_refresh = false; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; @@ -145,7 +168,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay)?; Ok(()) } @@ -173,7 +196,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if self.is_partial_refresh { // Modify local refresh status if full refresh is performed. self.is_partial_refresh = false; @@ -200,7 +223,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if !self.is_partial_refresh { // Initialize only on first call self.set_part_reg(spi, delay)?; @@ -231,7 +254,7 @@ where } /// actually is the "Turn on Display" sequence - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DisplayRefresh)?; delay.delay_us(1_000); self.wait_until_idle(spi, delay)?; @@ -243,13 +266,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, 0x00, EPD_ARRAY)?; @@ -266,7 +289,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } @@ -277,7 +300,7 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -286,18 +309,22 @@ where impl Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// Wake Up Screen /// /// After the screen sleeps, it enters deep sleep mode. If you need to refresh the screen while in deep sleep mode, you must first execute awaken(). /// Wake the screen. - // fn awaken(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // fn awaken(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // // reset the device - // self.interface.reset(delay, 20_000, 2_000); + // self.interface.reset(delay, 20_000, 2_000)?; // self.wait_until_idle(spi, delay)?; // // panel setting @@ -315,10 +342,14 @@ where // Ok(()) // } - fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn set_part_reg( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { // Reset the EPD driver circuit //TODO: 这里在微雪的例程中反复刷新了3次,后面有显示问题再进行修改 - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000)?; // Power settings //TODO: The data in the document is [0x03,0x00,0x2b,0x2b,0x09]. @@ -381,7 +412,7 @@ where lut_bw: &[u8], lut_wb: &[u8], lut_bb: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { let _ = delay; // LUT VCOM self.interface diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c01c49fa..fd33f0e6 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -2,11 +2,10 @@ //! //! //! 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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; pub(crate) mod command; mod constants; @@ -16,8 +15,9 @@ use self::constants::*; use crate::buffer_len; use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; /// Width of the display. pub const WIDTH: u32 = 280; @@ -42,26 +42,45 @@ pub type Display3in7 = crate::graphics::Display< Color, >; -/// EPD3in7 driver -pub struct EPD3in7 { +/// Epd3in7 driver +pub struct Epd3in7 { /// Connection Interface interface: DisplayInterface, /// Background Color background_color: Color, } +impl ErrorType for Epd3in7 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions - for EPD3in7 + for Epd3in7 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // reset the device - self.interface.reset(delay, 30, 10); + self.interface.reset(delay, 30, 10)?; self.interface.cmd(spi, Command::SwReset)?; delay.delay_us(300000u32); @@ -124,12 +143,16 @@ where } impl WaveshareDisplay - for EPD3in7 + for Epd3in7 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -141,8 +164,8 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { - let mut epd = EPD3in7 { + ) -> Result>::Error> { + let mut epd = Epd3in7 { interface: DisplayInterface::new(busy, dc, rst, delay_us), background_color: DEFAULT_BACKGROUND_COLOR, }; @@ -151,11 +174,19 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, Command::Sleep, &[0xF7])?; self.interface.cmd(spi, Command::PowerOff)?; self.interface @@ -184,7 +215,7 @@ where spi: &mut SPI, buffer: &[u8], _delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.interface .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; @@ -207,11 +238,15 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { todo!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { //self.interface // .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, &LUT_1GRAY_GC)?; self.interface.cmd(spi, Command::DisplayUpdateSequence)?; @@ -224,13 +259,17 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + ) -> Result<(), >::Error> { self.interface .cmd_with_data(spi, Command::SetRamXAddressCounter, &[0x00, 0x00])?; self.interface @@ -248,7 +287,7 @@ where spi: &mut SPI, _delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { let buffer = match refresh_rate { Some(RefreshLut::Full) | None => &LUT_1GRAY_GC, Some(RefreshLut::Quick) => &LUT_1GRAY_DU, @@ -259,7 +298,11 @@ where Ok(()) } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle( + &mut self, + _spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index a1c2a0d4..a22e5759 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -48,11 +48,14 @@ //! //! //! BE CAREFUL! The screen can get ghosting/burn-ins through the Partial Fast Update Drawing. +use core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; - +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; //The Lookup Tables for the Display mod constants; @@ -94,18 +97,37 @@ pub struct Epd4in2 { refresh: RefreshLut, } +impl ErrorType for Epd4in2 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd4in2 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; // set the power settings self.interface.cmd_with_data( @@ -152,9 +174,13 @@ impl WaveshareDisplay for Epd4in2 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -165,7 +191,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -180,7 +206,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating @@ -199,7 +225,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -224,7 +250,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; let color_value = self.color.get_byte_value(); @@ -246,7 +272,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that @@ -284,7 +310,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) @@ -295,13 +321,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -322,7 +348,7 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } @@ -342,7 +368,7 @@ where } } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -351,16 +377,28 @@ where impl Epd4in2 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -369,11 +407,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); @@ -394,7 +435,7 @@ where lut_bw: &[u8], lut_wb: &[u8], lut_bb: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; // LUT VCOM self.cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; @@ -422,7 +463,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.send_data(spi, &[(x >> 8) as u8])?; 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 @@ -446,9 +487,13 @@ impl QuickRefresh for Epd4in2 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// To be followed immediately after by `update_old_frame`. @@ -457,7 +502,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.interface.cmd(spi, Command::DataStartTransmission1)?; @@ -473,7 +518,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // self.send_resolution(spi)?; @@ -486,7 +531,7 @@ where /// 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> { + fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.display_frame(spi, delay) } @@ -499,7 +544,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_new_frame(spi, buffer, delay)?; self.display_frame(spi, delay) } @@ -513,7 +558,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; if buffer.len() as u32 != width / 8 * height { @@ -544,7 +589,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that @@ -569,7 +614,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 1a70b78a..4799b57e 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -5,16 +5,15 @@ //! - [Datasheet](https://www.waveshare.com/wiki/5.65inch_e-Paper_Module_(F)) //! - [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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::OctColor; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -48,18 +47,38 @@ pub struct Epd5in65f { color: OctColor, } +impl ErrorType + for Epd5in65f +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd5in65f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); + 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])?; @@ -84,9 +103,13 @@ impl WaveshareDisplay for Epd5in65f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = OctColor; @@ -97,7 +120,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -108,11 +131,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), Self::Error> { self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } @@ -122,7 +145,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.update_vcom(spi)?; self.send_resolution(spi)?; @@ -139,11 +162,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOn)?; self.wait_until_idle(spi, delay)?; @@ -159,13 +182,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { let bg = OctColor::colors_byte(self.color, self.color); self.wait_until_idle(spi, delay)?; self.update_vcom(spi)?; @@ -197,11 +220,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, true); Ok(()) } @@ -210,16 +233,28 @@ where impl Epd5in65f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -228,14 +263,17 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } fn wait_busy_low(&mut self, delay: &mut DELAY) { self.interface.wait_until_idle(delay, false); } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); @@ -246,7 +284,10 @@ where self.send_data(spi, &[h as u8]) } - fn update_vcom(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn update_vcom( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let bg_color = (self.color.get_nibble() & 0b111) << 5; self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17 | bg_color])?; Ok(()) diff --git a/src/epd5in83_v2/mod.rs b/src/epd5in83_v2/mod.rs index 58909b2c..0251d914 100644 --- a/src/epd5in83_v2/mod.rs +++ b/src/epd5in83_v2/mod.rs @@ -6,16 +6,16 @@ //! - [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 core::fmt::{Debug, Display}; + +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::Color; use crate::interface::DisplayInterface; -use crate::prelude::WaveshareDisplay; -use crate::traits::{InternalWiAdditions, RefreshLut}; +use crate::prelude::{ErrorKind, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut}; pub(crate) mod command; use self::command::Command; @@ -50,18 +50,38 @@ pub struct Epd5in83 { color: Color, } +impl ErrorType + for Epd5in83 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 2000, 50); + self.interface.reset(delay, 2000, 50)?; // Set the power settings: VGH=20V,VGL=-20V,VDH=15V,VDL=-15V self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; @@ -95,9 +115,13 @@ impl WaveshareDisplay for Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -108,7 +132,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -119,7 +143,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; @@ -127,7 +151,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -152,7 +176,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; let color_value = self.color.get_byte_value(); @@ -174,11 +198,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; Ok(()) @@ -189,13 +213,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DataStartTransmission1)?; @@ -212,11 +236,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -225,16 +249,28 @@ where impl Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -243,11 +279,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index 625b1e7c..ab47a643 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -5,17 +5,17 @@ //! - [Datasheet](https://www.waveshare.com/5.83inch-e-Paper-B.htm) //! - [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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; -use embedded_hal::{ - delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; - -use crate::color::Color; +use crate::color::{Color, TriColor}; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::prelude::{TriColor, WaveshareDisplay, WaveshareThreeColorDisplay}; -use crate::traits::{InternalWiAdditions, RefreshLut}; +use crate::traits::{ + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; pub(crate) mod command; use self::command::Command; @@ -50,18 +50,38 @@ pub struct Epd5in83 { color: Color, } +impl ErrorType + for Epd5in83 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; // Start the booster self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x1e, 0x17])?; @@ -98,9 +118,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -109,7 +133,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic)?; Ok(()) @@ -120,7 +144,7 @@ where spi: &mut SPI, delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission1, black)?; Ok(()) @@ -131,7 +155,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?; Ok(()) @@ -142,9 +166,13 @@ impl WaveshareDisplay for Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -155,7 +183,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -166,7 +194,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; @@ -174,7 +202,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -199,7 +227,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.update_achromatic_frame(spi, delay, buffer)?; let color = self.color.get_byte_value(); @@ -217,7 +245,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error @@ -257,7 +285,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(spi, delay)?; Ok(()) @@ -268,13 +296,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // The Waveshare controllers all implement clear using 0x33 @@ -292,11 +320,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -305,16 +333,28 @@ where impl Epd5in83 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -323,11 +363,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd7in3f/mod.rs b/src/epd7in3f/mod.rs index 11a733df..bd713e8f 100644 --- a/src/epd7in3f/mod.rs +++ b/src/epd7in3f/mod.rs @@ -6,17 +6,20 @@ //! - [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 core::fmt::{Debug, Display}; + +use embedded_hal::spi::SpiDevice; use embedded_hal::{ delay::DelayNs, digital::{InputPin, OutputPin}, - spi::SpiDevice, }; use crate::{ buffer_len, color::OctColor, interface::DisplayInterface, - traits::{InternalWiAdditions, WaveshareDisplay}, + prelude::ErrorKind, + traits::{ErrorType, InternalWiAdditions, WaveshareDisplay}, }; use self::command::Command; @@ -50,17 +53,37 @@ pub struct Epd7in3f { color: OctColor, } +impl ErrorType + for Epd7in3f +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd7in3f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { - self.interface.reset(delay, 20_000, 2_000); + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { + self.interface.reset(delay, 20_000, 2_000)?; self.wait_busy_low(delay); delay.delay_ms(30); @@ -90,9 +113,13 @@ impl WaveshareDisplay for Epd7in3f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = OctColor; @@ -104,7 +131,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result::Error> + ) -> Result where Self: Sized, { @@ -118,11 +145,11 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), ::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), Self::Error> { self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -147,7 +174,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), ::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission, buffer) } @@ -161,11 +188,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), ::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::PowerOn)?; self.wait_busy_low(delay); @@ -183,12 +210,12 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), ::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { let bg = OctColor::colors_byte(self.color, self.color); self.wait_busy_low(delay); @@ -203,11 +230,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), ::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_busy_low(delay); Ok(()) } @@ -216,12 +243,20 @@ where impl Epd7in3f where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } @@ -230,7 +265,7 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } @@ -239,7 +274,11 @@ where } /// 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 fn show_7block( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), >::Error> { let color_7 = [ OctColor::Black, OctColor::White, diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 121b780d..02d792bd 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -5,16 +5,15 @@ //! - [Datasheet](https://www.waveshare.com/wiki/7.5inch_e-Paper_HAT) //! - [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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -48,18 +47,37 @@ pub struct Epd7in5 { color: Color, } +impl ErrorType for Epd7in5 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 10_000, 10_000); + self.interface.reset(delay, 10_000, 10_000)?; // Set the power settings self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00])?; @@ -107,9 +125,13 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -120,7 +142,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -131,7 +153,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; @@ -139,7 +161,7 @@ where Ok(()) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } @@ -164,7 +186,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DataStartTransmission1)?; for byte in buffer { @@ -190,11 +212,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) @@ -205,13 +227,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -227,11 +249,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -240,16 +262,28 @@ where impl Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -258,11 +292,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index f78df1f2..ba818a66 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -9,15 +9,15 @@ //! - [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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -51,18 +51,37 @@ pub struct Epd7in5 { color: Color, } +impl ErrorType for Epd7in5 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000)?; // HD procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py @@ -107,9 +126,13 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -120,7 +143,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -131,11 +154,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?; Ok(()) @@ -146,7 +169,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; self.cmd_with_data(spi, Command::WriteRamBw, buffer)?; @@ -163,11 +186,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.command(spi, Command::MasterActivation)?; self.wait_until_idle(spi, delay)?; Ok(()) @@ -178,13 +201,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.display_frame(spi, delay)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { let pixel_count = WIDTH / 8 * HEIGHT; let background_color_byte = self.color.get_byte_value(); @@ -224,11 +247,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface.wait_until_idle(delay, IS_BUSY_LOW); Ok(()) } @@ -237,12 +260,20 @@ where impl Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } @@ -251,7 +282,7 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 7f09a253..7d27376c 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -10,15 +10,15 @@ //! 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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::Color; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -52,18 +52,37 @@ pub struct Epd7in5 { color: Color, } +impl ErrorType for Epd7in5 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { // Reset the device - self.interface.reset(delay, 10_000, 2_000); + self.interface.reset(delay, 10_000, 2_000)?; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py @@ -89,9 +108,13 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = Color; @@ -102,7 +125,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -113,11 +136,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; @@ -130,7 +153,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; Ok(()) @@ -145,11 +168,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) @@ -160,13 +183,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -201,11 +224,11 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) } @@ -214,16 +237,28 @@ where impl Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -232,11 +267,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 708dd452..dd445498 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -10,16 +10,16 @@ //! 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 core::fmt::{Debug, Display}; +use embedded_hal::delay::DelayNs; +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; use crate::color::TriColor; +use crate::error::ErrorKind; use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, + ErrorType, InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; pub(crate) mod command; @@ -57,19 +57,38 @@ pub struct Epd7in5 { color: TriColor, } +impl ErrorType for Epd7in5 +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, + DELAY: DelayNs, +{ + type Error = ErrorKind; +} + impl InternalWiAdditions for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::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)?; // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py @@ -110,9 +129,13 @@ impl WaveshareThreeColorDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { fn update_color_frame( @@ -121,7 +144,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_achromatic_frame(spi, delay, black)?; self.update_chromatic_frame(spi, delay, chromatic) } @@ -134,7 +157,7 @@ where spi: &mut SPI, _delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, black)?; self.interface.cmd(spi, Command::DataStop)?; @@ -149,7 +172,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; self.interface.cmd(spi, Command::DataStop)?; @@ -163,9 +186,13 @@ impl WaveshareDisplay for Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { type DisplayColor = TriColor; @@ -176,7 +203,7 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result { + ) -> Result { let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; @@ -187,11 +214,11 @@ where Ok(epd) } - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; @@ -204,7 +231,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; // (B) version sends one buffer for black and one for red self.cmd_with_data( @@ -230,11 +257,11 @@ where _y: u32, _width: u32, _height: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) @@ -245,13 +272,13 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { self.update_frame(spi, buffer, delay)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.wait_until_idle(spi, delay)?; self.send_resolution(spi)?; @@ -289,12 +316,12 @@ where _spi: &mut SPI, _delay: &mut DELAY, _refresh_rate: Option, - ) -> Result<(), SPI::Error> { + ) -> Result<(), Self::Error> { unimplemented!(); } /// wait - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error> { self.interface .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) } @@ -303,9 +330,13 @@ where impl Epd7in5 where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// temporary replacement for missing delay in the trait to call wait_until_idle @@ -319,7 +350,7 @@ where width: u32, height: u32, delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.wait_until_idle(spi, delay)?; if buffer.len() as u32 != width / 8 * height { //TODO panic or error @@ -355,11 +386,19 @@ where Ok(()) } - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + fn command( + &mut self, + spi: &mut SPI, + command: Command, + ) -> Result<(), >::Error> { self.interface.cmd(spi, command) } - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn send_data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), >::Error> { self.interface.data(spi, data) } @@ -368,11 +407,14 @@ where spi: &mut SPI, command: Command, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), >::Error> { self.interface.cmd_with_data(spi, command, data) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn send_resolution( + &mut self, + spi: &mut SPI, + ) -> Result<(), >::Error> { let w = self.width(); let h = self.height(); diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..8ffb1f12 --- /dev/null +++ b/src/error.rs @@ -0,0 +1,97 @@ +use core::fmt::{Debug, Display, Formatter}; + +use embedded_hal::digital::{InputPin, OutputPin}; +use embedded_hal::spi::SpiDevice; + +use crate::traits::Error; + +/// Epd error type +#[derive(Eq, PartialEq, Ord, PartialOrd, Hash)] +pub enum ErrorKind +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + /// Encountered an SPI error + SpiError(SPI::Error), + + /// Encountered an error on Busy GPIO + BusyError(BUSY::Error), + + /// Encountered an error on DC GPIO + DcError(DC::Error), + + /// Encountered an error on RST GPIO + RstError(RST::Error), + + /// Anything else + Other, +} + +impl Display for ErrorKind +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpiError(err) => Display::fmt(&err, f), + Self::BusyError(err) => Display::fmt(&err, f), + Self::DcError(err) => Display::fmt(&err, f), + Self::RstError(err) => Display::fmt(&err, f), + Self::Other => write!( + f, + "A different error occurred. The original error may contain more information" + ), + } + } +} + +impl Debug for ErrorKind +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { + match self { + Self::SpiError(err) => Debug::fmt(&err, f), + Self::BusyError(err) => Debug::fmt(&err, f), + Self::DcError(err) => Debug::fmt(&err, f), + Self::RstError(err) => Debug::fmt(&err, f), + Self::Other => write!( + f, + "A different error occurred. The original error may contain more information" + ), + } + } +} + +impl Error for ErrorKind +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + fn kind(&self) -> &ErrorKind { + self + } +} diff --git a/src/interface.rs b/src/interface.rs index f3a9a3d7..7012ebe5 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,6 +1,11 @@ -use crate::traits::Command; +use crate::{error::ErrorKind, traits::Command}; +use core::fmt::{Debug, Display}; use core::marker::PhantomData; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// @@ -25,9 +30,13 @@ impl DisplayInterface where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// Creates a new `DisplayInterface` struct @@ -49,9 +58,13 @@ 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) fn cmd( + &mut self, + spi: &mut SPI, + command: T, + ) -> Result<(), ErrorKind> { // low for commands - let _ = self.dc.set_low(); + let _ = self.dc.set_low().map_err(ErrorKind::DcError)?; // Transfer the command over spi self.write(spi, &[command.address()]) @@ -60,9 +73,13 @@ where /// 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) fn data( + &mut self, + spi: &mut SPI, + data: &[u8], + ) -> Result<(), ErrorKind> { // high for data - let _ = self.dc.set_high(); + let _ = self.dc.set_high().map_err(ErrorKind::DcError)?; if SINGLE_BYTE_WRITE { for val in data.iter().copied() { @@ -84,7 +101,7 @@ where spi: &mut SPI, command: T, data: &[u8], - ) -> Result<(), SPI::Error> { + ) -> Result<(), ErrorKind> { self.cmd(spi, command)?; self.data(spi, data) } @@ -97,9 +114,9 @@ where spi: &mut SPI, val: u8, repetitions: u32, - ) -> Result<(), SPI::Error> { + ) -> Result<(), ErrorKind> { // high for data - let _ = self.dc.set_high(); + let _ = self.dc.set_high().map_err(ErrorKind::DcError)?; // Transfer data (u8) over spi for _ in 0..repetitions { self.write(spi, &[val])?; @@ -108,17 +125,17 @@ where } // spi write helper/abstraction function - fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), ErrorKind> { // 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).map_err(ErrorKind::SpiError)?; } Ok(()) } else { - spi.write(data) + spi.write(data).map_err(ErrorKind::SpiError) } } @@ -155,7 +172,7 @@ where delay: &mut DELAY, is_busy_low: bool, status_command: T, - ) -> Result<(), SPI::Error> { + ) -> Result<(), ErrorKind> { self.cmd(spi, status_command)?; if self.delay_us > 0 { delay.delay_us(self.delay_us); @@ -194,15 +211,21 @@ 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) { - let _ = self.rst.set_high(); + pub(crate) fn reset( + &mut self, + delay: &mut DELAY, + initial_delay: u32, + duration: u32, + ) -> Result<(), ErrorKind> { + let _ = self.rst.set_high().map_err(ErrorKind::RstError)?; delay.delay_us(initial_delay); - let _ = self.rst.set_low(); + let _ = self.rst.set_low().map_err(ErrorKind::RstError)?; delay.delay_us(duration); - let _ = self.rst.set_high(); + let _ = self.rst.set_high().map_err(ErrorKind::RstError)?; //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); + Ok(()) } } diff --git a/src/lib.rs b/src/lib.rs index 9b393528..f3923e74 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -66,6 +66,7 @@ #[cfg(feature = "graphics")] pub mod graphics; +mod error; mod traits; pub mod color; @@ -106,6 +107,8 @@ pub mod prelude { QuickRefresh, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; + pub use crate::error::*; + pub use crate::SPI_MODE; #[cfg(feature = "graphics")] diff --git a/src/traits.rs b/src/traits.rs index b1f3f731..49d5fdf4 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,5 +1,56 @@ +use core::fmt::{Debug, Display}; use core::marker::Sized; -use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; +use embedded_hal::{ + delay::*, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +use crate::error::ErrorKind; + +pub trait Error: core::fmt::Debug +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + fn kind(&self) -> &ErrorKind; +} + +impl Error for core::convert::Infallible +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + fn kind(&self) -> &ErrorKind { + match *self {} + } +} + +pub trait ErrorType +where + SPI: SpiDevice, + SPI::Error: Debug + Display, + BUSY: InputPin, + BUSY::Error: Debug + Display, + DC: OutputPin, + DC::Error: Debug + Display, + RST: OutputPin, + RST::Error: Debug + Display, +{ + type Error: Error; +} /// 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,12 +69,17 @@ pub enum RefreshLut { Quick, } -pub(crate) trait InternalWiAdditions +pub(crate) trait InternalWiAdditions: + ErrorType where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// This initialises the EPD and powers it up @@ -36,7 +92,7 @@ where /// This function calls [reset](WaveshareDisplay::reset), /// so you don't need to call reset your self when trying to wake your device up /// after setting it to sleep. - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error>; } /// Functions to interact with three color panels @@ -44,9 +100,13 @@ pub trait WaveshareThreeColorDisplay: WaveshareDisplay where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// Transmit data to the SRAM of the EPD @@ -58,7 +118,7 @@ where delay: &mut DELAY, black: &[u8], chromatic: &[u8], - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Update only the black/white data of the display. /// @@ -68,7 +128,7 @@ where spi: &mut SPI, delay: &mut DELAY, black: &[u8], - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Update only the chromatic data of the display. /// @@ -79,7 +139,7 @@ where spi: &mut SPI, delay: &mut DELAY, chromatic: &[u8], - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; } /// All the functions to interact with the EPDs @@ -126,12 +186,16 @@ where ///# Ok(()) ///# } ///``` -pub trait WaveshareDisplay +pub trait WaveshareDisplay: ErrorType where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// The Color Type used by the Display @@ -150,19 +214,19 @@ where rst: RST, delay: &mut DELAY, delay_us: Option, - ) -> Result + ) -> Result where Self: Sized; /// 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>; + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::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>; + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error>; /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame) fn set_background_color(&mut self, color: Self::DisplayColor); @@ -182,7 +246,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Transmits partial data to the SRAM of the EPD /// @@ -199,12 +263,12 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// 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>; + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error>; /// Provide a combined update&display and save some time (skipping a busy check in between) fn update_and_display_frame( @@ -212,12 +276,12 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// 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>; + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error>; /// Trait for using various Waveforms from different LUTs /// E.g. for partial refreshes @@ -232,12 +296,12 @@ where spi: &mut SPI, delay: &mut DELAY, refresh_rate: Option, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// 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>; + fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), Self::Error>; } /// Allows quick refresh support for displays that support it; lets you send both @@ -285,12 +349,16 @@ where ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh: ErrorType where SPI: SpiDevice, + SPI::Error: Debug + Display, BUSY: InputPin, + BUSY::Error: Debug + Display, DC: OutputPin, + DC::Error: Debug + Display, RST: OutputPin, + RST::Error: Debug + Display, DELAY: DelayNs, { /// Updates the old frame. @@ -299,7 +367,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Updates the new frame. fn update_new_frame( @@ -307,10 +375,10 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Displays the new frame - fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error>; + fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), Self::Error>; /// Updates and displays the new frame. fn update_and_display_new_frame( @@ -318,7 +386,7 @@ where spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Updates the old frame for a portion of the display. #[allow(clippy::too_many_arguments)] @@ -331,7 +399,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Updates the new frame for a portion of the display. #[allow(clippy::too_many_arguments)] @@ -344,7 +412,7 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; /// Clears the partial frame buffer on the EPD with the declared background color /// The background color can be changed with [`WaveshareDisplay::set_background_color`] @@ -356,5 +424,5 @@ where y: u32, width: u32, height: u32, - ) -> Result<(), SPI::Error>; + ) -> Result<(), Self::Error>; }