From a8f990f79515004484288d7c9ea3cad25c7abec8 Mon Sep 17 00:00:00 2001 From: Tommy Gilligan <7865781+tommy-gilligan@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:08:26 +1100 Subject: [PATCH 1/8] Add some tests around TriColor --- src/color.rs | 29 +++++++++++++++++++++++++++++ src/graphics.rs | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/color.rs b/src/color.rs index c54a0573..0de50967 100644 --- a/src/color.rs +++ b/src/color.rs @@ -459,4 +459,33 @@ mod tests { Ok((left, right)) ); } + + #[test] + fn test_tricolor_bitmask() { + assert_eq!( + TriColor::Black.bitmask(false, 0), + (0b01111111, u16::from_le_bytes([0b00000000, 0b00000000])) + ); + assert_eq!( + TriColor::White.bitmask(false, 0), + (0b01111111, u16::from_le_bytes([0b10000000, 0b00000000])) + ); + assert_eq!( + TriColor::Chromatic.bitmask(false, 0), + (0b01111111, u16::from_le_bytes([0b10000000, 0b10000000])) + ); + + assert_eq!( + TriColor::Black.bitmask(true, 0), + (0b01111111, u16::from_le_bytes([0b00000000, 0b00000000])) + ); + assert_eq!( + TriColor::White.bitmask(true, 0), + (0b01111111, u16::from_le_bytes([0b10000000, 0b00000000])) + ); + assert_eq!( + TriColor::Chromatic.bitmask(true, 0), + (0b01111111, u16::from_le_bytes([0b00000000, 0b10000000])) + ); + } } diff --git a/src/graphics.rs b/src/graphics.rs index 4264b981..cd5e1eda 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -449,4 +449,40 @@ mod tests { assert_eq!(byte, 0); } } + + #[test] + fn graphics_set_pixel_tricolor_false() { + let mut display = Display::<4, 4, false, { 4 * 4 * 2 / 8 }, TriColor>::default(); + display.set_pixel(Pixel(Point::new(0, 0), TriColor::White)); + display.set_pixel(Pixel(Point::new(1, 0), TriColor::Chromatic)); + display.set_pixel(Pixel(Point::new(2, 0), TriColor::Black)); + + let bw_buffer = display.bw_buffer(); + let chromatic_buffer = display.chromatic_buffer(); + + extern crate std; + std::println!("{:?}", bw_buffer); + std::println!("{:?}", chromatic_buffer); + + assert_eq!(bw_buffer, [192, 0]); + assert_eq!(chromatic_buffer, [64, 0]); + } + + #[test] + fn graphics_set_pixel_tricolor_true() { + let mut display = Display::<4, 4, true, { 4 * 4 * 2 / 8 }, TriColor>::default(); + display.set_pixel(Pixel(Point::new(0, 0), TriColor::White)); + display.set_pixel(Pixel(Point::new(1, 0), TriColor::Chromatic)); + display.set_pixel(Pixel(Point::new(2, 0), TriColor::Black)); + + let bw_buffer = display.bw_buffer(); + let chromatic_buffer = display.chromatic_buffer(); + + extern crate std; + std::println!("{:?}", bw_buffer); + std::println!("{:?}", chromatic_buffer); + + assert_eq!(bw_buffer, [128, 0]); + assert_eq!(chromatic_buffer, [64, 0]); + } } From 85408f0d03cf678a6dbf5c4b439b3fe15c34bcf4 Mon Sep 17 00:00:00 2001 From: Tommy Gilligan <7865781+tommy-gilligan@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:08:40 +1100 Subject: [PATCH 2/8] Add support for EPD 2in13b V4 Amalgamation of waveshare/e-Paper code, datasheet PDF reference code and existing 2in13v2 driver --- src/epd2in13b_v4/command.rs | 148 +++++++++++ src/epd2in13b_v4/mod.rs | 517 ++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 666 insertions(+) create mode 100644 src/epd2in13b_v4/command.rs create mode 100644 src/epd2in13b_v4/mod.rs diff --git a/src/epd2in13b_v4/command.rs b/src/epd2in13b_v4/command.rs new file mode 100644 index 00000000..0c879de1 --- /dev/null +++ b/src/epd2in13b_v4/command.rs @@ -0,0 +1,148 @@ +//! SPI Commands for the Waveshare 2.13"B V4 E-Ink Display + +use crate::traits; + +extern crate bit_field; +use bit_field::BitField; + +/// Epd2in13 v4 +/// +/// 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 { + DriverOutputControl = 0x01, + GateDrivingVoltageCtrl = 0x03, + SourceDrivingVoltageCtrl = 0x04, + DeepSleepMode = 0x10, + DataEntryModeSetting = 0x11, + SwReset = 0x12, + TemperatureSensorRead = 0x18, + MasterActivation = 0x20, + DisplayUpdateControl1 = 0x21, + DisplayUpdateControl2 = 0x22, + WriteRam = 0x24, + WriteRamRed = 0x26, + WriteVcomRegister = 0x2C, + StatusBitRead = 0x2F, + WriteLutRegister = 0x32, + BorderWaveformControl = 0x3C, + SetRamXAddressStartEndPosition = 0x44, + SetRamYAddressStartEndPosition = 0x45, + SetRamXAddressCounter = 0x4E, + SetRamYAddressCounter = 0x4F, +} + +pub(crate) struct DriverOutput { + pub scan_is_linear: bool, + pub scan_g0_is_first: bool, + pub scan_dir_incr: bool, + pub width: u16, +} + +impl DriverOutput { + pub fn to_bytes(&self) -> [u8; 3] { + [ + self.width as u8, + (self.width >> 8) as u8, + *0u8.set_bit(0, !self.scan_dir_incr) + .set_bit(1, !self.scan_g0_is_first) + .set_bit(2, !self.scan_is_linear), + ] + } +} + +#[allow(dead_code, clippy::enum_variant_names)] +#[derive(Copy, Clone)] +pub(crate) enum RamOption { + Normal = 0x0, + BypassAs0 = 0x2, + Inverse = 0x4, +} + +pub(crate) struct DisplayUpdateControl { + pub red_ram_option: RamOption, + pub bw_ram_option: RamOption, + pub source_output_mode: bool, +} + +impl DisplayUpdateControl { + pub fn to_bytes(&self) -> [u8; 2] { + [ + ((self.red_ram_option as u8) << 4) | (self.bw_ram_option as u8), + if self.source_output_mode { 128 } else { 0 }, + ] + } +} + +#[allow(dead_code, clippy::enum_variant_names)] +pub(crate) enum DataEntryModeIncr { + XDecrYDecr = 0x0, + XIncrYDecr = 0x1, + XDecrYIncr = 0x2, + XIncrYIncr = 0x3, +} + +#[allow(dead_code)] +pub(crate) enum DataEntryModeDir { + XDir = 0x0, + YDir = 0x4, +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum BorderWaveFormVbd { + Gs = 0x0, + FixLevel = 0x1, + Vcom = 0x2, +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum BorderWaveFormFixLevel { + Vss = 0x0, + Vsh1 = 0x1, + Vsl = 0x2, + Vsh2 = 0x3, +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum BorderWaveFormGs { + Lut0 = 0x0, + Lut1 = 0x1, + Lut2 = 0x2, + Lut3 = 0x3, +} + +pub(crate) struct BorderWaveForm { + pub vbd: BorderWaveFormVbd, + pub fix_level: BorderWaveFormFixLevel, + pub gs_trans: BorderWaveFormGs, +} + +impl BorderWaveForm { + pub fn to_u8(&self) -> u8 { + *0u8.set_bits(6..8, self.vbd as u8) + .set_bits(4..6, self.fix_level as u8) + .set_bits(0..2, self.gs_trans as u8) + } +} + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub enum DeepSleepMode { + // Sleeps and keeps access to RAM and controller + Normal = 0x00, + // Sleeps without access to RAM/controller but keeps RAM content + Mode1 = 0x01, + // Same as MODE_1 but RAM content is not kept + Mode2 = 0x11, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs new file mode 100644 index 00000000..f9513848 --- /dev/null +++ b/src/epd2in13b_v4/mod.rs @@ -0,0 +1,517 @@ +//! A simple Drlever for the Waveshare 2.13" B V4 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.13-B) +//! This driver was build and tested for 250x122, 2.13inch E-Ink display HAT for Raspberry Pi, three-color, SPI interface +//! +//! # Example for the 2.13" B V4 E-Ink Display +//! +//!```rust, no_run +//!# use embedded_hal_mock::*; +//!# fn main() -> Result<(), MockError> { +//!use embedded_graphics::{prelude::*, primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder}}; +//!use epd_waveshare::{epd2in13b_v4::*, prelude::*}; +//!# +//!# 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 mut delay = delay::MockNoop::new(); +//! +//!// Setup EPD +//!let mut epd = Epd2in13b::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//! +//!// Use display graphics from embedded-graphics +//!// This display is for the black/white/chromatic pixels +//!let mut tricolor_display = Display2in13b::default(); +//! +//!// Use embedded graphics for drawing a black line +//!let _ = Line::new(Point::new(0, 120), Point::new(0, 200)) +//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) +//! .draw(&mut tricolor_display); +//! +//!// We use `chromatic` but it will be shown as red/yellow +//!let _ = Line::new(Point::new(15, 120), Point::new(15, 200)) +//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Chromatic, 1)) +//! .draw(&mut tricolor_display); +//! +//!// Display updated frame +//!epd.update_color_frame( +//! &mut spi, +//! &mut delay, +//! &tricolor_display.bw_buffer(), +//! &tricolor_display.chromatic_buffer() +//!)?; +//!epd.display_frame(&mut spi, &mut delay)?; +//! +//!// Set the EPD to sleep +//!epd.sleep(&mut spi, &mut delay)?; +//!# Ok(()) +//!# } +//!``` +// Original Waveforms from Waveshare +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::{InputPin, OutputPin}, +}; + +use crate::buffer_len; +use crate::color::TriColor; +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +pub(crate) mod command; +use self::command::{ + BorderWaveForm, BorderWaveFormFixLevel, BorderWaveFormGs, BorderWaveFormVbd, Command, + DataEntryModeDir, DataEntryModeIncr, DeepSleepMode, DisplayUpdateControl, DriverOutput, + RamOption, +}; + +/// Full size buffer for use with the 2.13" v4 EPD +#[cfg(feature = "graphics")] +pub type Display2in13b = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) * 2 }, + TriColor, +>; + +/// Width of the display. +pub const WIDTH: u32 = 122; + +/// Height of the display +pub const HEIGHT: u32 = 250; + +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; +const IS_BUSY_LOW: bool = false; + +/// Epd2in13b (V4) driver +pub struct Epd2in13b { + /// Connection Interface + interface: DisplayInterface, + + /// Background Color + background_color: TriColor, +} + +impl InternalWiAdditions + for Epd2in13b +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> { + // HW reset + self.interface.reset(delay, 10_000, 10_000); + + self.wait_until_idle(spi, delay)?; + self.interface.cmd(spi, Command::SwReset)?; + self.wait_until_idle(spi, delay)?; + + self.set_driver_output( + spi, + DriverOutput { + scan_is_linear: true, + scan_g0_is_first: true, + scan_dir_incr: true, + width: (HEIGHT - 1) as u16, + }, + )?; + + self.set_data_entry_mode(spi, DataEntryModeIncr::XIncrYIncr, DataEntryModeDir::XDir)?; + + // Use simple X/Y auto increase + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.set_ram_address_counters(spi, delay, 0, 0)?; + + self.set_border_waveform( + spi, + command::BorderWaveForm { + vbd: BorderWaveFormVbd::Gs, + fix_level: BorderWaveFormFixLevel::Vss, + gs_trans: BorderWaveFormGs::Lut3, + }, + )?; + + self.cmd_with_data(spi, Command::WriteVcomRegister, &[0x36])?; + self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[0x17])?; + self.cmd_with_data(spi, Command::SourceDrivingVoltageCtrl, &[0x41, 0x00, 0x32])?; + + self.set_display_update_control( + spi, + command::DisplayUpdateControl { + red_ram_option: RamOption::Normal, + bw_ram_option: RamOption::Normal, + source_output_mode: false, + }, + )?; + + self.wait_until_idle(spi, delay)?; + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for Epd2in13b +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.interface.cmd(spi, Command::WriteRam)?; + self.interface.data(spi, black)?; + Ok(()) + } + + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::WriteRamRed)?; + self.interface.data(spi, chromatic)?; + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in13b +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 { + let mut epd = Epd2in13b { + interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + background_color: DEFAULT_BACKGROUND_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.set_sleep_mode(spi, DeepSleepMode::Normal)?; + Ok(()) + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); + self.cmd_with_data(spi, Command::WriteRam, buffer)?; + + self.command(spi, Command::WriteRamRed)?; + self.interface.data_x_times( + spi, + TriColor::Black.get_byte_value(), + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + 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::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.clear_achromatic_frame(spi)?; + self.clear_chromatic_frame(spi) + } + + fn set_background_color(&mut self, background_color: TriColor) { + self.background_color = background_color; + } + + fn background_color(&self) -> &TriColor { + &self.background_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(delay, IS_BUSY_LOW); + Ok(()) + } +} + +impl Epd2in13b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn set_display_update_control( + &mut self, + spi: &mut SPI, + display_update_control: DisplayUpdateControl, + ) -> Result<(), SPI::Error> { + self.cmd_with_data( + spi, + Command::DisplayUpdateControl1, + &display_update_control.to_bytes(), + ) + } + + fn set_border_waveform( + &mut self, + spi: &mut SPI, + borderwaveform: BorderWaveForm, + ) -> Result<(), SPI::Error> { + self.cmd_with_data( + spi, + Command::BorderWaveformControl, + &[borderwaveform.to_u8()], + ) + } + + /// Triggers the deep sleep mode + fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DeepSleepMode, &[mode as u8]) + } + + fn set_driver_output(&mut self, spi: &mut SPI, output: DriverOutput) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) + } + + /// Sets the data entry mode (ie. how X and Y positions changes when writing + /// data to RAM) + fn set_data_entry_mode( + &mut self, + spi: &mut SPI, + counter_incr_mode: DataEntryModeIncr, + counter_direction: DataEntryModeDir, + ) -> Result<(), SPI::Error> { + let mode = counter_incr_mode as u8 | counter_direction as u8; + self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) + } + + /// Sets both X and Y pixels ranges + fn set_ram_area( + &mut self, + spi: &mut SPI, + start_x: u32, + start_y: u32, + end_x: u32, + end_y: u32, + ) -> Result<(), SPI::Error> { + self.cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + )?; + + self.cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + } + + /// Sets both X and Y pixels counters when writing data to RAM + fn set_ram_address_counters( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + x: u32, + y: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; + + self.cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + )?; + Ok(()) + } + + 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 clear_achromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + match self.background_color { + TriColor::White => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + TriColor::Chromatic => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + TriColor::Black => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + } + + Ok(()) + } + + fn clear_chromatic_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + match self.background_color { + TriColor::White => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + TriColor::Chromatic => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0xFF, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + TriColor::Black => { + self.command(spi, Command::WriteRam)?; + self.interface.data_x_times( + spi, + 0x00, + buffer_len(WIDTH as usize, HEIGHT as usize) as u32, + )?; + } + } + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn epd_size() { + assert_eq!(WIDTH, 122); + assert_eq!(HEIGHT, 250); + assert_eq!(DEFAULT_BACKGROUND_COLOR, TriColor::White); + } +} diff --git a/src/lib.rs b/src/lib.rs index ce50f7a4..3ef7291a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -81,6 +81,7 @@ pub mod epd1in54_v2; pub mod epd1in54b; pub mod epd1in54c; pub mod epd2in13_v2; +pub mod epd2in13b_v4; pub mod epd2in13bc; pub mod epd2in66b; pub mod epd2in7; From 5e557a03ee46fa10614245fc75a3da013400f44f Mon Sep 17 00:00:00 2001 From: Tommy Gilligan <7865781+tommy-gilligan@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:08:46 +1100 Subject: [PATCH 3/8] Fix wrong source output mode --- src/epd2in13b_v4/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs index f9513848..43e6210e 100644 --- a/src/epd2in13b_v4/mod.rs +++ b/src/epd2in13b_v4/mod.rs @@ -151,7 +151,7 @@ where command::DisplayUpdateControl { red_ram_option: RamOption::Normal, bw_ram_option: RamOption::Normal, - source_output_mode: false, + source_output_mode: true, }, )?; From 960c19f27d317f2ef20327e74585b2c835214ea5 Mon Sep 17 00:00:00 2001 From: Tommy Gilligan <7865781+tommy-gilligan@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:31:12 +1100 Subject: [PATCH 4/8] update epd2in13b_v4 for changes on main --- src/epd2in13b_v4/mod.rs | 48 ++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs index 43e6210e..cd526ef0 100644 --- a/src/epd2in13b_v4/mod.rs +++ b/src/epd2in13b_v4/mod.rs @@ -52,8 +52,9 @@ //!``` // Original Waveforms from Waveshare use embedded_hal::{ - blocking::{delay::*, spi::Write}, - digital::v2::{InputPin, OutputPin}, + delay::DelayNs, + spi::SpiDevice, + digital::{InputPin, OutputPin}, }; use crate::buffer_len; @@ -70,6 +71,8 @@ use self::command::{ RamOption, }; +const SINGLE_BYTE_WRITE: bool = true; + /// Full size buffer for use with the 2.13" v4 EPD #[cfg(feature = "graphics")] pub type Display2in13b = crate::graphics::Display< @@ -91,23 +94,22 @@ pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; const IS_BUSY_LOW: bool = false; /// Epd2in13b (V4) driver -pub struct Epd2in13b { +pub struct Epd2in13b { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, /// Background Color background_color: TriColor, } -impl InternalWiAdditions - for Epd2in13b +impl InternalWiAdditions + for Epd2in13b 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> { // HW reset @@ -161,15 +163,14 @@ where } } -impl WaveshareThreeColorDisplay - for Epd2in13b +impl WaveshareThreeColorDisplay + for Epd2in13b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn update_color_frame( &mut self, @@ -205,20 +206,18 @@ where } } -impl WaveshareDisplay - for Epd2in13b +impl WaveshareDisplay + for Epd2in13b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { type DisplayColor = TriColor; fn new( spi: &mut SPI, - cs: CS, busy: BUSY, dc: DC, rst: RST, @@ -226,7 +225,7 @@ where delay_us: Option, ) -> Result { let mut epd = Epd2in13b { - interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + interface: DisplayInterface::new(busy, dc, rst, delay_us), background_color: DEFAULT_BACKGROUND_COLOR, }; @@ -328,14 +327,13 @@ where } } -impl Epd2in13b +impl Epd2in13b where - SPI: Write, - CS: OutputPin, + SPI: SpiDevice, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayUs, + DELAY: DelayNs, { fn set_display_update_control( &mut self, From 28bbb60f32ad472e90bdf00d61bb593edfca8c32 Mon Sep 17 00:00:00 2001 From: Tommy Gilligan <7865781+tommy-gilligan@users.noreply.github.com> Date: Fri, 9 Feb 2024 00:33:05 +1100 Subject: [PATCH 5/8] formatting --- src/.DS_Store | Bin 0 -> 10244 bytes src/epd2in13b_v4/mod.rs | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 src/.DS_Store diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5b56030408ddb0e02c982f8a4e4cbab186465b6d GIT binary patch literal 10244 zcmeI1zfTlF6vy8p;fG*?jkX&N#6sg8$AJWi3ppdDh*DUH9*05#cUPd1NU?u{HYRFf zN1}~?fQcQIiJE9MRwi0lnNZuPZ+`5|o86h+Ye*!SO?DsberM*xcV=hj4FC|#-ffft zLICK)lf|JyyjTwQoSm7YOWwJPF~ITwYtV!$jIG}(FJ#pIhIha_;2rP|cn7=#|APbg z&1Og6fQbI;9qI#OpY;mEK(-vn3?<;LW4VyaA&5luSMPv#AnO3j-TPn# z+R%V9&EJ<>8*L#!^VX)>Xw_=<^;Vrddpz`DZ~o)%j9u60NY`F1FX%Q)tm%O?7c9X& z7-hQ)T3Ok4D=Fj1uwr!7yV265#cGo`V!Zts-nz+Jx^7od&Zwd|E%i~xe5J{E+0M6Y z@(rJ~@-0)o`_nmmsMH?jD^0$L@g@B-%Ew_DDz^S!n{q2D=hKwtJ)kS^G)0td+O6)cKn>62{)1Q$l zrJzhpJBlfz(r&p`CJ&z{P46ddZ_W8jNM+Sgw(2Xz=Fn=wBCW|8Ve@K!6n!uWbx4i6 zvy3vC^@xfx&c9ZSR;4D)S6cXz{;2TzXTt2)(iXC%6qM`uJH?ezX(qQShi8oQq`rHb ze+Z9MP@XqmGCWG9dE6?K=OH$xdZx;G#&M_rw&_u2)~=#lJwFsz(to5r`c~#EO}>cn zC3B{z?;L(V#C)7`ZfY@4OIe%06sxmtO5BOw!f{Lr0tNiV){9C!ogXgoG*^%a-vrIS)?^N`8Z70NlCw3-<}Ikkkp~1tnCrS>Qrmm zVzq_02R2~~GnW+{p|?ywkFf0k<2hy9`TjTFd(YQ~DUBv_X-p3O{l%vI;T04I=>Grzf&05Wuy?>a(76LacWt4@mhN(IJyWs^?}T{X#FHIN7mLV?;Dt%peZC!! zzp(G`DS1zQB=LD9@5LhW;#iIs$0&C5_x+y%xR*fJN Date: Fri, 9 Feb 2024 00:51:09 +1100 Subject: [PATCH 6/8] fix imports for updated depdencies --- src/epd2in13b_v4/mod.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs index f2f10c26..79749d67 100644 --- a/src/epd2in13b_v4/mod.rs +++ b/src/epd2in13b_v4/mod.rs @@ -5,7 +5,7 @@ //! # Example for the 2.13" B V4 E-Ink Display //! //!```rust, no_run -//!# use embedded_hal_mock::*; +//!# use embedded_hal_mock::eh1::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{prelude::*, primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder}}; //!use epd_waveshare::{epd2in13b_v4::*, 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 = Epd2in13b::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay, None)?; +//!let mut epd = Epd2in13b::new(&mut spi, busy_in, dc, rst, &mut delay, None).unwrap(); //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white/chromatic pixels @@ -42,11 +42,11 @@ //! &mut delay, //! &tricolor_display.bw_buffer(), //! &tricolor_display.chromatic_buffer() -//!)?; -//!epd.display_frame(&mut spi, &mut delay)?; +//!).unwrap(); +//!epd.display_frame(&mut spi, &mut delay).unwrap(); //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi, &mut delay)?; +//!epd.sleep(&mut spi, &mut delay).unwrap(); //!# Ok(()) //!# } //!``` From ffe993dab917d735a3c4b9526e8fb95cf90c93c1 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 30 Oct 2024 11:02:46 +0100 Subject: [PATCH 7/8] remove .DS_Store --- src/.DS_Store | Bin 10244 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/.DS_Store diff --git a/src/.DS_Store b/src/.DS_Store deleted file mode 100644 index 5b56030408ddb0e02c982f8a4e4cbab186465b6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10244 zcmeI1zfTlF6vy8p;fG*?jkX&N#6sg8$AJWi3ppdDh*DUH9*05#cUPd1NU?u{HYRFf zN1}~?fQcQIiJE9MRwi0lnNZuPZ+`5|o86h+Ye*!SO?DsberM*xcV=hj4FC|#-ffft zLICK)lf|JyyjTwQoSm7YOWwJPF~ITwYtV!$jIG}(FJ#pIhIha_;2rP|cn7=#|APbg z&1Og6fQbI;9qI#OpY;mEK(-vn3?<;LW4VyaA&5luSMPv#AnO3j-TPn# z+R%V9&EJ<>8*L#!^VX)>Xw_=<^;Vrddpz`DZ~o)%j9u60NY`F1FX%Q)tm%O?7c9X& z7-hQ)T3Ok4D=Fj1uwr!7yV265#cGo`V!Zts-nz+Jx^7od&Zwd|E%i~xe5J{E+0M6Y z@(rJ~@-0)o`_nmmsMH?jD^0$L@g@B-%Ew_DDz^S!n{q2D=hKwtJ)kS^G)0td+O6)cKn>62{)1Q$l zrJzhpJBlfz(r&p`CJ&z{P46ddZ_W8jNM+Sgw(2Xz=Fn=wBCW|8Ve@K!6n!uWbx4i6 zvy3vC^@xfx&c9ZSR;4D)S6cXz{;2TzXTt2)(iXC%6qM`uJH?ezX(qQShi8oQq`rHb ze+Z9MP@XqmGCWG9dE6?K=OH$xdZx;G#&M_rw&_u2)~=#lJwFsz(to5r`c~#EO}>cn zC3B{z?;L(V#C)7`ZfY@4OIe%06sxmtO5BOw!f{Lr0tNiV){9C!ogXgoG*^%a-vrIS)?^N`8Z70NlCw3-<}Ikkkp~1tnCrS>Qrmm zVzq_02R2~~GnW+{p|?ywkFf0k<2hy9`TjTFd(YQ~DUBv_X-p3O{l%vI;T04I=>Grzf&05Wuy?>a(76LacWt4@mhN(IJyWs^?}T{X#FHIN7mLV?;Dt%peZC!! zzp(G`DS1zQB=LD9@5LhW;#iIs$0&C5_x+y%xR*fJN Date: Wed, 30 Oct 2024 11:13:50 +0100 Subject: [PATCH 8/8] updated pr to newest hal mock --- src/epd2in13b_v4/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/epd2in13b_v4/mod.rs b/src/epd2in13b_v4/mod.rs index 79749d67..5bedea9a 100644 --- a/src/epd2in13b_v4/mod.rs +++ b/src/epd2in13b_v4/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