From a6ed7f7c6d370c8e2b066bff6404a0c9e4bf1ccb Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 7 Jan 2023 23:07:15 +0100 Subject: [PATCH 01/69] Add option to switch between single byte and blockwise data writen to the spi device --- src/epd1in54/mod.rs | 3 ++- src/epd1in54_v2/mod.rs | 3 ++- src/epd1in54b/mod.rs | 3 ++- src/epd1in54c/mod.rs | 3 ++- src/epd2in13_v2/mod.rs | 3 ++- src/epd2in13bc/mod.rs | 3 ++- src/epd2in7b/mod.rs | 3 ++- src/epd2in9/mod.rs | 3 ++- src/epd2in9_v2/mod.rs | 3 ++- src/epd2in9bc/mod.rs | 3 ++- src/epd3in7/mod.rs | 4 +++- src/epd4in2/mod.rs | 3 ++- src/epd5in65f/mod.rs | 4 +++- src/epd5in83b_v2/mod.rs | 3 ++- src/epd7in5/mod.rs | 3 ++- src/epd7in5_hd/mod.rs | 3 ++- src/epd7in5_v2/mod.rs | 3 ++- src/epd7in5_v3/mod.rs | 3 ++- src/epd7in5b_v2/mod.rs | 3 ++- src/interface.rs | 15 ++++++++++----- 20 files changed, 50 insertions(+), 24 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index be6a430b..aba10c99 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -52,6 +52,7 @@ pub const HEIGHT: u32 = 200; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; //const DPI: u16 = 184; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::{ blocking::{delay::*, spi::Write}, @@ -83,7 +84,7 @@ pub type Display1in54 = crate::graphics::Display< /// Epd1in54 driver pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 60a43d38..ce1ba7ea 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -9,6 +9,7 @@ pub const HEIGHT: u32 = 200; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::{ blocking::{delay::*, spi::Write}, @@ -32,7 +33,7 @@ pub use crate::epd1in54::Display1in54; /// Epd1in54 driver pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index ce8c4fb4..5a4a79f4 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -21,6 +21,7 @@ pub const HEIGHT: u32 = 200; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::Color; @@ -41,7 +42,7 @@ pub type Display1in54b = crate::graphics::Display< /// Epd1in54b driver pub struct Epd1in54b { - interface: DisplayInterface, + interface: DisplayInterface, color: Color, } diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 2934a827..b63d3189 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -18,6 +18,7 @@ pub const HEIGHT: u32 = 152; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::Color; @@ -38,7 +39,7 @@ pub type Display1in54c = crate::graphics::Display< /// Epd1in54c driver pub struct Epd1in54c { - interface: DisplayInterface, + interface: DisplayInterface, color: Color, } diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 0efad684..44172836 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -47,12 +47,13 @@ pub const HEIGHT: u32 = 250; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; /// Epd2in13 (V2) driver /// pub struct Epd2in13 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, sleep_mode: DeepSleepMode, diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index e009f315..964025e7 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -76,6 +76,7 @@ const WHITE_BORDER: u8 = 0x70; const BLACK_BORDER: u8 = 0x30; const CHROMATIC_BORDER: u8 = 0xb0; const FLOATING_BORDER: u8 = 0xF0; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::TriColor; @@ -95,7 +96,7 @@ pub type Display2in13bc = crate::graphics::Display< /// Epd2in13bc driver pub struct Epd2in13bc { - interface: DisplayInterface, + interface: DisplayInterface, color: TriColor, } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 6c3a49c5..8d442688 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -23,6 +23,7 @@ pub const HEIGHT: u32 = 264; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::Color; @@ -44,7 +45,7 @@ pub type Display2in7b = crate::graphics::Display< /// Epd2in7b driver pub struct Epd2in7b { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 6a3ee1d0..1d9d624c 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -48,6 +48,7 @@ pub const HEIGHT: u32 = 296; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; use embedded_hal::{ blocking::{delay::*, spi::Write}, @@ -80,7 +81,7 @@ pub type Display2in9 = crate::graphics::Display< /// pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index a2d8caf2..46d94bd1 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -61,6 +61,7 @@ pub const HEIGHT: u32 = 296; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; const LUT_PARTIAL_2IN9: [u8; 159] = [ 0x0, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x80, 0x0, 0x0, 0x0, 0x0, @@ -103,7 +104,7 @@ pub type Display2in9 = crate::graphics::Display< /// pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 4eb980fc..d884ecd9 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -79,6 +79,7 @@ const WHITE_BORDER: u8 = 0x70; const BLACK_BORDER: u8 = 0x30; const CHROMATIC_BORDER: u8 = 0xb0; const FLOATING_BORDER: u8 = 0xF0; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::{Color, TriColor}; @@ -99,7 +100,7 @@ pub type Display2in9bc = crate::graphics::Display< /// Epd2in9bc driver pub struct Epd2in9bc { - interface: DisplayInterface, + interface: DisplayInterface, color: Color, } diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index 66513eb8..a0540227 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -29,6 +29,8 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; + /// Display with Fullsize buffer for use with the 3in7 EPD #[cfg(feature = "graphics")] pub type Display3in7 = crate::graphics::Display< @@ -42,7 +44,7 @@ pub type Display3in7 = crate::graphics::Display< /// EPD3in7 driver pub struct EPD3in7 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color background_color: Color, } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index a5e52a8e..f344fd5c 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -68,6 +68,7 @@ pub const HEIGHT: u32 = 300; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = true; use crate::color::Color; @@ -89,7 +90,7 @@ pub type Display4in2 = crate::graphics::Display< /// pub struct Epd4in2 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, /// Refresh LUT diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index fde52050..3c275f7a 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -35,12 +35,14 @@ pub const WIDTH: u32 = 600; pub const HEIGHT: u32 = 448; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White; +/// Default mode of writing data (single byte vs blockwise) +const SINGLE_BYTE_WRITE: bool = true; /// Epd5in65f driver /// pub struct Epd5in65f { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: OctColor, } diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index 0a9ac8a5..e16a287a 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -38,12 +38,13 @@ pub const HEIGHT: u32 = 480; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const SINGLE_BYTE_WRITE: bool = true; /// Epd7in5 driver /// pub struct Epd5in83 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 52237e6e..f12c493e 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -36,12 +36,13 @@ pub const HEIGHT: u32 = 384; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 driver /// pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index c29d723e..2b19f962 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -39,12 +39,13 @@ pub const HEIGHT: u32 = 528; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; // Inverted for HD as compared to 7in5 v2 (HD: 0xFF = White) const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = false; /// EPD7in5 (HD) driver /// pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index fe6867dd..b1d51158 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -40,12 +40,13 @@ pub const HEIGHT: u32 = 480; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index 675ee048..d3c43c87 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -44,12 +44,13 @@ pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; /// Number of bits for b/w buffer and same for chromatic buffer const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V3) driver /// pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index cdf0186b..21855c19 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -42,12 +42,13 @@ pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; const NUM_DISPLAY_BYTES: usize = WIDTH as usize * HEIGHT as usize / 8; const IS_BUSY_LOW: bool = true; +const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } diff --git a/src/interface.rs b/src/interface.rs index d3007158..db2ff676 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -7,7 +7,7 @@ use embedded_hal::{ /// The Connection Interface of all (?) Waveshare EPD-Devices /// -pub(crate) struct DisplayInterface { +pub(crate) struct DisplayInterface { /// SPI _spi: PhantomData, /// DELAY @@ -24,7 +24,8 @@ pub(crate) struct DisplayInterface { delay_us: u32, } -impl DisplayInterface +impl + DisplayInterface where SPI: Write, CS: OutputPin, @@ -68,9 +69,13 @@ where // high for data let _ = self.dc.set_high(); - for val in data.iter().copied() { - // Transfer data one u8 at a time over spi - self.write(spi, &[val])?; + if SINGLE_BYTE_WRITE { + for val in data.iter().copied() { + // Transfer data one u8 at a time over spi + self.write(spi, &[val])?; + } + } else { + self.write(spi, data)?; } Ok(()) From 43d23c4639579097fda39a30413847722317b9bf Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 7 Jan 2023 23:12:01 +0100 Subject: [PATCH 02/69] Add comment for SINGLE_BYTE_WRITE --- src/interface.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/interface.rs b/src/interface.rs index db2ff676..0bcfd1ff 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -7,6 +7,8 @@ use embedded_hal::{ /// The Connection Interface of all (?) Waveshare EPD-Devices /// +/// SINGLE_BYTE_WRITE defines if a data block is written bytewise +/// or blockwise to the spi device pub(crate) struct DisplayInterface { /// SPI _spi: PhantomData, From bfedcbf0deb8d5327d1b68c2e93b210040fe8273 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 00:14:05 +0100 Subject: [PATCH 03/69] Initial commit - fully functional --- src/epd2in66b/command.rs | 117 +++++++++ src/epd2in66b/mod.rs | 511 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 629 insertions(+) create mode 100644 src/epd2in66b/command.rs create mode 100644 src/epd2in66b/mod.rs diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs new file mode 100644 index 00000000..a7528507 --- /dev/null +++ b/src/epd2in66b/command.rs @@ -0,0 +1,117 @@ +#![allow(dead_code)] +///! SPI Commands for the SSD1675B driver chip +use crate::traits; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + DriverOutputControl = 0x01, + GateDrivingVoltageControl = 0x02, + SourceDrivingVoltageControl = 0x04, + ProgramOTPInitialCodeSetting = 0x08, + WriteRegisterForInitialCodeSetting = 0x09, + ReadRegisterForInitiaslCodeSetting = 0x0a, + BoosterSoftstartControl = 0x0c, + GateScanStartPosition = 0x0f, + DeepSleepMode = 0x10, + DataEntryMode = 0x11, + Reset = 0x12, + HVReadyDetection = 0x14, + VCIDetection = 0x15, + TemperatureSensorSelection = 0x18, + WriteTemperatureRegister = 0x1a, + ReadTemperatureRegister = 0x1b, + ExternalTemperatureSensorWriteCommand = 0x1c, + MasterActivation = 0x20, + DisplayUpdateControl1 = 0x21, + DisplayUpdateControl2 = 0x22, + WriteBlackWhiteRAM = 0x24, + WriteRedRAM = 0x26, + ReadRAM = 0x27, + SenseVCOM = 0x28, + VCOMSenseDuration = 0x29, + ProgramOTPVCOM = 0x2a, + WriteRegisterForVCOMControl = 0x2b, + WriteVCOMRegister = 0x2c, + ReadOTPDisplayOptions = 0x2d, + ReadOTPUserId = 0x2e, + ReadStatusBits = 0x2f, + ProgramOTPWaveformSetting = 0x30, + LoadOTPWaveformSetting = 0x31, + WriteLUTRegister = 0x32, + CalculateCRC = 0x34, + ReadCRC = 0x35, + ProgramOTPSelection = 0x36, + WriteRegisterForDisplayOption = 0x37, + WriteRegisterForUserID = 0x38, + OTPProgramMode = 0x39, + SetDummyLinePeriod = 0x3a, + SetGateLineWidth = 0x3b, + BorderWaveformControl = 0x3c, + RAMReadOption = 0x41, + SetXAddressRange = 0x44, + SetYAddressRange = 0x45, + RedRAMTestPattern = 0x46, + BlackWhiteRAMTestPattern = 0x47, + SetXAddressCounter = 0x4e, + SetYAddressCounter = 0x4f, + SetAnalogBlockControl = 0x74, + SetDigitalBlockControl = 0x7e, + NOP = 0x7f, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} + +pub(crate) enum DataEntrySign { + DecYDecX = 0b00, + DecYIncX = 0b01, + IncYDecX = 0b10, + IncYIncX = 0b11, +} +pub(crate) enum DataEntryRow { + XMinor = 0b000, + YMinor = 0b100, +} + +pub(crate) enum WriteMode { + Normal = 0b0000, + ForceZero = 0b0100, + Invert = 01000, +} +pub(crate) enum OutputSource { + S0ToS175 = 0x00, + S8ToS167 = 0x80, +} + +pub(crate) enum DeepSleep { + Awake = 0b00, + SleepKeepingRAM = 0b01, + SleepLosingRAM = 0b11, +} + +pub(crate) enum PatH { + H8 = 0b000_0000, + H16 = 0b001_0000, + H32 = 0b010_0000, + H64 = 0b011_0000, + H128 = 0b100_0000, + H256 = 0b101_0000, + H296 = 0b110_0000, +} +pub(crate) enum PatW { + W8 = 0b000, + W16 = 0b001, + W32 = 0b010, + W64 = 0b011, + W128 = 0b100, + W160 = 0b101, +} +pub(crate) enum StartWith { + Zero = 0x00, + One = 0x80, +} diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs new file mode 100644 index 00000000..5dbfdd3f --- /dev/null +++ b/src/epd2in66b/mod.rs @@ -0,0 +1,511 @@ +//! A simple Driver for the Waveshare 2.66"-B E-Ink Display via SPI +//! +//! More information on this display can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) +//! This driver was built and tested for 296x152, 2.66inch E-Ink display HAT for Raspberry Pi Pico, three-color, SPI interface. +//! +//! # Example for the 2.66"B Pi Pico Hat E-Ink Display +//! +//!```rust, no_run +//!#![no_std] +//!#![no_main] +//! +//!use embedded_graphics::{ +//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, +//! prelude::*, +//! primitives::PrimitiveStyle, +//! text::{Alignment, Text}, +//!}; +//! +//!use cortex_m_rt::entry; +//!//use defmt::*; +//!use defmt_rtt as _; +//! +//!use panic_probe as _; +//!use rp_pico::hal::{ +//! self, +//! clocks::{init_clocks_and_plls, Clock}, +//! gpio::{FunctionSpi, PinState, Pins}, +//! pac, +//! sio::Sio, +//! watchdog::Watchdog, +//!}; +//! +//!use fugit::RateExtU32; +//! +//!use epd_waveshare::{epd2in66b::*, prelude::*}; +//! +//!// Use embedded-graphics to create a bitmap to show +//!fn drawing() -> Display2in66b { +//! // Create a Display buffer to draw on, specific for this ePaper +//! let mut display = Display2in66b::default(); +//! +//! // Landscape mode, USB plug to the right +//! display.set_rotation(DisplayRotation::Rotate270); +//! +//! // Change the background from the default black to white +//! let _ = display +//! .bounding_box() +//! .into_styled(PrimitiveStyle::with_fill(TriColor::White)) +//! .draw(&mut display); +//! +//! // Draw some text on the buffer +//! let text = "Pico-ePaper-2.66 B/W/R"; +//! Text::with_alignment( +//! text, +//! display.bounding_box().center() + Point::new(1, 0), +//! MonoTextStyle::new(&FONT_10X20, TriColor::Black), +//! Alignment::Center, +//! ) +//! .draw(&mut display) +//! .unwrap(); +//! Text::with_alignment( +//! text, +//! display.bounding_box().center() + Point::new(0, 1), +//! MonoTextStyle::new(&FONT_10X20, TriColor::Chromatic), +//! Alignment::Center, +//! ) +//! .draw(&mut display) +//! .unwrap(); +//! +//! display +//!} +//! +//!#[entry] +//!fn main() -> ! { +//! let mut pac = pac::Peripherals::take().unwrap(); +//! let core = pac::CorePeripherals::take().unwrap(); +//! let mut watchdog = Watchdog::new(pac.WATCHDOG); +//! let external_xtal_freq_hz = 12_000_000u32; +//! let clocks = init_clocks_and_plls( +//! external_xtal_freq_hz, +//! pac.XOSC, +//! pac.CLOCKS, +//! pac.PLL_SYS, +//! pac.PLL_USB, +//! &mut pac.RESETS, +//! &mut watchdog, +//! ) +//! .ok() +//! .unwrap(); +//! +//! let sio = Sio::new(pac.SIO); +//! let pins = Pins::new( +//! pac.IO_BANK0, +//! pac.PADS_BANK0, +//! sio.gpio_bank0, +//! &mut pac.RESETS, +//! ); +//! // pin assignemnts +//! let _ = pins.gpio10.into_mode::(); +//! let _ = pins.gpio11.into_mode::(); +//! let chip_select_pin = pins.gpio9.into_push_pull_output_in_state(PinState::High); +//! let is_busy_pin = pins.gpio13.into_floating_input(); +//! let data_or_command_pin = pins.gpio8.into_push_pull_output_in_state(PinState::High); +//! let reset_pin = pins.gpio12.into_push_pull_output_in_state(PinState::High); +//! +//! // spi +//! let spi = hal::Spi::<_, _, 8>::new(pac.SPI1); +//! let mut spi = spi.init( +//! &mut pac.RESETS, +//! clocks.peripheral_clock.freq(), +//! 20_000_000u32.Hz(), +//! &SPI_MODE, +//! ); +//! +//! //delay +//! let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); +//! +//! // Setup EPD +//! let mut e_paper = Epd2in66b::new( +//! &mut spi, +//! chip_select_pin, +//! is_busy_pin, +//! data_or_command_pin, +//! reset_pin, +//! &mut delay, +//! None, +//! ) +//! .unwrap(); +//! +//! // Create and fill a Display buffer +//! let display = drawing(); +//! +//! // Send the Display buffer to the ePaper RAM +//! e_paper +//! .update_color_frame( +//! &mut spi, +//! &mut delay, +//! &display.bw_buffer(), +//! &display.chromatic_buffer(), +//! ) +//! .unwrap(); +//! +//! // Render the ePaper RAM - takes time. +//! e_paper.display_frame(&mut spi, &mut delay).unwrap(); +//! +//! // Always sleep your EPD as much as possible - ePaper wears out while powered on. +//! e_paper.sleep(&mut spi, &mut delay).unwrap(); +//! +//! delay.delay_ms(60 * 1000); +//! +//! // Set the display all-white before storing your ePaper long-term. +//! e_paper.wake_up(&mut spi, &mut delay).unwrap(); +//! e_paper.clear_frame(&mut spi, &mut delay).unwrap(); +//! e_paper.display_frame(&mut spi, &mut delay).unwrap(); +//! e_paper.sleep(&mut spi, &mut delay).unwrap(); +//! +//! loop {} +//!} +//!``` + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::color::TriColor; +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +pub(crate) mod command; +use self::command::*; +use crate::buffer_len; + +/// Display height in pixels. +pub const WIDTH: u32 = 152; +/// Display width in pixels +pub const HEIGHT: u32 = 296; + +/// White, display this during long-term storage +pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; + +/// A Display buffer configured with our extent and color depth. +#[cfg(feature = "graphics")] +pub type Display2in66b = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) * 2 }, + TriColor, +>; + +/// The EPD 2in66-B driver. +pub struct Epd2in66b { + interface: DisplayInterface, + background: TriColor, +} + +impl InternalWiAdditions + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // We follow the sequence of the Pi-Pico hat example code. + self.hw_reset(delay)?; + self.sw_reset(spi, delay)?; + self.data_entry_mode(spi, DataEntryRow::XMinor, DataEntrySign::IncYIncX)?; + self.set_display_window(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.update_control1( + spi, + WriteMode::Normal, + WriteMode::Normal, + OutputSource::S8ToS167, + )?; + self.set_cursor(spi, 0, 0)?; + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, delay, black)?; + self.update_chromatic_frame(spi, delay, chromatic) + } + + fn update_achromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + black: &[u8], + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.interface.cmd(spi, Command::WriteBlackWhiteRAM)?; + self.interface.data(spi, black) + } + + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.interface.cmd(spi, Command::WriteRedRAM)?; + self.interface.data(spi, chromatic) + } +} + +impl WaveshareDisplay + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + type DisplayColor = TriColor; + + fn new( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result + where + Self: Sized, + { + let mut epd = Self { + interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + background: DEFAULT_BACKGROUND_COLOR, + }; + epd.init(spi, delay)?; + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::DeepSleepMode, + &[DeepSleep::SleepLosingRAM as u8], + ) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay) + } + + fn set_background_color(&mut self, color: Self::DisplayColor) { + self.background = color; + } + + fn background_color(&self) -> &Self::DisplayColor { + &self.background + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.update_achromatic_frame(spi, delay, buffer)?; + self.red_pattern(spi, delay, PatW::W160, PatH::H296, StartWith::Zero) // do NOT consider background here since red overrides other colors + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.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> { + self.interface.cmd(spi, Command::MasterActivation)?; + self.wait_until_idle(delay) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + let (white, red) = match self.background { + TriColor::Black => (StartWith::Zero, StartWith::Zero), + TriColor::White => (StartWith::One, StartWith::Zero), + TriColor::Chromatic => (StartWith::Zero, StartWith::One), + }; + self.black_white_pattern(spi, delay, PatW::W160, PatH::H296, white)?; + self.red_pattern(spi, delay, PatW::W160, PatH::H296, red) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + Ok(()) + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(delay) + } +} + +// Helper functions that enforce some type and value constraints. Meant to help with code readability. They caught some of my silly errors -> yay rust!. +impl Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, false); + Ok(()) + } + fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + // The initial delay is taken from other code here, the 2 ms comes from the SSD1675B datasheet. + self.interface.reset(delay, 20_000, 2_000); + self.wait_until_idle(delay) + } + fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::Reset)?; + self.wait_until_idle(delay) + } + fn data_entry_mode( + &mut self, + spi: &mut SPI, + row: DataEntryRow, + sign: DataEntrySign, + ) -> Result<(), SPI::Error> { + self.interface + .cmd_with_data(spi, Command::DataEntryMode, &[row as u8 | sign as u8]) + } + fn set_display_window( + &mut self, + spi: &mut SPI, + xstart: u32, + ystart: u32, + xend: u32, + yend: u32, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::SetXAddressRange, + &[(((xstart >> 3) & 0x1f) as u8), (((xend >> 3) & 0x1f) as u8)], + )?; + self.interface.cmd_with_data( + spi, + Command::SetYAddressRange, + &[ + ((ystart & 0xff) as u8), + (((ystart >> 8) & 0x01) as u8), + ((yend & 0xff) as u8), + (((yend >> 8) & 0x01) as u8), + ], + ) + } + fn update_control1( + &mut self, + spi: &mut SPI, + red_mode: WriteMode, + bw_mode: WriteMode, + source: OutputSource, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::DisplayUpdateControl1, + &[((red_mode as u8) << 4 | bw_mode as u8), (source as u8)], + ) + } + + fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::SetXAddressCounter, + &[((x >> 3) & 0x1f) as u8], + )?; + self.interface.cmd_with_data( + spi, + Command::SetYAddressCounter, + &[((y & 0xff) as u8), (((y >> 8) & 0x01) as u8)], + ) + } + + fn black_white_pattern( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + w: PatW, + h: PatH, + phase: StartWith, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::BlackWhiteRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + )?; + self.wait_until_idle(delay) + } + fn red_pattern( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + w: PatW, + h: PatH, + phase: StartWith, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::RedRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + )?; + self.wait_until_idle(delay) + } +} diff --git a/src/lib.rs b/src/lib.rs index 677f16b9..0d94ec76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ pub mod epd1in54b; pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in13bc; +pub mod epd2in66b; pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; From a5a1f319960e35042fdf126b1c52ba0175fbdf2e Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:40:03 +0100 Subject: [PATCH 04/69] documentation --- src/epd2in66b/mod.rs | 70 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 5dbfdd3f..7ce8fba0 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -1,41 +1,38 @@ -//! A simple Driver for the Waveshare 2.66"-B E-Ink Display via SPI +//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B'. //! -//! More information on this display can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) -//! This driver was built and tested for 296x152, 2.66inch E-Ink display HAT for Raspberry Pi Pico, three-color, SPI interface. //! -//! # Example for the 2.66"B Pi Pico Hat E-Ink Display +//! This driver was built and tested for this 296x152, 2.66inch E-Ink display hat for the Pi Pico, it is expected to work for +//! other boards too, but that might depend on how the OTP memory in the display is programmed by the factory. //! +//! The driver embedded in the display of this board is the SSD1675B, [documented by cursedhardware](https://cursedhardware.github.io/epd-driver-ic/SSD1675B.pdf). +//! +//! The pin assigments are shown on the Waveshare wiki [schematic](https://www.waveshare.com/w/upload/8/8d/Pico-ePaper-2.66.pdf). +//! +//! Information on this display/hat can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B). +//! Do read this documentation, in particular to understand how often this display both must and cannot be updated. +//! +//! # Example for the 'Pico-ePaper-2.66-B' Pi Pico Hat E-Ink Display +//! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will +//! need to adjust for your preferred setup. //!```rust, no_run //!#![no_std] //!#![no_main] -//! -//!use embedded_graphics::{ -//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, -//! prelude::*, -//! primitives::PrimitiveStyle, -//! text::{Alignment, Text}, -//!}; +//!use epd_waveshare::{epd2in66b::*, prelude::*}; //! //!use cortex_m_rt::entry; //!//use defmt::*; //!use defmt_rtt as _; -//! //!use panic_probe as _; -//!use rp_pico::hal::{ -//! self, -//! clocks::{init_clocks_and_plls, Clock}, -//! gpio::{FunctionSpi, PinState, Pins}, -//! pac, -//! sio::Sio, -//! watchdog::Watchdog, -//!}; -//! -//!use fugit::RateExtU32; -//! -//!use epd_waveshare::{epd2in66b::*, prelude::*}; //! //!// Use embedded-graphics to create a bitmap to show //!fn drawing() -> Display2in66b { +//! use embedded_graphics::{ +//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, +//! prelude::*, +//! primitives::PrimitiveStyle, +//! text::{Alignment, Text}, +//! }; +//! //! // Create a Display buffer to draw on, specific for this ePaper //! let mut display = Display2in66b::default(); //! @@ -72,6 +69,17 @@ //! //!#[entry] //!fn main() -> ! { +//! use fugit::RateExtU32; +//! use rp_pico::hal::{ +//! self, +//! clocks::{init_clocks_and_plls, Clock}, +//! gpio::{FunctionSpi, PinState, Pins}, +//! pac, +//! sio::Sio, +//! watchdog::Watchdog, +//! }; +//! +//! // Boilerplate to access the peripherals //! let mut pac = pac::Peripherals::take().unwrap(); //! let core = pac::CorePeripherals::take().unwrap(); //! let mut watchdog = Watchdog::new(pac.WATCHDOG); @@ -87,7 +95,6 @@ //! ) //! .ok() //! .unwrap(); -//! //! let sio = Sio::new(pac.SIO); //! let pins = Pins::new( //! pac.IO_BANK0, @@ -95,7 +102,8 @@ //! sio.gpio_bank0, //! &mut pac.RESETS, //! ); -//! // pin assignemnts +//! +//! // Pin assignments of the Pi Pico-ePaper-2.66 Hat //! let _ = pins.gpio10.into_mode::(); //! let _ = pins.gpio11.into_mode::(); //! let chip_select_pin = pins.gpio9.into_push_pull_output_in_state(PinState::High); @@ -103,19 +111,19 @@ //! let data_or_command_pin = pins.gpio8.into_push_pull_output_in_state(PinState::High); //! let reset_pin = pins.gpio12.into_push_pull_output_in_state(PinState::High); //! -//! // spi +//! // SPI //! let spi = hal::Spi::<_, _, 8>::new(pac.SPI1); //! let mut spi = spi.init( //! &mut pac.RESETS, //! clocks.peripheral_clock.freq(), -//! 20_000_000u32.Hz(), +//! 20_000_000u32.Hz(), // The SSD1675B docs say 20MHz max //! &SPI_MODE, //! ); //! -//! //delay +//! // Delay //! let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); //! -//! // Setup EPD +//! // Setup the EPD driver //! let mut e_paper = Epd2in66b::new( //! &mut spi, //! chip_select_pin, @@ -143,7 +151,7 @@ //! // Render the ePaper RAM - takes time. //! e_paper.display_frame(&mut spi, &mut delay).unwrap(); //! -//! // Always sleep your EPD as much as possible - ePaper wears out while powered on. +//! // Always turn off your EPD as much as possible - ePaper wears out while powered on. //! e_paper.sleep(&mut spi, &mut delay).unwrap(); //! //! delay.delay_ms(60 * 1000); From ba6b8ef2a3e33660105b7cd7cdd90b569eabc582 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:40:57 +0100 Subject: [PATCH 05/69] fix number base bug & clippy remarks --- src/epd2in66b/command.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs index a7528507..bd6c28f1 100644 --- a/src/epd2in66b/command.rs +++ b/src/epd2in66b/command.rs @@ -57,7 +57,7 @@ pub(crate) enum Command { SetYAddressCounter = 0x4f, SetAnalogBlockControl = 0x74, SetDigitalBlockControl = 0x7e, - NOP = 0x7f, + Nop = 0x7f, } impl traits::Command for Command { @@ -81,7 +81,7 @@ pub(crate) enum DataEntryRow { pub(crate) enum WriteMode { Normal = 0b0000, ForceZero = 0b0100, - Invert = 01000, + Invert = 0b1000, } pub(crate) enum OutputSource { S0ToS175 = 0x00, From 7fe3069a829d68486113c160976a9deef30e2477 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:42:01 +0100 Subject: [PATCH 06/69] remove a redundant attribute --- src/epd2in66b/command.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs index bd6c28f1..d0d22059 100644 --- a/src/epd2in66b/command.rs +++ b/src/epd2in66b/command.rs @@ -2,7 +2,6 @@ ///! SPI Commands for the SSD1675B driver chip use crate::traits; -#[allow(dead_code)] #[derive(Copy, Clone)] pub(crate) enum Command { DriverOutputControl = 0x01, From b176194a7639e51a328e65073fd381927a4c46f3 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 12:29:10 +0100 Subject: [PATCH 07/69] add 2in66 entry to the README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bb088199..97b399bb 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [2.9 Inch B/W/R (B/C)](https://www.waveshare.com/product/displays/e-paper/epaper-2/2.9inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | +| [2.66 Inch 3 Color (B)](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | ### [1]: 7.5 Inch B/W V2 (A) From 1c717ebe595e949be755d67d7b44342452b8c2c4 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 12:35:02 +0100 Subject: [PATCH 08/69] documentation tweaks --- src/epd2in66b/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 7ce8fba0..17a4abcd 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -1,7 +1,7 @@ -//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B'. +//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B' B/W/R. //! //! -//! This driver was built and tested for this 296x152, 2.66inch E-Ink display hat for the Pi Pico, it is expected to work for +//! This driver was built and tested for this 296x152, 2.66inch three-color E-Ink display hat for the Pi Pico, it is expected to work for //! other boards too, but that might depend on how the OTP memory in the display is programmed by the factory. //! //! The driver embedded in the display of this board is the SSD1675B, [documented by cursedhardware](https://cursedhardware.github.io/epd-driver-ic/SSD1675B.pdf). @@ -9,9 +9,9 @@ //! The pin assigments are shown on the Waveshare wiki [schematic](https://www.waveshare.com/w/upload/8/8d/Pico-ePaper-2.66.pdf). //! //! Information on this display/hat can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B). -//! Do read this documentation, in particular to understand how often this display both must and cannot be updated. +//! Do read this documentation, in particular to understand how often this display both should and should not be updated. //! -//! # Example for the 'Pico-ePaper-2.66-B' Pi Pico Hat E-Ink Display +//! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. //!```rust, no_run From 058483c2780d49667941d3c8d4a674c734b45aaf Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 13:06:59 +0100 Subject: [PATCH 09/69] tweak documentation to pass (skip) doc test --- src/epd2in66b/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 17a4abcd..ed67d850 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -14,7 +14,7 @@ //! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. -//!```rust, no_run +//!```no_run //!#![no_std] //!#![no_main] //!use epd_waveshare::{epd2in66b::*, prelude::*}; From b94f12b3ebdd3513b99d48fa7103b3b7aeb02bf9 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 13:32:12 +0100 Subject: [PATCH 10/69] tweak documentation to pass (skip) doc test, try2 --- src/epd2in66b/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index ed67d850..42666312 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -14,7 +14,7 @@ //! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. -//!```no_run +//!```ignore //!#![no_std] //!#![no_main] //!use epd_waveshare::{epd2in66b::*, prelude::*}; From 9e77eefb40ceb2a31b6aa8b51719e001b439e605 Mon Sep 17 00:00:00 2001 From: andber1 <82754113+andber1@users.noreply.github.com> Date: Wed, 29 Mar 2023 19:20:04 +0200 Subject: [PATCH 11/69] Update refresh rate see also https://github.com/waveshare/e-Paper/commit/588163b --- src/epd2in9_v2/mod.rs | 26 +++++++++++++++++++++++++- src/type_a/command.rs | 4 ++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 5158627a..515c6fab 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -74,6 +74,18 @@ const LUT_PARTIAL_2IN9: [u8; 153] = [ 0x22, 0x0, 0x0, 0x0, ]; +const WS_20_30: [u8; 159] = [ + 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x10, 0x66, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, + 0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x0, 0x0, 0x0, 0x1, 0xA, 0xA, 0x0, 0xA, 0xA, 0x0, + 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x14, 0x8, 0x0, 0x1, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x0, 0x0, 0x0, 0x22, 0x17, 0x41, 0x0, 0x32, 0x36, +]; + use embedded_hal::{ blocking::{delay::*, spi::Write}, digital::v2::*, @@ -141,6 +153,18 @@ where self.set_ram_counter(spi, 0, 0)?; self.wait_until_idle(); + + // set LUT by host + self.set_lut_helper(spi, &WS_20_30[0..153])?; + self.interface + .cmd_with_data(spi, Command::Eopq, &WS_20_30[153..154])?; + self.interface + .cmd_with_data(spi, Command::GateVoltage, &WS_20_30[154..155])?; + self.interface + .cmd_with_data(spi, Command::SourceVoltage, &WS_20_30[155..158])?; + self.interface + .cmd_with_data(spi, Command::WriteVcomRegister, &WS_20_30[158..159])?; + Ok(()) } } @@ -231,7 +255,7 @@ where self.wait_until_idle(); // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface - .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; self.interface.cmd(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) diff --git a/src/type_a/command.rs b/src/type_a/command.rs index 97af56ac..da3bec4b 100644 --- a/src/type_a/command.rs +++ b/src/type_a/command.rs @@ -17,6 +17,8 @@ pub(crate) enum Command { /// 0.. B[2:0] /// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0 DriverOutputControl = 0x01, + GateVoltage = 0x03, + SourceVoltage = 0x04, /// Booster Soft start control /// 3 Databytes: /// 1.. A[6:0] @@ -63,6 +65,8 @@ pub(crate) enum Command { BorderWaveformControl = 0x3C, + Eopq = 0x3F, + SetRamXAddressStartEndPosition = 0x44, SetRamYAddressStartEndPosition = 0x45, From 24c2bd0e383077f10b6028fb52c2eb972283b4eb Mon Sep 17 00:00:00 2001 From: andber1 <82754113+andber1@users.noreply.github.com> Date: Wed, 29 Mar 2023 19:53:28 +0200 Subject: [PATCH 12/69] Fix build error --- src/epd2in9_v2/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index bca922c6..265f63ec 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -161,7 +161,7 @@ where self.wait_until_idle(spi, delay)?; // set LUT by host - self.set_lut_helper(spi, &WS_20_30[0..153])?; + self.set_lut_helper(spi, delay, &WS_20_30[0..153])?; self.interface .cmd_with_data(spi, Command::WriteLutRegisterEnd, &WS_20_30[153..154])?; self.interface From 819391d2e6f5e81fcd32c41e8b7eddc32ce2eb56 Mon Sep 17 00:00:00 2001 From: Fabian Kunze Date: Mon, 1 May 2023 17:08:44 +0200 Subject: [PATCH 13/69] Added loading of look-up-table to init for 1in54_v2 --- src/epd1in54_v2/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 60a43d38..745d54d7 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -71,9 +71,6 @@ where self.set_ram_area(spi, delay, 0, 0, WIDTH - 1, HEIGHT - 1)?; - self.interface - .cmd_with_data(spi, Command::BorderWaveformControl, &[0x1])?; - self.interface.cmd_with_data( spi, Command::TemperatureSensorSelection, @@ -85,6 +82,9 @@ where self.set_ram_counter(spi, delay, 0, 0)?; + //Initialize the lookup table with a refresh waveform + self.set_lut(spi, delay, None)?; + self.wait_until_idle(spi, delay)?; Ok(()) } From 4ede237cd01dbbc967563bd4756cbfbbcd9bc2c7 Mon Sep 17 00:00:00 2001 From: Carbonhell Date: Sat, 10 Jun 2023 22:47:09 +0200 Subject: [PATCH 14/69] Adds support for the Waveshare 5.83" E-Ink Display --- src/epd5in83_v2/command.rs | 134 ++++++++++++++++++ src/epd5in83_v2/mod.rs | 274 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 409 insertions(+) create mode 100644 src/epd5in83_v2/command.rs create mode 100644 src/epd5in83_v2/mod.rs diff --git a/src/epd5in83_v2/command.rs b/src/epd5in83_v2/command.rs new file mode 100644 index 00000000..46b6b642 --- /dev/null +++ b/src/epd5in83_v2/command.rs @@ -0,0 +1,134 @@ +//! SPI Commands for the Waveshare 5.83" E-Ink Display + +use crate::traits; + +/// Epd5in83 commands +/// +/// Should rarely (never?) be needed directly. +/// +/// For more infos about the addresses and what they are doing look into the PDFs. +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift + /// direction, booster switch, soft reset. + PanelSetting = 0x00, + + /// Selecting internal and external power + PowerSetting = 0x01, + + /// After the Power Off command, the driver will power off following the Power Off + /// Sequence; BUSY signal will become "0". This command will turn off charge pump, + /// T-con, source driver, gate driver, VCOM, and temperature sensor, but register + /// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain + /// as previous condition, which may have 2 conditions: 0V or floating. + PowerOff = 0x02, + + /// Setting Power OFF sequence + PowerOffSequenceSetting = 0x03, + + /// Turning On the Power + /// + /// After the Power ON command, the driver will power on following the Power ON + /// sequence. Once complete, the BUSY signal will become "1". + PowerOn = 0x04, + + /// Starting data transmission + BoosterSoftStart = 0x06, + + /// This command makes the chip enter the deep-sleep mode to save power. + /// + /// The deep sleep mode would return to stand-by by hardware reset. + /// + /// The only one parameter is a check code, the command would be excuted if check code = 0xA5. + DeepSleep = 0x07, + + /// This command starts transmitting B/W data and write them into SRAM. To complete data + /// transmission, commands Display Refresh or Data Start Transmission2 must be issued. Then the chip will start to + /// send data/VCOM for panel. + DataStartTransmission1 = 0x10, + + /// This command starts transmitting RED data and write them into SRAM. To complete data + /// transmission, command Display refresh must be issued. Then the chip will start to + /// send data/VCOM for panel. + DataStartTransmission2 = 0x13, + + /// To stop data transmission, this command must be issued to check the `data_flag`. + /// + /// After this command, BUSY signal will become "0" until the display update is + /// finished. + DataStop = 0x11, + + /// After this command is issued, driver will refresh display (data/VCOM) according to + /// SRAM data and LUT. + /// + /// After Display Refresh command, BUSY signal will become "0" until the display + /// update is finished. + DisplayRefresh = 0x12, + + /// Enables or disables Dual SPI mode + DualSPI = 0x15, + + /// The command controls the PLL clock frequency. + PllControl = 0x30, + + /// This command reads the temperature sensed by the temperature sensor. + TemperatureSensorCalibration = 0x40, + /// This command selects the Internal or External temperature sensor. + TemperatureSensorSelection = 0x41, + /// This command could write data to the external temperature sensor. + TemperatureSensorWrite = 0x42, + /// This command could read data from the external temperature sensor. + TemperatureSensorRead = 0x43, + + /// This command indicates the interval of Vcom and data output. When setting the + /// vertical back porch, the total blanking will be kept (20 Hsync). + VcomAndDataIntervalSetting = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn + /// the battery condition. + LowPowerDetection = 0x51, + + /// This command defines non-overlap period of Gate and Source. + TconSetting = 0x60, + /// This command defines alternative resolution and this setting is of higher priority + /// than the RES\[1:0\] in R00H (PSR). + TconResolution = 0x61, + + /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. + Revision = 0x70, + /// This command reads the IC status. + GetStatus = 0x71, + + /// This command implements related VCOM sensing setting. + AutoMeasurementVcom = 0x80, + /// This command gets the VCOM value. + ReadVcomValue = 0x81, + /// This command sets `VCOM_DC` value. + VcmDcSetting = 0x82, + + /// Sets window size for the partial update + PartialWindow = 0x90, + /// Sets chip into partial update mode + PartialIn = 0x91, + /// Quits partial update mode + PartialOut = 0x92, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::traits::Command as CommandTrait; + + #[test] + fn command_addr() { + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); + } +} diff --git a/src/epd5in83_v2/mod.rs b/src/epd5in83_v2/mod.rs new file mode 100644 index 00000000..4cc6bf5f --- /dev/null +++ b/src/epd5in83_v2/mod.rs @@ -0,0 +1,274 @@ +//! A simple Driver for the Waveshare 5.83" v2 E-Ink Display via SPI +//! +//! # References +//! +//! - [Datasheet](https://www.waveshare.com/5.83inch-e-paper-hat.htm) +//! - [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::{ + blocking::{delay::*, spi::Write}, + digital::v2::{InputPin, OutputPin}, +}; + +use crate::color::Color; +use crate::interface::DisplayInterface; +use crate::prelude::WaveshareDisplay; +use crate::traits::{InternalWiAdditions, RefreshLut}; + +pub(crate) mod command; +use self::command::Command; +use crate::buffer_len; + +/// Full size buffer for use with the 5in83 v2 EPD +#[cfg(feature = "graphics")] +pub type Display5in83 = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) }, + Color, +>; + +/// Width of the display +pub const WIDTH: u32 = 648; +/// Height of the display +pub const HEIGHT: u32 = 480; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; +const IS_BUSY_LOW: bool = true; +const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; + +/// Epd5in83 driver +/// +pub struct Epd5in83 { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: Color, +} + +impl InternalWiAdditions + for Epd5in83 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // Reset the device + 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])?; + + // Power on + self.command(spi, Command::PowerOn)?; + delay.delay_us(5000); + self.wait_until_idle(spi, delay)?; + + // Set the panel settings: BWOTP + self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; + + // Set the real resolution + self.send_resolution(spi)?; + + // Disable dual SPI + self.cmd_with_data(spi, Command::DualSPI, &[0x00])?; + + // Set Vcom and data interval + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?; + + // Set S2G and G2S non-overlap periods to 12 (default) + self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + + self.wait_until_idle(spi, delay)?; + Ok(()) + } +} + +impl WaveshareDisplay + for Epd5in83 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + type DisplayColor = Color; + fn new( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd5in83 { interface, color }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.command(spi, Command::PowerOff)?; + self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + Ok(()) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay) + } + + fn set_background_color(&mut self, color: Color) { + self.color = color; + } + + fn background_color(&self) -> &Color { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + let color_value = self.color.get_byte_value(); + + self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; + + self.interface + .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _buffer: &[u8], + _x: u32, + _y: u32, + _width: u32, + _height: u32, + ) -> Result<(), SPI::Error> { + unimplemented!() + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh)?; + self.wait_until_idle(spi, delay)?; + Ok(()) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + + self.command(spi, Command::DataStartTransmission1)?; + self.interface.data_x_times(spi, 0xFF, NUM_DISPLAY_BITS)?; + + self.command(spi, Command::DataStartTransmission2)?; + self.interface.data_x_times(spi, 0x00, NUM_DISPLAY_BITS)?; + + Ok(()) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + unimplemented!(); + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW); + Ok(()) + } +} + +impl Epd5in83 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command) + } + + fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data) + } + + fn cmd_with_data( + &mut self, + spi: &mut SPI, + command: Command, + data: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data(spi, command, data) + } + + fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.command(spi, Command::TconResolution)?; + self.send_data(spi, &[(w >> 8) as u8])?; + self.send_data(spi, &[w as u8])?; + self.send_data(spi, &[(h >> 8) as u8])?; + self.send_data(spi, &[h as u8]) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn epd_size() { + assert_eq!(WIDTH, 648); + assert_eq!(HEIGHT, 480); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); + } +} diff --git a/src/lib.rs b/src/lib.rs index 677f16b9..0d0fd154 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,6 +86,7 @@ pub mod epd2in9bc; pub mod epd3in7; pub mod epd4in2; pub mod epd5in65f; +pub mod epd5in83_v2; pub mod epd5in83b_v2; pub mod epd7in5; pub mod epd7in5_hd; From 6fd7b54889fed7e2ac523f9b7b2ca92414e92533 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 12 Jun 2023 23:41:50 +0200 Subject: [PATCH 15/69] Remove manual default impl and instead derive --- src/graphics.rs | 9 ++------- src/traits.rs | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/src/graphics.rs b/src/graphics.rs index 950401f6..7037cef5 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -5,9 +5,10 @@ use core::marker::PhantomData; use embedded_graphics_core::prelude::*; /// Display rotation, only 90° increments supported -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Default)] pub enum DisplayRotation { /// No rotation + #[default] Rotate0, /// Rotate by 90 degrees clockwise Rotate90, @@ -17,12 +18,6 @@ pub enum DisplayRotation { Rotate270, } -impl Default for DisplayRotation { - fn default() -> Self { - DisplayRotation::Rotate0 - } -} - /// count the number of bytes per line knowing that it may contains padding bits const fn line_bytes(width: u32, bits_per_pixel: usize) -> usize { // round to upper 8 bit count diff --git a/src/traits.rs b/src/traits.rs index 00cceb6a..f496f64d 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -11,21 +11,16 @@ pub(crate) trait Command: Copy { } /// Seperates the different LUT for the Display Refresh process -#[derive(Debug, Clone, PartialEq, Eq, Copy)] +#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)] pub enum RefreshLut { /// The "normal" full Lookuptable for the Refresh-Sequence + #[default] Full, /// The quick LUT where not the full refresh sequence is followed. /// This might lead to some Quick, } -impl Default for RefreshLut { - fn default() -> Self { - RefreshLut::Full - } -} - pub(crate) trait InternalWiAdditions where SPI: Write, From cef5279bd8a641cfb680c275f1afa08981639623 Mon Sep 17 00:00:00 2001 From: Dom Rodriguez Date: Sun, 11 Jun 2023 19:09:35 +0100 Subject: [PATCH 16/69] Order displays from largest size to smallest This makes it easier to read, and organises the supported displays in the table. --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index bb088199..437572f4 100644 --- a/README.md +++ b/README.md @@ -51,17 +51,17 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [7.5 Inch B/W V2 (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) [[1](#1-75-inch-bw-v2-a)] | Black, White | ✕ | ✕ | ✔ | ✔ | | [7.5 Inch B/W (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) | Black, White | ✕ | ✕ | ✔ | ✔ | | [5.83 Inch B/W/R (b)](https://www.waveshare.com/5.83inch-e-Paper-B.htm) | Black, White, Red | ✕ | Not officially | ✔ | ✔ | +| [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | | [4.2 Inch B/W (A)](https://www.waveshare.com/product/4.2inch-e-paper-module.htm) | Black, White | ✕ | Not officially [[2](#2-42-inch-e-ink-blackwhite---partial-refresh)] | ✔ | ✔ | -| [1.54 Inch B/W (A)](https://www.waveshare.com/1.54inch-e-Paper-Module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.13 Inch B/W (A) V2](https://www.waveshare.com/product/2.13inch-e-paper-hat.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.13 Inch B/W/R (B/C) V2](https://www.waveshare.com/product/raspberry-pi/displays/e-paper/2.13inch-e-paper-hat-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | +| [2.9 Inch B/W/R (B/C)](https://www.waveshare.com/product/displays/e-paper/epaper-2/2.9inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | +| [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | | [1.54 Inch B/W/R (B)](https://www.waveshare.com/product/modules/oleds-lcds/e-paper/1.54inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/Y (C)](https://www.waveshare.com/1.54inch-e-paper-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | -| [2.9 Inch B/W/R (B/C)](https://www.waveshare.com/product/displays/e-paper/epaper-2/2.9inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | -| [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | -| [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | +| [1.54 Inch B/W (A)](https://www.waveshare.com/1.54inch-e-Paper-Module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | ### [1]: 7.5 Inch B/W V2 (A) From b2bcfa179dc6fd9d85c5b3971e63f3be43181118 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 7 Dec 2022 21:56:00 +0100 Subject: [PATCH 17/69] Use feature gate to add 2in13 v3 --- Cargo.toml | 4 ++- src/epd2in13_v2/constants.rs | 51 ++++++++++++++++++++++++++++++++++++ src/epd2in13_v2/mod.rs | 27 +++++++++++++++---- 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31fdde89..ebaa06de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,9 +50,11 @@ required-features = ["linux-dev"] [features] # Remove the linux-dev feature to build the tests on non unix systems -default = ["graphics", "linux-dev"] +default = ["graphics", "linux-dev", "epd2in13_v2"] graphics = ["embedded-graphics-core"] +epd2in13_v2 = [] +epd2in13_v3 = [] linux-dev = [] # Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking diff --git a/src/epd2in13_v2/constants.rs b/src/epd2in13_v2/constants.rs index 8c5ef373..68959599 100644 --- a/src/epd2in13_v2/constants.rs +++ b/src/epd2in13_v2/constants.rs @@ -1,5 +1,6 @@ #[rustfmt::skip] +#[cfg(feature = "epd2in13_v2")] // Original Waveforms from Waveshare pub(crate) const LUT_FULL_UPDATE: [u8; 70] =[ 0x80,0x60,0x40,0x00,0x00,0x00,0x00, // LUT0: BB: VS 0 ~7 @@ -17,6 +18,7 @@ pub(crate) const LUT_FULL_UPDATE: [u8; 70] =[ 0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 ]; +#[cfg(feature = "epd2in13_v2")] #[rustfmt::skip] pub(crate) const LUT_PARTIAL_UPDATE: [u8; 70] =[ 0x00,0x00,0x00,0x00,0x00,0x00,0x00, // LUT0: BB: VS 0 ~7 @@ -33,3 +35,52 @@ pub(crate) const LUT_PARTIAL_UPDATE: [u8; 70] =[ 0x00,0x00,0x00,0x00,0x00, // TP5 A~D RP5 0x00,0x00,0x00,0x00,0x00, // TP6 A~D RP6 ]; + +#[cfg(feature = "epd2in13_v3")] +#[rustfmt::skip] +// Original Waveforms from Waveshare +pub(crate) const LUT_PARTIAL_UPDATE: [u8; 159] =[ + 0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x14,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, + 0x22,0x17,0x41,0x00,0x32,0x36, +]; + +#[cfg(feature = "epd2in13_v3")] +#[rustfmt::skip] +pub(crate) const LUT_FULL_UPDATE: [u8; 159] =[ + 0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xF,0x0,0x0,0x0,0x0,0x0,0x0, + 0xF,0x0,0x0,0xF,0x0,0x0,0x2, + 0xF,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0, + 0x22,0x17,0x41,0x0,0x32,0x36 +]; diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 0efad684..4a97026e 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -1,12 +1,19 @@ -//! A Driver for the Waveshare 2.13" E-Ink Display (V2) via SPI +//! A Driver for the Waveshare 2.13" E-Ink Display (V2 and V3) via SPI //! -//! # References +//! # References V2 //! //! - [Waveshare product page](https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT) //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_2in13_V2.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd2in13_V2.py) //! - [Controller Datasheet SS1780](http://www.e-paper-display.com/download_detail/downloadsId=682.html) //! +//! # References V3 +//! +//! - [Waveshare product page](https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT) +//! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in13_V3.c) +//! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in9b_V3.py) +//! - [Controller Datasheet SS1780](http://www.e-paper-display.com/download_detail/downloadsId=682.html) +//! use embedded_hal::{ blocking::{delay::*, spi::Write}, @@ -26,9 +33,18 @@ use self::command::{ }; pub(crate) mod constants; -use self::constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}; -/// Full size buffer for use with the 2in13 v2 EPD +use self::constants::{LUT_FULL_UPDATE, LUT_PARTIAL_UPDATE}; +#[cfg(all(feature = "epd2in13_v2", feature = "epd2in13_v3"))] +compile_error!( + "feature \"epd2in13_v2\" and feature \"epd2in13_v3\" cannot be enabled at the same time" +); +#[cfg(not(any(feature = "epd2in13_v2", feature = "epd2in13_v3")))] +compile_error!( + "One of feature \"epd2in13_v2\" and feature \"epd2in13_v3\" needs to be enabled as a feature" +); + +/// Full size buffer for use with the 2in13 v2 and v3 EPD #[cfg(feature = "graphics")] pub type Display2in13 = crate::graphics::Display< WIDTH, @@ -48,8 +64,9 @@ pub const HEIGHT: u32 = 250; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; -/// Epd2in13 (V2) driver +/// Epd2in13 (V2 & V3) driver /// +/// To use this driver for V3 of the display, feature \"epd2in13_v2\" needs to be disabled and feature \"epd2in13_v3\" enabled. pub struct Epd2in13 { /// Connection Interface interface: DisplayInterface, From 038fae9b256f2714a4fb3791b15ed94acff5ea31 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:01:34 +0100 Subject: [PATCH 18/69] Remove all-features from clippy Since we added 2 conflicting features, it's not possible to activate both of them at the same time anymore. --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 62031c15..845ce4c2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -21,7 +21,7 @@ jobs: - name: Build lib run: cargo check --all-targets --verbose - name: Clippy - run: cargo clippy --all-targets --all-features -- -D warnings -A clippy::new_ret_no_self + run: cargo clippy --all-targets -- -D warnings -A clippy::new_ret_no_self - name: Build examples run: cargo build --examples --all-targets --verbose - name: Run tests From dbd3636931cf19b7ba26fed63954d4e790da4721 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 7 Dec 2022 22:06:14 +0100 Subject: [PATCH 19/69] Remove all_features from `cargo doc` as well in the ci --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 845ce4c2..ca6e1da0 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -27,5 +27,5 @@ jobs: - name: Run tests run: cargo test --verbose - name: Build docs - run: cargo doc --all-features + run: cargo doc From d49054ace0f30b3ffcafae73957ffbde8f54e25e Mon Sep 17 00:00:00 2001 From: Christoph Gross <11088935+caemor@users.noreply.github.com> Date: Mon, 12 Jun 2023 23:12:21 +0200 Subject: [PATCH 20/69] Change default version to v3 instead of v2 for the epd2in13 --- Cargo.toml | 2 +- src/epd2in13_v2/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ebaa06de..8d5406fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ required-features = ["linux-dev"] [features] # Remove the linux-dev feature to build the tests on non unix systems -default = ["graphics", "linux-dev", "epd2in13_v2"] +default = ["graphics", "linux-dev", "epd2in13_v3"] graphics = ["embedded-graphics-core"] epd2in13_v2 = [] diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 4a97026e..480c70cd 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -66,7 +66,7 @@ const IS_BUSY_LOW: bool = false; /// Epd2in13 (V2 & V3) driver /// -/// To use this driver for V3 of the display, feature \"epd2in13_v2\" needs to be disabled and feature \"epd2in13_v3\" enabled. +/// To use this driver for V2 of the display, feature \"epd2in13_v3\" needs to be disabled and feature \"epd2in13_v2\" enabled. pub struct Epd2in13 { /// Connection Interface interface: DisplayInterface, From 6948a631e1c00a17c5f599a50254bf970cb0a407 Mon Sep 17 00:00:00 2001 From: Dom Rodriguez Date: Wed, 30 Aug 2023 21:28:57 +0100 Subject: [PATCH 21/69] Update 'B' 1.54" e-ink display, and remove 'C' display link The 1.54" B/W/R (B) e-ink display URI has changed. However, the 1.54" B/W/Y (C) e-ink display is no longer available. Resolves #161. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 437572f4..b651884f 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,8 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | -| [1.54 Inch B/W/R (B)](https://www.waveshare.com/product/modules/oleds-lcds/e-paper/1.54inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | -| [1.54 Inch B/W/Y (C)](https://www.waveshare.com/1.54inch-e-paper-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | +| [1.54 Inch B/W/R (B)](https://www.waveshare.com/1.54inch-e-Paper-B.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | +| 1.54 Inch B/W/Y (C) - no longer available | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W (A)](https://www.waveshare.com/1.54inch-e-Paper-Module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | ### [1]: 7.5 Inch B/W V2 (A) From c0ae80620ad96f15453bb7b8e9694aad71589fde Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 31 Aug 2023 08:51:11 +0200 Subject: [PATCH 22/69] Update to embedded hal 1.0-rc.1 --- Cargo.toml | 4 ++-- src/epd1in54/mod.rs | 35 +++++++++++++------------------ src/epd1in54_v2/mod.rs | 35 +++++++++++++------------------ src/epd1in54b/mod.rs | 46 +++++++++++++++++------------------------ src/epd1in54c/mod.rs | 46 +++++++++++++++++------------------------ src/epd2in13_v2/mod.rs | 37 +++++++++++++++------------------ src/epd2in13bc/mod.rs | 46 +++++++++++++++++------------------------ src/epd2in7b/mod.rs | 46 +++++++++++++++++------------------------ src/epd2in9/mod.rs | 35 +++++++++++++------------------ src/epd2in9_v2/mod.rs | 44 ++++++++++++++++----------------------- src/epd2in9bc/mod.rs | 46 +++++++++++++++++------------------------ src/epd3in7/mod.rs | 30 +++++++++++++-------------- src/epd4in2/mod.rs | 46 +++++++++++++++++------------------------ src/epd5in65f/mod.rs | 37 +++++++++++++++------------------ src/epd5in83b_v2/mod.rs | 46 +++++++++++++++++++---------------------- src/epd7in5/mod.rs | 37 +++++++++++++++------------------ src/epd7in5_hd/mod.rs | 37 +++++++++++++++------------------ src/epd7in5_v2/mod.rs | 37 +++++++++++++++------------------ src/epd7in5_v3/mod.rs | 46 +++++++++++++++++++---------------------- src/epd7in5b_v2/mod.rs | 37 +++++++++++++++------------------ src/interface.rs | 32 ++++++++-------------------- src/traits.rs | 36 +++++++++++++------------------- 22 files changed, 357 insertions(+), 484 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 8d5406fb..441776d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,8 @@ edition = "2021" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics-core = { version = "0.3.2", optional = true} -embedded-hal = {version = "0.2.4", features = ["unproven"]} +embedded-graphics-core = { version = "0.3.2", optional = true } +embedded-hal = { version = "1.0.0-rc.1" } bit_field = "0.10.1" [dev-dependencies] diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index aba10c99..8cb58c0a 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -54,10 +54,7 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -82,23 +79,22 @@ pub type Display1in54 = crate::graphics::Display< >; /// Epd1in54 driver -pub struct Epd1in54 { +pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd1in54 +impl Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -146,15 +142,14 @@ where } } -impl WaveshareDisplay - for Epd1in54 +impl WaveshareDisplay + for Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -167,14 +162,13 @@ where fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd1in54 { interface, @@ -300,14 +294,13 @@ where } } -impl Epd1in54 +impl Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index ce1ba7ea..0f0399f7 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -11,10 +11,7 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::type_a::command::Command; @@ -31,9 +28,9 @@ use crate::interface::DisplayInterface; pub use crate::epd1in54::Display1in54; /// Epd1in54 driver -pub struct Epd1in54 { +pub struct Epd1in54 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, @@ -41,14 +38,13 @@ pub struct Epd1in54 { refresh: RefreshLut, } -impl Epd1in54 +impl Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -91,15 +87,14 @@ where } } -impl WaveshareDisplay - for Epd1in54 +impl WaveshareDisplay + for Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -112,14 +107,13 @@ where fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd1in54 { interface, @@ -267,14 +261,13 @@ where } } -impl Epd1in54 +impl Epd1in54 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 5a4a79f4..0a477bf4 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -1,9 +1,6 @@ //! A simple Driver for the Waveshare 1.54" (B) E-Ink Display via SPI -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -41,20 +38,19 @@ pub type Display1in54b = crate::graphics::Display< >; /// Epd1in54b driver -pub struct Epd1in54b { - interface: DisplayInterface, +pub struct Epd1in54b { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd1in54b +impl InternalWiAdditions + for Epd1in54b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -93,15 +89,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd1in54b +impl WaveshareThreeColorDisplay + for Epd1in54b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -144,27 +139,25 @@ where } } -impl WaveshareDisplay - for Epd1in54b +impl WaveshareDisplay + for Epd1in54b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd1in54b { interface, color }; @@ -325,14 +318,13 @@ where } } -impl Epd1in54b +impl Epd1in54b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index b63d3189..341baf7d 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -1,9 +1,6 @@ //! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -38,20 +35,19 @@ pub type Display1in54c = crate::graphics::Display< >; /// Epd1in54c driver -pub struct Epd1in54c { - interface: DisplayInterface, +pub struct Epd1in54c { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd1in54c +impl InternalWiAdditions + for Epd1in54c where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Based on Reference Program Code from: @@ -80,15 +76,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd1in54c +impl WaveshareThreeColorDisplay + for Epd1in54c where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -126,27 +121,25 @@ where } } -impl WaveshareDisplay - for Epd1in54c +impl WaveshareDisplay + for Epd1in54c where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd1in54c { interface, color }; @@ -266,14 +259,13 @@ where } } -impl Epd1in54c +impl Epd1in54c where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 43412910..7712835d 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,8 +16,9 @@ //! use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::buffer_len; @@ -68,9 +69,9 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd2in13 (V2 & V3) driver /// /// To use this driver for V2 of the display, feature \"epd2in13_v3\" needs to be disabled and feature \"epd2in13_v2\" enabled. -pub struct Epd2in13 { +pub struct Epd2in13 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, sleep_mode: DeepSleepMode, @@ -79,15 +80,14 @@ pub struct Epd2in13 { refresh: RefreshLut, } -impl InternalWiAdditions - for Epd2in13 +impl InternalWiAdditions + for Epd2in13 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // HW reset @@ -173,20 +173,18 @@ where } } -impl WaveshareDisplay - for Epd2in13 +impl WaveshareDisplay + for Epd2in13 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, @@ -194,7 +192,7 @@ where delay_us: Option, ) -> Result { let mut epd = Epd2in13 { - interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + interface: DisplayInterface::new(busy, dc, rst, delay_us), sleep_mode: DeepSleepMode::Mode1, background_color: DEFAULT_BACKGROUND_COLOR, refresh: RefreshLut::Full, @@ -388,14 +386,13 @@ where } } -impl Epd2in13 +impl Epd2in13 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 964025e7..8a91d196 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -50,10 +50,7 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -95,20 +92,19 @@ pub type Display2in13bc = crate::graphics::Display< >; /// Epd2in13bc driver -pub struct Epd2in13bc { - interface: DisplayInterface, +pub struct Epd2in13bc { + interface: DisplayInterface, color: TriColor, } -impl InternalWiAdditions - for Epd2in13bc +impl InternalWiAdditions + for Epd2in13bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -144,15 +140,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd2in13bc +impl WaveshareThreeColorDisplay + for Epd2in13bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -196,27 +191,25 @@ where } } -impl WaveshareDisplay - for Epd2in13bc +impl WaveshareDisplay + for Epd2in13bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = TriColor; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd2in13bc { interface, color }; @@ -348,14 +341,13 @@ where } } -impl Epd2in13bc +impl Epd2in13bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 8d442688..941d0393 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -2,10 +2,7 @@ //! //! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -43,22 +40,21 @@ pub type Display2in7b = crate::graphics::Display< >; /// Epd2in7b driver -pub struct Epd2in7b { +pub struct Epd2in7b { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd2in7b +impl InternalWiAdditions + for Epd2in7b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -116,27 +112,25 @@ where } } -impl WaveshareDisplay - for Epd2in7b +impl WaveshareDisplay + for Epd2in7b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd2in7b { interface, color }; @@ -279,15 +273,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd2in7b +impl WaveshareThreeColorDisplay + for Epd2in7b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -336,14 +329,13 @@ where } } -impl Epd2in7b +impl Epd2in7b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 1d9d624c..1ff905b0 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -50,10 +50,7 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const SINGLE_BYTE_WRITE: bool = true; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::type_a::{ command::Command, @@ -79,23 +76,22 @@ pub type Display2in9 = crate::graphics::Display< /// Epd2in9 driver /// -pub struct Epd2in9 { +pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd2in9 +impl Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -139,15 +135,14 @@ where } } -impl WaveshareDisplay - for Epd2in9 +impl WaveshareDisplay + for Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -160,14 +155,13 @@ where fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd2in9 { interface, @@ -296,14 +290,13 @@ where } } -impl Epd2in9 +impl Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 46d94bd1..a867658b 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -75,10 +75,7 @@ const LUT_PARTIAL_2IN9: [u8; 159] = [ 0x22, 0x0, 0x0, 0x0, 0x22, 0x17, 0x41, 0xB0, 0x32, 0x36, ]; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::type_a::command::Command; @@ -102,23 +99,22 @@ pub type Display2in9 = crate::graphics::Display< /// Epd2in9 driver /// -pub struct Epd2in9 { +pub struct Epd2in9 { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT refresh: RefreshLut, } -impl Epd2in9 +impl Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 2_000); @@ -152,15 +148,14 @@ where } } -impl WaveshareDisplay - for Epd2in9 +impl WaveshareDisplay + for Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -173,14 +168,13 @@ where fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let mut epd = Epd2in9 { interface, @@ -297,14 +291,13 @@ where } } -impl Epd2in9 +impl Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram @@ -383,15 +376,14 @@ where } } -impl QuickRefresh - for Epd2in9 +impl QuickRefresh + for Epd2in9 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// To be followed immediately by `update_new_frame`. fn update_old_frame( diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index d884ecd9..0266e134 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -54,10 +54,7 @@ //!# Ok(()) //!# } //!``` -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{ @@ -99,20 +96,19 @@ pub type Display2in9bc = crate::graphics::Display< >; /// Epd2in9bc driver -pub struct Epd2in9bc { - interface: DisplayInterface, +pub struct Epd2in9bc { + interface: DisplayInterface, color: Color, } -impl InternalWiAdditions - for Epd2in9bc +impl InternalWiAdditions + for Epd2in9bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -148,15 +144,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd2in9bc +impl WaveshareThreeColorDisplay + for Epd2in9bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -200,27 +195,25 @@ where } } -impl WaveshareDisplay - for Epd2in9bc +impl WaveshareDisplay + for Epd2in9bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd2in9bc { interface, color }; @@ -352,14 +345,13 @@ where } } -impl Epd2in9bc +impl Epd2in9bc where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index a0540227..c7f06855 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -3,8 +3,9 @@ //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), use embedded_hal::{ - blocking::{delay::DelayUs, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; pub(crate) mod command; @@ -42,22 +43,21 @@ pub type Display3in7 = crate::graphics::Display< >; /// EPD3in7 driver -pub struct EPD3in7 { +pub struct EPD3in7 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color background_color: Color, } -impl InternalWiAdditions - for EPD3in7 +impl InternalWiAdditions + for EPD3in7 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -123,21 +123,19 @@ where } } -impl WaveshareDisplay - for EPD3in7 +impl WaveshareDisplay + for EPD3in7 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, @@ -145,7 +143,7 @@ where delay_us: Option, ) -> Result { let mut epd = EPD3in7 { - interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + interface: DisplayInterface::new(busy, dc, rst, delay_us), background_color: DEFAULT_BACKGROUND_COLOR, }; diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index f344fd5c..2a335837 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -49,10 +49,7 @@ //! //! BE CAREFUL! The screen can get ghosting/burn-ins through the Partial Fast Update Drawing. -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; @@ -88,24 +85,23 @@ pub type Display4in2 = crate::graphics::Display< /// Epd4in2 driver /// -pub struct Epd4in2 { +pub struct Epd4in2 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, /// Refresh LUT refresh: RefreshLut, } -impl InternalWiAdditions - for Epd4in2 +impl InternalWiAdditions + for Epd4in2 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -152,27 +148,25 @@ where } } -impl WaveshareDisplay - for Epd4in2 +impl WaveshareDisplay + for Epd4in2 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd4in2 { @@ -354,14 +348,13 @@ where } } -impl Epd4in2 +impl Epd4in2 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -449,15 +442,14 @@ where } } -impl QuickRefresh - for Epd4in2 +impl QuickRefresh + for Epd4in2 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// To be followed immediately after by `update_old_frame`. fn update_old_frame( diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 3c275f7a..6233955b 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -7,8 +7,9 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::OctColor; @@ -40,22 +41,21 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd5in65f driver /// -pub struct Epd5in65f { +pub struct Epd5in65f { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: OctColor, } -impl InternalWiAdditions - for Epd5in65f +impl InternalWiAdditions + for Epd5in65f where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -80,27 +80,25 @@ where } } -impl WaveshareDisplay - for Epd5in65f +impl WaveshareDisplay + for Epd5in65f where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = OctColor; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd5in65f { interface, color }; @@ -209,14 +207,13 @@ where } } -impl Epd5in65f +impl Epd5in65f where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index e16a287a..d1df524e 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -7,8 +7,9 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::Color; @@ -42,22 +43,21 @@ const SINGLE_BYTE_WRITE: bool = true; /// Epd7in5 driver /// -pub struct Epd5in83 { +pub struct Epd5in83 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd5in83 +impl InternalWiAdditions + for Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -94,15 +94,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd5in83 +impl WaveshareThreeColorDisplay + for Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -139,27 +138,25 @@ where } } -impl WaveshareDisplay - for Epd5in83 +impl WaveshareDisplay + for Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd5in83 { interface, color }; @@ -305,14 +302,13 @@ where } } -impl Epd5in83 +impl Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index f12c493e..5b89e1a1 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -7,8 +7,9 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::Color; @@ -40,22 +41,21 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -103,27 +103,25 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd7in5 { interface, color }; @@ -239,14 +237,13 @@ where } } -impl Epd7in5 +impl Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 2b19f962..5ef9cd47 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -10,8 +10,9 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::Color; @@ -43,22 +44,21 @@ const SINGLE_BYTE_WRITE: bool = false; /// EPD7in5 (HD) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -103,27 +103,25 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd7in5 { interface, color }; @@ -236,14 +234,13 @@ where } } -impl Epd7in5 +impl Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index b1d51158..f971bf43 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -11,8 +11,9 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::Color; @@ -44,22 +45,21 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -85,27 +85,25 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd7in5 { interface, color }; @@ -213,14 +211,13 @@ where } } -impl Epd7in5 +impl Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index d3c43c87..962924af 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -8,8 +8,9 @@ //! use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::TriColor; @@ -48,22 +49,21 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V3) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -90,15 +90,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd7in5 +impl WaveshareThreeColorDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn update_color_frame( &mut self, @@ -142,27 +141,25 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = TriColor; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd7in5 { interface, color }; @@ -281,14 +278,13 @@ where } } -impl Epd7in5 +impl Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 21855c19..c71d030c 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -11,8 +11,9 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::TriColor; @@ -46,22 +47,21 @@ const SINGLE_BYTE_WRITE: bool = false; /// Epd7in5 (V2) driver /// -pub struct Epd7in5 { +pub struct Epd7in5 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: TriColor, } -impl InternalWiAdditions - for Epd7in5 +impl InternalWiAdditions + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -103,27 +103,25 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = TriColor; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd7in5 { interface, color }; @@ -243,14 +241,13 @@ where } } -impl Epd7in5 +impl Epd7in5 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// temporary replacement for missing delay in the trait to call wait_until_idle #[allow(clippy::too_many_arguments)] diff --git a/src/interface.rs b/src/interface.rs index 0bcfd1ff..31b6cce7 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -1,21 +1,16 @@ use crate::traits::Command; use core::marker::PhantomData; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; /// The Connection Interface of all (?) Waveshare EPD-Devices /// /// SINGLE_BYTE_WRITE defines if a data block is written bytewise /// or blockwise to the spi device -pub(crate) struct DisplayInterface { +pub(crate) struct DisplayInterface { /// SPI _spi: PhantomData, /// DELAY _delay: PhantomData, - /// CS for SPI - cs: CS, /// Low for busy, Wait until display is ready! busy: BUSY, /// Data/Command Control Pin (High for data, Low for command) @@ -26,26 +21,24 @@ pub(crate) struct DisplayInterface - DisplayInterface +impl + DisplayInterface where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// Creates a new `DisplayInterface` struct /// /// If no delay is given, a default delay of 10ms is used. - pub fn new(cs: CS, busy: BUSY, dc: DC, rst: RST, delay_us: Option) -> Self { + pub fn new(busy: BUSY, dc: DC, rst: RST, delay_us: Option) -> Self { // default delay of 10ms let delay_us = delay_us.unwrap_or(10_000); DisplayInterface { _spi: PhantomData::default(), _delay: PhantomData::default(), - cs, busy, dc, rst, @@ -116,9 +109,6 @@ where // spi write helper/abstraction function fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - // activate spi with cs low - let _ = self.cs.set_low(); - // 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 @@ -126,14 +116,10 @@ where for data_chunk in data.chunks(4096) { spi.write(data_chunk)?; } + Ok(()) } else { - spi.write(data)?; + spi.write(data) } - - // deactivate spi with cs high - let _ = self.cs.set_high(); - - Ok(()) } /// Waits until device isn't busy anymore (busy == HIGH) diff --git a/src/traits.rs b/src/traits.rs index f496f64d..86f44687 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,8 +1,5 @@ use core::marker::Sized; -use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, -}; +use embedded_hal::{delay::*, digital::*, spi::SpiDevice}; /// All commands need to have this trait which gives the address of the command /// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode) @@ -21,14 +18,13 @@ pub enum RefreshLut { Quick, } -pub(crate) trait InternalWiAdditions +pub(crate) trait InternalWiAdditions where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// This initialises the EPD and powers it up /// @@ -44,15 +40,14 @@ where } /// Functions to interact with three color panels -pub trait WaveshareThreeColorDisplay: - WaveshareDisplay +pub trait WaveshareThreeColorDisplay: + WaveshareDisplay where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// Transmit data to the SRAM of the EPD /// @@ -131,14 +126,13 @@ where ///# Ok(()) ///# } ///``` -pub trait WaveshareDisplay +pub trait WaveshareDisplay where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// The Color Type used by the Display type DisplayColor; @@ -151,7 +145,6 @@ where /// This already initialises the device. fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, @@ -292,14 +285,13 @@ where ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// Updates the old frame. fn update_old_frame( From 54a91366a26c4b10b8a69ed00ae9762711a458e7 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 31 Aug 2023 15:43:34 +0200 Subject: [PATCH 23/69] Change ci to run clippy at the end and to check (only!) the lib first before building the examples. --- .github/workflows/rust.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index ca6e1da0..30677bc3 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -19,13 +19,13 @@ jobs: - name: Check Fmt run: cargo fmt --all -- --check - name: Build lib - run: cargo check --all-targets --verbose - - name: Clippy - run: cargo clippy --all-targets -- -D warnings -A clippy::new_ret_no_self + run: cargo check --lib --verbose - name: Build examples run: cargo build --examples --all-targets --verbose - name: Run tests run: cargo test --verbose - name: Build docs run: cargo doc + - name: Clippy + run: cargo clippy --all-targets -- -D warnings -A clippy::new_ret_no_self From 053d58ddbc33e6f2fee683afedae853b17a8f8fa Mon Sep 17 00:00:00 2001 From: Dom Rodriguez Date: Sat, 9 Sep 2023 00:20:38 +0100 Subject: [PATCH 24/69] Re-add discontinued fixed link for 1.54" 'C' display Related to 6948a63. I reached out to Waveshare, who provided a working link, but advised the module is now discontinued. This PR re-adds the link, but notes it is discontinued. See also: #161. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b651884f..79c9fec3 100644 --- a/README.md +++ b/README.md @@ -59,8 +59,8 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | +| [1.54 Inch B/W/Y (C) (Discontinued)](https://www.waveshare.com/1.54inch-e-paper-module-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/R (B)](https://www.waveshare.com/1.54inch-e-Paper-B.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | -| 1.54 Inch B/W/Y (C) - no longer available | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W (A)](https://www.waveshare.com/1.54inch-e-Paper-Module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | ### [1]: 7.5 Inch B/W V2 (A) From f9e985ca31855bc1664670cdfb46eba8a7dc2861 Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 12 Sep 2023 13:56:28 +0200 Subject: [PATCH 25/69] Github CI continue on error for examples and clippy --- .github/workflows/rust.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 30677bc3..55a8c545 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -21,11 +21,13 @@ jobs: - name: Build lib run: cargo check --lib --verbose - name: Build examples + continue-on-error: true run: cargo build --examples --all-targets --verbose - name: Run tests run: cargo test --verbose - name: Build docs run: cargo doc - name: Clippy + continue-on-error: true run: cargo clippy --all-targets -- -D warnings -A clippy::new_ret_no_self From c3ba92245cd443d9d9d1506b68bfb64833e6711d Mon Sep 17 00:00:00 2001 From: Christoph Date: Tue, 12 Sep 2023 13:57:31 +0200 Subject: [PATCH 26/69] Clippy improvement --- src/interface.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 31b6cce7..e53d9186 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -37,8 +37,8 @@ where // default delay of 10ms let delay_us = delay_us.unwrap_or(10_000); DisplayInterface { - _spi: PhantomData::default(), - _delay: PhantomData::default(), + _spi: PhantomData, + _delay: PhantomData, busy, dc, rst, From 059200f4a436eee6f1f4dd12f98dab775944fb38 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 28 Sep 2023 14:07:06 +0200 Subject: [PATCH 27/69] Updates deps, update linux-embedded-hal to git main --- Cargo.toml | 9 +++++---- examples/epd1in54_no_graphics.rs | 18 +++++++++--------- examples/epd2in13_v2.rs | 20 ++++++++++---------- examples/epd2in13bc.rs | 22 +++++++++++----------- examples/epd4in2.rs | 20 ++++++++++---------- examples/epd4in2_variable_size.rs | 20 ++++++++++---------- 6 files changed, 55 insertions(+), 54 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 441776d0..c6c1f809 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,17 +16,18 @@ edition = "2021" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics-core = { version = "0.3.2", optional = true } +embedded-graphics-core = { version = "0.4", optional = true } embedded-hal = { version = "1.0.0-rc.1" } bit_field = "0.10.1" [dev-dependencies] -embedded-graphics = "0.7.1" +embedded-graphics = "0.8" -embedded-hal-mock = "0.8" +embedded-hal-mock = "0.9" [target.'cfg(unix)'.dev-dependencies] -linux-embedded-hal = "0.3" +# linux-embedded-hal = "0.3" +linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal" } [[example]] name = "epd1in54_no_graphics" diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index e6ab75bb..7df04a00 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -1,18 +1,18 @@ #![deny(warnings)] -use embedded_hal::prelude::*; +use embedded_hal::delay::DelayUs; use epd_waveshare::{epd1in54::Epd1in54, prelude::*}; use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, Pin, Spidev, + Delay, SPIError, Spidev, 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<(), std::io::Error> { +fn main() -> Result<(), SPIError> { // Configure SPI // SPI settings are from eink-waveshare-rs documenation let mut spi = Spidev::open("/dev/spidev0.0")?; @@ -24,7 +24,7 @@ fn main() -> Result<(), std::io::Error> { spi.configure(&options).expect("spi configuration"); // Configure Digital I/O Pin to be used as Chip Select for SPI - let cs_pin = Pin::new(26); //BCM7 CE0 + let cs_pin = SysfsPin::new(26); //BCM7 CE0 cs_pin.export().expect("cs_pin export"); while !cs_pin.is_exported() {} cs_pin @@ -33,21 +33,21 @@ fn main() -> Result<(), std::io::Error> { cs_pin.set_value(1).expect("cs_pin Value set to 1"); // Configure Busy Input Pin - let busy = Pin::new(5); //pin 29 + let busy = SysfsPin::new(5); //pin 29 busy.export().expect("busy export"); while !busy.is_exported() {} busy.set_direction(Direction::In).expect("busy Direction"); //busy.set_value(1).expect("busy Value set to 1"); // Configure Data/Command OutputPin - let dc = Pin::new(6); //pin 31 //bcm6 + let dc = SysfsPin::new(6); //pin 31 //bcm6 dc.export().expect("dc export"); while !dc.is_exported() {} dc.set_direction(Direction::Out).expect("dc Direction"); dc.set_value(1).expect("dc Value set to 1"); // Configure Reset OutputPin - let rst = Pin::new(16); //pin 36 //bcm16 + let rst = SysfsPin::new(16); //pin 36 //bcm16 rst.export().expect("rst export"); while !rst.is_exported() {} rst.set_direction(Direction::Out).expect("rst Direction"); @@ -58,7 +58,7 @@ fn main() -> Result<(), std::io::Error> { // 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, cs_pin, busy, dc, rst, &mut delay, Some(5))?; + let mut epd = Epd1in54::new(&mut spi, busy, dc, rst, &mut delay, Some(5))?; // Clear the full screen epd.clear_frame(&mut spi, &mut delay)?; @@ -98,7 +98,7 @@ fn main() -> Result<(), std::io::Error> { // Display updated frame epd.display_frame(&mut spi, &mut delay)?; - delay.delay_ms(5000u16); + delay.delay_ms(5000); // Set the EPD to sleep epd.sleep(&mut spi, &mut delay)?; diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index 3815a0d2..d4c63c4c 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::prelude::*; +use embedded_hal::delay::DelayUs; use epd_waveshare::{ color::*, epd2in13_v2::{Display2in13, Epd2in13}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, Pin, Spidev, + Delay, SPIError, Spidev, SysfsPin, }; // The pins in this example are for the Universal e-Paper Raw Panel Driver HAT @@ -24,7 +24,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<(), std::io::Error> { +fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); @@ -36,25 +36,25 @@ fn main() -> Result<(), std::io::Error> { spi.configure(&options).expect("spi configuration"); // Configure Digital I/O Pin to be used as Chip Select for SPI - let cs = Pin::new(26); //BCM7 CE0 + let cs = SysfsPin::new(26); //BCM7 CE0 cs.export().expect("cs export"); while !cs.is_exported() {} cs.set_direction(Direction::Out).expect("CS Direction"); cs.set_value(1).expect("CS Value set to 1"); - let busy = Pin::new(24); // GPIO 24, board J-18 + let busy = SysfsPin::new(24); // GPIO 24, board J-18 busy.export().expect("busy export"); while !busy.is_exported() {} busy.set_direction(Direction::In).expect("busy Direction"); //busy.set_value(1).expect("busy Value set to 1"); - let dc = Pin::new(25); // GPIO 25, board J-22 + let dc = SysfsPin::new(25); // GPIO 25, board J-22 dc.export().expect("dc export"); while !dc.is_exported() {} dc.set_direction(Direction::Out).expect("dc Direction"); dc.set_value(1).expect("dc Value set to 1"); - let rst = Pin::new(17); // GPIO 17, board J-11 + let rst = SysfsPin::new(17); // GPIO 17, board J-11 rst.export().expect("rst export"); while !rst.is_exported() {} rst.set_direction(Direction::Out).expect("rst Direction"); @@ -63,7 +63,7 @@ fn main() -> Result<(), std::io::Error> { let mut delay = Delay {}; let mut epd2in13 = - Epd2in13::new(&mut spi, cs, busy, dc, rst, &mut delay, None).expect("eink initalize error"); + Epd2in13::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error"); //println!("Test all the rotations"); let mut display = Display2in13::default(); @@ -84,7 +84,7 @@ fn main() -> Result<(), std::io::Error> { epd2in13 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); - delay.delay_ms(5000u16); + delay.delay_ms(5000); //println!("Now test new graphics with default rotation and some special stuff:"); display.clear(Color::White).ok(); @@ -136,7 +136,7 @@ fn main() -> Result<(), std::io::Error> { epd2in13 .update_and_display_frame(&mut spi, display.buffer(), &mut delay) .expect("display frame new graphics"); - delay.delay_ms(1_000u16); + delay.delay_ms(1_000); } // Show a spinning bar without any delay between frames. Shows how «fast» diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 2eb4fe7b..82a23961 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::prelude::*; +use embedded_hal::delay::DelayUs; use epd_waveshare::{ color::*, epd2in13bc::{Display2in13bc, Epd2in13bc}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, Pin, Spidev, + Delay, SPIError, Spidev, SysfsPin, }; // activate spi, gpio in raspi-config @@ -34,26 +34,26 @@ use linux_embedded_hal::{ // // after finishing, put the display to sleep -fn main() -> Result<(), std::io::Error> { - let busy = Pin::new(24); // GPIO 24, board J-18 +fn main() -> Result<(), SPIError> { + let busy = SysfsPin::new(24); // GPIO 24, board J-18 busy.export().expect("busy export"); while !busy.is_exported() {} busy.set_direction(Direction::In).expect("busy Direction"); - let dc = Pin::new(25); // GPIO 25, board J-22 + let dc = SysfsPin::new(25); // GPIO 25, board J-22 dc.export().expect("dc export"); while !dc.is_exported() {} dc.set_direction(Direction::Out).expect("dc Direction"); // dc.set_value(1).expect("dc Value set to 1"); - let rst = Pin::new(17); // GPIO 17, board J-11 + let rst = SysfsPin::new(17); // GPIO 17, board J-11 rst.export().expect("rst export"); while !rst.is_exported() {} rst.set_direction(Direction::Out).expect("rst Direction"); // rst.set_value(1).expect("rst Value set to 1"); // Configure Digital I/O Pin to be used as Chip Select for SPI - let cs = Pin::new(26); // CE0, board J-24, GPIO 8 -> doesn work. use this from 2in19 example which works + let cs = SysfsPin::new(26); // CE0, board J-24, GPIO 8 -> doesn work. use this from 2in19 example which works cs.export().expect("cs export"); while !cs.is_exported() {} cs.set_direction(Direction::Out).expect("CS Direction"); @@ -71,8 +71,8 @@ fn main() -> Result<(), std::io::Error> { let mut delay = Delay {}; - let mut epd2in13 = Epd2in13bc::new(&mut spi, cs, busy, dc, rst, &mut delay, None) - .expect("eink initalize error"); + let mut epd2in13 = + Epd2in13bc::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error"); println!("Test all the rotations"); let mut display = Display2in13bc::default(); @@ -98,7 +98,7 @@ fn main() -> Result<(), std::io::Error> { .expect("display frame new graphics"); println!("First frame done. Waiting 5s"); - delay.delay_ms(5000u16); + delay.delay_ms(5000); println!("Now test new graphics with default rotation and three colors:"); display.clear(TriColor::White).ok(); @@ -148,7 +148,7 @@ fn main() -> Result<(), std::io::Error> { .expect("display frame new graphics"); println!("Second frame done. Waiting 5s"); - delay.delay_ms(5000u16); + delay.delay_ms(5000); // clear both bw buffer and chromatic buffer display.clear(TriColor::White).ok(); diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index c09115cd..74a6a992 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::prelude::*; +use embedded_hal::delay::DelayUs; use epd_waveshare::{ color::*, epd4in2::{Display4in2, Epd4in2}, @@ -16,14 +16,14 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, Pin, Spidev, + Delay, SPIError, Spidev, 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<(), std::io::Error> { +fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); @@ -35,25 +35,25 @@ fn main() -> Result<(), std::io::Error> { spi.configure(&options).expect("spi configuration"); // Configure Digital I/O Pin to be used as Chip Select for SPI - let cs = Pin::new(26); //BCM7 CE0 + let cs = SysfsPin::new(26); //BCM7 CE0 cs.export().expect("cs export"); while !cs.is_exported() {} cs.set_direction(Direction::Out).expect("CS Direction"); cs.set_value(1).expect("CS Value set to 1"); - let busy = Pin::new(5); //pin 29 + let busy = SysfsPin::new(5); //pin 29 busy.export().expect("busy export"); while !busy.is_exported() {} busy.set_direction(Direction::In).expect("busy Direction"); //busy.set_value(1).expect("busy Value set to 1"); - let dc = Pin::new(6); //pin 31 //bcm6 + let dc = SysfsPin::new(6); //pin 31 //bcm6 dc.export().expect("dc export"); while !dc.is_exported() {} dc.set_direction(Direction::Out).expect("dc Direction"); dc.set_value(1).expect("dc Value set to 1"); - let rst = Pin::new(16); //pin 36 //bcm16 + let rst = SysfsPin::new(16); //pin 36 //bcm16 rst.export().expect("rst export"); while !rst.is_exported() {} rst.set_direction(Direction::Out).expect("rst Direction"); @@ -62,7 +62,7 @@ fn main() -> Result<(), std::io::Error> { let mut delay = Delay {}; let mut epd4in2 = - Epd4in2::new(&mut spi, cs, busy, dc, rst, &mut delay, None).expect("eink initalize error"); + Epd4in2::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error"); println!("Test all the rotations"); let mut display = Display4in2::default(); @@ -83,7 +83,7 @@ fn main() -> Result<(), std::io::Error> { epd4in2 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); - delay.delay_ms(5000u16); + delay.delay_ms(5000); println!("Now test new graphics with default rotation and some special stuff"); display.clear(Color::White).ok(); @@ -143,7 +143,7 @@ fn main() -> Result<(), std::io::Error> { .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); - delay.delay_ms(1_000u16); + delay.delay_ms(1_000); } println!("Finished tests - going to sleep"); diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 6da2b427..e6d92c68 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -7,7 +7,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::prelude::*; +use embedded_hal::delay::DelayUs; use epd_waveshare::{ color::*, epd4in2::{self, Epd4in2}, @@ -17,14 +17,14 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, Pin, Spidev, + Delay, SPIError, Spidev, 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<(), std::io::Error> { +fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); @@ -36,25 +36,25 @@ fn main() -> Result<(), std::io::Error> { spi.configure(&options).expect("spi configuration"); // Configure Digital I/O Pin to be used as Chip Select for SPI - let cs = Pin::new(26); //BCM7 CE0 + let cs = SysfsPin::new(26); //BCM7 CE0 cs.export().expect("cs export"); while !cs.is_exported() {} cs.set_direction(Direction::Out).expect("CS Direction"); cs.set_value(1).expect("CS Value set to 1"); - let busy = Pin::new(5); //pin 29 + let busy = SysfsPin::new(5); //pin 29 busy.export().expect("busy export"); while !busy.is_exported() {} busy.set_direction(Direction::In).expect("busy Direction"); //busy.set_value(1).expect("busy Value set to 1"); - let dc = Pin::new(6); //pin 31 //bcm6 + let dc = SysfsPin::new(6); //pin 31 //bcm6 dc.export().expect("dc export"); while !dc.is_exported() {} dc.set_direction(Direction::Out).expect("dc Direction"); dc.set_value(1).expect("dc Value set to 1"); - let rst = Pin::new(16); //pin 36 //bcm16 + let rst = SysfsPin::new(16); //pin 36 //bcm16 rst.export().expect("rst export"); while !rst.is_exported() {} rst.set_direction(Direction::Out).expect("rst Direction"); @@ -63,7 +63,7 @@ fn main() -> Result<(), std::io::Error> { let mut delay = Delay {}; let mut epd4in2 = - Epd4in2::new(&mut spi, cs, busy, dc, rst, &mut delay, None).expect("eink initalize error"); + Epd4in2::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error"); println!("Test all the rotations"); @@ -89,7 +89,7 @@ fn main() -> Result<(), std::io::Error> { epd4in2 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); - delay.delay_ms(5000u16); + delay.delay_ms(5000); println!("Now test new graphics with default rotation and some special stuff:"); display.set_rotation(DisplayRotation::Rotate0); @@ -146,7 +146,7 @@ fn main() -> Result<(), std::io::Error> { .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); - delay.delay_ms(1_000u16); + delay.delay_ms(1_000); } println!("Finished tests - going to sleep"); From d38d47b1c47be4087531e765dfc05f9c440b26b2 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 28 Sep 2023 15:17:28 +0200 Subject: [PATCH 28/69] Update to to git branch of e-h mock 1.0-rc1 --- Cargo.toml | 5 ++++- src/epd1in54/mod.rs | 8 ++++---- src/epd2in13bc/mod.rs | 8 ++++---- src/epd2in9/mod.rs | 8 ++++---- src/epd2in9_v2/mod.rs | 8 ++++---- src/epd2in9bc/mod.rs | 8 ++++---- src/epd4in2/mod.rs | 8 ++++---- src/lib.rs | 8 ++++---- src/traits.rs | 16 ++++++++-------- 9 files changed, 40 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c6c1f809..6eff17ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,10 @@ bit_field = "0.10.1" [dev-dependencies] embedded-graphics = "0.8" -embedded-hal-mock = "0.9" +embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", default-features = false, features = [ + "eh1", +] } +# embedded-hal-mock = "0.9" [target.'cfg(unix)'.dev-dependencies] # linux-embedded-hal = "0.3" diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 8cb58c0a..9bc1b7fe 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -3,8 +3,8 @@ //! # Example for the 1.54 in E-Ink Display //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, //!}; @@ -17,10 +17,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 8a91d196..280f47a7 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -5,8 +5,8 @@ //! # Example for the 2.13" E-Ink Display //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{prelude::*, primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder}}; //!use epd_waveshare::{epd2in13bc::*, prelude::*}; //!# @@ -17,10 +17,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in13bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in13bc::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white/chromatic pixels diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 1ff905b0..6e3e178d 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -4,8 +4,8 @@ //! # Example for the 2.9 in E-Ink Display //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; @@ -18,10 +18,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display2in9::default(); diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index a867658b..7004a77e 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -5,8 +5,8 @@ //! # Example for the 2.9 in E-Ink Display V2 //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; @@ -19,10 +19,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display2in9::default(); diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 0266e134..121c5680 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -3,8 +3,8 @@ //! # Example for the 2.9" E-Ink Display //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; @@ -17,10 +17,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in9bc::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white pixels diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 2a335837..fe43d0ef 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -8,8 +8,8 @@ //! # Examples //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; @@ -22,10 +22,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display4in2::default(); diff --git a/src/lib.rs b/src/lib.rs index 677f16b9..bdedf055 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,8 +11,8 @@ //! # Example //! //!```rust, no_run -//!# use embedded_hal_mock::*; -//!# fn main() -> Result<(), MockError> { +//!# use embedded_hal_mock::eh1::*; +//!# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; @@ -25,10 +25,10 @@ //!# let busy_in = pin::Mock::new(&expectations); //!# let dc = pin::Mock::new(&expectations); //!# let rst = pin::Mock::new(&expectations); -//!# let mut delay = delay::MockNoop::new(); +//!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD -//!let mut epd = Epd1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd1in54::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); diff --git a/src/traits.rs b/src/traits.rs index 86f44687..25df34ad 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -89,8 +89,8 @@ where /// # Example /// ///```rust, no_run -///# use embedded_hal_mock::*; -///# fn main() -> Result<(), MockError> { +///# use embedded_hal_mock::eh1::*; +///# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { ///use embedded_graphics::{ /// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, ///}; @@ -103,10 +103,10 @@ where ///# let busy_in = pin::Mock::new(&expectations); ///# let dc = pin::Mock::new(&expectations); ///# let rst = pin::Mock::new(&expectations); -///# let mut delay = delay::MockNoop::new(); +///# let mut delay = delay::NoopDelay::new(); /// ///// Setup EPD -///let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +///let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; /// ///// Use display graphics from embedded-graphics ///let mut display = Display4in2::default(); @@ -250,8 +250,8 @@ where /// (todo: Example ommitted due to CI failures.) /// Example: ///```rust, no_run -///# use embedded_hal_mock::*; -///# fn main() -> Result<(), MockError> { +///# use embedded_hal_mock::eh1::*; +///# fn main() -> Result<(), embedded_hal::spi::ErrorKind> { ///# use embedded_graphics::{ ///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, ///# }; @@ -265,10 +265,10 @@ where ///# let busy_in = pin::Mock::new(&expectations); ///# let dc = pin::Mock::new(&expectations); ///# let rst = pin::Mock::new(&expectations); -///# let mut delay = delay::MockNoop::new(); +///# let mut delay = delay::NoopDelay::new(); ///# ///# // Setup EPD -///# let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +///# let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?; ///let (x, y, frame_width, frame_height) = (20, 40, 80,80); /// ///let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 80 / 8 * 80]; From 1bc31cb3fc36acc418cfef6277faba7f4d0439d4 Mon Sep 17 00:00:00 2001 From: zzlwd Date: Sun, 8 Oct 2023 01:19:05 +0800 Subject: [PATCH 29/69] Add new device: Epd2in9d --- src/epd2in9d/command.rs | 150 ++++++++++ src/epd2in9d/constants.rs | 61 ++++ src/epd2in9d/mod.rs | 567 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 779 insertions(+) create mode 100644 src/epd2in9d/command.rs create mode 100644 src/epd2in9d/constants.rs create mode 100644 src/epd2in9d/mod.rs diff --git a/src/epd2in9d/command.rs b/src/epd2in9d/command.rs new file mode 100644 index 00000000..cd55ee11 --- /dev/null +++ b/src/epd2in9d/command.rs @@ -0,0 +1,150 @@ +//! SPI Commands for the Waveshare 2.9" FLEXIBLE E-PAPER DISPLAY +use crate::traits; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + PanelSetting = 0x00, + /// selecting internal and external power + /// self.send_data(0x03)?; //VDS_EN, VDG_EN + /// self.send_data(0x00)?; //VCOM_HV, VGHL_LV[1], VGHL_LV[0] + /// self.send_data(0x2b)?; //VDH + /// self.send_data(0x2b)?; //VDL + /// self.send_data(0xff)?; //VDHR + PowerSetting = 0x01, + /// After the Power Off command, the driver will power off following the Power Off Sequence. This command will turn off charge + /// pump, T-con, source driver, gate driver, VCOM, and temperature sensor, but register data will be kept until VDD becomes OFF. + /// Source Driver output and Vcom will remain as previous condition, which may have 2 conditions: floating. + PowerOff = 0x02, + /// Setting Power OFF sequence + PowerOffSequenceSetting = 0x03, + /// Turning On the Power + PowerOn = 0x04, + /// This command enables the internal bandgap, which will be cleared by the next POF. + PowerOnMeasure = 0x05, + /// Starting data transmission + /// 3-times: self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f + BoosterSoftStart = 0x06, + /// After this command is transmitted, the chip would enter the deep-sleep mode to save power. + /// + /// The deep sleep mode would return to standby by hardware reset. + /// + /// The only one parameter is a check code, the command would be excuted if check code = 0xA5. + DeepSleep = 0x07, + /// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data + /// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel. + /// + /// - In B/W mode, this command writes “OLD” data to SRAM. + /// - In B/W/Red mode, this command writes “B/W” data to SRAM. + /// - In Program mode, this command writes “OTP” data to SRAM for programming. + DataStartTransmission1 = 0x10, + /// Stopping data transmission + DataStop = 0x11, + /// While user sent this command, driver will refresh display (data/VCOM) according to SRAM data and LUT. + /// + /// After Display Refresh command, BUSY_N signal will become “0” and the refreshing of panel starts. + DisplayRefresh = 0x12, + /// This command starts transmitting data and write them into SRAM. To complete data transmission, command DSP (Data + /// transmission Stop) must be issued. Then the chip will start to send data/VCOM for panel. + /// - In B/W mode, this command writes “NEW” data to SRAM. + /// - In B/W/Red mode, this command writes “RED” data to SRAM. + DataStartTransmission2 = 0x13, + + /// This command stores VCOM Look-Up Table with 7 groups of data. Each group contains information for one state and is stored + /// with 6 bytes, while the sixth byte indicates how many times that phase will repeat. + /// + /// from IL0373 + LutForVcom = 0x20, + /// This command stores White-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is + /// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat. + /// + /// from IL0373 + LutWhiteToWhite = 0x21, + /// This command stores Black-to-White Look-Up Table with 7 groups of data. Each group contains information for one state and is + /// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat. + /// + /// from IL0373 + LutBlackToWhite = 0x22, + /// This command stores White-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is + /// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat. + /// + /// from IL0373 + LutWhiteToBlack = 0x23, + /// This command stores Black-to-Black Look-Up Table with 7 groups of data. Each group contains information for one state and is + /// stored with 6 bytes, while the sixth byte indicates how many times that phase will repeat. + /// + /// from IL0373 + LutBlackToBlack = 0x24, + /// The command controls the PLL clock frequency. + PllControl = 0x30, + /// This command reads the temperature sensed by the temperature sensor. + /// + /// Doesn't work! Waveshare doesn't connect the read pin + TemperatureSensor = 0x40, + /// Selects the Internal or External temperature sensor and offset + TemperatureSensorSelection = 0x41, + /// Write External Temperature Sensor + TemperatureSensorWrite = 0x42, + /// Read External Temperature Sensor + /// + /// Doesn't work! Waveshare doesn't connect the read pin + TemperatureSensorRead = 0x43, + /// This command indicates the interval of Vcom and data output. When setting the vertical back porch, the total blanking will be kept (20 Hsync) + VcomAndDataIntervalSetting = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn the battery condition. + LowPowerDetection = 0x51, + /// This command defines non-overlap period of Gate and Source. + TconSetting = 0x60, + /// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR). + ResolutionSetting = 0x61, + /// This command defines the Fist Active Gate and First Active Source of active channels. + // GsstSetting = 0x65, + /// The LUT_REV / Chip Revision is read from OTP address = 0x001. + /// + /// Doesn't work! Waveshare doesn't connect the read pin + // Revision = 0x70, + /// Read Flags. This command reads the IC status + /// PTL, I2C_ERR, I2C_BUSY, DATA, PON, POF, BUSY + /// + /// Doesn't work! Waveshare doesn't connect the read pin + GetStatus = 0x71, + /// Automatically measure VCOM. This command reads the IC status + AutoMeasurementVcom = 0x80, + /// This command gets the VCOM value + /// + /// Doesn't work! Waveshare doesn't connect the read pin + ReadVcomValue = 0x81, + /// Set VCM_DC + VcmDcSetting = 0x82, + /// This command sets partial window + PartialWindow = 0x90, + /// This command makes the display enter partial mode + PartialIn = 0x91, + /// This command makes the display exit partial mode and enter normal mode + PartialOut = 0x92, + /// After this command is issued, the chip would enter the program mode. + /// + /// After the programming procedure completed, a hardware reset is necessary for leaving program mode. + /// + /// The only one parameter is a check code, the command would be excuted if check code = 0xA5. + ProgramMode = 0xA0, + /// After this command is transmitted, the programming state machine would be activated. + /// + /// The BUSY flag would fall to 0 until the programming is completed. + ActiveProgramming = 0xA1, + /// The command is used for reading the content of OTP for checking the data of programming. + /// + /// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF. + ReadOtp = 0xA2, + /// This command is set for saving power during fresh period. If the output voltage of VCOM / Source is from negative to positive or + /// from positive to negative, the power saving mechanism will be activated. The active period width is defined by the following two + /// parameters. + PowerSaving = 0xE3, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} \ No newline at end of file diff --git a/src/epd2in9d/constants.rs b/src/epd2in9d/constants.rs new file mode 100644 index 00000000..aaf169f4 --- /dev/null +++ b/src/epd2in9d/constants.rs @@ -0,0 +1,61 @@ +//! This file contains look-up-tables used to set voltages used during +//! various categories of pixel refreshes. + +/** + * partial screen update LUT +**/ +#[rustfmt::skip] +pub(crate) const LUT_VCOM1: [u8; 44] = [ + 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, +]; + +#[rustfmt::skip] +pub(crate) const LUT_WW1: [u8; 42] =[ + 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +#[rustfmt::skip] +pub(crate) const LUT_BW1: [u8; 42] =[ + 0x80, 0x19, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +#[rustfmt::skip] +pub(crate) const LUT_BB1: [u8; 42] =[ + 0x00, 0x19, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +#[rustfmt::skip] +pub(crate) const LUT_WB1: [u8; 42] =[ + 0x40, 0x19, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; \ No newline at end of file diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs new file mode 100644 index 00000000..36db92ce --- /dev/null +++ b/src/epd2in9d/mod.rs @@ -0,0 +1,567 @@ +//! A simple Driver for the Waveshare 2.9" D E-Ink Display via SPI +//! +//! +//! 参考[Waveshare](https://www.waveshare.net/wiki/2.9inch_e-Paper_HAT_%28D%29)的文档/例程进行构建 +//! +//! Specification: https://www.waveshare.net/w/upload/b/b5/2.9inch_e-Paper_%28D%29_Specification.pdf + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::interface::DisplayInterface; +use crate::traits::{RefreshLut, WaveshareDisplay}; + +//The Lookup Tables for the Display +mod constants; +use crate::epd2in9d::constants::*; + +/// Width of Epd2in9d in pixels +pub const WIDTH: u32 = 128; +/// Height of Epd2in9d in pixels +pub const HEIGHT: u32 = 296; +/// Default Background Color (white) +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::Black; +const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; + +use crate::color::Color; + +pub(crate) mod command; +use self::command::Command; +use crate::buffer_len; + +/// Display with Fullsize buffer for use with the 2in9 EPD D +#[cfg(feature = "graphics")] +pub type Display2in9d = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) }, + Color, +>; + +/// Epd2in9d driver +/// +pub struct Epd2in9d { + /// SPI + interface: DisplayInterface, + /// Color + // background_color: Color, + color: Color, + /// Refresh LUT + refresh: RefreshLut, +} + +impl Epd2in9d +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.reset(delay, 20_000, 2_000); + + self.interface.cmd(spi, Command::PowerOn)?; + //waiting for the electronic paper IC to release the idle signal + self.wait_until_idle(spi, delay)?; + + //panel setting + //LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f + self.interface + .cmd_with_data(spi, Command::PanelSetting, &[0x1f])?; + + //resolution setting + self.interface + .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + + //VCOM AND DATA INTERVAL SETTING + self.interface + .cmd(spi, Command::VcomAndDataIntervalSetting)?; + + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in9d +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + type DisplayColor = Color; + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn new( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd2in9d { + interface, + color, + refresh: RefreshLut::Full, + }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; + self.interface.cmd(spi, Command::PowerOff)?; + self.wait_until_idle(spi, delay)?; + self.interface + .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + + //TODO: 这还有一个命令没实现,先放着等下回头写 + // DigitalWrite(reset_pin, LOW); + + Ok(()) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay)?; + Ok(()) + } + + // 对应的是Display函数 + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + + self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + + // self.interface.cmd(spi,Command::DataStartTransmission2)?; + // for j in 0..h { + // for i in 0..w { + // let mut miao = (i+j*w) as u8; + // self.interface.data(spi, &buffer[miao])?; + // } + // } + //TODO: 不太确定这样写对不对 + self.interface + .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + Ok(()) + } + + // 这个是DisplayPart + fn update_partial_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + + self.set_part_reg(spi, delay)?; + self.interface.cmd(spi, Command::PartialIn)?; + + // 这部分按照例程来说应该是下面这样 + // self.interface.cmd_with_data( + // spi, + // Command::PartialWindow, + // &[ + // 0x00, + // (WIDTH - 1) as u8, + // 0x00, + // 0x00, + // (HEIGHT / 256) as u8, + // (HEIGHT % 256 - 1) as u8, + // 0x28, + // ], + // )?; + // 但看了下隔壁4in2的代码,决定抄抄 + self.interface.cmd(spi, Command::PartialWindow)?; + self.interface.data(spi, &[(x >> 8) as u8])?; + let tmp = x & 0xf8; + self.interface.data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored + let tmp = tmp + width - 1; + self.interface.data(spi, &[(tmp >> 8) as u8])?; + self.interface.data(spi, &[(tmp | 0x07) as u8])?; + + self.interface.data(spi, &[(y >> 8) as u8])?; + self.interface.data(spi, &[y as u8])?; + + self.interface.data(spi, &[((y + height - 1) >> 8) as u8])?; + self.interface.data(spi, &[(y + height - 1) as u8])?; + + self.interface.data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + + self.interface + .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + + self.turn_on_display(spi, delay)?; + Ok(()) + } + + /// actually is the "Turn on Display" sequence + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.interface.cmd(spi, Command::DisplayRefresh)?; + Ok(()) + + // 其实也可以是下面这样 + // self.wait_until_idle(spi, delay)?; + // self.turn_on_display(spi, delay)?; + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + + // let mut w = if WIDTH % 8 == 0 { + // WIDTH / 8 + // } else { + // WIDTH / 8 + 1 + // }; + // let mut h = HEIGHT; + + self.interface.cmd(spi, Command::DataStartTransmission1)?; + // for _ in 0..h { + // for _ in 0..w { + // self.interface.data(spi, &[0x00])?; + // } + // } + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + + self.interface.cmd(spi, Command::DataStartTransmission2)?; + // for _ in 0..h { + // for _ in 0..w { + // self.interface.data(spi, &[0xFF])?; + // } + // } + self.interface.data_x_times(spi, 0xFF, WIDTH / 8 * HEIGHT)?; + + self.turn_on_display(spi, delay)?; + + Ok(()) + } + + fn set_background_color(&mut self, background_color: Color) { + self.color = background_color; + } + + fn background_color(&self) -> &Color { + &self.color + } + + fn set_lut( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + refresh_rate: Option, + ) -> Result<(), SPI::Error> { + if let Some(refresh_lut) = refresh_rate { + self.refresh = refresh_lut; + } + self.set_lut_helper( + spi, delay, &LUT_VCOM1, &LUT_WW1, &LUT_BW1, &LUT_WB1, &LUT_BB1, + )?; + + Ok(()) + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW); + Ok(()) + } +} + +impl Epd2in9d +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn turn_on_display(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + //DISPLAY REFRESH + self.interface.cmd(spi, Command::DisplayRefresh)?; + //The delay here is necessary, 200uS at least!!! + delay.delay_us(200); + + self.wait_until_idle(spi, delay)?; + Ok(()) + } + + /// 唤醒屏幕 + /// + /// 在屏幕执行sleep之后,会进入深度睡眠模式。在深度睡眠模式下若需要刷新屏幕,必须先执行awaken() + /// 唤醒屏幕 + // fn awaken(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // // reset the device + // self.interface.reset(delay, 20_000, 2_000); + // self.wait_until_idle(spi, delay)?; + + // // panel setting + // // LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f + // self.interface + // .cmd_with_data(spi, Command::PanelSetting, &[0x1f])?; + + // // resolution setting + // self.interface + // .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + + // // VCOM AND DATA INTERVAL SETTING + // self.interface + // .cmd(spi, Command::VcomAndDataIntervalSetting)?; + // Ok(()) + // } + + fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // 重置EPD驱动电路 + //TODO: 这里在微雪的例程中反复刷新了3次,后面有显示问题再进行修改 + self.interface.reset(delay, 20_000, 2_000); + + // 电源设置 + //TODO: 文档中的数据为[0x03,0x00,0x2b,0x2b,0x09] + self.interface.cmd_with_data( + spi, + Command::PowerSetting, + &[0x03, 0x00, 0x2b, 0x2b, 0x03], + )?; + + // 软启动 + self.interface + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + + // 开启电源 + // self.interface.cmd_with_data( + // spi, + // Command::PowerOn, + // &[0x04], + // ); + self.interface.cmd(spi, Command::PowerOn)?; + + // 获取BUSY电平,高电平继续执行,低电平则等待屏幕响应 + //TODO: 这里是文档推荐的步骤,但我看其他屏幕的也没等待就先忽略了 + // self.wait_until_idle(spi, delay)?; + + // 面板设置 + self.interface + .cmd_with_data(spi, Command::PanelSetting, &[0xbf])?; + + // 设置刷新率 + // 3a 100HZ | 29 150Hz | 39 200HZ | 31 171HZ + // 例程中使用3a + self.interface + .cmd_with_data(spi, Command::PllControl, &[0x3a])?; + + // 分辨率设置 + self.interface + .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + + // vcom_DC设置 + self.interface + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + + // vcom和数据间隔设置 + self.interface + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; + + self.set_lut(spi, delay, None)?; + Ok(()) + } + + #[allow(clippy::too_many_arguments)] + fn set_lut_helper( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + lut_vcom: &[u8], + lut_ww: &[u8], + lut_bw: &[u8], + lut_wb: &[u8], + lut_bb: &[u8], + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + // LUT VCOM + self.interface + .cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; + + // LUT WHITE to WHITE + self.interface + .cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?; + + // LUT BLACK to WHITE + self.interface + .cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?; + + // LUT WHITE to BLACK + self.interface + .cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?; + + // LUT BLACK to BLACK + self.interface + .cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?; + Ok(()) + } +} + +// impl QuickRefresh +// for Epd2in9d +// where +// SPI: Write, +// CS: OutputPin, +// BUSY: InputPin, +// DC: OutputPin, +// RST: OutputPin, +// DELAY: DelayUs, +// { +// /// To be followed immediately by `update_new_frame`. +// fn update_old_frame( +// &mut self, +// spi: &mut SPI, +// buffer: &[u8], +// delay: &mut DELAY, +// ) -> Result<(), SPI::Error> { +// self.wait_until_idle(spi, delay)?; +// self.interface +// .cmd_with_data(spi, Command::WriteRam2, buffer) +// } + +// /// To be used immediately after `update_old_frame`. +// fn update_new_frame( +// &mut self, +// spi: &mut SPI, +// buffer: &[u8], +// delay: &mut DELAY, +// ) -> Result<(), SPI::Error> { +// self.wait_until_idle(spi, delay)?; +// self.interface.reset(delay, 10_000, 2_000); + +// self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; +// self.interface.cmd_with_data( +// spi, +// Command::WriteOtpSelection, +// &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], +// )?; +// self.interface +// .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; +// self.interface +// .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0])?; +// self.interface.cmd(spi, Command::MasterActivation)?; + +// self.wait_until_idle(spi, delay)?; + +// self.use_full_frame(spi, delay)?; + +// self.interface +// .cmd_with_data(spi, Command::WriteRam, buffer)?; +// Ok(()) +// } + +// /// For a quick refresh of the new updated frame. To be used immediately after `update_new_frame` +// fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { +// self.wait_until_idle(spi, delay)?; +// self.interface +// .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; +// self.interface.cmd(spi, Command::MasterActivation)?; +// self.wait_until_idle(spi, delay)?; +// Ok(()) +// } + +// /// Updates and displays the new frame. +// fn update_and_display_new_frame( +// &mut self, +// spi: &mut SPI, +// buffer: &[u8], +// delay: &mut DELAY, +// ) -> Result<(), SPI::Error> { +// self.update_new_frame(spi, buffer, delay)?; +// self.display_new_frame(spi, delay)?; +// Ok(()) +// } + +// /// Partial quick refresh not supported yet +// #[allow(unused)] +// fn update_partial_old_frame( +// &mut self, +// spi: &mut SPI, +// delay: &mut DELAY, +// buffer: &[u8], +// x: u32, +// y: u32, +// width: u32, +// height: u32, +// ) -> Result<(), SPI::Error> { +// //TODO supported by display? +// unimplemented!() +// } + +// /// Partial quick refresh not supported yet +// #[allow(unused)] +// fn update_partial_new_frame( +// &mut self, +// spi: &mut SPI, +// delay: &mut DELAY, +// buffer: &[u8], +// x: u32, +// y: u32, +// width: u32, +// height: u32, +// ) -> Result<(), SPI::Error> { +// //TODO supported by display? +// unimplemented!() +// } + +// /// Partial quick refresh not supported yet +// #[allow(unused)] +// fn clear_partial_frame( +// &mut self, +// spi: &mut SPI, +// delay: &mut DELAY, +// x: u32, +// y: u32, +// width: u32, +// height: u32, +// ) -> Result<(), SPI::Error> { +// //TODO supported by display? +// unimplemented!() +// } +// } diff --git a/src/lib.rs b/src/lib.rs index 677f16b9..405c299a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -92,6 +92,7 @@ pub mod epd7in5_hd; pub mod epd7in5_v2; pub mod epd7in5_v3; pub mod epd7in5b_v2; +pub mod epd2in9d; pub(crate) mod type_a; From f50c72b86fcec3ff069f9da55fb4a96aa55984fa Mon Sep 17 00:00:00 2001 From: zzlwd Date: Sun, 8 Oct 2023 11:03:03 +0800 Subject: [PATCH 30/69] Format document --- src/epd2in9d/command.rs | 2 +- src/epd2in9d/constants.rs | 2 +- src/epd2in9d/mod.rs | 4 ++-- src/lib.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/epd2in9d/command.rs b/src/epd2in9d/command.rs index cd55ee11..c7abc249 100644 --- a/src/epd2in9d/command.rs +++ b/src/epd2in9d/command.rs @@ -147,4 +147,4 @@ impl traits::Command for Command { fn address(self) -> u8 { self as u8 } -} \ No newline at end of file +} diff --git a/src/epd2in9d/constants.rs b/src/epd2in9d/constants.rs index aaf169f4..6a56d2e7 100644 --- a/src/epd2in9d/constants.rs +++ b/src/epd2in9d/constants.rs @@ -58,4 +58,4 @@ pub(crate) const LUT_WB1: [u8; 42] =[ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -]; \ No newline at end of file +]; diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index 36db92ce..b0f3e7ce 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -87,7 +87,7 @@ where } } -impl WaveshareDisplay +impl WaveshareDisplay for Epd2in9d where SPI: Write, @@ -139,7 +139,7 @@ where //TODO: 这还有一个命令没实现,先放着等下回头写 // DigitalWrite(reset_pin, LOW); - + Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 7cbed131..38ce84d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,7 @@ pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; pub mod epd2in9bc; +pub mod epd2in9d; pub mod epd3in7; pub mod epd4in2; pub mod epd5in65f; @@ -92,7 +93,6 @@ pub mod epd7in5_hd; pub mod epd7in5_v2; pub mod epd7in5_v3; pub mod epd7in5b_v2; -pub mod epd2in9d; pub(crate) mod type_a; From bde5962f1b72ff060e067c0491a47cccd7b8bb2a Mon Sep 17 00:00:00 2001 From: Luca Di Carlo Date: Thu, 12 Oct 2023 14:10:10 +0200 Subject: [PATCH 31/69] fix: overflow error Currently on my computer it displays an error message: ``` 44 | const NUM_DISPLAY_BYTES: usize = WIDTH as usize * HEIGHT as usize /8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `800_usize * 480_usize`, which would overflow ``` as said in #151. This a fix to this error (when compiling for arduino, in my case). --- src/epd7in5b_v2/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index c71d030c..0afb7fb0 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -41,7 +41,7 @@ pub const HEIGHT: u32 = 480; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; -const NUM_DISPLAY_BYTES: usize = WIDTH as usize * HEIGHT as usize / 8; +const NUM_DISPLAY_BYTES: usize = WIDTH as usize / 8 * HEIGHT as usize; const IS_BUSY_LOW: bool = true; const SINGLE_BYTE_WRITE: bool = false; From 84a5d349fac31ccb5b9ebc7e0db9aaeda4b2b56d Mon Sep 17 00:00:00 2001 From: zzlwd Date: Sun, 15 Oct 2023 18:52:27 +0800 Subject: [PATCH 32/69] Test and support partial refresh; Made some modifications with reference to the documentation of `GDEW029T5D`, and tested the support for partial refresh. (cherry picked from commit da2764dd41f29f69ecbcda09200698f4ce89850e) --- src/epd2in9d/mod.rs | 344 ++++++++++++-------------------------------- 1 file changed, 93 insertions(+), 251 deletions(-) diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index b0f3e7ce..e8047c9f 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -5,6 +5,8 @@ //! //! Specification: https://www.waveshare.net/w/upload/b/b5/2.9inch_e-Paper_%28D%29_Specification.pdf +use core::slice::from_raw_parts; + use embedded_hal::{ blocking::{delay::*, spi::Write}, digital::v2::*, @@ -21,6 +23,9 @@ use crate::epd2in9d::constants::*; pub const WIDTH: u32 = 128; /// Height of Epd2in9d in pixels pub const HEIGHT: u32 = 296; +/// EPD_ARRAY of Epd2in9d in pixels +/// WIDTH / 8 * HEIGHT +pub const EPD_ARRAY: u32 = 4736; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::Black; const IS_BUSY_LOW: bool = false; @@ -44,7 +49,7 @@ pub type Display2in9d = crate::graphics::Display< /// Epd2in9d driver /// -pub struct Epd2in9d { +pub struct Epd2in9d<'a, SPI, CS, BUSY, DC, RST, DELAY> { /// SPI interface: DisplayInterface, /// Color @@ -52,9 +57,13 @@ pub struct Epd2in9d { color: Color, /// Refresh LUT refresh: RefreshLut, + // 存放旧数据,以供部分刷新使用 + old_data: &'a [u8], + // 标记是否局刷的状态 + is_partial_refresh: bool, } -impl Epd2in9d +impl Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> where SPI: Write, CS: OutputPin, @@ -64,31 +73,30 @@ where DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.reset(delay, 20_000, 2_000); - - self.interface.cmd(spi, Command::PowerOn)?; - //waiting for the electronic paper IC to release the idle signal - self.wait_until_idle(spi, delay)?; + self.interface.reset(delay, 10_000, 2_000); //panel setting //LUT from OTP,KW-BF KWR-AF BWROTP 0f BWOTP 1f self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0x1f])?; + .cmd_with_data(spi, Command::PanelSetting, &[0x1f, 0x0D])?; //resolution setting self.interface .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; + self.interface.cmd(spi, Command::PowerOn)?; + self.wait_until_idle(spi, delay)?; + //VCOM AND DATA INTERVAL SETTING self.interface - .cmd(spi, Command::VcomAndDataIntervalSetting)?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; Ok(()) } } impl WaveshareDisplay - for Epd2in9d + for Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> where SPI: Write, CS: OutputPin, @@ -98,14 +106,6 @@ where DELAY: DelayUs, { type DisplayColor = Color; - fn width(&self) -> u32 { - WIDTH - } - - fn height(&self) -> u32 { - HEIGHT - } - fn new( spi: &mut SPI, cs: CS, @@ -117,11 +117,15 @@ where ) -> Result { let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; + let old_data: &[u8] = &[]; + let is_partial_refresh = false; let mut epd = Epd2in9d { interface, color, refresh: RefreshLut::Full, + old_data, + is_partial_refresh, }; epd.init(spi, delay)?; @@ -130,16 +134,15 @@ where } fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.is_partial_refresh = false; self.interface .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; self.interface.cmd(spi, Command::PowerOff)?; self.wait_until_idle(spi, delay)?; + delay.delay_us(100_000); self.interface .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; - //TODO: 这还有一个命令没实现,先放着等下回头写 - // DigitalWrite(reset_pin, LOW); - Ok(()) } @@ -148,32 +151,47 @@ where Ok(()) } + fn set_background_color(&mut self, background_color: Color) { + self.color = background_color; + } + + fn background_color(&self) -> &Color { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + // 对应的是Display函数 + // 用于将要显示的数据写入屏幕SRAM fn update_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { + if self.is_partial_refresh { + // 若进行全刷则修改局刷状态 + self.is_partial_refresh = false; + } self.wait_until_idle(spi, delay)?; self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; - - // self.interface.cmd(spi,Command::DataStartTransmission2)?; - // for j in 0..h { - // for i in 0..w { - // let mut miao = (i+j*w) as u8; - // self.interface.data(spi, &buffer[miao])?; - // } - // } - //TODO: 不太确定这样写对不对 + self.interface.data_x_times(spi, 0xFF, EPD_ARRAY)?; + self.interface .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.old_data = unsafe { from_raw_parts(buffer.as_ptr(), buffer.len()) }; Ok(()) } // 这个是DisplayPart + // Partial refresh write address and data fn update_partial_frame( &mut self, spi: &mut SPI, @@ -184,58 +202,41 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - - self.set_part_reg(spi, delay)?; + if !self.is_partial_refresh { + // 仅在初次调用时初始化 + self.set_part_reg(spi, delay)?; + self.is_partial_refresh = true; + } self.interface.cmd(spi, Command::PartialIn)?; - // 这部分按照例程来说应该是下面这样 - // self.interface.cmd_with_data( - // spi, - // Command::PartialWindow, - // &[ - // 0x00, - // (WIDTH - 1) as u8, - // 0x00, - // 0x00, - // (HEIGHT / 256) as u8, - // (HEIGHT % 256 - 1) as u8, - // 0x28, - // ], - // )?; - // 但看了下隔壁4in2的代码,决定抄抄 self.interface.cmd(spi, Command::PartialWindow)?; - self.interface.data(spi, &[(x >> 8) as u8])?; - let tmp = x & 0xf8; - self.interface.data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored - let tmp = tmp + width - 1; - self.interface.data(spi, &[(tmp >> 8) as u8])?; - self.interface.data(spi, &[(tmp | 0x07) as u8])?; - - self.interface.data(spi, &[(y >> 8) as u8])?; - self.interface.data(spi, &[y as u8])?; - - self.interface.data(spi, &[((y + height - 1) >> 8) as u8])?; - self.interface.data(spi, &[(y + height - 1) as u8])?; + self.interface.data(spi, &[(x - x % 8) as u8])?; + self.interface + .data(spi, &[(((x - x % 8) + width - 1) - 1) as u8])?; + self.interface.data(spi, &[(y / 256) as u8])?; + self.interface.data(spi, &[(y % 256) as u8])?; + self.interface + .data(spi, &[((y + height - 1) / 256) as u8])?; + self.interface + .data(spi, &[((y + height - 1) % 256 - 1) as u8])?; + self.interface.data(spi, &[0x28])?; - self.interface.data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + self.interface + .cmd_with_data(spi, Command::DataStartTransmission1, self.old_data)?; self.interface .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + self.old_data = unsafe { from_raw_parts(buffer.as_ptr(), buffer.len()) }; - self.turn_on_display(spi, delay)?; Ok(()) } /// actually is the "Turn on Display" sequence fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; self.interface.cmd(spi, Command::DisplayRefresh)?; + delay.delay_us(1_000); + self.wait_until_idle(spi, delay)?; Ok(()) - - // 其实也可以是下面这样 - // self.wait_until_idle(spi, delay)?; - // self.turn_on_display(spi, delay)?; } fn update_and_display_frame( @@ -250,44 +251,17 @@ where } fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - - // let mut w = if WIDTH % 8 == 0 { - // WIDTH / 8 - // } else { - // WIDTH / 8 + 1 - // }; - // let mut h = HEIGHT; - self.interface.cmd(spi, Command::DataStartTransmission1)?; - // for _ in 0..h { - // for _ in 0..w { - // self.interface.data(spi, &[0x00])?; - // } - // } - self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + self.interface.data_x_times(spi, 0x00, EPD_ARRAY)?; self.interface.cmd(spi, Command::DataStartTransmission2)?; - // for _ in 0..h { - // for _ in 0..w { - // self.interface.data(spi, &[0xFF])?; - // } - // } - self.interface.data_x_times(spi, 0xFF, WIDTH / 8 * HEIGHT)?; + self.interface.data_x_times(spi, 0xFF, EPD_ARRAY)?; - self.turn_on_display(spi, delay)?; + self.display_frame(spi, delay)?; Ok(()) } - fn set_background_color(&mut self, background_color: Color) { - self.color = background_color; - } - - fn background_color(&self) -> &Color { - &self.color - } - fn set_lut( &mut self, spi: &mut SPI, @@ -310,7 +284,7 @@ where } } -impl Epd2in9d +impl Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> where SPI: Write, CS: OutputPin, @@ -319,16 +293,6 @@ where RST: OutputPin, DELAY: DelayUs, { - fn turn_on_display(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - //DISPLAY REFRESH - self.interface.cmd(spi, Command::DisplayRefresh)?; - //The delay here is necessary, 200uS at least!!! - delay.delay_us(200); - - self.wait_until_idle(spi, delay)?; - Ok(()) - } - /// 唤醒屏幕 /// /// 在屏幕执行sleep之后,会进入深度睡眠模式。在深度睡眠模式下若需要刷新屏幕,必须先执行awaken() @@ -356,7 +320,7 @@ where fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // 重置EPD驱动电路 //TODO: 这里在微雪的例程中反复刷新了3次,后面有显示问题再进行修改 - self.interface.reset(delay, 20_000, 2_000); + self.interface.reset(delay, 10_000, 2_000); // 电源设置 //TODO: 文档中的数据为[0x03,0x00,0x2b,0x2b,0x09] @@ -370,27 +334,15 @@ where self.interface .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; - // 开启电源 - // self.interface.cmd_with_data( - // spi, - // Command::PowerOn, - // &[0x04], - // ); - self.interface.cmd(spi, Command::PowerOn)?; - - // 获取BUSY电平,高电平继续执行,低电平则等待屏幕响应 - //TODO: 这里是文档推荐的步骤,但我看其他屏幕的也没等待就先忽略了 - // self.wait_until_idle(spi, delay)?; - // 面板设置 self.interface - .cmd_with_data(spi, Command::PanelSetting, &[0xbf])?; + .cmd_with_data(spi, Command::PanelSetting, &[0xbf, 0x0D])?; // 设置刷新率 // 3a 100HZ | 29 150Hz | 39 200HZ | 31 171HZ // 例程中使用3a self.interface - .cmd_with_data(spi, Command::PllControl, &[0x3a])?; + .cmd_with_data(spi, Command::PllControl, &[0x3C])?; // 分辨率设置 self.interface @@ -400,11 +352,24 @@ where self.interface .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; + self.set_lut(spi, delay, None)?; + + // 开启电源 + // self.interface.cmd_with_data( + // spi, + // Command::PowerOn, + // &[0x04], + // ); + self.interface.cmd(spi, Command::PowerOn)?; + + // 获取BUSY电平,高电平继续执行,低电平则等待屏幕响应 + //TODO: 这里是文档推荐的步骤,但我看其他屏幕的也没等待就先忽略了 + self.wait_until_idle(spi, delay)?; + // vcom和数据间隔设置 - self.interface - .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; + // self.interface + // .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; - self.set_lut(spi, delay, None)?; Ok(()) } @@ -419,7 +384,7 @@ where lut_wb: &[u8], lut_bb: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; + let _ = delay; // LUT VCOM self.interface .cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; @@ -442,126 +407,3 @@ where Ok(()) } } - -// impl QuickRefresh -// for Epd2in9d -// where -// SPI: Write, -// CS: OutputPin, -// BUSY: InputPin, -// DC: OutputPin, -// RST: OutputPin, -// DELAY: DelayUs, -// { -// /// To be followed immediately by `update_new_frame`. -// fn update_old_frame( -// &mut self, -// spi: &mut SPI, -// buffer: &[u8], -// delay: &mut DELAY, -// ) -> Result<(), SPI::Error> { -// self.wait_until_idle(spi, delay)?; -// self.interface -// .cmd_with_data(spi, Command::WriteRam2, buffer) -// } - -// /// To be used immediately after `update_old_frame`. -// fn update_new_frame( -// &mut self, -// spi: &mut SPI, -// buffer: &[u8], -// delay: &mut DELAY, -// ) -> Result<(), SPI::Error> { -// self.wait_until_idle(spi, delay)?; -// self.interface.reset(delay, 10_000, 2_000); - -// self.set_lut_helper(spi, delay, &LUT_PARTIAL_2IN9)?; -// self.interface.cmd_with_data( -// spi, -// Command::WriteOtpSelection, -// &[0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00], -// )?; -// self.interface -// .cmd_with_data(spi, Command::BorderWaveformControl, &[0x80])?; -// self.interface -// .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC0])?; -// self.interface.cmd(spi, Command::MasterActivation)?; - -// self.wait_until_idle(spi, delay)?; - -// self.use_full_frame(spi, delay)?; - -// self.interface -// .cmd_with_data(spi, Command::WriteRam, buffer)?; -// Ok(()) -// } - -// /// For a quick refresh of the new updated frame. To be used immediately after `update_new_frame` -// fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { -// self.wait_until_idle(spi, delay)?; -// self.interface -// .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; -// self.interface.cmd(spi, Command::MasterActivation)?; -// self.wait_until_idle(spi, delay)?; -// Ok(()) -// } - -// /// Updates and displays the new frame. -// fn update_and_display_new_frame( -// &mut self, -// spi: &mut SPI, -// buffer: &[u8], -// delay: &mut DELAY, -// ) -> Result<(), SPI::Error> { -// self.update_new_frame(spi, buffer, delay)?; -// self.display_new_frame(spi, delay)?; -// Ok(()) -// } - -// /// Partial quick refresh not supported yet -// #[allow(unused)] -// fn update_partial_old_frame( -// &mut self, -// spi: &mut SPI, -// delay: &mut DELAY, -// buffer: &[u8], -// x: u32, -// y: u32, -// width: u32, -// height: u32, -// ) -> Result<(), SPI::Error> { -// //TODO supported by display? -// unimplemented!() -// } - -// /// Partial quick refresh not supported yet -// #[allow(unused)] -// fn update_partial_new_frame( -// &mut self, -// spi: &mut SPI, -// delay: &mut DELAY, -// buffer: &[u8], -// x: u32, -// y: u32, -// width: u32, -// height: u32, -// ) -> Result<(), SPI::Error> { -// //TODO supported by display? -// unimplemented!() -// } - -// /// Partial quick refresh not supported yet -// #[allow(unused)] -// fn clear_partial_frame( -// &mut self, -// spi: &mut SPI, -// delay: &mut DELAY, -// x: u32, -// y: u32, -// width: u32, -// height: u32, -// ) -> Result<(), SPI::Error> { -// //TODO supported by display? -// unimplemented!() -// } -// } From 8986f935818812f52d9222273488fa2833302041 Mon Sep 17 00:00:00 2001 From: zzlwd Date: Sun, 15 Oct 2023 23:19:33 +0800 Subject: [PATCH 33/69] Follow the master branch to update to 1.0-rc1 --- src/epd2in9d/mod.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index e8047c9f..87b5e8ad 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -8,12 +8,13 @@ use core::slice::from_raw_parts; use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::*, + delay::DelayUs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::interface::DisplayInterface; -use crate::traits::{RefreshLut, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; //The Lookup Tables for the Display mod constants; @@ -49,9 +50,9 @@ pub type Display2in9d = crate::graphics::Display< /// Epd2in9d driver /// -pub struct Epd2in9d<'a, SPI, CS, BUSY, DC, RST, DELAY> { +pub struct Epd2in9d<'a, SPI, BUSY, DC, RST, DELAY> { /// SPI - interface: DisplayInterface, + interface: DisplayInterface, /// Color // background_color: Color, color: Color, @@ -63,14 +64,14 @@ pub struct Epd2in9d<'a, SPI, CS, BUSY, DC, RST, DELAY> { is_partial_refresh: bool, } -impl Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> +impl InternalWiAdditions + for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 2_000); @@ -95,27 +96,25 @@ where } } -impl WaveshareDisplay - for Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> +impl WaveshareDisplay + for Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let old_data: &[u8] = &[]; let is_partial_refresh = false; @@ -284,14 +283,13 @@ where } } -impl Epd2in9d<'_, SPI, CS, BUSY, DC, RST, DELAY> +impl Epd2in9d<'_, SPI, BUSY, DC, RST, DELAY> where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayUs, { /// 唤醒屏幕 /// From d5286a825491259b651da2998dfca08b8606ada6 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Mon, 6 Nov 2023 08:57:42 +0100 Subject: [PATCH 34/69] fix build when feature graphics is not enabled --- src/color.rs | 2 +- src/graphics.rs | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/color.rs b/src/color.rs index 21e0ecdd..af1f8083 100644 --- a/src/color.rs +++ b/src/color.rs @@ -66,7 +66,7 @@ pub enum OctColor { } /// Color trait for use in `Display`s -pub trait ColorType: PixelColor { +pub trait ColorType { /// Number of bit used to represent this color type in a single buffer. /// To get the real number of bits per pixel you should multiply this by `BUFFER_COUNT` const BITS_PER_PIXEL_PER_BUFFER: usize; diff --git a/src/graphics.rs b/src/graphics.rs index 7037cef5..51ddda58 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -51,7 +51,7 @@ pub struct Display< const HEIGHT: u32, const BWRBIT: bool, const BYTECOUNT: usize, - COLOR: ColorType, + COLOR: ColorType + PixelColor, > { buffer: [u8; BYTECOUNT], rotation: DisplayRotation, @@ -63,7 +63,7 @@ impl< const HEIGHT: u32, const BWRBIT: bool, const BYTECOUNT: usize, - COLOR: ColorType, + COLOR: ColorType + PixelColor, > Default for Display { /// Initialize display with the color '0', which may not be the same on all device. @@ -91,7 +91,7 @@ impl< const HEIGHT: u32, const BWRBIT: bool, const BYTECOUNT: usize, - COLOR: ColorType, + COLOR: ColorType + PixelColor, > DrawTarget for Display { type Color = COLOR; @@ -114,7 +114,7 @@ impl< const HEIGHT: u32, const BWRBIT: bool, const BYTECOUNT: usize, - COLOR: ColorType, + COLOR: ColorType + PixelColor, > OriginDimensions for Display { fn size(&self) -> Size { @@ -130,7 +130,7 @@ impl< const HEIGHT: u32, const BWRBIT: bool, const BYTECOUNT: usize, - COLOR: ColorType, + COLOR: ColorType + PixelColor, > Display { /// get internal buffer to use it (to draw in epd) @@ -182,7 +182,7 @@ impl { +pub struct VarDisplay<'a, COLOR: ColorType + PixelColor> { width: u32, height: u32, bwrbit: bool, @@ -192,7 +192,7 @@ pub struct VarDisplay<'a, COLOR: ColorType> { } /// For use with embedded_grahics -impl<'a, COLOR: ColorType> DrawTarget for VarDisplay<'a, COLOR> { +impl<'a, COLOR: ColorType + PixelColor> DrawTarget for VarDisplay<'a, COLOR> { type Color = COLOR; type Error = core::convert::Infallible; @@ -208,7 +208,7 @@ impl<'a, COLOR: ColorType> DrawTarget for VarDisplay<'a, COLOR> { } /// For use with embedded_grahics -impl<'a, COLOR: ColorType> OriginDimensions for VarDisplay<'a, COLOR> { +impl<'a, COLOR: ColorType + PixelColor> OriginDimensions for VarDisplay<'a, COLOR> { fn size(&self) -> Size { match self.rotation { DisplayRotation::Rotate0 | DisplayRotation::Rotate180 => { @@ -228,7 +228,7 @@ pub enum VarDisplayError { BufferTooSmall, } -impl<'a, COLOR: ColorType> VarDisplay<'a, COLOR> { +impl<'a, COLOR: ColorType + PixelColor> VarDisplay<'a, COLOR> { /// You must allocate the buffer by yourself, it must be large enough to contain all pixels. /// /// Parameters are documented in `Display` as they are the same as the const generics there. @@ -312,7 +312,7 @@ impl<'a> VarDisplay<'a, TriColor> { // It sets a specific pixel in a buffer to a given color. // The big number of parameters is due to the fact that it is an internal function to both // strctures. -fn set_pixel( +fn set_pixel( buffer: &mut [u8], width: u32, height: u32, From 46c38bd2b9d6ba882b8918d9f710e375b9078281 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Tue, 7 Nov 2023 10:17:44 +0100 Subject: [PATCH 35/69] fix buffer size for 7in5v3 --- src/epd7in5_v3/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index 962924af..79ba7653 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -29,7 +29,7 @@ pub type Display7in5 = crate::graphics::Display< WIDTH, HEIGHT, false, - { buffer_len(WIDTH as usize, HEIGHT as usize) }, + { buffer_len(WIDTH as usize, HEIGHT as usize * 2) }, TriColor, >; From 2f33f194ce398494b695bdbd084e3f4079864499 Mon Sep 17 00:00:00 2001 From: Dirk Van Haerenborgh Date: Tue, 7 Nov 2023 17:01:59 +0100 Subject: [PATCH 36/69] update v2 driver and remove v3 --- src/epd7in5_v3/command.rs | 153 ----------------- src/epd7in5_v3/mod.rs | 328 ------------------------------------- src/epd7in5b_v2/command.rs | 20 ++- src/epd7in5b_v2/mod.rs | 69 +++++++- src/lib.rs | 2 +- 5 files changed, 79 insertions(+), 493 deletions(-) delete mode 100644 src/epd7in5_v3/command.rs delete mode 100644 src/epd7in5_v3/mod.rs diff --git a/src/epd7in5_v3/command.rs b/src/epd7in5_v3/command.rs deleted file mode 100644 index cc7dcdc7..00000000 --- a/src/epd7in5_v3/command.rs +++ /dev/null @@ -1,153 +0,0 @@ -//! SPI Commands for the Waveshare 7.5" V3 E-Ink Display - -use crate::traits; - -/// Epd7in5 commands -/// -/// Should rarely (never?) be needed directly. -/// -/// For more infos about the addresses and what they are doing look into the PDFs. -#[allow(dead_code)] -#[derive(Copy, Clone)] -pub(crate) enum Command { - /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift - /// direction, booster switch, soft reset. - PanelSetting = 0x00, - - /// Selecting internal and external power - PowerSetting = 0x01, - - /// After the Power Off command, the driver will power off following the Power Off - /// Sequence; BUSY signal will become "0". This command will turn off charge pump, - /// T-con, source driver, gate driver, VCOM, and temperature sensor, but register - /// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain - /// as previous condition, which may have 2 conditions: 0V or floating. - PowerOff = 0x02, - - /// Setting Power OFF sequence - PowerOffSequenceSetting = 0x03, - - /// Turning On the Power - /// - /// After the Power ON command, the driver will power on following the Power ON - /// sequence. Once complete, the BUSY signal will become "1". - PowerOn = 0x04, - - /// Starting data transmission - BoosterSoftStart = 0x06, - - /// This command makes the chip enter the deep-sleep mode to save power. - /// - /// The deep sleep mode would return to stand-by by hardware reset. - /// - /// The only one parameter is a check code, the command would be excuted if check code = 0xA5. - DeepSleep = 0x07, - - /// This command starts transmitting data and write them into SRAM. To complete data - /// transmission, command DSP (Data Stop) must be issued. Then the chip will start to - /// send data/VCOM for panel. - /// - /// BLACK/WHITE or OLD_DATA - DataStartTransmission1 = 0x10, - - /// To stop data transmission, this command must be issued to check the `data_flag`. - /// - /// After this command, BUSY signal will become "0" until the display update is - /// finished. - DataStop = 0x11, - - /// After this command is issued, driver will refresh display (data/VCOM) according to - /// SRAM data and LUT. - /// - /// After Display Refresh command, BUSY signal will become "0" until the display - /// update is finished. - DisplayRefresh = 0x12, - - /// RED or NEW_DATA - DataStartTransmission2 = 0x13, - - /// Dual SPI - what for? - DualSpi = 0x15, - - /// This command builds the VCOM Look-Up Table (LUTC). - LutForVcom = 0x20, - /// This command builds the Black Look-Up Table (LUTB). - LutBlack = 0x21, - /// This command builds the White Look-Up Table (LUTW). - LutWhite = 0x22, - /// This command builds the Gray1 Look-Up Table (LUTG1). - LutGray1 = 0x23, - /// This command builds the Gray2 Look-Up Table (LUTG2). - LutGray2 = 0x24, - /// This command builds the Red0 Look-Up Table (LUTR0). - LutRed0 = 0x25, - /// This command builds the Red1 Look-Up Table (LUTR1). - LutRed1 = 0x26, - /// This command builds the Red2 Look-Up Table (LUTR2). - LutRed2 = 0x27, - /// This command builds the Red3 Look-Up Table (LUTR3). - LutRed3 = 0x28, - /// This command builds the XON Look-Up Table (LUTXON). - LutXon = 0x29, - - /// The command controls the PLL clock frequency. - PllControl = 0x30, - - /// This command reads the temperature sensed by the temperature sensor. - TemperatureSensor = 0x40, - /// This command selects the Internal or External temperature sensor. - TemperatureCalibration = 0x41, - /// This command could write data to the external temperature sensor. - TemperatureSensorWrite = 0x42, - /// This command could read data from the external temperature sensor. - TemperatureSensorRead = 0x43, - - /// This command indicates the interval of Vcom and data output. When setting the - /// vertical back porch, the total blanking will be kept (20 Hsync). - VcomAndDataIntervalSetting = 0x50, - /// This command indicates the input power condition. Host can read this flag to learn - /// the battery condition. - LowPowerDetection = 0x51, - - /// This command defines non-overlap period of Gate and Source. - TconSetting = 0x60, - /// This command defines alternative resolution and this setting is of higher priority - /// than the RES\[1:0\] in R00H (PSR). - TconResolution = 0x61, - /// This command defines MCU host direct access external memory mode. - SpiFlashControl = 0x65, - - /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. - Revision = 0x70, - /// This command reads the IC status. - GetStatus = 0x71, - - /// This command implements related VCOM sensing setting. - AutoMeasurementVcom = 0x80, - /// This command gets the VCOM value. - ReadVcomValue = 0x81, - /// This command sets `VCOM_DC` value. - VcmDcSetting = 0x82, - // /// This is in all the Waveshare controllers for Epd7in5, but it's not documented - // /// anywhere in the datasheet `¯\_(ツ)_/¯` - // FlashMode = 0xE5, -} - -impl traits::Command for Command { - /// Returns the address of the command - fn address(self) -> u8 { - self as u8 - } -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::traits::Command as CommandTrait; - - #[test] - fn command_addr() { - assert_eq!(Command::PanelSetting.address(), 0x00); - assert_eq!(Command::DisplayRefresh.address(), 0x12); - } -} diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs deleted file mode 100644 index 79ba7653..00000000 --- a/src/epd7in5_v3/mod.rs +++ /dev/null @@ -1,328 +0,0 @@ -//! A simple Driver for the Waveshare 7.5" E-Ink Display (V3) via SPI -//! -//! # References -//! -//! - [Datasheet](https://www.waveshare.com/wiki/7.5inch_e-Paper_HAT) -//! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/702def0/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_7in5_V2.c) -//! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5_V2.py) -//! - -use embedded_hal::{ - delay::DelayUs, - digital::{InputPin, OutputPin}, - spi::SpiDevice, -}; - -use crate::color::TriColor; -use crate::interface::DisplayInterface; -use crate::traits::{ - InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, -}; - -pub(crate) mod command; -use self::command::Command; -use crate::buffer_len; - -/// Full size buffer for use with the 7in5 v3 EPD -#[cfg(feature = "graphics")] -pub type Display7in5 = crate::graphics::Display< - WIDTH, - HEIGHT, - false, - { buffer_len(WIDTH as usize, HEIGHT as usize * 2) }, - TriColor, ->; - -/// Width of the display -pub const WIDTH: u32 = 800; -/// Height of the display -pub const HEIGHT: u32 = 480; -/// Default Background Color -//pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; - -pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; - -/// Number of bits for b/w buffer and same for chromatic buffer -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; -const IS_BUSY_LOW: bool = true; -const SINGLE_BYTE_WRITE: bool = false; - -/// Epd7in5 (V3) driver -/// -pub struct Epd7in5 { - /// Connection Interface - interface: DisplayInterface, - /// Background Color - color: TriColor, -} - -impl InternalWiAdditions - for Epd7in5 -where - SPI: SpiDevice, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayUs, -{ - fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - // Reset the device - self.interface.reset(delay, 200_000, 4_000); - - // V2 procedure as described here: - // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py - // and as per specs: - // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf - - //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; - self.command(spi, Command::PowerOn)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; - //self.cmd_with_data(spi, Command::PllControl, &[0x06])?; - self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; - self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?; - self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00])?; - self.wait_until_idle(spi, delay)?; - Ok(()) - } -} - -impl WaveshareThreeColorDisplay - for Epd7in5 -where - SPI: SpiDevice, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayUs, -{ - fn update_color_frame( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - black: &[u8], - chromatic: &[u8], - ) -> Result<(), SPI::Error> { - self.update_achromatic_frame(spi, delay, black)?; - self.update_chromatic_frame(spi, delay, chromatic) - } - - /// Update only the black/white data of the display. - /// - /// Finish by calling `update_chromatic_frame`. - fn update_achromatic_frame( - &mut self, - spi: &mut SPI, - _delay: &mut DELAY, - black: &[u8], - ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, black)?; - Ok(()) - } - - /// Update only chromatic data of the display. - /// - /// This data takes precedence over the black/white data. - fn update_chromatic_frame( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - chromatic: &[u8], - ) -> Result<(), SPI::Error> { - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data(spi, chromatic)?; - - self.wait_until_idle(spi, delay)?; - Ok(()) - } -} - -impl WaveshareDisplay - for Epd7in5 -where - SPI: SpiDevice, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayUs, -{ - type DisplayColor = TriColor; - fn new( - spi: &mut SPI, - busy: BUSY, - dc: DC, - rst: RST, - delay: &mut DELAY, - delay_us: Option, - ) -> Result { - let interface = DisplayInterface::new(busy, dc, rst, delay_us); - let color = DEFAULT_BACKGROUND_COLOR; - - let mut epd = Epd7in5 { interface, color }; - - epd.init(spi, delay)?; - - Ok(epd) - } - - fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.init(spi, delay) - } - - fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::PowerOff)?; - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; - Ok(()) - } - - fn update_frame( - &mut self, - spi: &mut SPI, - buffer: &[u8], - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; - - self.interface.data(spi, buffer)?; - - // Clear the chromatic layer - let color = self.color.get_byte_value(); - - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; - - self.wait_until_idle(spi, delay)?; - - Ok(()) - } - - fn update_partial_frame( - &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, - _buffer: &[u8], - _x: u32, - _y: u32, - _width: u32, - _height: u32, - ) -> Result<(), SPI::Error> { - unimplemented!(); - } - - fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; - Ok(()) - } - - fn update_and_display_frame( - &mut self, - spi: &mut SPI, - buffer: &[u8], - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer, delay)?; - self.command(spi, Command::DisplayRefresh)?; - Ok(()) - } - - fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.wait_until_idle(spi, delay)?; - self.send_resolution(spi)?; - - self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; - - self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; - - self.command(spi, Command::DisplayRefresh)?; - Ok(()) - } - - fn set_background_color(&mut self, color: TriColor) { - self.color = color; - } - - fn background_color(&self) -> &TriColor { - &self.color - } - - fn width(&self) -> u32 { - WIDTH - } - - fn height(&self) -> u32 { - HEIGHT - } - - fn set_lut( - &mut self, - _spi: &mut SPI, - _delay: &mut DELAY, - _refresh_rate: Option, - ) -> Result<(), SPI::Error> { - unimplemented!(); - } - - fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface - .wait_until_idle_with_cmd(spi, delay, IS_BUSY_LOW, Command::GetStatus) - } -} - -impl Epd7in5 -where - SPI: SpiDevice, - BUSY: InputPin, - DC: OutputPin, - RST: OutputPin, - DELAY: DelayUs, -{ - fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { - self.interface.cmd(spi, command) - } - - fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - self.interface.data(spi, data) - } - - fn cmd_with_data( - &mut self, - spi: &mut SPI, - command: Command, - data: &[u8], - ) -> Result<(), SPI::Error> { - self.interface.cmd_with_data(spi, command, data) - } - - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - let w = self.width(); - let h = self.height(); - - self.command(spi, Command::TconResolution)?; - self.send_data(spi, &[(w >> 8) as u8])?; - self.send_data(spi, &[w as u8])?; - self.send_data(spi, &[(h >> 8) as u8])?; - self.send_data(spi, &[h as u8]) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn epd_size() { - assert_eq!(WIDTH, 800); - assert_eq!(HEIGHT, 480); - assert_eq!(DEFAULT_BACKGROUND_COLOR, TriColor::White); - } -} diff --git a/src/epd7in5b_v2/command.rs b/src/epd7in5b_v2/command.rs index da3b16be..fd2d70c4 100644 --- a/src/epd7in5b_v2/command.rs +++ b/src/epd7in5b_v2/command.rs @@ -70,17 +70,25 @@ pub(crate) enum Command { DualSpi = 0x15, /// This command builds the VCOM Look-Up Table (LUTC). - LutC = 0x20, + LutForVcom = 0x20, /// This command builds the Black Look-Up Table (LUTB). - LutWW = 0x21, + LutBlack = 0x21, /// This command builds the White Look-Up Table (LUTW). - LutBW = 0x22, + LutWhite = 0x22, /// This command builds the Gray1 Look-Up Table (LUTG1). - LutWB = 0x23, + LutGray1 = 0x23, /// This command builds the Gray2 Look-Up Table (LUTG2). - LutBB = 0x24, + LutGray2 = 0x24, /// This command builds the Red0 Look-Up Table (LUTR0). - LutBD = 0x25, + LutRed0 = 0x25, + /// This command builds the Red1 Look-Up Table (LUTR1). + LutRed1 = 0x26, + /// This command builds the Red2 Look-Up Table (LUTR2). + LutRed2 = 0x27, + /// This command builds the Red3 Look-Up Table (LUTR3). + LutRed3 = 0x28, + /// This command builds the XON Look-Up Table (LUTXON). + LutXon = 0x29, /// LUT Option LutOpt = 0x2A, diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index c71d030c..3b204e31 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -18,13 +18,15 @@ use embedded_hal::{ use crate::color::TriColor; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; +use crate::traits::{ + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; pub(crate) mod command; use self::command::Command; use crate::buffer_len; -/// Full size buffer for use with the 1in54 EPD +/// Full size buffer for use with the 7in5b v2 EPD #[cfg(feature = "graphics")] pub type Display7in5 = crate::graphics::Display< WIDTH, @@ -41,7 +43,8 @@ pub const HEIGHT: u32 = 480; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; -const NUM_DISPLAY_BYTES: usize = WIDTH as usize * HEIGHT as usize / 8; +/// Number of bits for b/w buffer and same for chromatic buffer +const NUM_DISPLAY_BITS: usize = WIDTH as usize * HEIGHT as usize / 8; const IS_BUSY_LOW: bool = true; const SINGLE_BYTE_WRITE: bool = false; @@ -103,6 +106,59 @@ where } } +impl WaveshareThreeColorDisplay + for Epd7in5 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, delay, black)?; + self.update_chromatic_frame(spi, delay, chromatic) + } + + /// Update only the black/white data of the display. + /// + /// Finish by calling `update_chromatic_frame`. + fn update_achromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + black: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface.data(spi, black)?; + self.interface.cmd(spi, Command::DataStop)?; + Ok(()) + } + + /// Update only chromatic data of the display. + /// + /// This data takes precedence over the black/white data. + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.data(spi, chromatic)?; + self.interface.cmd(spi, Command::DataStop)?; + + self.wait_until_idle(spi, delay)?; + Ok(()) + } +} + impl WaveshareDisplay for Epd7in5 where @@ -154,13 +210,14 @@ where self.cmd_with_data( spi, Command::DataStartTransmission1, - &buffer[..NUM_DISPLAY_BYTES], + &buffer[..NUM_DISPLAY_BITS], )?; self.cmd_with_data( spi, Command::DataStartTransmission2, - &buffer[NUM_DISPLAY_BYTES..], + &buffer[NUM_DISPLAY_BITS..], )?; + self.interface.cmd(spi, Command::DataStop)?; Ok(()) } @@ -204,6 +261,8 @@ where self.command(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.interface.cmd(spi, Command::DataStop)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) diff --git a/src/lib.rs b/src/lib.rs index bdedf055..4fec13ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,8 +90,8 @@ pub mod epd5in83b_v2; pub mod epd7in5; pub mod epd7in5_hd; pub mod epd7in5_v2; -pub mod epd7in5_v3; pub mod epd7in5b_v2; +pub use epd7in5b_v2 as epd7in5b_v3; pub(crate) mod type_a; From 378918f7ad11919e2d3cf86022f617605eb05482 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Thu, 28 Dec 2023 14:44:48 -0800 Subject: [PATCH 37/69] embedded-hal: 1.0.0-rc.1 -> 1.0.0-rc.3 --- Cargo.toml | 8 +++----- examples/epd1in54_no_graphics.rs | 6 +++--- examples/epd2in13_v2.rs | 6 +++--- examples/epd2in13bc.rs | 6 +++--- examples/epd4in2.rs | 6 +++--- examples/epd4in2_variable_size.rs | 6 +++--- src/epd1in54/mod.rs | 6 +++--- src/epd1in54_v2/mod.rs | 6 +++--- src/epd1in54b/mod.rs | 8 ++++---- src/epd1in54c/mod.rs | 8 ++++---- src/epd2in13_v2/mod.rs | 8 ++++---- src/epd2in13bc/mod.rs | 8 ++++---- src/epd2in7b/mod.rs | 8 ++++---- src/epd2in9/mod.rs | 6 +++--- src/epd2in9_v2/mod.rs | 8 ++++---- src/epd2in9bc/mod.rs | 8 ++++---- src/epd3in7/mod.rs | 6 +++--- src/epd4in2/mod.rs | 8 ++++---- src/epd5in65f/mod.rs | 8 ++++---- src/epd5in83b_v2/mod.rs | 10 +++++----- src/epd7in5/mod.rs | 8 ++++---- src/epd7in5_hd/mod.rs | 8 ++++---- src/epd7in5_v2/mod.rs | 8 ++++---- src/epd7in5_v3/mod.rs | 10 +++++----- src/epd7in5b_v2/mod.rs | 8 ++++---- src/interface.rs | 4 ++-- src/traits.rs | 8 ++++---- 27 files changed, 98 insertions(+), 100 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6eff17ec..69f4b33c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,20 +17,18 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } -embedded-hal = { version = "1.0.0-rc.1" } +embedded-hal = "1.0.0-rc.3" bit_field = "0.10.1" [dev-dependencies] embedded-graphics = "0.8" - -embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", default-features = false, features = [ +embedded-hal-mock = { version = "=0.10.0-rc.4", default-features = false, features = [ "eh1", ] } -# embedded-hal-mock = "0.9" [target.'cfg(unix)'.dev-dependencies] # linux-embedded-hal = "0.3" -linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal" } +linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal", rev = "a1fb24103e575615a29c6748cdeff1f0e7a3dae3" } [[example]] name = "epd1in54_no_graphics" diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 7df04a00..4baac378 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -1,11 +1,11 @@ #![deny(warnings)] -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{epd1in54::Epd1in54, prelude::*}; use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -15,7 +15,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // SPI settings are from eink-waveshare-rs documenation - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi = SpidevDevice::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index d4c63c4c..b3cb64eb 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd2in13_v2::{Display2in13, Epd2in13}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // The pins in this example are for the Universal e-Paper Raw Panel Driver HAT @@ -27,7 +27,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 82a23961..8007acf3 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd2in13bc::{Display2in13bc, Epd2in13bc}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -61,7 +61,7 @@ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(10_000_000) diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 74a6a992..10576124 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd4in2::{Display4in2, Epd4in2}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -26,7 +26,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index e6d92c68..8ff8259d 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -7,7 +7,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd4in2::{self, Epd4in2}, @@ -17,7 +17,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -27,7 +27,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 9bc1b7fe..4a4514ed 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -94,7 +94,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -149,7 +149,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -300,7 +300,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 0f0399f7..1208d960 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -44,7 +44,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -94,7 +94,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -267,7 +267,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 0a477bf4..22177db9 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -50,7 +50,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -96,7 +96,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -146,7 +146,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -324,7 +324,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 341baf7d..445f9ab7 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -47,7 +47,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Based on Reference Program Code from: @@ -83,7 +83,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -128,7 +128,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -265,7 +265,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 7712835d..5d8d4e0b 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,7 +16,7 @@ //! use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -87,7 +87,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // HW reset @@ -180,7 +180,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -392,7 +392,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 280f47a7..b47250de 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -104,7 +104,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -147,7 +147,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -198,7 +198,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( @@ -347,7 +347,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 941d0393..2db23059 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -54,7 +54,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -119,7 +119,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -280,7 +280,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -335,7 +335,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 6e3e178d..48c5bdcc 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -91,7 +91,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -142,7 +142,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -296,7 +296,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 7004a77e..d9c4bcf0 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -114,7 +114,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 2_000); @@ -155,7 +155,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -297,7 +297,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram @@ -383,7 +383,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// To be followed immediately by `update_new_frame`. fn update_old_frame( diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 121c5680..30611706 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -108,7 +108,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -151,7 +151,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -202,7 +202,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -351,7 +351,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c7f06855..c01c49fa 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -3,7 +3,7 @@ //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -57,7 +57,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -130,7 +130,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index fe43d0ef..a1c2a0d4 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -101,7 +101,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -155,7 +155,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -354,7 +354,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -449,7 +449,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// To be followed immediately after by `update_old_frame`. fn update_old_frame( diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 6233955b..1a70b78a 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -55,7 +55,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -87,7 +87,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = OctColor; fn new( @@ -213,7 +213,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index d1df524e..abafbf3b 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -57,7 +57,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -101,7 +101,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -145,7 +145,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -308,7 +308,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 5b89e1a1..121b780d 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -55,7 +55,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -110,7 +110,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -243,7 +243,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 5ef9cd47..c566b56c 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -10,7 +10,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -58,7 +58,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -110,7 +110,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -240,7 +240,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index f971bf43..26fa9dba 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -59,7 +59,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -92,7 +92,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -217,7 +217,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index 962924af..657db1e0 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -8,7 +8,7 @@ //! use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -63,7 +63,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -97,7 +97,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -148,7 +148,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( @@ -284,7 +284,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index c71d030c..ed79a36e 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -61,7 +61,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -110,7 +110,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( @@ -247,7 +247,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// temporary replacement for missing delay in the trait to call wait_until_idle #[allow(clippy::too_many_arguments)] diff --git a/src/interface.rs b/src/interface.rs index e53d9186..f3a9a3d7 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -28,7 +28,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Creates a new `DisplayInterface` struct /// @@ -182,7 +182,7 @@ where /// /// Most likely there was a mistake with the 2in9 busy connection /// //TODO: use the #cfg feature to make this compile the right way for the certain types - pub(crate) fn is_busy(&self, is_busy_low: bool) -> bool { + pub(crate) fn is_busy(&mut self, is_busy_low: bool) -> bool { (is_busy_low && self.busy.is_low().unwrap_or(false)) || (!is_busy_low && self.busy.is_high().unwrap_or(false)) } diff --git a/src/traits.rs b/src/traits.rs index 25df34ad..b1f3f731 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -24,7 +24,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// This initialises the EPD and powers it up /// @@ -47,7 +47,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Transmit data to the SRAM of the EPD /// @@ -132,7 +132,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// The Color Type used by the Display type DisplayColor; @@ -291,7 +291,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Updates the old frame. fn update_old_frame( From a9e4c915f79f45dfeb8bdab9543fba546d7a1381 Mon Sep 17 00:00:00 2001 From: Alex Martens Date: Thu, 28 Dec 2023 14:44:48 -0800 Subject: [PATCH 38/69] embedded-hal: 1.0.0-rc.1 -> 1.0.0-rc.3 --- Cargo.toml | 8 +++----- examples/epd1in54_no_graphics.rs | 6 +++--- examples/epd2in13_v2.rs | 6 +++--- examples/epd2in13bc.rs | 6 +++--- examples/epd4in2.rs | 6 +++--- examples/epd4in2_variable_size.rs | 6 +++--- src/epd1in54/mod.rs | 6 +++--- src/epd1in54_v2/mod.rs | 6 +++--- src/epd1in54b/mod.rs | 8 ++++---- src/epd1in54c/mod.rs | 8 ++++---- src/epd2in13_v2/mod.rs | 8 ++++---- src/epd2in13bc/mod.rs | 8 ++++---- src/epd2in7b/mod.rs | 8 ++++---- src/epd2in9/mod.rs | 6 +++--- src/epd2in9_v2/mod.rs | 8 ++++---- src/epd2in9bc/mod.rs | 8 ++++---- src/epd3in7/mod.rs | 6 +++--- src/epd4in2/mod.rs | 8 ++++---- src/epd5in65f/mod.rs | 8 ++++---- src/epd5in83b_v2/mod.rs | 10 +++++----- src/epd7in5/mod.rs | 8 ++++---- src/epd7in5_hd/mod.rs | 8 ++++---- src/epd7in5_v2/mod.rs | 8 ++++---- src/epd7in5b_v2/mod.rs | 8 ++++---- src/interface.rs | 4 ++-- src/traits.rs | 8 ++++---- 26 files changed, 93 insertions(+), 95 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6eff17ec..69f4b33c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,20 +17,18 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } -embedded-hal = { version = "1.0.0-rc.1" } +embedded-hal = "1.0.0-rc.3" bit_field = "0.10.1" [dev-dependencies] embedded-graphics = "0.8" - -embedded-hal-mock = { git = "https://github.com/newAM/embedded-hal-mock", branch = "eh1-rc.1", default-features = false, features = [ +embedded-hal-mock = { version = "=0.10.0-rc.4", default-features = false, features = [ "eh1", ] } -# embedded-hal-mock = "0.9" [target.'cfg(unix)'.dev-dependencies] # linux-embedded-hal = "0.3" -linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal" } +linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal", rev = "a1fb24103e575615a29c6748cdeff1f0e7a3dae3" } [[example]] name = "epd1in54_no_graphics" diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 7df04a00..4baac378 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -1,11 +1,11 @@ #![deny(warnings)] -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{epd1in54::Epd1in54, prelude::*}; use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -15,7 +15,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // SPI settings are from eink-waveshare-rs documenation - let mut spi = Spidev::open("/dev/spidev0.0")?; + let mut spi = SpidevDevice::open("/dev/spidev0.0")?; let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index d4c63c4c..b3cb64eb 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd2in13_v2::{Display2in13, Epd2in13}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // The pins in this example are for the Universal e-Paper Raw Panel Driver HAT @@ -27,7 +27,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 82a23961..8007acf3 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd2in13bc::{Display2in13bc, Epd2in13bc}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -61,7 +61,7 @@ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(10_000_000) diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 74a6a992..10576124 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -6,7 +6,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd4in2::{Display4in2, Epd4in2}, @@ -16,7 +16,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -26,7 +26,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index e6d92c68..8ff8259d 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -7,7 +7,7 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_hal::delay::DelayUs; +use embedded_hal::delay::DelayNs; use epd_waveshare::{ color::*, epd4in2::{self, Epd4in2}, @@ -17,7 +17,7 @@ use epd_waveshare::{ use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, - Delay, SPIError, Spidev, SysfsPin, + Delay, SPIError, SpidevDevice, SysfsPin, }; // activate spi, gpio in raspi-config @@ -27,7 +27,7 @@ use linux_embedded_hal::{ fn main() -> Result<(), SPIError> { // Configure SPI // Settings are taken from - let mut spi = Spidev::open("/dev/spidev0.0").expect("spidev directory"); + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); let options = SpidevOptions::new() .bits_per_word(8) .max_speed_hz(4_000_000) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 9bc1b7fe..4a4514ed 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -94,7 +94,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -149,7 +149,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -300,7 +300,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54_v2/mod.rs b/src/epd1in54_v2/mod.rs index 0f0399f7..1208d960 100644 --- a/src/epd1in54_v2/mod.rs +++ b/src/epd1in54_v2/mod.rs @@ -44,7 +44,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -94,7 +94,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -267,7 +267,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { pub(crate) fn use_full_frame( &mut self, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 0a477bf4..22177db9 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -50,7 +50,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -96,7 +96,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -146,7 +146,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -324,7 +324,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 341baf7d..445f9ab7 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -47,7 +47,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Based on Reference Program Code from: @@ -83,7 +83,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -128,7 +128,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -265,7 +265,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 7712835d..5d8d4e0b 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,7 +16,7 @@ //! use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -87,7 +87,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // HW reset @@ -180,7 +180,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -392,7 +392,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 280f47a7..b47250de 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -104,7 +104,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -147,7 +147,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -198,7 +198,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( @@ -347,7 +347,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 941d0393..2db23059 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -54,7 +54,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -119,7 +119,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -280,7 +280,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -335,7 +335,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 6e3e178d..48c5bdcc 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -91,7 +91,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 10_000); @@ -142,7 +142,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -296,7 +296,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 7004a77e..d9c4bcf0 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -114,7 +114,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 2_000); @@ -155,7 +155,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -297,7 +297,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // choose full frame/ram @@ -383,7 +383,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// To be followed immediately by `update_new_frame`. fn update_old_frame( diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 121c5680..30611706 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -108,7 +108,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code @@ -151,7 +151,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -202,7 +202,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -351,7 +351,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd3in7/mod.rs b/src/epd3in7/mod.rs index c7f06855..c01c49fa 100644 --- a/src/epd3in7/mod.rs +++ b/src/epd3in7/mod.rs @@ -3,7 +3,7 @@ //! //! Build with the help of documentation/code from [Waveshare](https://www.waveshare.com/wiki/3.7inch_e-Paper_HAT), use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -57,7 +57,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -130,7 +130,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index fe43d0ef..a1c2a0d4 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -101,7 +101,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device @@ -155,7 +155,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -354,7 +354,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -449,7 +449,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// To be followed immediately after by `update_old_frame`. fn update_old_frame( diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 6233955b..1a70b78a 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -55,7 +55,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -87,7 +87,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = OctColor; fn new( @@ -213,7 +213,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index d1df524e..abafbf3b 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83b_V2.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -57,7 +57,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -101,7 +101,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -145,7 +145,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -308,7 +308,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 5b89e1a1..121b780d 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -7,7 +7,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def06bcb75983c98b0f9d25d43c552c248eb0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5.py) use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -55,7 +55,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -110,7 +110,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -243,7 +243,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 5ef9cd47..c566b56c 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -10,7 +10,7 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) //! use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -58,7 +58,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -110,7 +110,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -240,7 +240,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index f971bf43..26fa9dba 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -59,7 +59,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -92,7 +92,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -217,7 +217,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 3b204e31..767bb9ff 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -11,7 +11,7 @@ //! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -64,7 +64,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -166,7 +166,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( @@ -306,7 +306,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// temporary replacement for missing delay in the trait to call wait_until_idle #[allow(clippy::too_many_arguments)] diff --git a/src/interface.rs b/src/interface.rs index e53d9186..f3a9a3d7 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -28,7 +28,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Creates a new `DisplayInterface` struct /// @@ -182,7 +182,7 @@ where /// /// Most likely there was a mistake with the 2in9 busy connection /// //TODO: use the #cfg feature to make this compile the right way for the certain types - pub(crate) fn is_busy(&self, is_busy_low: bool) -> bool { + pub(crate) fn is_busy(&mut self, is_busy_low: bool) -> bool { (is_busy_low && self.busy.is_low().unwrap_or(false)) || (!is_busy_low && self.busy.is_high().unwrap_or(false)) } diff --git a/src/traits.rs b/src/traits.rs index 25df34ad..b1f3f731 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -24,7 +24,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// This initialises the EPD and powers it up /// @@ -47,7 +47,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Transmit data to the SRAM of the EPD /// @@ -132,7 +132,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// The Color Type used by the Display type DisplayColor; @@ -291,7 +291,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { /// Updates the old frame. fn update_old_frame( From c406af867921c06008fb17c06343b7a42b55e1aa Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Fri, 12 Jan 2024 00:42:45 +0100 Subject: [PATCH 39/69] fmt --- src/epd2in9_v2/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index bca1d473..3a36fdf7 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -75,7 +75,6 @@ const LUT_PARTIAL_2IN9: [u8; 159] = [ 0x22, 0x0, 0x0, 0x0, 0x22, 0x17, 0x41, 0xB0, 0x32, 0x36, ]; - const WS_20_30: [u8; 159] = [ 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, 0x10, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x80, 0x66, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, 0x0, 0x0, 0x0, From c3d516851db8b1632ccb372f949a65badaeea016 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 11 Jan 2024 10:18:49 +0100 Subject: [PATCH 40/69] Update leh to 0.4 alpha.4 --- Cargo.toml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 69f4b33c..2c2e36b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,8 +27,7 @@ embedded-hal-mock = { version = "=0.10.0-rc.4", default-features = false, featur ] } [target.'cfg(unix)'.dev-dependencies] -# linux-embedded-hal = "0.3" -linux-embedded-hal = { git = "https://github.com/rust-embedded/linux-embedded-hal", rev = "a1fb24103e575615a29c6748cdeff1f0e7a3dae3" } +linux-embedded-hal = "0.4.0-alpha.4" [[example]] name = "epd1in54_no_graphics" From 9f70c167316e2bba2b7c9724156f419b9e193ae2 Mon Sep 17 00:00:00 2001 From: Christoph Date: Thu, 11 Jan 2024 11:55:20 +0100 Subject: [PATCH 41/69] Update to eh-1.0, eh-mock 0.10 (not released), leh 0.4.0 (not released) --- Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 2c2e36b4..55d682a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,17 +17,17 @@ edition = "2021" [dependencies] embedded-graphics-core = { version = "0.4", optional = true } -embedded-hal = "1.0.0-rc.3" +embedded-hal = "1.0.0" bit_field = "0.10.1" [dev-dependencies] embedded-graphics = "0.8" -embedded-hal-mock = { version = "=0.10.0-rc.4", default-features = false, features = [ +embedded-hal-mock = { version = "=0.10.0", default-features = false, features = [ "eh1", ] } [target.'cfg(unix)'.dev-dependencies] -linux-embedded-hal = "0.4.0-alpha.4" +linux-embedded-hal = "0.4.0" [[example]] name = "epd1in54_no_graphics" From 05ac118f48bec10920f42c148af2781f8517b39e Mon Sep 17 00:00:00 2001 From: Christoph Date: Fri, 12 Jan 2024 11:06:44 +0100 Subject: [PATCH 42/69] Fix epd2in9d Change delayUs to delayNs and translate part of the chinese docs to english. --- src/epd2in9d/mod.rs | 50 ++++++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index 87b5e8ad..95d72398 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -8,7 +8,7 @@ use core::slice::from_raw_parts; use embedded_hal::{ - delay::DelayUs, + delay::DelayNs, digital::{InputPin, OutputPin}, spi::SpiDevice, }; @@ -58,7 +58,7 @@ pub struct Epd2in9d<'a, SPI, BUSY, DC, RST, DELAY> { color: Color, /// Refresh LUT refresh: RefreshLut, - // 存放旧数据,以供部分刷新使用 + // Storing old data for partial refreshes old_data: &'a [u8], // 标记是否局刷的状态 is_partial_refresh: bool, @@ -71,7 +71,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10_000, 2_000); @@ -103,7 +103,7 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( @@ -166,8 +166,8 @@ where HEIGHT } - // 对应的是Display函数 - // 用于将要显示的数据写入屏幕SRAM + // Corresponds to the Display function. + // Used to write the data to be displayed to the screen SRAM. fn update_frame( &mut self, spi: &mut SPI, @@ -175,7 +175,7 @@ where delay: &mut DELAY, ) -> Result<(), SPI::Error> { if self.is_partial_refresh { - // 若进行全刷则修改局刷状态 + // Modify local refresh status if full refresh is performed. self.is_partial_refresh = false; } self.wait_until_idle(spi, delay)?; @@ -202,7 +202,7 @@ where height: u32, ) -> Result<(), SPI::Error> { if !self.is_partial_refresh { - // 仅在初次调用时初始化 + // Initialize only on first call self.set_part_reg(spi, delay)?; self.is_partial_refresh = true; } @@ -289,12 +289,12 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { - /// 唤醒屏幕 + /// Wake Up Screen /// - /// 在屏幕执行sleep之后,会进入深度睡眠模式。在深度睡眠模式下若需要刷新屏幕,必须先执行awaken() - /// 唤醒屏幕 + /// 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> { // // reset the device // self.interface.reset(delay, 20_000, 2_000); @@ -316,43 +316,43 @@ where // } fn set_part_reg(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - // 重置EPD驱动电路 + // Reset the EPD driver circuit //TODO: 这里在微雪的例程中反复刷新了3次,后面有显示问题再进行修改 self.interface.reset(delay, 10_000, 2_000); - // 电源设置 - //TODO: 文档中的数据为[0x03,0x00,0x2b,0x2b,0x09] + // Power settings + //TODO: The data in the document is [0x03,0x00,0x2b,0x2b,0x09]. self.interface.cmd_with_data( spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x03], )?; - // 软启动 + // Soft start self.interface .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; - // 面板设置 + // Panel settings self.interface .cmd_with_data(spi, Command::PanelSetting, &[0xbf, 0x0D])?; - // 设置刷新率 + // Setting the refresh rate // 3a 100HZ | 29 150Hz | 39 200HZ | 31 171HZ - // 例程中使用3a + // 3a is used in the example self.interface .cmd_with_data(spi, Command::PllControl, &[0x3C])?; - // 分辨率设置 + // Resolution Settings self.interface .cmd_with_data(spi, Command::ResolutionSetting, &[0x80, 0x01, 0x28])?; - // vcom_DC设置 + // vcom_DC settings self.interface .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; self.set_lut(spi, delay, None)?; - // 开启电源 + // Power on // self.interface.cmd_with_data( // spi, // Command::PowerOn, @@ -360,11 +360,11 @@ where // ); self.interface.cmd(spi, Command::PowerOn)?; - // 获取BUSY电平,高电平继续执行,低电平则等待屏幕响应 - //TODO: 这里是文档推荐的步骤,但我看其他屏幕的也没等待就先忽略了 + // Get the BUSY level, high to continue, low to wait for the screen to respond. + //TODO: This is the recommended step in the documentation, but I've ignored it since I've seen other screens that don't wait. self.wait_until_idle(spi, delay)?; - // vcom和数据间隔设置 + // vcom and data interval settings // self.interface // .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; From cd45c9f99c65102ce9ed81775aecaea970649290 Mon Sep 17 00:00:00 2001 From: tippfehlr Date: Sun, 14 Jan 2024 18:52:59 +0100 Subject: [PATCH 43/69] fix: overflow error for all displays Related: #173 --- src/epd1in54b/mod.rs | 4 ++-- src/epd1in54c/mod.rs | 2 +- src/epd2in13bc/mod.rs | 2 +- src/epd2in7b/mod.rs | 6 +++--- src/epd2in9bc/mod.rs | 2 +- src/epd5in83b_v2/mod.rs | 2 +- src/epd7in5_hd/mod.rs | 2 +- src/epd7in5_v2/mod.rs | 4 ++-- src/epd7in5b_v2/mod.rs | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 22177db9..08aae37c 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -279,12 +279,12 @@ where // Uses 2 bits per pixel self.interface - .data_x_times(spi, color, 2 * (WIDTH * HEIGHT / 8))?; + .data_x_times(spi, color, 2 * (WIDTH / 8 * HEIGHT))?; // Clear the red self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; + .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; Ok(()) } diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 445f9ab7..bbe27302 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -14,7 +14,7 @@ pub const HEIGHT: u32 = 152; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT; const SINGLE_BYTE_WRITE: bool = true; use crate::color::Color; diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index b47250de..9d1f0d88 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -65,7 +65,7 @@ pub const HEIGHT: u32 = 212; pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; /// Number of bits for b/w buffer and same for chromatic buffer -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT; const IS_BUSY_LOW: bool = true; const VCOM_DATA_INTERVAL: u8 = 0x07; diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 2db23059..42f25f19 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -168,7 +168,7 @@ where // Clear chromatic layer since we won't be using it here self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; + .data_x_times(spi, !self.color.get_byte_value(), WIDTH / 8 * HEIGHT)?; self.interface.cmd(spi, Command::DataStop)?; Ok(()) @@ -225,13 +225,13 @@ where let color_value = self.color.get_byte_value(); self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; self.interface.cmd(spi, Command::DataStop)?; self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface - .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; self.interface.cmd(spi, Command::DataStop)?; Ok(()) } diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 30611706..0f6d52b2 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -68,7 +68,7 @@ pub const HEIGHT: u32 = 296; /// Default background color (white) of epd2in9bc display pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT; const IS_BUSY_LOW: bool = true; const VCOM_DATA_INTERVAL: u8 = 0x07; diff --git a/src/epd5in83b_v2/mod.rs b/src/epd5in83b_v2/mod.rs index abafbf3b..625b1e7c 100644 --- a/src/epd5in83b_v2/mod.rs +++ b/src/epd5in83b_v2/mod.rs @@ -38,7 +38,7 @@ pub const HEIGHT: u32 = 480; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT; const SINGLE_BYTE_WRITE: bool = true; /// Epd7in5 driver diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index c566b56c..f78df1f2 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -185,7 +185,7 @@ where } fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - let pixel_count = WIDTH * HEIGHT / 8; + let pixel_count = WIDTH / 8 * HEIGHT; let background_color_byte = self.color.get_byte_value(); self.wait_until_idle(spi, delay)?; diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 26fa9dba..7f09a253 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -171,10 +171,10 @@ where self.send_resolution(spi)?; self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; self.command(spi, Command::DisplayRefresh)?; Ok(()) diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 1baec3a2..708dd452 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -256,10 +256,10 @@ where self.send_resolution(spi)?; self.command(spi, Command::DataStartTransmission1)?; - self.interface.data_x_times(spi, 0xFF, WIDTH * HEIGHT / 8)?; + self.interface.data_x_times(spi, 0xFF, WIDTH / 8 * HEIGHT)?; self.command(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; self.interface.cmd(spi, Command::DataStop)?; From 46e689ed9c0fd60eb45c7b08c12ed9d9830964c0 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 15 Jan 2024 18:14:36 +0100 Subject: [PATCH 44/69] Update 5in83_v2 to newest traits --- src/epd5in83_v2/mod.rs | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/src/epd5in83_v2/mod.rs b/src/epd5in83_v2/mod.rs index 4cc6bf5f..58909b2c 100644 --- a/src/epd5in83_v2/mod.rs +++ b/src/epd5in83_v2/mod.rs @@ -7,8 +7,9 @@ //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd5in83_V2.py) use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, }; use crate::color::Color; @@ -38,25 +39,25 @@ pub const HEIGHT: u32 = 480; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +const SINGLE_BYTE_WRITE: bool = true; /// Epd5in83 driver /// -pub struct Epd5in83 { +pub struct Epd5in83 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color color: Color, } -impl InternalWiAdditions - for Epd5in83 +impl InternalWiAdditions + for Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device @@ -90,27 +91,25 @@ where } } -impl WaveshareDisplay - for Epd5in83 +impl WaveshareDisplay + for Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = Color; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, delay: &mut DELAY, delay_us: Option, ) -> Result { - let interface = DisplayInterface::new(cs, busy, dc, rst, delay_us); + let interface = DisplayInterface::new(busy, dc, rst, delay_us); let color = DEFAULT_BACKGROUND_COLOR; let mut epd = Epd5in83 { interface, color }; @@ -223,14 +222,13 @@ where } } -impl Epd5in83 +impl Epd5in83 where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) From 553c7aad44afed102101dce5e30586bfa6fc5f7d Mon Sep 17 00:00:00 2001 From: Jinser Kafka Date: Sun, 4 Feb 2024 15:41:52 +0800 Subject: [PATCH 45/69] docs(readme): update example --- README.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 15c2f90b..e569aecd 100644 --- a/README.md +++ b/README.md @@ -22,25 +22,28 @@ There are multiple examples in the examples folder. Use `cargo run --example exa ```Rust // Setup the epd -let mut epd = Epd4in2::new( & mut spi, cs, busy, dc, rst, & mut delay) ?; +let mut epd4in2 = + Epd4in2::new(&mut spi, busy, dc, rst, &mut delay, None).expect("eink initalize error"); // Setup the graphics -let mut display = Display4in2::default (); - -// Draw some text -display.draw( -let _ = Text::new("Hello Rust!", Point::new(x, y)) -.into_styled(text_style!( - font = Font12x16, - text_color = Black, - background_color = White - )) -.draw(display); -); - -// Transfer the frame data to the epd and display it -epd.update_and_display_frame( & mut spi, & display.buffer()) ?; +let mut display = Display4in2::default(); + +// Build the style +let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(Color::White) + .background_color(Color::Black) + .build(); +let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); + +// Draw some text at a certain point using the specified text style +let _ = Text::with_text_style("It's working-WoB!", Point::new(175, 250), style, text_style) + .draw(&mut display); + +// Going to sleep +epd4in2.sleep(&mut spi, &mut delay) ``` +> Check the complete example [here](./examples/epd4in2.rs). ## (Supported) Devices From 0b1644c3bc57f7fbd794e33c73d0fa765a59e2e0 Mon Sep 17 00:00:00 2001 From: Jinser Kafka Date: Sun, 4 Feb 2024 15:47:53 +0800 Subject: [PATCH 46/69] fix: color bitmask calculation --- src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color.rs b/src/color.rs index af1f8083..1b38e740 100644 --- a/src/color.rs +++ b/src/color.rs @@ -124,7 +124,7 @@ impl ColorType for OctColor { const BITS_PER_PIXEL_PER_BUFFER: usize = 4; const BUFFER_COUNT: usize = 1; fn bitmask(&self, _bwrbit: bool, pos: u32) -> (u8, u16) { - let mask = !(0xF0 >> (pos % 2)); + let mask = !(0xF0 >> (pos % 2) * 4); let bits = self.get_nibble() as u16; (mask, if pos % 2 == 1 { bits } else { bits << 4 }) } From 928aa1e3823f6d5ed6c6362080feda7f27599762 Mon Sep 17 00:00:00 2001 From: Jinser Kafka Date: Sun, 4 Feb 2024 16:33:33 +0800 Subject: [PATCH 47/69] feat: Add support for the 7.3inch e-Paper HAT (F) Display via SPI --- src/color.rs | 2 +- src/epd7in3f/command.rs | 55 ++++++++ src/epd7in3f/mod.rs | 275 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 332 insertions(+), 1 deletion(-) create mode 100644 src/epd7in3f/command.rs create mode 100644 src/epd7in3f/mod.rs diff --git a/src/color.rs b/src/color.rs index af1f8083..86f35a36 100644 --- a/src/color.rs +++ b/src/color.rs @@ -44,7 +44,7 @@ pub enum TriColor { Chromatic, } -/// For the 5in65 7 Color Display +/// For the 7 Color Display #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum OctColor { /// Black Color diff --git a/src/epd7in3f/command.rs b/src/epd7in3f/command.rs new file mode 100644 index 00000000..0122ac74 --- /dev/null +++ b/src/epd7in3f/command.rs @@ -0,0 +1,55 @@ +use crate::traits; + +#[allow(dead_code, clippy::upper_case_acronyms)] +#[derive(Clone, Copy, Debug)] +pub(crate) enum Command { + Ox00 = 0x00, + Ox01 = 0x01, + + PowerOff = 0x02, + + Ox03 = 0x03, + + PowerOn = 0x04, + + Ox05 = 0x05, + Ox06 = 0x06, + + DeepSleep = 0x07, + + Ox08 = 0x08, + + DataStartTransmission = 0x10, + + DataFresh = 0x12, + + IPC = 0x13, + + Ox30 = 0x30, + + TSE = 0x41, + + Ox50 = 0x50, + Ox60 = 0x60, + Ox61 = 0x61, + + Ox82 = 0x82, + Ox84 = 0x84, + + CMDH = 0xAA, + + AGID = 0x86, + + CCSET = 0xE0, + + OxE3 = 0xE3, + + TSSET = 0xE6, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} diff --git a/src/epd7in3f/mod.rs b/src/epd7in3f/mod.rs new file mode 100644 index 00000000..11a733df --- /dev/null +++ b/src/epd7in3f/mod.rs @@ -0,0 +1,275 @@ +//! A simple Driver for the Waveshare 7.3inch e-Paper HAT (F) Display via SPI +//! +//! # References +//! +//! - [Datasheet](https://www.waveshare.com/wiki/7.3inch_e-Paper_HAT_(F)) +//! - [Waveshare C driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_7in3f.c) +//! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/8be47b27f1a6808fd82ea9ceeac04c172e4ee9a8/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in3f.py) + +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +use crate::{ + buffer_len, + color::OctColor, + interface::DisplayInterface, + traits::{InternalWiAdditions, WaveshareDisplay}, +}; + +use self::command::Command; + +mod command; + +/// Full size buffer for use with the 7in3f EPD +#[cfg(feature = "graphics")] +pub type Display7in3f = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize * 4) }, + OctColor, +>; + +/// Width of the display +pub const WIDTH: u32 = 800; +/// Height of the display +pub const HEIGHT: u32 = 480; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White; +/// Default mode of writing data (single byte vs blockwise) +const SINGLE_BYTE_WRITE: bool = true; + +/// Epd57n3f driver +pub struct Epd7in3f { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: OctColor, +} + +impl InternalWiAdditions + for Epd7in3f +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.interface.reset(delay, 20_000, 2_000); + self.wait_busy_low(delay); + delay.delay_ms(30); + + self.cmd_with_data(spi, Command::CMDH, &[0x49, 0x55, 0x20, 0x08, 0x09, 0x18])?; + self.cmd_with_data(spi, Command::Ox01, &[0x3F, 0x00, 0x32, 0x2A, 0x0E, 0x2A])?; + self.cmd_with_data(spi, Command::Ox00, &[0x5F, 0x69])?; + self.cmd_with_data(spi, Command::Ox03, &[0x00, 0x54, 0x00, 0x44])?; + self.cmd_with_data(spi, Command::Ox05, &[0x40, 0x1F, 0x1F, 0x2C])?; + self.cmd_with_data(spi, Command::Ox06, &[0x6F, 0x1F, 0x1F, 0x22])?; + self.cmd_with_data(spi, Command::Ox08, &[0x6F, 0x1F, 0x1F, 0x22])?; + self.cmd_with_data(spi, Command::IPC, &[0x00, 0x04])?; + self.cmd_with_data(spi, Command::Ox30, &[0x3C])?; + self.cmd_with_data(spi, Command::TSE, &[0x00])?; + self.cmd_with_data(spi, Command::Ox50, &[0x3F])?; + self.cmd_with_data(spi, Command::Ox60, &[0x02, 0x00])?; + self.cmd_with_data(spi, Command::Ox61, &[0x03, 0x20, 0x01, 0xE0])?; + self.cmd_with_data(spi, Command::Ox82, &[0x1E])?; + self.cmd_with_data(spi, Command::Ox84, &[0x00])?; + self.cmd_with_data(spi, Command::AGID, &[0x00])?; + self.cmd_with_data(spi, Command::OxE3, &[0x2F])?; + self.cmd_with_data(spi, Command::CCSET, &[0x00])?; + self.cmd_with_data(spi, Command::TSSET, &[0x00]) + } +} + +impl WaveshareDisplay + for Epd7in3f +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + type DisplayColor = OctColor; + + fn new( + spi: &mut SPI, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result::Error> + where + Self: Sized, + { + let interface = DisplayInterface::new(busy, dc, rst, delay_us); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd7in3f { interface, color }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), ::Error> { + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5]) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.init(spi, delay) + } + + fn set_background_color(&mut self, color: Self::DisplayColor) { + self.color = color; + } + + fn background_color(&self) -> &Self::DisplayColor { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::DataStartTransmission, buffer) + } + + fn update_partial_frame( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _buffer: &[u8], + _x: u32, + _y: u32, + _width: u32, + _height: u32, + ) -> Result<(), ::Error> { + unimplemented!() + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.command(spi, Command::PowerOn)?; + self.wait_busy_low(delay); + + self.cmd_with_data(spi, Command::DataFresh, &[0x00])?; + self.wait_busy_low(delay); + + self.cmd_with_data(spi, Command::PowerOff, &[0x00])?; + self.wait_busy_low(delay); + + Ok(()) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + let bg = OctColor::colors_byte(self.color, self.color); + + self.wait_busy_low(delay); + self.command(spi, Command::DataStartTransmission)?; + self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; + + self.display_frame(spi, delay) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _refresh_rate: Option, + ) -> Result<(), ::Error> { + unimplemented!() + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.wait_busy_low(delay); + Ok(()) + } +} + +impl Epd7in3f +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command) + } + + fn cmd_with_data( + &mut self, + spi: &mut SPI, + command: Command, + data: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data(spi, command, data) + } + + fn wait_busy_low(&mut self, delay: &mut DELAY) { + self.interface.wait_until_idle(delay, true); + } + + /// Show 7 blocks of color, used for quick testing + pub fn show_7block(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + let color_7 = [ + OctColor::Black, + OctColor::White, + OctColor::Green, + OctColor::Blue, + OctColor::Red, + OctColor::Yellow, + OctColor::Orange, + OctColor::White, + ]; + + self.command(spi, Command::DataStartTransmission)?; + for _ in 0..240 { + for color in color_7.iter().take(4) { + for _ in 0..100 { + self.interface + .data(spi, &[OctColor::colors_byte(*color, *color)])?; + } + } + } + + for _ in 0..240 { + for color in color_7.iter().skip(4) { + for _ in 0..100 { + self.interface + .data(spi, &[OctColor::colors_byte(*color, *color)])?; + } + } + } + + self.display_frame(spi, delay) + } +} diff --git a/src/lib.rs b/src/lib.rs index fc1d392d..9b393528 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -90,6 +90,7 @@ pub mod epd4in2; pub mod epd5in65f; pub mod epd5in83_v2; pub mod epd5in83b_v2; +pub mod epd7in3f; pub mod epd7in5; pub mod epd7in5_hd; pub mod epd7in5_v2; From cd972e0332e690bbd1fa400c450c79a23269e8ed Mon Sep 17 00:00:00 2001 From: Jinser Kafka Date: Sun, 4 Feb 2024 16:36:05 +0800 Subject: [PATCH 48/69] doc: add 7.3 Inch HAT (F) to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 15c2f90b..0948b7fa 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [7.5 Inch B/W HD (A)](https://www.waveshare.com/product/displays/e-paper/epaper-1/7.5inch-hd-e-paper-hat.htm) | Black, White | ✕ | ✕ | ✔ | ✔ | | [7.5 Inch B/W V2 (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) [[1](#1-75-inch-bw-v2-a)] | Black, White | ✕ | ✕ | ✔ | ✔ | | [7.5 Inch B/W (A)](https://www.waveshare.com/product/7.5inch-e-paper-hat.htm) | Black, White | ✕ | ✕ | ✔ | ✔ | +| [7.3 Inch HAT (F)](https://www.waveshare.com/product/7.3inch-e-paper-hat-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | | [5.83 Inch B/W/R (b)](https://www.waveshare.com/5.83inch-e-Paper-B.htm) | Black, White, Red | ✕ | Not officially | ✔ | ✔ | | [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | | [4.2 Inch B/W (A)](https://www.waveshare.com/product/4.2inch-e-paper-module.htm) | Black, White | ✕ | Not officially [[2](#2-42-inch-e-ink-blackwhite---partial-refresh)] | ✔ | ✔ | From 4ce27fbe4ecdabce7c4c87872b9ae7e32b97c9ec Mon Sep 17 00:00:00 2001 From: blamster19 Date: Sat, 17 Feb 2024 21:52:36 +0100 Subject: [PATCH 49/69] example: add example 7in5 v2 program The program tests rotations and draws analog clock (based on example code for different models from the repository), tests default fonts of embedded-graphics crate and displays an image of Ferris from `exampl es/assets/` directory. --- examples/assets/ferris.raw | Bin 0 -> 17806 bytes examples/epd7in5_v2.rs | 172 +++++++++++++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) create mode 100644 examples/assets/ferris.raw create mode 100644 examples/epd7in5_v2.rs diff --git a/examples/assets/ferris.raw b/examples/assets/ferris.raw new file mode 100644 index 0000000000000000000000000000000000000000..f60803dddec4a98893506d03f2b610389412b144 GIT binary patch literal 17806 zcmeHueRLbuweOMaIA1LZaDh@D#idR{2yIv^ZE~sep-cH_XdyHp8_PKI0xV%Wl2}Qt zsjWz(uC8@gxp%$S)QN3mA=~c-J4CK6UW28|LLT?h5JJ8vi7o80G zO{fy9z6SCxz%0TYaQ*vrq8}VYXgPi#A%*ffk#`j$lqVw#QrCx6koyt33x6srwqF-i zi9bYW4gM0LJMeV@kpf>tXuXWwbe+gWGDwTlGQ8uulrF-OjLclF51EHWgsABYIQTkf zImULyHhjsh!1B~w2i<|ON`xGqMb|)^py_&yFM>L}AC$w)t^v_C(2C6b<1beL@-yh-63i^1 zuYt6p9qqt44Hn}IT8#gW6cluJ4MagI0D$NNBuB}}JQCvK8i;}z2PBrQ{Tm6&Q9iyV zq=JOGrvQ~D5muUHzXp|nyf_cJ>6($BUyiizxJD#6=hsKc(G#{UMN97(@{ z(lw3~ugSq=<`d9+El31yKfDYHu`8*r!ME}f`S>#AaVT9Y@-kqi@c#pO4Z}q8IKN8& z(AvA~S3nLT#nrdN%1X58s|rD4M+Ny;wYYud6_6ch$yK*Q#kO~@hsA0jvF!VxUx#vaB);lKVPK_`m3)r&?o-qS79Le zYx~u80#dqsZDzZPlK&8if0u21+5K-&`Um5@to`MMt05QmYZm|Yk#=-tx{6NmAI?hF zw0UX0-^1BR@ ziGe?kV<>o#cxgc&tz142DT6p{ogOU~colko$%4o=pS?71Rv3s@a1ulDq&!m9q7|<# zh}7am*>TG84JJ-sWut`%Tq-+4pDl=_@Mq(h#?ycdD*=p|?u26w-yokm7a$7byiD`# z1q9P1&j}~uL9l%R98!>&%uHLxBa}Qa0fS8BF(~G6J3cL8$-V#-kTXQhcr#O!0F8N{ z2z_8mTzEf&7BeI}D5GAEJ2E2#V*!Z0SJpXgFD4}tGXf~507sA%4^~5e+=A935*jh` zXL^Z<{LE6}B^iWqSfudSLOPLEuFeo6UrG3|0g7PYjwu0yxtLyf_oXszGA(3Zf_^X^ z+zEdqpg0bUNG#x5gea(%&4SJ$Nit9%u}mE0!2%U0Vc^1o^NF?rBr~+2eC04B;uI}_ zUJ?Uu69k3}E{ya{8%i=@BMByEvKHJ0EQuL=p}(;Ot-T8~^8A5j*%{C_V*s{+R*@I6 zFpy5h7CsYc<@PXhK%``m-6JxPgm{Wia3sSqa%X?Kf=;=0h$LhzPRTKjgCSsfu!W;3 z+2YR^L~5bY0DQnZECC~>1i2?n%T^08_7KkxG+Y5Ga5H0*;Ry*RND2Efi>=m(2uX!y zuAuV=&@qsNV_>GNoFXAw;U@DW<|!=k3qOahhenhnFkl)bL1TGc26^x+z(|SXY+%vC zd1wXZv3mtP34r87cMTvs(!c+>Nm=ePYd7KNsmADNCDEeTS)BiY52tyc=*u?Nw@Hk2P zNYlbP^8`7_AybO-j3z`L`k(?rM1t_;2x1DJxW(TtXf3>-!3@t>;5GoN1Q{VOp9pjS zK}^AFXBO~~(p0%P1eM?g>wp(#-bj&*$g-joz#$9dTaJg6AiP^p)G<%(x6n6tKoW_| z(+6ld@5Lbez^z!Y!lI=pQ8ZxEydN!@hg>ZT-i9R#lLXiYKmjHq!1LHgu`tR=D9&>p z-kSVualL9DQVSCRK+woQj+1920bMW&E=;B|$Br_}F?kLLIz(p)_DuG2wf~^?)gs?bOhvU3804C_&Z6W5f$ zO+kcHkw}tHq(zYq#T}`TB!w|{yfEKd5{?EU$FZ=Qs3~#)&IqvNNFGN>hJj=X4iJd| z_8Go%m|6}2U}eBZkT3-bT*`5lAjeSw9HZzMON0eRmq>WALHzqXo!SUEMT!#y$4qg8 zsZJCIL~J8P#$$_1HgJMA4W8$^aQn`A$Q>{lu;GQnc#44lg)RdJA#64Py)FwkXewfFH@i+#WDr?o1C7X4c?N&eX9BWZ|fE))vFfsL0SAVLHfhXu1ZKnHYmU$Do7 zr-rCRnjV~oRAK|gKv=`TBq=14Fe54I$Owh?usSj%Hc>c5wcGa3LoR}3CE>fQw=)x1D4d5xM7rGr3(7`QTwG)#*diN%r*uJq5p?tv zHkoK?DnN~D=L3}jWK~F7u-Otg92jO;hJjQdh=#NYygtlR!?pl!!(Cq0d?@D=Mc4sw zvR3NjVcB4_*jnG_p?FWKy*x?R^YXhlQ^E@oF)z*CU8{%l5-cN z7aXBr#ZWdXDuuM??elah2r70q$@~>0BgRQ^rYDVAEv##k6<5)z z_6QZ-m29_BQ&MNG6pW{ZBs(AZ!-&u)krK&s)p*2+Q>o;XsKK~AD$?yKdcq)JQouDn z##8$A<(CNjNREY^i8(w!HXp}Bh!*MxOsXDi0e zDL6Wh;1NpHmk&>AnWof~B)LQ7{e05hofx1!*wWx@F3jm%BH3(@HKFJf0!V()@(j#?C5D%Ivh^W$jAmAQG?8CKkUi3`iT?sxgBw($U7wQ6HqBrUBq_u*RXEv2< zZ8$lYLn^2?m_w=G^JGwmbL`$(Ik_$AQ!H+z^0P+B-_M_hKQ63?L0i2ik3Ps z4T%a)JL0bPlsGI(B&H}b&O|z4ItJSNCjvf81h+&mL9b6}h4*thm&248=pHXq?hyp7 z2YbrnrSXxZt>1@}f;ygN$jF(*rcTMy8Gbf(bZVD9hg2}5LQqS>PVO6Zj!?E#GLHA( zqD|BZxYml%`e%KUVxK3~-H=XFT=&^z4v3H+M`EccGp>hyh>FLw+Ti~|ill|BaEtN3 zp#mX79_ISivymOH$v(Dk{j5$U(_T)I2~#lC0+Hk`!3hpt-G9eZ!4W%1%C2At+6E86 zrPdS=TO*gAqf?l|Nt#S^l4vswaoBAM;0tJRTBu`_qrm+*+#gfBO;X6?I;OGJ?^4Y| zx8fQ+95%ocMzFIptz|-L`I|XkGP%X+!Ji?Rs2&Wf+`dw**rd3|d0`Q05!R zAu%kq1fY){!iy1OFX!o42gP(nK+#o=%pz6*hAJ@N~N~}xu|{I zrcK7bXb60f~oNLC0N7Z z28~eB@2SvQqzX#jd2UbRIEL>8QQr7?OE1q@-DjBoP5-On!W`sMJcJv{VUY?P$c+9EEdqDn{{CKf!bS`p+ZUPa^fAM{a+ExHCPvLLR5BA)@vD0ar*z z!;g+ZV9p_ZFvPq2EAEBOH$f(GOGf9S7VS26h1|zz#PUZq_w%Ff@P=gfU*_PT)6hUK zZ0@*rxU_Cq+X*Wh+AkKT#=Gy5b(WV;a#lajas=xN+UDw1Y$;6#@jy?fFOilk+I060 z8L8BkdU`X~5*z^;!_l<&jDx24U8eI6$wTi9!3jFBzJ>jKhjdm(<_(2EPiL%EyN8P0 zVK{DDutxLe%aC^sS>Vwq5F~n2qLoYi>~}H}5rp>LjLtjY*+@F1c1!z8f&-Tys#~dx z8gqFs4UZMwA+JfwXv#~3llwBrtzhO;0|a{@WRAsOnX6M#Y!H~BdZ>KL<2%&J39bxM z(bl`^r4@4Q-{2u=)^>3ddpu?^d^i`0SO}3gJb1Pz;o+gKmtQP@v4ZNNwBX8Md*%j#tO@=L+OP8QL zONtQIcE*yHXWP>kBh#N*rAgm>j+-}4_PWAmcE`oOT@x#^V#PpHFE9kp7Ec3kVua|_SEQG!J|mlgw$2R&k#9? z(6^uM-@5PQxs$uM?rR<{1woFMd#9$7ltlVqQ<2ES<7YBR1wq7K$skwo@sE$&Y_`zH z$EW(newD+)4>q_k6Km+{tG`5laW+}sn?`pH!Zi530*WXsZiT3Q9 zgRHM3>a1Fx(;l`x{>R4|L7S;l1Y#xkXSna|sXfV@v7GUwm_*IQJ1cWg<&N?2Q0Psy z`^$s|j+PA-znrcL$7X&Sb3^^5zOKG{?{IDNM8euOm_wp8RjRGvM9Sl%+v?lS?hR$C z6q`0X-pFt_pKS^EhtG!Vdh0fAZ2m%(L*{v`^Hw_pE;Ji5yb-WhvuwL(2SlMY!K)4NVf6Dn(!T(sUoU3~!EAOqNbemT2Pj zZ?(-jcfB^bhfg%Y(NNgCOH=M+OQ(@157quK!`-)9Q3WG24!1K;`p3CXHCEatj z&ByoFwf3H&>Cr^-w5B}UfMI4<{5@mw^IJmR-5c3~q;(*N{N1LuNP;L92Vz!Y#Njk2 zeA87Q`{J)=xbH;59*rmI_V8R|@IGho-7NHn3Bj@{Jh|$S^;np~;&AtHrY3LeANs${ zaK+D;OqeHH*oh_w`8*$eKKEjj^Hr#m{R2E#9%wlA_V>13+Gdvl1(8riO$NEPp5Jn| z_^rLgV_U{;t!88HDZSz17rd)C=BgiM&k#0gqI5zf1M-g6g^U^G_s`xJtsmC6MfK61 z_h{$nhZ!lvXWc;Db%qZHXqP|aXtBYcO0HULG>mEC|NT{@1}j5bb7tR`6wG4nGO&X7&=59vj#*@?bdy@L3gY_ z)(^kYLul)n=Ue(@KyOrS4 zqv-X_LkHR8G9QcZB{K5yN*Goc^t{ShGV zwE1d?W3b>>OrCH$%!js$C!8af4%1F{Qs>Axf01+ZX5&GdcZ{Y#K0fNQ?yXOpN&E?+ zM>H1$YHRHvdZE{9CY-^K9|@X`k51^!j^Y4uLDsn)AhGARggiYP!@fO{50cXR+L z2%2!yPV)<^h;<+7qOOy{fsb@Lkaq>$j%el$++C%?U~up^hKYFMfmajnFb^>Ayn5!) zGX<}!Q2N zBj$R)c?6H`or;b)&YWsL;s}}#+tNoIj@i**|a|3MjPzG$-zqkD>nLv(K){Y8Io zUpY~6CSE}l>0RG<8RPZD`2?YJ_C57Pf-wKQP@$s34t=GJJQ|p2d9!H$oiSZcT~Gh+ z-W|2Ey`v#>pVJorOy3V#V$X<+2s?f2)|sDpzhhO=13F#weHj_)*|zURwCusn(8ENp zZz9$2*k!D69yT|f0y__L8%}ABQHO4-GnFb&w-q4e>TuZA0YK%}FNWh6{#{v6?~%c7jPXvf8I7w)UmW^DM3t+(^X#_9z?4Bi*!ak z>n)3(Aov4*uP*2ej-6+N!IJNvhjE%6&LBbP9{rzanPPb~%Bp0YNoKOdzDl{Q(ls(x z>?De9YKKif5;$Z&P}=T3amf66?OCJQ$(j$T)qzW&qW$;W=W;phGP1TS;TuE_<ES5X1`p6iL?b?naf-hg!DcN!h8_XvUo6_24sdYuk{a5RGeu%kv~-x&R5 zbyT-!Bp@fe&2*r+=LucUn5FG)n z@ziFJF4ojcj;F)pX>?-;YOeOP=EKK}ohduoZ(n@GF{YA{>mkrDpe0YDJN$k}u=RvK zvxJl}ed*Q%j;;GqEgsxxauLyezZw}i0K1Lq5i0zOT}J-PMwWO@*_glV5q&MKW37I5 zM!b1!?A!oxt|PB`d*Sl)QHSf~FT6%rWQFLC=XARP2Z`GA!Oup~_I&UPYvyY|8VMmq zKSBnzI{0YRpxS60cwOm(xTPKn=^jC7KU!)vPk+aJrBc_` zjPg&NvNfez^Cq0>4IQV#I-6>>!SM>pUxseej_l7MmC>HQe?^a}kV0qtWx*#2{~OCI zykS*dAn=rL%`X+3%uj@$By@qDzrVxF{%_gZwR?;gGDsAC%KsKpst}6mS{E7UTA0|x z$V;dNlJdHjmePBC&KK_VIsdA<*|+XRl)oRXPCRx2$)wz3)5FXbKum7jf48n#;q+7b zI<$(|xUc=fUj2!EgyV+N7x!0=?`t1Kg-g)w+YU^R6M2FoG*T+<$VfOIUQ#ewpwmC+ zFR|a|piiDhr{A(3Z!#(C6w8#ZljrRyzXK5;1!r^?obx-7?4sMEZ~aB7xbF@#YaIy{ z=7(KDLg{xr=O2sy`oD^b7C+}F>}Y8r+GzdRw6W-$TlF9UdfBD#P`!dSIvppBj=$&W zqKBT&>*AR%y`!?wu6UU0Ez2MbCoZWn3{s36FRIW=*h%~~AAxq=NI{z(Rh{{5>7jD`6!yvk62?VYgUbp9I9UEFo#z*ZxsO~S^CT(gj(N?{p zM2e%G>6Z|C1}R3`8)bbm>2&V<5h_FqI@*PbzIh_-PDi&o2iF){>?aQNPSl*(?O*cS zn`^uWK0!!@kTdm01_qZqg6su!6AZ=d^1q_`wpGWjD?VqgTIN+rXkV6c$ z20L1^6e-N>2D8ZRj&&cvguz95sRxk!zc6mzxKAYqSIW&E3;zj~73NhpHzzgKwbk||>vh8|g$UWvjbYZF zMSjoL{yIDmA~X;^JctrUM%y=RusK>`Kr_3x;9?WmtzOLEZ=xzM3r4HKgQ+ZO*twbcN66NdHz-#vXkdmJ` zzkBuhgm0bGdEPl{toQGYSDQL-}K=R)_=mA1i6o(cfsh zs?ryCo1!L_O7#F$<)}TEqI6X!;aUk+K@_ zSE{ttE>l{=7;3BQHSN`Qgp?}SE2gt;2J9P#sVao`I#!zP^@an67AKs{;n!cUHTS>S zY$$5<(#<_DG}$w5EPz#?qn{J!Kni5=*3vDt!xP>&z0W=IB0|-!>Lcsk>La^`P4qj#&MH&pi2<_J%`*>( z8L0B~c%{rJ8cy>%gTvu-I8K+fjv|HkKNf{j&IdKgV3YGF&p?YO5&CfeRAgzXxn~eT zK14To?+Z5@yw$_QUL&Nnf@&~$-P6II$4Y8n2v$OKn1CB}gTTztlD4Pbn4Zw)Mnf}A zHyeE3UV{tWf@+>Y|9!h-r%%_@Cp!p1Fl-`JGcdRn?6q}dO3Mwn)zDQ1|4!4RAE71r z2tBBvbcV9vXie>Od&MoMRMVV%Rn#2YhY+lIl&t;n;!f9~JbcK#RjZvN zx$F-D$P}7golWix3zr+WLLAMZjnT^KQW;I_R@cm_ff4j|YHFTV$ubyc!N;#(R(k{S zTqbbQGNaeqGFq^9WkSqUS#+5n2?S{e`zN);se|8d3 z{w?Zz6h*dON#R*`i`|j?IcpnG6LbrKYLm$PrC8ov0sjHxSxJd|suNZWJ#40GrESxL#z)19rFr(s1wmR#h}jW~4&vvp`m zTaL{#t6$7=NA5nNS=H37lFRmGRR@cTiaKOILpPtd&v3cht+_O+ak~$yAA7o4p8aJz z&#!v?kDaR7W>4F5{0y`Fhgr#Y)#~l;-~UH-2M81|FV)=t4UIiphw`$H%t?^q6V*&% z(Z4r0cCG4aR3Sw{iB9)+SJh8uo83KsI$=x6Z02&4Z@cd?{9?4M3UbcK+Jgs+wl~f? z2o>y^?Ip_vvW(*4RXab}xwF%b^0yZOZu?{RWUC-)R?hNSPM2jA&AOM@c2+$IQ@gsg ztm?k5s=;g(tkyYvR=T<{%T+sc1rNL`yXB4N-#OTMf4=PH8TxPbEH``Kl9Ro5x8wYS z555Lfk3V$x+Q!Fc@_(l3ql1~-WtW%j+2Y#9qUy*0D5svr=IXU~H$IZBfcvd0=M-kx zM?cNV7IkWt-T#djpt!xd`JiL_E2?Y_Y!&udKFi%unC0^Cd%LkKlXDlr+tB8+%4`MP z%T#j;Gpr(~b17K6{r80+U*( z%?jY2e<4>`+xYg3jR$YDi;u5lc>;sP0bc+1QGl7=pVW8>-G9i)c Result<(), SPIError> { + // Set up the device + let mut spi = SpidevDevice::open("/dev/spidev0.0").expect("spidev directory"); + let options = SpidevOptions::new() + .bits_per_word(8) + .max_speed_hz(10_000_000) + .mode(spidev::SpiModeFlags::SPI_MODE_0) + .build(); + spi.configure(&options).expect("spi configuration"); + + let cs = SysfsPin::new(26); + cs.export().expect("cs export"); + while !cs.is_exported() {} + cs.set_direction(Direction::Out).expect("CS Direction"); + cs.set_value(1).expect("CS Value set to 1"); + + let busy = SysfsPin::new(24); + busy.export().expect("busy export"); + while !busy.is_exported() {} + busy.set_direction(Direction::In).expect("busy Direction"); + + let dc = SysfsPin::new(25); + dc.export().expect("dc export"); + while !dc.is_exported() {} + dc.set_direction(Direction::Out).expect("dc Direction"); + dc.set_value(1).expect("dc Value set to 1"); + + let rst = SysfsPin::new(17); + rst.export().expect("rst export"); + while !rst.is_exported() {} + rst.set_direction(Direction::Out).expect("rst Direction"); + rst.set_value(1).expect("rst Value set to 1"); + + let mut delay = Delay {}; + + let mut epd7in5 = Epd7in5::new(&mut spi, busy, dc, rst, &mut delay, None).expect("epd new"); + let mut display = Display7in5::default(); + println!("Device successfully initialized!"); + + // Test graphics display + + println!("Test all the rotations"); + + display.set_rotation(DisplayRotation::Rotate0); + draw_text(&mut display, "Rotate 0!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate90); + draw_text(&mut display, "Rotate 90!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate180); + draw_text(&mut display, "Rotate 180!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate270); + draw_text(&mut display, "Rotate 270!", 5, 50); + + epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; + delay.delay_ms(5000); + + // Draw an analog clock + println!("Draw a clock"); + display.clear(Color::White).ok(); + let style = PrimitiveStyleBuilder::new() + .stroke_color(Color::Black) + .stroke_width(1) + .build(); + + let _ = Circle::with_center(Point::new(64, 64), 80) + .into_styled(style) + .draw(&mut display); + let _ = Line::new(Point::new(64, 64), Point::new(0, 64)) + .into_styled(style) + .draw(&mut display); + let _ = Line::new(Point::new(64, 64), Point::new(80, 80)) + .into_styled(style) + .draw(&mut display); + epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; + delay.delay_ms(5000); + + // Draw some text + println!("Print text in all sizes"); + // Color is inverted - black means white, white means black; the output will be black text on white background + display.clear(Color::Black).ok(); + let fonts = [ + &FONT_4X6, + &FONT_5X7, + &FONT_5X8, + &FONT_6X9, + &FONT_6X10, + &FONT_6X12, + &FONT_6X13, + &FONT_6X13_BOLD, + &FONT_6X13_ITALIC, + &FONT_7X13, + &FONT_7X13_BOLD, + &FONT_7X13_ITALIC, + &FONT_7X14, + &FONT_7X14_BOLD, + &FONT_8X13, + &FONT_8X13_BOLD, + &FONT_8X13_ITALIC, + &FONT_9X15, + &FONT_9X15_BOLD, + &FONT_9X18, + &FONT_9X18_BOLD, + &FONT_10X20, + ]; + for n in 0..fonts.len() { + let style = MonoTextStyleBuilder::new() + .font(fonts[n]) + .text_color(Color::White) + .background_color(Color::Black) + .build(); + let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); + let y = 10 + n * 30; + let _ = Text::with_text_style( + "Rust is awesome!", + Point::new(20, y.try_into().unwrap()), + style, + text_style, + ) + .draw(&mut display); + } + epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; + delay.delay_ms(5000); + + // Draw an image + println!("Draw Ferris"); + display.clear(Color::Black).ok(); + let data = include_bytes!("./assets/ferris.raw"); + let raw_image = ImageRaw::::new(data, 460); + let image = Image::new(&raw_image, Point::zero()); + image.draw(&mut display.color_converted()).unwrap(); + epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; + + // Clear and sleep + println!("Clear the display"); + display.clear(Color::Black).ok(); + epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; + println!("Finished tests - going to sleep"); + epd7in5.sleep(&mut spi, &mut delay) +} + +fn draw_text(display: &mut Display7in5, text: &str, x: i32, y: i32) { + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(Color::White) + .background_color(Color::Black) + .build(); + + let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); + + let _ = Text::with_text_style(text, Point::new(x, y), style, text_style).draw(display); +} From baa905b98dec35527e027b75f9cef0746bae5d01 Mon Sep 17 00:00:00 2001 From: Christoph Gross <11088935+caemor@users.noreply.github.com> Date: Tue, 7 May 2024 14:23:46 +0200 Subject: [PATCH 50/69] Update src/color.rs --- src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color.rs b/src/color.rs index 86f35a36..74823d3c 100644 --- a/src/color.rs +++ b/src/color.rs @@ -44,7 +44,7 @@ pub enum TriColor { Chromatic, } -/// For the 7 Color Display +/// For the 7 Color Displays #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum OctColor { /// Black Color From b8ed4f1d89353dcc152494ab74ee575d3e42231f Mon Sep 17 00:00:00 2001 From: Tom Cheung Date: Wed, 15 May 2024 16:56:18 +0800 Subject: [PATCH 51/69] Add support for epd2in9b_v4 --- src/epd2in9b_v4/command.rs | 28 +++ src/epd2in9b_v4/mod.rs | 404 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 433 insertions(+) create mode 100644 src/epd2in9b_v4/command.rs create mode 100644 src/epd2in9b_v4/mod.rs diff --git a/src/epd2in9b_v4/command.rs b/src/epd2in9b_v4/command.rs new file mode 100644 index 00000000..d65e1a04 --- /dev/null +++ b/src/epd2in9b_v4/command.rs @@ -0,0 +1,28 @@ +//! SPI Commands for the Waveshare 2.9" (B/C) E-Ink Display +use crate::traits; + +#[derive(Copy, Clone)] +pub(crate) enum Command { + SwReset = 0x12, + DriverOutputControl = 0x01, + DataEntryMode = 0x11, + BorderWavefrom = 0x3c, + DisplayUpdateControl = 0x21, + TurnOnDisplay = 0x22, + ActivateDisplayUpdateSequence = 0x20, + ReadBuiltInTemperatureSensor = 0x18, + RamXPosition = 0x44, + RamYPosition = 0x45, + RamXAddressCount = 0x4e, + RamYAddressCount = 0x4f, + WriteBlackData = 0x24, + WriteRedData = 0x26, + DeepSleep = 0x10, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} diff --git a/src/epd2in9b_v4/mod.rs b/src/epd2in9b_v4/mod.rs new file mode 100644 index 00000000..b67f90a1 --- /dev/null +++ b/src/epd2in9b_v4/mod.rs @@ -0,0 +1,404 @@ +//! A simple Driver for the Waveshare 2.9" B (v4) Tri-Color E-Ink Display via SPI +//! +//! [Documentation](https://www.waveshare.com/wiki/2.9inch_e-Paper_Module_(B)_Manual) +//! +//! [Reference code](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in9b_V4.c) + +use crate::{ + buffer_len, color::TriColor, interface::DisplayInterface, traits::{InternalWiAdditions, WaveshareDisplay, WaveshareThreeColorDisplay} +}; +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +pub(crate) mod command; +use self::command::Command; + +const SINGLE_BYTE_WRITE: bool = false; + +/// Default Background Color (white) +pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; +/// Width of Epd2in9b in pixels +pub const WIDTH: u32 = 128; +/// HEIGHT of Epd2in9b in pixels +pub const HEIGHT: u32 = 296; + +const IS_BUSY_LOW: bool = false; + +#[cfg(feature = "graphics")] +/// Full size buffer for use with the 2.9" black/red EPD +pub type Display2in9b = crate::graphics::Display< + WIDTH, + HEIGHT, + true, + { buffer_len(WIDTH as usize, HEIGHT as usize * 2) }, + TriColor, +>; + +/// Epd2in9b (v4) driver +pub struct Epd2in9b { + /// SPI + interface: DisplayInterface, + /// Color + background_color: TriColor, +} + +enum DisplayMode { + Default, + Partial, + Fast, + Base +} + +impl Epd2in9b +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs { + + /// set the base image before partially update + /// + /// https://github.com/waveshareteam/e-Paper/blob/bc23f8ee814486edb6a364c802847224e079e523/RaspberryPi_JetsonNano/c/examples/EPD_2in9b_V4_test.c#L130 + pub fn update_and_display_frame_base( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + )-> Result<(), ::Error> { + self.update_frame(spi, buffer, delay)?; + self.turn_on_display(spi, delay, DisplayMode::Base)?; + + self.command(spi, Command::WriteRedData)?; + self.send_data(spi, buffer)?; + + Ok(()) + } + + /// display frame partially + /// + /// To perform partial update, it need to call update_and_display_frame_base + /// than call update_partial_frame before call display_frame_partial + pub fn display_frame_partial(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.turn_on_display(spi, delay, DisplayMode::Partial)?; + Ok(()) + } + + fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command) + } + + fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data) + } + + fn turn_on_display( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + mode: DisplayMode, + ) -> Result<(), SPI::Error> { + self.command(spi, Command::TurnOnDisplay)?; + + let data = match mode { + DisplayMode::Default => 0xf7, + DisplayMode::Partial => 0x1c, + DisplayMode::Fast => 0xc7, + DisplayMode::Base => 0xf4 + }; + + self.send_data(spi, &[data])?; + self.command(spi, Command::ActivateDisplayUpdateSequence)?; + self.wait_until_idle(spi, delay)?; + Ok(()) + } + +} + +impl InternalWiAdditions + for Epd2in9b +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.interface.reset(delay, 200_000, 2_000); + + self.wait_until_idle(spi, delay)?; + self.command(spi, Command::SwReset)?; + self.wait_until_idle(spi, delay)?; + + self.command(spi, Command::DriverOutputControl)?; + self.send_data(spi, &[((h - 1) % 256) as u8])?; + self.send_data(spi, &[((h - 1) / 256) as u8])?; + self.send_data(spi, &[0])?; + + self.command(spi, Command::DataEntryMode)?; + self.send_data(spi, &[0x03])?; + + self.command(spi, Command::RamXPosition)?; + self.send_data(spi, &[0])?; + self.send_data(spi, &[(w / 8 - 1) as u8])?; + + self.command(spi, Command::RamYPosition)?; + self.send_data(spi, &[0])?; + self.send_data(spi, &[0])?; + self.send_data(spi, &[((h - 1) % 256) as u8])?; + self.send_data(spi, &[((h - 1) / 256) as u8])?; + + self.command(spi, Command::BorderWavefrom)?; + self.send_data(spi, &[0x05])?; + + self.command(spi, Command::DisplayUpdateControl)?; + self.send_data(spi, &[0x00])?; + self.send_data(spi, &[0x80])?; + + self.command(spi, Command::ReadBuiltInTemperatureSensor)?; + self.send_data(spi, &[0x80])?; + + self.command(spi, Command::RamXAddressCount)?; + self.send_data(spi, &[0x00])?; // set RAM x address count to 0 + self.command(spi, Command::RamYAddressCount)?; // set RAM y address count to 0X199 + self.send_data(spi, &[0x00])?; + self.send_data(spi, &[0x00])?; + + self.wait_until_idle(spi, delay)?; + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for Epd2in9b +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), ::Error> { + self.update_achromatic_frame(spi, delay, black)?; + self.update_chromatic_frame(spi, delay, chromatic)?; + Ok(()) + } + + fn update_achromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + black: &[u8], + ) -> Result<(), ::Error> { + self.command(spi, Command::WriteBlackData)?; + self.send_data(spi, black)?; + Ok(()) + } + + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + chromatic: &[u8], + ) -> Result<(), ::Error> { + self.command(spi, Command::WriteRedData)?; + self.send_data(spi, chromatic)?; + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in9b +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + type DisplayColor = TriColor; + + fn new( + spi: &mut SPI, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result::Error> + where + Self: Sized, + { + let interface = DisplayInterface::new(busy, dc, rst, delay_us); + let background_color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd2in9b { + interface, + background_color, + }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.command(spi, Command::DeepSleep)?; + self.send_data(spi, &[1])?; + delay.delay_ms(100); + + Ok(()) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.init(spi, delay)?; + Ok(()) + } + + fn set_background_color(&mut self, color: Self::DisplayColor) { + self.background_color = color + } + + fn background_color(&self) -> &Self::DisplayColor { + &self.background_color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.command(spi, Command::WriteBlackData)?; + self.send_data(spi, buffer)?; + + self.command(spi, Command::WriteRedData)?; + self.interface.data_x_times(spi, 0x00, WIDTH / 8 * HEIGHT)?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), ::Error> { + assert!(width % 8 == 0, "width must multiple of 8"); + let mut x_start = x; + let mut x_end = x + width; + + let y_start = y; + let mut y_end = y + height; + + if (x_start % 8 + x_end % 8 == 8 && x_start % 8 > x_end % 8) || x_start % 8 + x_end % 8 == 0 || (x_end - x_start) % 8 == 0 { + x_start = x_start / 8; + x_end = x_end / 8; + } else { + x_start = x_start / 8; + x_end = if x_end % 8 == 0 { + x_end / 8 + } else { + x_end / 8 + 1 + }; + } + + x_end -= 1; + y_end -= 1; + + let x_start = x_start as u8; + let x_end = x_end as u8; + + let y_start_1 = y_start as u8; + let y_start_2 = (y_start >> 8) as u8; + + let y_end_1 = y_end as u8; + let y_end_2 = (y_end >> 8) as u8; + + self.command(spi, Command::RamXPosition)?; + self.send_data(spi, &[x_start, x_end])?; + self.command(spi, Command::RamYPosition)?; + self.send_data(spi, &[y_start_1, y_start_2])?; + self.send_data(spi, &[y_end_1, y_end_2])?; + + self.command(spi, Command::RamXAddressCount)?; + self.send_data(spi, &[x_start])?; + self.command(spi, Command::RamYAddressCount)?; + self.send_data(spi, &[y_start_1, y_start_2])?; + + self.command(spi, Command::WriteBlackData)?; + self.send_data(spi, buffer)?; + + Ok(()) + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + self.turn_on_display(spi, delay, DisplayMode::Default)?; + + Ok(()) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), ::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay)?; + + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + const SIZE: u32 = WIDTH / 8 * HEIGHT; + + self.command(spi, Command::WriteBlackData)?; + self.interface.data_x_times(spi, 0xff, SIZE)?; + + self.command(spi, Command::WriteRedData)?; + self.interface.data_x_times(spi, 0, SIZE)?; + + self.display_frame(spi, delay)?; + Ok(()) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _refresh_rate: Option, + ) -> Result<(), ::Error> { + Ok(()) + } + + 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/lib.rs b/src/lib.rs index 9b393528..ffb0a1a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,6 +83,7 @@ pub mod epd2in66b; pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; +pub mod epd2in9b_v4; pub mod epd2in9bc; pub mod epd2in9d; pub mod epd3in7; From 3261a9d15ae0af072c776b1aab7b17907106451e Mon Sep 17 00:00:00 2001 From: Tom Cheung Date: Wed, 15 May 2024 17:18:48 +0800 Subject: [PATCH 52/69] Fix formatting --- src/epd2in9b_v4/mod.rs | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/src/epd2in9b_v4/mod.rs b/src/epd2in9b_v4/mod.rs index b67f90a1..350cbe41 100644 --- a/src/epd2in9b_v4/mod.rs +++ b/src/epd2in9b_v4/mod.rs @@ -5,7 +5,10 @@ //! [Reference code](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in9b_V4.c) use crate::{ - buffer_len, color::TriColor, interface::DisplayInterface, traits::{InternalWiAdditions, WaveshareDisplay, WaveshareThreeColorDisplay} + buffer_len, + color::TriColor, + interface::DisplayInterface, + traits::{InternalWiAdditions, WaveshareDisplay, WaveshareThreeColorDisplay}, }; use embedded_hal::{ delay::DelayNs, @@ -45,11 +48,12 @@ pub struct Epd2in9b { background_color: TriColor, } +#[allow(dead_code)] enum DisplayMode { Default, Partial, - Fast, - Base + Fast, // TODO: Add support in future + Base, } impl Epd2in9b @@ -58,17 +62,17 @@ where BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayNs { - + DELAY: DelayNs, +{ /// set the base image before partially update - /// + /// /// https://github.com/waveshareteam/e-Paper/blob/bc23f8ee814486edb6a364c802847224e079e523/RaspberryPi_JetsonNano/c/examples/EPD_2in9b_V4_test.c#L130 pub fn update_and_display_frame_base( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, - )-> Result<(), ::Error> { + ) -> Result<(), ::Error> { self.update_frame(spi, buffer, delay)?; self.turn_on_display(spi, delay, DisplayMode::Base)?; @@ -79,10 +83,14 @@ where } /// display frame partially - /// + /// /// To perform partial update, it need to call update_and_display_frame_base /// than call update_partial_frame before call display_frame_partial - pub fn display_frame_partial(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), ::Error> { + pub fn display_frame_partial( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), ::Error> { self.turn_on_display(spi, delay, DisplayMode::Partial)?; Ok(()) } @@ -107,7 +115,7 @@ where DisplayMode::Default => 0xf7, DisplayMode::Partial => 0x1c, DisplayMode::Fast => 0xc7, - DisplayMode::Base => 0xf4 + DisplayMode::Base => 0xf4, }; self.send_data(spi, &[data])?; @@ -115,7 +123,6 @@ where self.wait_until_idle(spi, delay)?; Ok(()) } - } impl InternalWiAdditions @@ -316,18 +323,21 @@ where let y_start = y; let mut y_end = y + height; - if (x_start % 8 + x_end % 8 == 8 && x_start % 8 > x_end % 8) || x_start % 8 + x_end % 8 == 0 || (x_end - x_start) % 8 == 0 { - x_start = x_start / 8; - x_end = x_end / 8; + if (x_start % 8 + x_end % 8 == 8 && x_start % 8 > x_end % 8) + || x_start % 8 + x_end % 8 == 0 + || (x_end - x_start) % 8 == 0 + { + x_start /= 8; + x_end /= 8; } else { - x_start = x_start / 8; + x_start /= 8; x_end = if x_end % 8 == 0 { x_end / 8 } else { x_end / 8 + 1 }; } - + x_end -= 1; y_end -= 1; From e962e10c1d5a2b624482546faba380040bf4b41e Mon Sep 17 00:00:00 2001 From: Tom Cheung Date: Wed, 29 May 2024 23:35:02 +0800 Subject: [PATCH 53/69] Update for partial update on red color --- src/epd2in9b_v4/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/epd2in9b_v4/mod.rs b/src/epd2in9b_v4/mod.rs index 350cbe41..3889cfe5 100644 --- a/src/epd2in9b_v4/mod.rs +++ b/src/epd2in9b_v4/mod.rs @@ -70,14 +70,19 @@ where pub fn update_and_display_frame_base( &mut self, spi: &mut SPI, - buffer: &[u8], + black: &[u8], + chromatic: Option<&[u8]>, delay: &mut DELAY, ) -> Result<(), ::Error> { - self.update_frame(spi, buffer, delay)?; + self.update_frame(spi, black, delay)?; + if let Some(chromatic) = chromatic { + self.update_chromatic_frame(spi, delay, chromatic)?; + } + self.turn_on_display(spi, delay, DisplayMode::Base)?; self.command(spi, Command::WriteRedData)?; - self.send_data(spi, buffer)?; + self.send_data(spi, black)?; Ok(()) } From 03a3ad515471fadec4dddc4907e1368ffce14665 Mon Sep 17 00:00:00 2001 From: Aiden Scandella Date: Mon, 15 Jul 2024 15:06:03 -0700 Subject: [PATCH 54/69] feat: Add 2.7 Inch V2 support --- src/epd2in7_v2/mod.rs | 308 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 309 insertions(+) create mode 100644 src/epd2in7_v2/mod.rs diff --git a/src/epd2in7_v2/mod.rs b/src/epd2in7_v2/mod.rs new file mode 100644 index 00000000..19df56f4 --- /dev/null +++ b/src/epd2in7_v2/mod.rs @@ -0,0 +1,308 @@ +//! A simple Driver for the Waveshare 2.7inch v2 e-Paper HAT Display via SPI +//! +//! # References +//! +//! - [Datasheet](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_Manual) +//! - [Waveshare C driver](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/c/lib/e-Paper/EPD_2in7_V2.c) +//! - [Waveshare Python driver](https://github.com/waveshareteam/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in7_V2.py) + +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +use crate::{ + buffer_len, + color::Color, + interface::DisplayInterface, + traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}, + type_a::command::Command, +}; + +/// Width of the display +pub const WIDTH: u32 = 176; +/// Height of the display +pub const HEIGHT: u32 = 264; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; + +const IS_BUSY_LOW: bool = false; +const SINGLE_BYTE_WRITE: bool = true; + +/// Full size buffer for use with the 2in7B EPD +/// TODO this should be a TriColor, but let's keep it as is at first +#[cfg(feature = "graphics")] +pub type Display2in7 = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) }, + Color, +>; + +/// Epd2in7b driver +pub struct Epd2in7 { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: Color, + refresh: RefreshLut, +} + +impl InternalWiAdditions + for Epd2in7 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // reset the device + self.interface.reset(delay, 200_000, 2_000); + + self.wait_until_idle(spi, delay)?; + self.command(spi, Command::SwReset)?; + self.wait_until_idle(spi, delay)?; + + self.use_full_frame(spi, delay)?; + + self.interface + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in7 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + type DisplayColor = Color; + fn new( + spi: &mut SPI, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result { + let interface = DisplayInterface::new(busy, dc, rst, delay_us); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd2in7 { + interface, + color, + refresh: RefreshLut::Full, + }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay) + } + + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.interface + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + Ok(()) + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.use_full_frame(spi, delay)?; + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.set_ram_area(spi, x, y, x + width, y + height)?; + self.set_ram_counter(spi, delay, x, y)?; + + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; + + Ok(()) + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + if self.refresh == RefreshLut::Full { + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + } else if self.refresh == RefreshLut::Quick { + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC7])?; + } + + self.interface.cmd(spi, Command::MasterActivation)?; + self.wait_until_idle(spi, delay)?; + Ok(()) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.use_full_frame(spi, delay)?; + + let color = self.color.get_byte_value(); + + self.interface.cmd(spi, Command::WriteRam)?; + self.interface + .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; + + Ok(()) + } + + fn set_background_color(&mut self, color: Color) { + self.color = color; + } + + fn background_color(&self) -> &Color { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + refresh_rate: Option, + ) -> Result<(), SPI::Error> { + if let Some(refresh_lut) = refresh_rate { + self.refresh = refresh_lut; + } + Ok(()) + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW); + Ok(()) + } +} + +impl Epd2in7 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command) + } + + fn set_ram_area( + &mut self, + spi: &mut SPI, + start_x: u32, + start_y: u32, + end_x: u32, + end_y: u32, + ) -> Result<(), SPI::Error> { + assert!(start_x < end_x); + assert!(start_y < end_y); + + self.interface.cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + )?; + + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + (start_y & 0xFF) as u8, + ((start_y >> 8) & 0x01) as u8, + (end_y & 0xFF) as u8, + ((end_y >> 8) & 0x01) as u8, + ], + )?; + Ok(()) + } + + fn set_ram_counter( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + x: u32, + y: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.interface + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x & 0xFF) as u8])?; + + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[(y & 0xFF) as u8, ((y >> 8) & 0x01) as u8], + )?; + Ok(()) + } + + fn use_full_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // choose full frame/ram + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + + // start from the beginning + self.set_ram_counter(spi, delay, 0, 0) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn epd_size() { + assert_eq!(WIDTH, 176); + assert_eq!(HEIGHT, 264); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); + } +} diff --git a/src/lib.rs b/src/lib.rs index 9b393528..6acf39ff 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,7 @@ pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in13bc; pub mod epd2in66b; +pub mod epd2in7_v2; pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; From 23ad13aad910e911548fdf041aabe6d183a0bacd Mon Sep 17 00:00:00 2001 From: Aiden Scandella Date: Wed, 17 Jul 2024 08:14:51 -0700 Subject: [PATCH 55/69] doc: add 2.7 Inch V2 to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 3df65ccc..63699335 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ epd4in2.sleep(&mut spi, &mut delay) | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | +| [2.7 Inch B/W V2](https://www.waveshare.com/2.7inch-e-paper.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.66 Inch 3 Color (B)](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/Y (C) (Discontinued)](https://www.waveshare.com/1.54inch-e-paper-module-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/R (B)](https://www.waveshare.com/1.54inch-e-Paper-B.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | From 6c83ac07fe35f333104b387b51da63f368206b58 Mon Sep 17 00:00:00 2001 From: Yuri Volkov Date: Sun, 13 Oct 2024 18:26:39 +0200 Subject: [PATCH 56/69] Add support for epd1in02 --- src/epd1in02/command.rs | 162 +++++++++++ src/epd1in02/constants.rs | 27 ++ src/epd1in02/mod.rs | 558 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 4 files changed, 748 insertions(+) create mode 100644 src/epd1in02/command.rs create mode 100644 src/epd1in02/constants.rs create mode 100644 src/epd1in02/mod.rs diff --git a/src/epd1in02/command.rs b/src/epd1in02/command.rs new file mode 100644 index 00000000..13ae805f --- /dev/null +++ b/src/epd1in02/command.rs @@ -0,0 +1,162 @@ +//! SPI Commands for the Waveshare 1.02" E-Ink Display + +use crate::traits; + +/// Epd1in02 commands +/// +/// Should rarely (never?) be needed directly. +/// +/// For more infos about the addresses and what they are doing look into the PDFs. +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + /// Set Resolution, LUT selection, gate scan direction, source shift + /// direction, charge pump switch, soft reset. + PanelSetting = 0x00, + + /// Selecting internal and external power + PowerSetting = 0x01, + + /// After the Power Off command, the driver will power off following the Power Off + /// Sequence; BUSY signal will become "0". This command will turn off charge pump, + /// T-con, source driver, gate driver, VCOM, and temperature sensor, but register + /// data will be kept until VDD becomes OFF. Source Driver output and Vcom will remain + /// as previous condition, which may have 2 conditions: 0V or floating. + PowerOff = 0x02, + + /// Setting Power OFF sequence + PowerOffSequenceSetting = 0x03, + + /// Turning On the Power + /// + /// After the Power ON command, the driver will power on following the Power ON + /// sequence. Once complete, the BUSY signal will become "1". + PowerOn = 0x04, + + /// Setting charge pump time interval, driving strength and frequency + ChargePumpSetting = 0x06, + + /// This command makes the chip enter the deep-sleep mode to save power. + /// + /// The deep sleep mode would return to stand-by by hardware reset. + /// + /// The only one parameter is a check code, the command would be excuted if check code = 0xA5. + DeepSleep = 0x07, + + /// This command starts transmitting B/W data and write them into SRAM. To complete data + /// transmission, commands Display Refresh or Data Start Transmission2 must be issued. Then the chip will start to + /// send data/VCOM for panel. + DataStartTransmission1 = 0x10, + + /// This command starts transmitting RED data and write them into SRAM. To complete data + /// transmission, command Display refresh must be issued. Then the chip will start to + /// send data/VCOM for panel. + DataStartTransmission2 = 0x13, + + /// To stop data transmission, this command must be issued to check the `data_flag`. + /// + /// After this command, BUSY signal will become "0" until the display update is + /// finished. + DataStop = 0x11, + + /// After this command is issued, driver will refresh display (data/VCOM) according to + /// SRAM data and LUT. + /// + /// After Display Refresh command, BUSY signal will become "0" until the display + /// update is finished. + /// The waiting interval from BUSY falling to the first FLG command must be longer than 200us. + DisplayRefresh = 0x12, + + /// This command stores white Look-Up Table + SetWhiteLut = 0x23, + + /// This command stores black Look-Up Table + SetBlackLut = 0x24, + + /// This command sets XON and the options of LUT. + LutOption = 0x2A, + + /// The command controls the PLL clock frequency. + PllControl = 0x30, + + /// This command reads the temperature sensed by the temperature sensor. + TemperatureSensorCalibration = 0x40, + /// This command selects temperature option. + TemperatureSensorSelection = 0x41, + + /// This command indicates the interval of Vcom and data output. When setting the + /// vertical back porch, the total blanking will be kept (20 Hsync). + VcomAndDataIntervalSetting = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn + /// the battery condition. + LowPowerDetection = 0x51, + + /// This command defines non-overlap period of Gate and Source. + TconSetting = 0x60, + + /// This command defines alternative resolution and this setting is of higher priority + /// than the RES\[1:0\] in R00H (PSR). + TconResolution = 0x61, + + /// The command reads LUT revision and chip revision. + Revision = 0x70, + /// This command reads the IC status. + GetStatus = 0x71, + + /// This command reads Cyclic redundancy check (CRC) result. + /// + /// The calculation only incudes image data (DTM1 & DTM2), and don't containt DTM1(0x10) & DTM2(0x13). + /// Polynomial = x^16 + x^12 + x^5 + 1, initial value: 0xFFFF + /// + /// The result will be reset after this command. + CyclicRedundancyCheck = 0x72, + + /// This command implements related VCOM sensing setting. + AutoMeasurementVcom = 0x80, + /// This command gets the VCOM value. + ReadVcomValue = 0x81, + /// This command sets `VCOM_DC` value. + VcomDcSetting = 0x82, + + /// Sets window size for the partial update + PartialWindow = 0x90, + /// Sets chip into partial update mode + PartialIn = 0x91, + /// Quits partial update mode + PartialOut = 0x92, + + /// After this command is issued, the chip would enter the program mode. + /// After the programming procedure completed, a hardware reset is necessary for leaving program mode. + ProgramMode = 0xA0, + /// After this command is transmitted, the programming state machine would be activated. + /// The BUSY flag would fall to 0 until the programming is completed. + ActiveProgramming = 0xA1, + /// The command is used for reading the content of OTP for checking the data of programming. + /// The value of (n) is depending on the amount of programmed data, tha max address = 0xFFF. + ReadOtp = 0xA2, + + /// This command is set for saving power during refresh period. + /// If the output voltage of VCOM / Source is from negative to positive or + /// from positive to negative, the power saving mechanism will be activated. + /// The active period width is defined by the following two parameters. + PowerSaving = 0xE3, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::traits::Command as CommandTrait; + + #[test] + fn command_addr() { + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); + } +} diff --git a/src/epd1in02/constants.rs b/src/epd1in02/constants.rs new file mode 100644 index 00000000..807a4e7c --- /dev/null +++ b/src/epd1in02/constants.rs @@ -0,0 +1,27 @@ +/// Epd1in02 waveforms +/// +/// from Waveshare +/// +pub(crate) const LUT_FULL_UPDATE_WHITE: [u8; 42] = [ + 0x60, 0x5A, 0x5A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +pub(crate) const LUT_FULL_UPDATE_BLACK: [u8; 42] = [ + 0x90, 0x5A, 0x5A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +pub(crate) const LUT_PARTIAL_UPDATE_WHITE: [u8; 42] = [ + 0x60, 0x01, 0x01, 0x00, 0x00, 0x01, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; + +pub(crate) const LUT_PARTIAL_UPDATE_BLACK: [u8; 42] = [ + 0x90, 0x01, 0x01, 0x00, 0x00, 0x01, 0x40, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +]; diff --git a/src/epd1in02/mod.rs b/src/epd1in02/mod.rs new file mode 100644 index 00000000..17d9566f --- /dev/null +++ b/src/epd1in02/mod.rs @@ -0,0 +1,558 @@ +//! A simple Driver for the Waveshare 1.02" E-Ink Display via SPI +//! +//! - [Datasheet](https://www.waveshare.com/product/1.02inch-e-paper.htm) +//! +//! The display controller IC is UC8175 + +use embedded_hal::{ + delay::DelayNs, + digital::{InputPin, OutputPin}, + spi::SpiDevice, +}; + +use crate::color::Color; +use crate::interface::DisplayInterface; +use crate::prelude::WaveshareDisplay; +use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut}; + +pub(crate) mod command; +use self::command::Command; +use crate::buffer_len; + +pub(crate) mod constants; +use self::constants::{ + LUT_FULL_UPDATE_BLACK, LUT_FULL_UPDATE_WHITE, LUT_PARTIAL_UPDATE_BLACK, + LUT_PARTIAL_UPDATE_WHITE, +}; + +/// Full size buffer for use with the 1in02 EPD +#[cfg(feature = "graphics")] +pub type Display1in02 = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) }, + Color, +>; + +/// Width of the display +pub const WIDTH: u32 = 80; +/// Height of the display +pub const HEIGHT: u32 = 128; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; +/// BUSY is low active +const IS_BUSY_LOW: bool = true; +/// Number of bytes to contain values of all display pixels +const NUMBER_OF_BYTES: u32 = WIDTH * HEIGHT / 8; +const SINGLE_BYTE_WRITE: bool = true; + +/// Epd1in02 driver +/// +pub struct Epd1in02 { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: Color, + is_turned_on: bool, + refresh_mode: RefreshLut, +} + +impl WaveshareDisplay + for Epd1in02 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + type DisplayColor = Color; + + fn new( + spi: &mut SPI, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result { + let interface = DisplayInterface::new(busy, dc, rst, delay_us); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd1in02 { + interface, + color, + is_turned_on: false, + refresh_mode: RefreshLut::Full, + }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.turn_off(spi, delay)?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; + + // display registers are set to default value + self.refresh_mode = RefreshLut::Full; + + Ok(()) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay) + } + + fn set_background_color(&mut self, color: Color) { + self.color = color; + } + + fn background_color(&self) -> &Color { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + + self.set_full_mode(spi, delay)?; + + let color_value = self.background_color().get_byte_value(); + + self.command(spi, Command::DataStartTransmission1)?; + self.interface + .data_x_times(spi, color_value, NUMBER_OF_BYTES)?; + + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + Ok(()) + } + + // Implemented as quick partial update + // as it requires old frame update + fn update_partial_frame( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _buffer: &[u8], + _x: u32, + _y: u32, + _width: u32, + _height: u32, + ) -> Result<(), SPI::Error> { + unimplemented!() + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.turn_on_if_turned_off(spi, delay)?; + + self.command(spi, Command::DisplayRefresh)?; + self.wait_until_idle(spi, delay)?; + Ok(()) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.set_full_mode(spi, delay)?; + + let color_value = self.background_color().get_byte_value(); + + self.command(spi, Command::DataStartTransmission1)?; + self.interface + .data_x_times(spi, !color_value, NUMBER_OF_BYTES)?; + + self.command(spi, Command::DataStartTransmission2)?; + self.interface + .data_x_times(spi, color_value, NUMBER_OF_BYTES)?; + + Ok(()) + } + + fn set_lut( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + refresh_rate: Option, + ) -> Result<(), SPI::Error> { + let (white_lut, black_lut) = match refresh_rate { + Some(RefreshLut::Full) => (&LUT_FULL_UPDATE_WHITE, &LUT_FULL_UPDATE_BLACK), + Some(RefreshLut::Quick) => (&LUT_PARTIAL_UPDATE_WHITE, &LUT_PARTIAL_UPDATE_BLACK), + None => return Ok(()), + }; + + self.cmd_with_data(spi, Command::SetWhiteLut, white_lut)?; + self.cmd_with_data(spi, Command::SetBlackLut, black_lut)?; + Ok(()) + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, IS_BUSY_LOW); + Ok(()) + } +} + +impl QuickRefresh + for Epd1in02 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + /// To be followed immediately by update_new_frame + fn update_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.set_partial_mode(spi, delay)?; + self.set_partial_window(spi, delay, 0, 0, WIDTH, HEIGHT)?; + + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + Ok(()) + } + + /// To be used immediately after update_old_frame + fn update_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + Ok(()) + } + + fn display_new_frame(&mut self, _spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + unimplemented!() + } + + fn update_and_display_new_frame( + &mut self, + _spi: &mut SPI, + _buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + unimplemented!() + } + + /// To be followed immediately by update_partial_new_frame + /// isn't faster then full update + fn update_partial_old_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + if !is_buffer_size_ok(buffer, width, height) { + panic!("Image buffer size is not correct") + } + + self.set_partial_mode(spi, delay)?; + self.set_partial_window(spi, delay, x, y, width, height)?; + + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; + Ok(()) + } + + /// To be used immediately after update_partial_old_frame + fn update_partial_new_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + buffer: &[u8], + _x: u32, + _y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + if !is_buffer_size_ok(buffer, width, height) { + panic!("Image buffer size is not correct") + } + + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + Ok(()) + } + + /// Isn't faster then full clear + fn clear_partial_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + // set full LUT as quick LUT requires old image + self.set_full_mode(spi, delay)?; + self.command(spi, Command::PartialIn)?; + self.set_partial_window(spi, delay, x, y, width, height)?; + + let color_value = self.background_color().get_byte_value(); + let number_of_bytes = buffer_len(width as usize, height as usize) as u32; + + self.command(spi, Command::DataStartTransmission1)?; + self.interface + .data_x_times(spi, !color_value, number_of_bytes)?; + + self.command(spi, Command::DataStartTransmission2)?; + self.interface + .data_x_times(spi, color_value, number_of_bytes)?; + + self.command(spi, Command::PartialOut)?; + + Ok(()) + } +} + +impl InternalWiAdditions + for Epd1in02 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // Reset the device + self.interface.reset(delay, 20_000, 2000); + + // Set the panel settings: LUT from register + self.cmd_with_data(spi, Command::PanelSetting, &[0x6F])?; + + // Set the power settings: VGH=16V, VGL=-16V, VDH=11V, VDL=-11V + self.cmd_with_data(spi, Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b])?; + + // Set the charge pump settings: 50ms, Strength 4, 8kHz + self.cmd_with_data(spi, Command::ChargePumpSetting, &[0x3F])?; + + // Set LUT option: no All-Gate-ON + self.cmd_with_data(spi, Command::LutOption, &[0x00, 0x00])?; + + // Set the clock frequency: 50 Hz + self.cmd_with_data(spi, Command::PllControl, &[0x17])?; + + // Set Vcom and data interval: default + // set the border color the same as background color + let value = match self.background_color() { + Color::Black => 0x57, + Color::White => 0x97, + }; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[value])?; + + // Set the non-overlapping period of Gate and Source: 24us + self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + + // Set the real resolution + self.send_resolution(spi)?; + + // Set Vcom DC value: -1 V + self.cmd_with_data(spi, Command::VcomDcSetting, &[0x12])?; + + // Set pover saving settings + self.cmd_with_data(spi, Command::PowerSaving, &[0x33])?; + + self.set_lut(spi, delay, Some(self.refresh_mode))?; + + self.wait_until_idle(spi, delay)?; + Ok(()) + } +} + +impl Epd1in02 +where + SPI: SpiDevice, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayNs, +{ + fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { + self.interface.cmd(spi, command) + } + + fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { + self.interface.data(spi, data) + } + + fn cmd_with_data( + &mut self, + spi: &mut SPI, + command: Command, + data: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data(spi, command, data) + } + + fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.command(spi, Command::TconResolution)?; + self.send_data(spi, &[h as u8])?; + self.send_data(spi, &[w as u8]) + } + + /// PowerOn command + fn turn_on_if_turned_off( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + if !self.is_turned_on { + self.command(spi, Command::PowerOn)?; + self.wait_until_idle(spi, delay)?; + self.is_turned_on = true; + } + Ok(()) + } + + fn turn_off(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::PowerOff)?; + self.wait_until_idle(spi, delay)?; + self.is_turned_on = false; + Ok(()) + } + + fn set_full_mode(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + if self.refresh_mode != RefreshLut::Full { + self.command(spi, Command::PartialOut)?; + self.set_lut(spi, delay, Some(RefreshLut::Full))?; + self.refresh_mode = RefreshLut::Full; + } + Ok(()) + } + + fn set_partial_mode(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + if self.refresh_mode != RefreshLut::Quick { + self.command(spi, Command::PartialIn)?; + self.set_lut(spi, delay, Some(RefreshLut::Quick))?; + self.refresh_mode = RefreshLut::Quick; + } + Ok(()) + } + + fn set_partial_window( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + if !is_window_size_ok(x, y, width, height) { + panic!("Partial update window size is not correct") + } + + self.cmd_with_data( + spi, + Command::PartialWindow, + &[ + x as u8, + (x + width - 1) as u8, + y as u8, + (y + height - 1) as u8, + 0x00, + ], + )?; + + Ok(()) + } +} + +fn is_window_size_ok(x: u32, y: u32, width: u32, height: u32) -> bool { + // partial update window is inside the screen + x + width <= WIDTH && y + height <= HEIGHT + // 3 less significant bits are ignored + && x % 8 == 0 && width % 8 == 0 +} + +fn is_buffer_size_ok(buffer: &[u8], width: u32, height: u32) -> bool { + buffer_len(width as usize, height as usize) == buffer.len() +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn epd_size() { + assert_eq!(WIDTH, 80); + assert_eq!(HEIGHT, 128); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); + } + + #[test] + fn inside_of_screen() { + assert_eq!(is_window_size_ok(0, 0, 80, 128), true); + } + + #[test] + fn x_too_big() { + assert_eq!(is_window_size_ok(8, 8, 80, 1), false); + } + + #[test] + fn y_too_big() { + assert_eq!(is_window_size_ok(8, 8, 8, 121), false); + } + + #[test] + fn x_is_not_multiple_of_8() { + assert_eq!(is_window_size_ok(1, 0, 72, 128), false); + } + + #[test] + fn width_is_not_multiple_of_8() { + assert_eq!(is_window_size_ok(0, 0, 79, 128), false); + } + + #[test] + fn buffer_size_incorrect() { + let buf = [0u8; 10]; + assert_eq!(is_buffer_size_ok(&buf, 10, 10), false); + } + + #[test] + fn buffer_size_correct() { + let buf = [0u8; 10]; + assert_eq!(is_buffer_size_ok(&buf, 8, 10), true); + } +} diff --git a/src/lib.rs b/src/lib.rs index 9b393528..f20d71b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -73,6 +73,7 @@ pub mod color; /// Interface for the physical connection between display and the controlling device mod interface; +pub mod epd1in02; pub mod epd1in54; pub mod epd1in54_v2; pub mod epd1in54b; From d69884eb7c0d35d98a08b2e66f15597979b1f08d Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:17:21 +0100 Subject: [PATCH 57/69] Update to embedded hal mock 0.11 --- Cargo.toml | 2 +- src/epd1in54/mod.rs | 8 ++++---- src/epd2in13bc/mod.rs | 8 ++++---- src/epd2in9/mod.rs | 8 ++++---- src/epd2in9_v2/mod.rs | 8 ++++---- src/epd2in9bc/mod.rs | 8 ++++---- src/epd4in2/mod.rs | 8 ++++---- src/lib.rs | 8 ++++---- src/traits.rs | 16 ++++++++-------- 9 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 55d682a7..8c2f029d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ bit_field = "0.10.1" [dev-dependencies] embedded-graphics = "0.8" -embedded-hal-mock = { version = "=0.10.0", default-features = false, features = [ +embedded-hal-mock = { version = "0.11", default-features = false, features = [ "eh1", ] } diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 4a4514ed..b598693e 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -13,10 +13,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 9d1f0d88..d1256c4c 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -13,10 +13,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 48c5bdcc..0ad3d771 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -14,10 +14,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 3a36fdf7..86997be9 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -15,10 +15,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 0f6d52b2..7a4ba92c 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -13,10 +13,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index a1c2a0d4..6de676e6 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -18,10 +18,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/lib.rs b/src/lib.rs index 9b393528..2f64bef3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -21,10 +21,10 @@ //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); //!# let expectations = []; -//!# let cs_pin = pin::Mock::new(&expectations); -//!# let busy_in = pin::Mock::new(&expectations); -//!# let dc = pin::Mock::new(&expectations); -//!# let rst = pin::Mock::new(&expectations); +//!# let cs_pin = digital::Mock::new(&expectations); +//!# let busy_in = digital::Mock::new(&expectations); +//!# let dc = digital::Mock::new(&expectations); +//!# let rst = digital::Mock::new(&expectations); //!# let mut delay = delay::NoopDelay::new(); //! //!// Setup EPD diff --git a/src/traits.rs b/src/traits.rs index b1f3f731..487cfaa0 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -99,10 +99,10 @@ where ///# let expectations = []; ///# let mut spi = spi::Mock::new(&expectations); ///# let expectations = []; -///# let cs_pin = pin::Mock::new(&expectations); -///# let busy_in = pin::Mock::new(&expectations); -///# let dc = pin::Mock::new(&expectations); -///# let rst = pin::Mock::new(&expectations); +///# let cs_pin = digital::Mock::new(&expectations); +///# let busy_in = digital::Mock::new(&expectations); +///# let dc = digital::Mock::new(&expectations); +///# let rst = digital::Mock::new(&expectations); ///# let mut delay = delay::NoopDelay::new(); /// ///// Setup EPD @@ -261,10 +261,10 @@ where ///# let expectations = []; ///# let mut spi = spi::Mock::new(&expectations); ///# let expectations = []; -///# let cs_pin = pin::Mock::new(&expectations); -///# let busy_in = pin::Mock::new(&expectations); -///# let dc = pin::Mock::new(&expectations); -///# let rst = pin::Mock::new(&expectations); +///# let cs_pin = digital::Mock::new(&expectations); +///# let busy_in = digital::Mock::new(&expectations); +///# let dc = digital::Mock::new(&expectations); +///# let rst = digital::Mock::new(&expectations); ///# let mut delay = delay::NoopDelay::new(); ///# ///# // Setup EPD From b7963764ae57006dc799b70f51716673994a4a84 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:19:06 +0100 Subject: [PATCH 58/69] Remove empty doc comments and other clippy improvements --- examples/epd4in2_variable_size.rs | 1 - src/color.rs | 4 ++-- src/epd3in7/command.rs | 12 ------------ src/epd7in5b_v2/mod.rs | 2 +- 4 files changed, 3 insertions(+), 16 deletions(-) diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 8ff8259d..978b21d6 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -1,5 +1,4 @@ #![deny(warnings)] -#![deny(warnings)] use embedded_graphics::{ mono_font::MonoTextStyleBuilder, diff --git a/src/color.rs b/src/color.rs index 74823d3c..c768b2d0 100644 --- a/src/color.rs +++ b/src/color.rs @@ -78,7 +78,7 @@ pub trait ColorType { /// Return the data used to set a pixel color /// /// * bwrbit is used to tell the value of the unused bit when a chromatic - /// color is set (TriColor only as for now) + /// color is set (TriColor only as for now) /// * pos is the pixel position in the line, used to know which pixels must be set /// /// Return values are : @@ -405,7 +405,7 @@ mod tests { // test all values aside from 0 and 1 which all should panic #[test] fn from_u8_panic() { - for val in 2..=u8::max_value() { + for val in 2..=u8::MAX { extern crate std; let result = std::panic::catch_unwind(|| Color::from(val)); assert!(result.is_err()); diff --git a/src/epd3in7/command.rs b/src/epd3in7/command.rs index 5aba926a..13d44a65 100644 --- a/src/epd3in7/command.rs +++ b/src/epd3in7/command.rs @@ -12,24 +12,17 @@ use crate::traits; #[allow(dead_code)] #[derive(Copy, Clone)] pub(crate) enum Command { - /// GateSetting = 0x01, - /// PowerOff = 0x02, - /// Sleep2 = 0x07, - /// GateVoltage = 0x03, - /// GateVoltageSource = 0x04, - /// BoosterSoftStartControl = 0x0C, /// After this command initiated, the chip will enter Deep Sleep Mode, /// BUSY pad will keep output high. /// /// Note: To exit Deep Sleep Mode, User required to send HWRESET to the driver. DeepSleep = 0x10, - /// DataEntrySequence = 0x11, /// This command resets commands and parameters to their S/W Reset default values, /// except Deep Sleep Mode. @@ -58,9 +51,7 @@ pub(crate) enum Command { /// This command writes LUT register from MCU interface (105 bytes), /// which contains the content of VS [nx-LUT], TP #[nX], RP #[n] WriteLutRegister = 0x32, - /// DisplayOption = 0x37, - /// BorderWaveformControl = 0x3C, /// This command specifies the start/end positions of the window address in the X direction, /// by an address unit of RAM. @@ -68,15 +59,12 @@ pub(crate) enum Command { /// This command specifies the start/end positions of the window address in the Y direction, /// by an address unit of RAM. SetRamYAddressStartEndPosition = 0x45, - /// AutoWriteRedRamRegularPattern = 0x46, - /// AutoWriteBwRamRegularPattern = 0x47, /// This command makes the initial settings for the RAM X address in the address counter (AC) SetRamXAddressCounter = 0x4E, /// This command makes the initial settings for the RAM Y address in the address counter (AC) SetRamYAddressCounter = 0x4F, - /// Sleep = 0x50, } diff --git a/src/epd7in5b_v2/mod.rs b/src/epd7in5b_v2/mod.rs index 708dd452..69963c57 100644 --- a/src/epd7in5b_v2/mod.rs +++ b/src/epd7in5b_v2/mod.rs @@ -1,4 +1,4 @@ -//! A simple Driver for the Waveshare 7.5" (B) E-Ink Display (V2) via SPI +//! A simple Driver for the Waveshare 7.5" (B) E-Ink Display (V2 and V3) via SPI //! //! # References //! From 22f726f968e07f555600e4a3813b4399d5938999 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 12:22:51 +0100 Subject: [PATCH 59/69] Release v0.6 To hopefully allow for faster updates, v0.6 is released as an intermediate release. --- CHANGELOG.md | 59 +++++++++++++++++++++++++++++++++++++++------------- Cargo.toml | 5 +---- 2 files changed, 46 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 210397ee..f0517fbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,24 +1,55 @@ -# Change Log +# Changelog All notable changes to this project will be documented in this file. -The format is based on [Keep a Changelog](http://keepachangelog.com/) -and this project adheres to [Semantic Versioning](http://semver.org/). +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [v0.6.0] - 2024-10-28 ### Added -- Added support for positive and negatives modes of rendering in TriColor display in #92 (thanks to @akashihi) -- Added Epd 5in83 V2 (B) support in #92 (thanks to @akashihi) -- Added Epd 7in5 (B) V2 and V3 support +- Add support for positive and negatives modes of rendering in TriColor display in #92 (thanks to @akashihi) +- Add Epd 5in83 V2 (B) support in #92 (thanks to @akashihi) +- Add Epd 7in5 (B) V2 and V3 support in #118 (should also work on v3), thanks to @peckpeck +- Add 7.3 Inch HAT (F) support in #191 (thanks to @jetjinser) +- Add support for EPD 2in9 D in #171 (thanks to @wsndshx) +- Add Epd 5in83 V2 support in #159 (thanks to @Carbonhell) +- Add support for Pi hat Pico Epd2in66B (B/W/R) in #147 (thanks to @ReinoutHeeck and @Lite5h4dow) +- Add support for EPD 2in13 v3 in #126 and #138 (thanks to @fmeef) +- Add embedded-graphics traits for color in #132 (thanks to @peckpeck) +- Add support for EPD 3in7 in #129 (thanks to @mangelajo) +- Add convert traits for TriColor +- Add support for GDEH0154D67 (aka epd1in54_v2) in #106 (thanks to @jcard0na) +- Add option to switch between single byte and blockwise data writen to the spi device +- Added tests and fixed sized method when rotated ### Changed - Made Examples and Linux embedded hal optional (linux only) and therefore allowed building on other hosts (#101, #94) +- Update to eh-1.0, eh-mock 0.10 , leh 0.4.0 +- Documentation tweaks +- Updated and improved Examples and Readme multiple times (thanks to @shymega and many others) +- Updated refresh rate for 2.9in v2 display to make it much faster thanks to @andber1 in #150 (and #185) +- Removed epd7in5_v3 in favour of edp7in5b_v2 since they work the same way in #177 +- Migrated to Rust 2021 in #133 (thanks to @peckpeck) +- Migrate `DelayMs` to `DelayUs` to allow shorter and longer sleeps in #131 (thanks to @peckpeck) +- Improved delay handling by allowing busy or sleep loops in wait_for_idle in #125 thanks to @peckpeck +- Make Display more generic in #123 and #121 (thanks to @peckpeck) ### Fixed +- Overflow error for all displays thanks to @tippfehlr in @186 +- Fix build when feature graphics is not enabled in #176 (thanks to @vhdirk) +- Optimize overflow in the calculation of `NUM_DISPLAY_BYTES` on small architectures in #173 (thanks to @Idicarlo) +- Fixed init code for epd1in54 thanks to @fakusb in #156 +- Fix off-by-one bug for `set_pixel` in #148 thanks to @ReinoutHeeck +- Fix 7in5(HD) by allowing blockwise data to be written in #141 (see issues and discussions in #70, #83, #142) +- Fix enter deep sleep for epd1in54 v2 in #139 (thanks to @jcard0na) +- Fixed buffer length in display struct in #128 (thanks to @peckpeck) +- LUT Fixes for EPD 2in9 v2 in #103 (thanks to @mike-kfed) +- Fix pins for epd2in13_v2 example in #91 Universal e-Paper Raw Panel Driver HAT (thanks to @ole-treichel) + ## [v0.5.0] - 2021-11-28 ### Added @@ -31,7 +62,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added Color conversion methods in #87 & #88 (thanks to @crzysdrs) - Provide full QuickRefresh interface for 4.2 inch display in #81 (thanks to @sirhcel) - ### Changed - Updated embedded-graphics to 0.7 and switch to e-g-core #78 (@Irbalt) & #85 (@jamwaffles) @@ -42,7 +72,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Write data over SPI 1 byte at a time due to #82 (thanks to @belak) - Enable drawing in three colors for epd2in13bc in #76 (thanks to @Irbalt) - ## [v0.4.0] - 2020-04-06 ### Added @@ -130,12 +159,14 @@ Initial release with Changelog - Lots of internal changes - Renamed to `epd-waveshare` -[Unreleased]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.4.0...HEAD +[v0.6.0]: https://github.com/Caemor/epd-waveshare/compare/v0.5.0...v0.6.0 + +[v0.5.0]: https://github.com/Caemor/epd-waveshare/compare/v0.4.0...v0.5.0 -[v0.4.0]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.3.2...v0.4.0 +[v0.4.0]: https://github.com/Caemor/epd-waveshare/compare/v0.3.2...v0.4.0 -[v0.3.2]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.3.1...v0.3.2 +[v0.3.2]: https://github.com/Caemor/epd-waveshare/compare/v0.3.1...v0.3.2 -[v0.3.1]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.3.0...v0.3.1 +[v0.3.1]: https://github.com/Caemor/epd-waveshare/compare/v0.3.0...v0.3.1 -[v0.3.0]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.2.0...v0.3.0 +[v0.3.0]: https://github.com/Caemor/epd-waveshare/compare/v0.2.0...v0.3.0 diff --git a/Cargo.toml b/Cargo.toml index 8c2f029d..763e25ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,12 +9,9 @@ license = "ISC" name = "epd-waveshare" readme = "README.md" repository = "https://github.com/Caemor/epd-waveshare.git" -version = "0.5.0" +version = "0.6.0" edition = "2021" -[badges] -# travis-ci = { repository = "caemor/epd-waveshare" } - [dependencies] embedded-graphics-core = { version = "0.4", optional = true } embedded-hal = "1.0.0" From 5633d506bea60bd4d047dd028df45982f44b6d80 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:13:42 +0100 Subject: [PATCH 60/69] OctColor Bitmask fix to Changelog for 0.6 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0517fbe..71bd6e9d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed buffer length in display struct in #128 (thanks to @peckpeck) - LUT Fixes for EPD 2in9 v2 in #103 (thanks to @mike-kfed) - Fix pins for epd2in13_v2 example in #91 Universal e-Paper Raw Panel Driver HAT (thanks to @ole-treichel) +- Fix Color Bitmask calculation for OctColor in #190 (thanks to @jetjinser) ## [v0.5.0] - 2021-11-28 From d5c202969c30af96cf571a5ea5402e014085fdda Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 13:44:52 +0100 Subject: [PATCH 61/69] Parenthesize color mask thanks to clippy --- src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color.rs b/src/color.rs index e53aa0b7..da0b00e6 100644 --- a/src/color.rs +++ b/src/color.rs @@ -124,7 +124,7 @@ impl ColorType for OctColor { const BITS_PER_PIXEL_PER_BUFFER: usize = 4; const BUFFER_COUNT: usize = 1; fn bitmask(&self, _bwrbit: bool, pos: u32) -> (u8, u16) { - let mask = !(0xF0 >> (pos % 2) * 4); + let mask = !(0xF0 >> ((pos % 2) * 4)); let bits = self.get_nibble() as u16; (mask, if pos % 2 == 1 { bits } else { bits << 4 }) } From 01e68b4d895e2250c34dda0c76d565e35ead9d5e Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Mon, 28 Oct 2024 14:35:26 +0100 Subject: [PATCH 62/69] v0.6 doc fixes --- .github/workflows/rust.yml | 2 ++ src/epd2in9d/mod.rs | 2 +- src/graphics.rs | 8 ++++---- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 55a8c545..0c06d2f5 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -7,6 +7,8 @@ jobs: build: runs-on: ubuntu-latest + env: + RUSTDOCFLAGS: -Dwarnings strategy: matrix: rust: diff --git a/src/epd2in9d/mod.rs b/src/epd2in9d/mod.rs index 95d72398..4a7e0952 100644 --- a/src/epd2in9d/mod.rs +++ b/src/epd2in9d/mod.rs @@ -3,7 +3,7 @@ //! //! 参考[Waveshare](https://www.waveshare.net/wiki/2.9inch_e-Paper_HAT_%28D%29)的文档/例程进行构建 //! -//! Specification: https://www.waveshare.net/w/upload/b/b5/2.9inch_e-Paper_%28D%29_Specification.pdf +//! Specification: use core::slice::from_raw_parts; diff --git a/src/graphics.rs b/src/graphics.rs index 51ddda58..4264b981 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -24,7 +24,7 @@ const fn line_bytes(width: u32, bits_per_pixel: usize) -> usize { (width as usize * bits_per_pixel + 7) / 8 } -/// Display bffer used for drawing with embedded graphics +/// Display buffer used for drawing with embedded graphics /// This can be rendered on EPD using ... /// /// - WIDTH: width in pixel when display is not rotated @@ -32,17 +32,17 @@ const fn line_bytes(width: u32, bits_per_pixel: usize) -> usize { /// - BWRBIT: mandatory value of the B/W when chromatic bit is set, can be any value for non /// tricolor epd /// - COLOR: color type used by the target display -/// - BYTECOUNT: This is redundant with prvious data and should be removed when const generic +/// - BYTECOUNT: This is redundant with previous data and should be removed when const generic /// expressions are stabilized /// /// More on BWRBIT: /// /// Different chromatic displays differently treat the bits in chromatic color planes. /// Some of them ([crate::epd2in13bc]) will render a color pixel if bit is set for that pixel, -/// which is a [DisplayColorRendering::Positive] mode. +/// which is a `BWRBIT = true` mode. /// /// Other displays, like [crate::epd5in83b_v2] in opposite, will draw color pixel if bit is -/// cleared for that pixel, which is a [DisplayColorRendering::Negative] mode. +/// cleared for that pixel, which is a `BWRBIT = false` mode. /// /// BWRBIT=true: chromatic doesn't override white, white bit cleared for black, white bit set for white, both bits set for chromatic /// BWRBIT=false: chromatic does override white, both bits cleared for black, white bit set for white, red bit set for black From aa8a73eb00103d071fb7f4ee03bded81a3b13b21 Mon Sep 17 00:00:00 2001 From: Christoph Gross <11088935+caemor@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:27:00 +0100 Subject: [PATCH 63/69] Update examples/epd7in5_v2.rs Add documentation to the example --- examples/epd7in5_v2.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/epd7in5_v2.rs b/examples/epd7in5_v2.rs index 4086d1e2..b2ba074f 100644 --- a/examples/epd7in5_v2.rs +++ b/examples/epd7in5_v2.rs @@ -1,3 +1,4 @@ +// This example tests rotations and draws analog clock, tests default fonts of embedded-graphics crate and displays an image of Ferris from examples/assets/ directory. use embedded_graphics::{ image::Image, image::ImageRaw, From 8de8b9109f382506fb5d0f2466107325f939862e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christoph=20Gro=C3=9F?= <11088935+caemor@users.noreply.github.com> Date: Tue, 29 Oct 2024 16:35:32 +0100 Subject: [PATCH 64/69] fix bare url in documentation --- src/epd2in9b_v4/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in9b_v4/mod.rs b/src/epd2in9b_v4/mod.rs index 3889cfe5..12cfdd90 100644 --- a/src/epd2in9b_v4/mod.rs +++ b/src/epd2in9b_v4/mod.rs @@ -66,7 +66,7 @@ where { /// set the base image before partially update /// - /// https://github.com/waveshareteam/e-Paper/blob/bc23f8ee814486edb6a364c802847224e079e523/RaspberryPi_JetsonNano/c/examples/EPD_2in9b_V4_test.c#L130 + /// pub fn update_and_display_frame_base( &mut self, spi: &mut SPI, From 9b4d8093547bcc939afe37ba367bbe448d5e050e Mon Sep 17 00:00:00 2001 From: Aiden Scandella Date: Tue, 29 Oct 2024 09:11:23 -0700 Subject: [PATCH 65/69] doc: remove partial refresh --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63699335..76d2262d 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ epd4in2.sleep(&mut spi, &mut delay) | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | -| [2.7 Inch B/W V2](https://www.waveshare.com/2.7inch-e-paper.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | +| [2.7 Inch B/W V2](https://www.waveshare.com/2.7inch-e-paper.htm) | Black, White | ✕ | ✕ | ✔ | ✔ | | [2.66 Inch 3 Color (B)](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/Y (C) (Discontinued)](https://www.waveshare.com/1.54inch-e-paper-module-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/R (B)](https://www.waveshare.com/1.54inch-e-Paper-B.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | From f78dd05b7f2399e93b1a7dcfbea86bf27a41956b Mon Sep 17 00:00:00 2001 From: andber1 <82754113+andber1@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:19:11 +0100 Subject: [PATCH 66/69] Add update_and_display_frame to example in readme --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 3df65ccc..e7284bb3 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,9 @@ let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); let _ = Text::with_text_style("It's working-WoB!", Point::new(175, 250), style, text_style) .draw(&mut display); +// Show display on e-paper +epd4in2.update_and_display_frame(&mut spi, display.buffer(), &mut delay).expect("display error"); + // Going to sleep epd4in2.sleep(&mut spi, &mut delay) ``` From 7c815376aaa1109c578a5ea9c81817409a7c250b Mon Sep 17 00:00:00 2001 From: andber1 <82754113+andber1@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:27:59 +0100 Subject: [PATCH 67/69] Implement PixelColor for Color and TriColor --- src/color.rs | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/color.rs b/src/color.rs index da0b00e6..c54a0573 100644 --- a/src/color.rs +++ b/src/color.rs @@ -288,9 +288,21 @@ impl From for Color { } } +#[cfg(feature = "graphics")] +impl From for Color { + fn from(b: embedded_graphics_core::pixelcolor::raw::RawU1) -> Self { + use embedded_graphics_core::prelude::RawData; + if b.into_inner() == 0 { + Color::White + } else { + Color::Black + } + } +} + #[cfg(feature = "graphics")] impl PixelColor for Color { - type Raw = (); + type Raw = embedded_graphics_core::pixelcolor::raw::RawU1; } #[cfg(feature = "graphics")] @@ -351,9 +363,23 @@ impl TriColor { } } +#[cfg(feature = "graphics")] +impl From for TriColor { + fn from(b: embedded_graphics_core::pixelcolor::raw::RawU2) -> Self { + use embedded_graphics_core::prelude::RawData; + if b.into_inner() == 0b00 { + TriColor::White + } else if b.into_inner() == 0b01 { + TriColor::Black + } else { + TriColor::Chromatic + } + } +} + #[cfg(feature = "graphics")] impl PixelColor for TriColor { - type Raw = (); + type Raw = embedded_graphics_core::pixelcolor::raw::RawU2; } #[cfg(feature = "graphics")] From b01193a11847d7df277062dd6815a51b77b1981e Mon Sep 17 00:00:00 2001 From: andber1 <82754113+andber1@users.noreply.github.com> Date: Tue, 29 Oct 2024 21:57:35 +0100 Subject: [PATCH 68/69] Remove unnecessary color_converted in example --- examples/epd7in5_v2.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/epd7in5_v2.rs b/examples/epd7in5_v2.rs index b2ba074f..61a1583f 100644 --- a/examples/epd7in5_v2.rs +++ b/examples/epd7in5_v2.rs @@ -8,7 +8,6 @@ use embedded_graphics::{ primitives::{Circle, Line, PrimitiveStyleBuilder}, text::{Baseline, Text, TextStyleBuilder}, }; -use embedded_graphics_core::pixelcolor::{BinaryColor, PixelColor}; use embedded_hal::delay::DelayNs; #[cfg(feature = "graphics")] use epd_waveshare::{color::Color, epd7in5_v2::*, graphics::DisplayRotation, prelude::*}; @@ -147,9 +146,9 @@ fn main() -> Result<(), SPIError> { println!("Draw Ferris"); display.clear(Color::Black).ok(); let data = include_bytes!("./assets/ferris.raw"); - let raw_image = ImageRaw::::new(data, 460); + let raw_image = ImageRaw::::new(data, 460); let image = Image::new(&raw_image, Point::zero()); - image.draw(&mut display.color_converted()).unwrap(); + image.draw(&mut display).unwrap(); epd7in5.update_and_display_frame(&mut spi, display.buffer(), &mut delay)?; // Clear and sleep From dcde7876ffc4237f2101de22af90a974cb5267bd Mon Sep 17 00:00:00 2001 From: Christoph Gross <11088935+caemor@users.noreply.github.com> Date: Wed, 30 Oct 2024 08:28:31 +0100 Subject: [PATCH 69/69] Improve documentation of partial updates for epd2in7v2-bw Add a small comment to the documentation of the display and include the partial refresh once more in the readme --- README.md | 2 +- src/epd2in7_v2/mod.rs | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 76d2262d..525603fa 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ epd4in2.sleep(&mut spi, &mut delay) | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W V2 (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | -| [2.7 Inch B/W V2](https://www.waveshare.com/2.7inch-e-paper.htm) | Black, White | ✕ | ✕ | ✔ | ✔ | +| [2.7 Inch B/W V2](https://www.waveshare.com/2.7inch-e-paper.htm) | Black, White | ✕ | (✔) | ✔ | ✔ | | [2.66 Inch 3 Color (B)](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/Y (C) (Discontinued)](https://www.waveshare.com/1.54inch-e-paper-module-c.htm) | Black, White, Yellow | ✕ | ✕ | ✔ | ✔ | | [1.54 Inch B/W/R (B)](https://www.waveshare.com/1.54inch-e-Paper-B.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | diff --git a/src/epd2in7_v2/mod.rs b/src/epd2in7_v2/mod.rs index 19df56f4..b1687326 100644 --- a/src/epd2in7_v2/mod.rs +++ b/src/epd2in7_v2/mod.rs @@ -1,5 +1,7 @@ //! A simple Driver for the Waveshare 2.7inch v2 e-Paper HAT Display via SPI //! +//! 4 Gray support and partial refresh is not fully implemented yet. +//! //! # References //! //! - [Datasheet](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_Manual)