From 96d505647d5b668fef7ea7cf364a209c1bcb7892 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Sun, 15 Nov 2020 03:25:10 -0800 Subject: [PATCH 01/80] Add support for ep5in65f --- Cargo.toml | 2 +- src/color.rs | 74 ++++++++++++ src/epd1in54/mod.rs | 1 + src/epd1in54b/mod.rs | 1 + src/epd2in13_v2/mod.rs | 1 + src/epd2in9/mod.rs | 1 + src/epd2in9bc/mod.rs | 1 + src/epd4in2/mod.rs | 1 + src/epd5in65f/command.rs | 151 +++++++++++++++++++++++ src/epd5in65f/graphics.rs | 173 ++++++++++++++++++++++++++ src/epd5in65f/mod.rs | 247 ++++++++++++++++++++++++++++++++++++++ src/epd7in5/mod.rs | 1 + src/epd7in5_v2/mod.rs | 1 + src/graphics.rs | 80 +++++++++++- src/lib.rs | 2 + src/traits.rs | 7 +- 16 files changed, 736 insertions(+), 8 deletions(-) create mode 100644 src/epd5in65f/command.rs create mode 100644 src/epd5in65f/graphics.rs create mode 100644 src/epd5in65f/mod.rs diff --git a/Cargo.toml b/Cargo.toml index fb127c6..5d69b64 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,7 @@ license = "ISC" name = "epd-waveshare" readme = "README.md" repository = "https://github.com/Caemor/epd-waveshare.git" -version = "0.4.0" +version = "0.5.0" edition = "2018" [badges] diff --git a/src/color.rs b/src/color.rs index a1e5ec7..ee446da 100644 --- a/src/color.rs +++ b/src/color.rs @@ -2,6 +2,8 @@ #[cfg(feature = "graphics")] use embedded_graphics::pixelcolor::BinaryColor; +#[cfg(feature = "graphics")] +use embedded_graphics::pixelcolor::PixelColor; #[cfg(feature = "graphics")] pub use BinaryColor::Off as White; @@ -28,6 +30,78 @@ pub enum TriColor { Chromatic, } +/// For the 5in65 8 Color Display +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum OctColor { + /// Black Color + Black = 0x00, + /// White Color + White = 0x01, + /// Green Color + Green = 0x02, + /// Blue Color + Blue = 0x03, + /// Red Color + Red = 0x04, + /// Yellow Color + Yellow = 0x05, + /// Orange Color + Orange = 0x06, +} + +impl From<()> for OctColor { + fn from(_: ()) -> OctColor { + OctColor::White + } +} + +#[cfg(feature = "graphics")] +impl PixelColor for OctColor { + type Raw = (); +} + +impl OctColor { + /// Gets the Nibble representation of the Color as needed by the display + pub fn get_nibble(self) -> u8 { + self as u8 + } + /// Converts two colors into a single byte for the Display + pub fn colors_byte(a: OctColor, b: OctColor) -> u8 { + a.get_nibble() << 4 | b.get_nibble() + } + + ///Take the nibble (lower 4 bits) and convert to an OctColor if possible + pub fn from_nibble(nibble: u8) -> Result { + match nibble & 0xf { + 0x00 => Ok(OctColor::Black), + 0x01 => Ok(OctColor::White), + 0x02 => Ok(OctColor::Green), + 0x03 => Ok(OctColor::Blue), + 0x04 => Ok(OctColor::Red), + 0x05 => Ok(OctColor::Yellow), + 0x06 => Ok(OctColor::Orange), + _ => Err(()) + } + } + ///Split the nibbles of a single byte and convert both to an OctColor if possible + pub fn split_byte(byte: u8) -> Result<(OctColor, OctColor), ()> { + let low = OctColor::from_nibble(byte & 0xf)?; + let high = OctColor::from_nibble((byte >> 4) & 0xf)?; + Ok((high, low)) + } + /// Converts to limited range of RGB values. + pub fn rgb(self) -> (u8, u8, u8) { + match self { + OctColor::White => (0xff, 0xff, 0xff), + OctColor::Black => (0x00, 0x00, 0x00), + OctColor::Green => (0x00, 0xff, 0x00), + OctColor::Blue => (0x00, 0x00, 0xff), + OctColor::Red => (0xff, 0x00, 0x00), + OctColor::Yellow => (0xff, 0xff, 0x00), + OctColor::Orange => (0xff, 0x80, 0x00), + } + } +} //TODO: Rename get_bit_value to bit() and get_byte_value to byte() ? impl Color { diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index e4f833f..66420ea 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -151,6 +151,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn width(&self) -> u32 { WIDTH } diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 11fd985..c14050e 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -142,6 +142,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index b636c9f..704d262 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -166,6 +166,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 46a9155..d2fbabb 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -147,6 +147,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn width(&self) -> u32 { WIDTH } diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 9bab93b..300352c 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -197,6 +197,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 8894132..a3a972b 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -148,6 +148,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/epd5in65f/command.rs b/src/epd5in65f/command.rs new file mode 100644 index 0000000..54c4ac2 --- /dev/null +++ b/src/epd5in65f/command.rs @@ -0,0 +1,151 @@ +//! SPI Commands for the Waveshare 7.5" E-Ink Display + +use crate::traits; + +/// EPD6in65f 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)] +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift + /// direction, booster switch, soft reset. + PANEL_SETTING = 0x00, + + /// Selecting internal and external power + POWER_SETTING = 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. + POWER_OFF = 0x02, + + /// Setting Power OFF sequence + POWER_OFF_SEQUENCE_SETTING = 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". + POWER_ON = 0x04, + + /// Starting data transmission + BOOSTER_SOFT_START = 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. + DEEP_SLEEP = 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 + DATA_START_TRANSMISSION_1 = 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. + DATA_STOP = 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. + DISPLAY_REFRESH = 0x12, + + /// Image Process Command + IMAGE_PROCESS_COMMAND = 0x13, + + /// This command builds the VCOM Look-Up Table (LUTC). + LUT_FOR_VCOM = 0x20, + /// This command builds the Black Look-Up Table (LUTB). + LUT_BLACK = 0x21, + /// This command builds the White Look-Up Table (LUTW). + LUT_WHITE = 0x22, + /// This command builds the Gray1 Look-Up Table (LUTG1). + LUT_GRAY_1 = 0x23, + /// This command builds the Gray2 Look-Up Table (LUTG2). + LUT_GRAY_2 = 0x24, + /// This command builds the Red0 Look-Up Table (LUTR0). + LUT_RED_0 = 0x25, + /// This command builds the Red1 Look-Up Table (LUTR1). + LUT_RED_1 = 0x26, + /// This command builds the Red2 Look-Up Table (LUTR2). + LUT_RED_2 = 0x27, + /// This command builds the Red3 Look-Up Table (LUTR3). + LUT_RED_3 = 0x28, + /// This command builds the XON Look-Up Table (LUTXON). + LUT_XON = 0x29, + + /// The command controls the PLL clock frequency. + PLL_CONTROL = 0x30, + + /// This command reads the temperature sensed by the temperature sensor. + TEMPERATURE_SENSOR_COMMAND = 0x40, + /// This command selects the Internal or External temperature sensor. + TEMPERATURE_CALIBRATION = 0x41, + /// This command could write data to the external temperature sensor. + TEMPERATURE_SENSOR_WRITE = 0x42, + /// This command could read data from the external temperature sensor. + TEMPERATURE_SENSOR_READ = 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). + VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn + /// the battery condition. + LOW_POWER_DETECTION = 0x51, + + /// This command defines non-overlap period of Gate and Source. + TCON_SETTING = 0x60, + /// This command defines alternative resolution and this setting is of higher priority + /// than the RES\[1:0\] in R00H (PSR). + TCON_RESOLUTION = 0x61, + /// This command defines MCU host direct access external memory mode. + //SPI_FLASH_CONTROL = 0x65, + + /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. + //REVISION = 0x70, + /// This command reads the IC status. + GET_STATUS = 0x71, + + /// This command implements related VCOM sensing setting. + //AUTO_MEASUREMENT_VCOM = 0x80, + /// This command gets the VCOM value. + READ_VCOM_VALUE = 0x81, + /// This command sets `VCOM_DC` value. + VCM_DC_SETTING = 0x82, + // /// This is in all the Waveshare controllers for EPD6in65f, but it's not documented + // /// anywhere in the datasheet `¯\_(ツ)_/¯` + FLASH_MODE = 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::PANEL_SETTING.address(), 0x00); + assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + } +} diff --git a/src/epd5in65f/graphics.rs b/src/epd5in65f/graphics.rs new file mode 100644 index 0000000..9ec124c --- /dev/null +++ b/src/epd5in65f/graphics.rs @@ -0,0 +1,173 @@ +use crate::epd5in65f::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; +use crate::graphics::{OctDisplay, DisplayRotation}; +use embedded_graphics::prelude::*; +use crate::color::OctColor; + +/// Full size buffer for use with the 5in65f EPD +/// +/// Can also be manually constructed: +/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 2 * HEIGHT]` +pub struct Display5in65f { + buffer: [u8; WIDTH as usize * HEIGHT as usize / 2], + rotation: DisplayRotation, +} + +impl Default for Display5in65f { + fn default() -> Self { + Display5in65f { + buffer: [OctColor::colors_byte(DEFAULT_BACKGROUND_COLOR, DEFAULT_BACKGROUND_COLOR); + WIDTH as usize * HEIGHT as usize / 2], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display5in65f { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl OctDisplay for Display5in65f { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::epd5in65f; + use crate::graphics::{OctDisplay, DisplayRotation}; + use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + + // test buffer length + #[test] + fn graphics_size() { + let display = Display5in65f::default(); + assert_eq!(display.buffer().len(), 448*600 / 2); + } + + // test default background color on all bytes + #[test] + fn graphics_default() { + let display = Display5in65f::default(); + for &byte in display.buffer() { + assert_eq!(byte, OctColor::colors_byte( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR, + )); + } + } + + #[test] + fn graphics_rotation_0() { + let mut display = Display5in65f::default(); + + let _ = Line::new(Point::new(0, 0), Point::new(1, 0)) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + for &byte in buffer.iter().take(1) { + assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + } + + for &byte in buffer.iter().skip(1) { + assert_eq!( + OctColor::split_byte(byte), + Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + ); + } + } + + #[test] + fn graphics_rotation_90() { + let mut display = Display5in65f::default(); + display.set_rotation(DisplayRotation::Rotate90); + + let _ = Line::new(Point::new(0, WIDTH as i32 - 2), Point::new(0, WIDTH as i32- 1)) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + for &byte in buffer.iter().take(1) { + assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + } + + for &byte in buffer.iter().skip(1) { + assert_eq!( + OctColor::split_byte(byte), + Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + ); + } + } + + #[test] + fn graphics_rotation_180() { + let mut display = Display5in65f::default(); + display.set_rotation(DisplayRotation::Rotate180); + + let _ = Line::new(Point::new(WIDTH as i32 - 2, HEIGHT as i32 - 1), + Point::new(WIDTH as i32 - 1, HEIGHT as i32 - 1)) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + for &byte in buffer.iter().take(1) { + assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + } + + for &byte in buffer.iter().skip(1) { + assert_eq!( + OctColor::split_byte(byte), + Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + ); + } + } + + #[test] + fn graphics_rotation_270() { + let mut display = Display5in65f::default(); + display.set_rotation(DisplayRotation::Rotate270); + + let _ = Line::new(Point::new(HEIGHT as i32 -1, 0), + Point::new(HEIGHT as i32 -1, 1)) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + for &byte in buffer.iter().take(1) { + assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + } + + for &byte in buffer.iter().skip(1) { + assert_eq!( + OctColor::split_byte(byte), + Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + ); + } + } +} diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs new file mode 100644 index 0000000..59fa103 --- /dev/null +++ b/src/epd5in65f/mod.rs @@ -0,0 +1,247 @@ +//! A simple Driver for the Waveshare 6.65 inch (F) E-Ink Display via SPI +//! +//! # References +//! +//! - [Datasheet](https://www.waveshare.com/wiki/5.65inch_e-Paper_Module_(F)) +//! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_5in65f.c) +//! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) + + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::{InputPin, OutputPin}, +}; + +use crate::color::OctColor; +use crate::interface::DisplayInterface; +use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; + +pub(crate) mod command; +use self::command::Command; + +#[cfg(feature = "graphics")] +mod graphics; +#[cfg(feature = "graphics")] +pub use self::graphics::Display5in65f; + +/// Width of the display +pub const WIDTH: u32 = 600; +/// Height of the display +pub const HEIGHT: u32 = 448; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White; +const IS_BUSY_LOW: bool = false; + +/// EPD5in65f driver +/// +pub struct EPD5in65f { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: OctColor, +} + +impl InternalWiAdditions + for EPD5in65f +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn init>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + // Reset the device + self.interface.reset(delay, 2); + + self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xEF, 0x08])?; + self.cmd_with_data(spi, Command::POWER_SETTING, &[0x37, 0x00, 0x23, 0x23])?; + self.cmd_with_data(spi, Command::POWER_OFF_SEQUENCE_SETTING, &[0x00])?; + self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0xC7, 0xC7, 0x1D])?; + self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3C])?; + self.cmd_with_data(spi, Command::TEMPERATURE_SENSOR_COMMAND, &[0x00])?; + self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; + self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?; + self.send_resolution(spi)?; + + self.cmd_with_data(spi, Command::FLASH_MODE, &[0xAA])?; + + delay.delay_ms(100); + + self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; + Ok(()) + } +} + +impl WaveshareDisplay + for EPD5in65f +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + type DisplayColor = OctColor; + fn new>( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = EPD5in65f { 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) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + Ok(()) + } + + fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, buffer)?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + _spi: &mut SPI, + _buffer: &[u8], + _x: u32, + _y: u32, + _width: u32, + _height: u32, + ) -> Result<(), SPI::Error> { + unimplemented!(); + } + + fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.command(spi, Command::POWER_ON)?; + self.wait_busy_high(); + self.command(spi, Command::DISPLAY_REFRESH)?; + self.wait_busy_high(); + self.command(spi, Command::POWER_OFF)?; + self.wait_busy_low(); + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let bg = 0x77; /*clear frame */ //OctColor::colors_byte(self.color, self.color); + + self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; + + self.display_frame(spi)?; + Ok(()) + } + + fn set_background_color(&mut self, color: OctColor) { + self.color = color; + } + + fn background_color(&self) -> &OctColor { + &self.color + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + unimplemented!(); + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl EPD5in65f +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + 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 wait_busy_high(&mut self) { + self.interface.wait_until_idle(true) + } + fn wait_busy_low(&mut self) { + self.interface.wait_until_idle(false) + } + + fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.command(spi, Command::TCON_RESOLUTION)?; + 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, 600); + assert_eq!(HEIGHT, 448); + assert_eq!(DEFAULT_BACKGROUND_COLOR, OctColor::White); + } +} diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index cdc142e..883deb3 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -108,6 +108,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 3c0fcc4..67f9dab 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -90,6 +90,7 @@ where DC: OutputPin, RST: OutputPin, { + type DisplayColor = Color; fn new>( spi: &mut SPI, cs: CS, diff --git a/src/graphics.rs b/src/graphics.rs index e378a64..524e550 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,7 +1,7 @@ //! Graphics Support for EPDs use crate::buffer_len; -use crate::color::Color; +use crate::color::{OctColor, Color}; use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; /// Displayrotation @@ -85,6 +85,64 @@ pub trait Display: DrawTarget { } } +/// Necessary traits for all displays to implement for drawing +/// +/// Adds support for: +/// - Drawing (With the help of DrawTarget/Embedded Graphics) +/// - Rotations +/// - Clearing +pub trait OctDisplay: DrawTarget { + /// Clears the buffer of the display with the chosen background color + fn clear_buffer(&mut self, background_color: Color) { + for elem in self.get_mut_buffer().iter_mut() { + *elem = background_color.get_byte_value(); + } + } + + /// Returns the buffer + fn buffer(&self) -> &[u8]; + + /// Returns a mutable buffer + fn get_mut_buffer(&mut self) -> &mut [u8]; + + /// Sets the rotation of the display + fn set_rotation(&mut self, rotation: DisplayRotation); + + /// Get the current rotation of the display + fn rotation(&self) -> DisplayRotation; + + /// Helperfunction for the Embedded Graphics draw trait + /// + /// Becomes uneccesary when const_generics become stablised + fn draw_helper( + &mut self, + width: u32, + height: u32, + pixel: Pixel, + ) -> Result<(), Self::Error> { + let rotation = self.rotation(); + let buffer = self.get_mut_buffer(); + + let Pixel(point, color) = pixel; + if outside_display(point, width, height, rotation) { + return Ok(()); + } + + // Give us index inside the buffer and the bit-position in that u8 which needs to be changed + let (index, upper) = find_oct_position(point.x as u32, point.y as u32, width, height, rotation); + let index = index as usize; + + // "Draw" the Pixel on that bit + let (mask, color_nibble) = if upper { + (0x0f, color.get_nibble() << 4) + } else { + (0xf0, color.get_nibble()) + }; + buffer[index] = (buffer[index] & mask) | color_nibble; + Ok(()) + } +} + /// A variable Display without a predefined buffer /// /// The buffer can be created as following: @@ -186,9 +244,7 @@ fn outside_display(p: Point, width: u32, height: u32, rotation: DisplayRotation) false } -#[rustfmt::skip] -//returns index position in the u8-slice and the bit-position inside that u8 -fn find_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> (u32, u8) { +fn find_rotation(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> (u32, u32) { let nx; let ny; match rotation { @@ -209,7 +265,23 @@ fn find_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotat ny = height - 1 - x; }, } + (nx, ny) +} +#[rustfmt::skip] +//returns index position in the u8-slice and the bit-position inside that u8 +fn find_oct_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> (u32, bool) { + let (nx, ny) = find_rotation(x, y, width, height, rotation); + ( + nx / 2 + (width / 2) * ny, + (nx & 0x1) == 0, + ) +} + +#[rustfmt::skip] +//returns index position in the u8-slice and the bit-position inside that u8 +fn find_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> (u32, u8) { + let (nx, ny) = find_rotation(x, y, width, height, rotation); ( nx / 8 + ((width + 7) / 8) * ny, 0x80 >> (nx % 8), diff --git a/src/lib.rs b/src/lib.rs index 6c4b94b..4685308 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -80,6 +80,8 @@ pub mod epd2in9bc; pub mod epd4in2; pub mod epd7in5; pub mod epd7in5_v2; +pub mod epd5in65f; + pub(crate) mod type_a; /// Includes everything important besides the chosen Display diff --git a/src/traits.rs b/src/traits.rs index 360e63c..9b5aa01 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -1,4 +1,3 @@ -use crate::color::Color; use core::marker::Sized; use embedded_hal::{ blocking::{delay::*, spi::Write}, @@ -136,6 +135,8 @@ where DC: OutputPin, RST: OutputPin, { + /// The Color Type used by the Display + type DisplayColor; /// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC /// /// This already initialises the device. @@ -165,10 +166,10 @@ where ) -> Result<(), SPI::Error>; /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame) - fn set_background_color(&mut self, color: Color); + fn set_background_color(&mut self, color: Self::DisplayColor); /// Get current background color - fn background_color(&self) -> &Color; + fn background_color(&self) -> &Self::DisplayColor; /// Get the width of the display fn width(&self) -> u32; From c7d32ca86ea4d2557929146108184c84d4872ba3 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Sun, 15 Nov 2020 05:32:17 -0800 Subject: [PATCH 02/80] Added some busy checks and seem to be avoiding missing pictures --- src/epd5in65f/mod.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 59fa103..1ccb4ff 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -30,7 +30,7 @@ pub const WIDTH: u32 = 600; pub const HEIGHT: u32 = 448; /// Default Background Color pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White; -const IS_BUSY_LOW: bool = false; +const IS_BUSY_LOW: bool = true; /// EPD5in65f driver /// @@ -119,6 +119,8 @@ where } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_busy_high(); + self.send_resolution(spi)?; self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, buffer)?; Ok(()) } @@ -136,6 +138,7 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_busy_high(); self.command(spi, Command::POWER_ON)?; self.wait_busy_high(); self.command(spi, Command::DISPLAY_REFRESH)?; @@ -153,10 +156,10 @@ where fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let bg = 0x77; /*clear frame */ //OctColor::colors_byte(self.color, self.color); - + self.wait_busy_high(); + self.send_resolution(spi)?; self.command(spi, Command::DATA_START_TRANSMISSION_1)?; - self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; - + self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; self.display_frame(spi)?; Ok(()) } @@ -221,7 +224,6 @@ where fn wait_busy_low(&mut self) { self.interface.wait_until_idle(false) } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); From 231cc63009b7383b24e26e9f478cfdeef7d63a7e Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Sun, 15 Nov 2020 17:57:40 -0800 Subject: [PATCH 03/80] Minor cleanup, added HiZ as color --- src/color.rs | 6 +++++- src/epd5in65f/mod.rs | 2 +- src/lib.rs | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/color.rs b/src/color.rs index ee446da..c8bd818 100644 --- a/src/color.rs +++ b/src/color.rs @@ -30,7 +30,7 @@ pub enum TriColor { Chromatic, } -/// For the 5in65 8 Color Display +/// For the 5in65 7 Color Display #[derive(Clone, Copy, PartialEq, Debug)] pub enum OctColor { /// Black Color @@ -47,6 +47,8 @@ pub enum OctColor { Yellow = 0x05, /// Orange Color Orange = 0x06, + /// HiZ / Clean Color + HiZ = 0x07, } impl From<()> for OctColor { @@ -80,6 +82,7 @@ impl OctColor { 0x04 => Ok(OctColor::Red), 0x05 => Ok(OctColor::Yellow), 0x06 => Ok(OctColor::Orange), + 0x07 => Ok(OctColor::HiZ), _ => Err(()) } } @@ -99,6 +102,7 @@ impl OctColor { OctColor::Red => (0xff, 0x00, 0x00), OctColor::Yellow => (0xff, 0xff, 0x00), OctColor::Orange => (0xff, 0x80, 0x00), + OctColor::HiZ => (0x80, 0x80, 0x80), /* looks greyish */ } } } diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 1ccb4ff..fb80fb7 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -155,7 +155,7 @@ where } fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - let bg = 0x77; /*clear frame */ //OctColor::colors_byte(self.color, self.color); + let bg = OctColor::colors_byte(self.color, self.color); self.wait_busy_high(); self.send_resolution(spi)?; self.command(spi, Command::DATA_START_TRANSMISSION_1)?; diff --git a/src/lib.rs b/src/lib.rs index 4685308..94f275e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -86,13 +86,13 @@ pub(crate) mod type_a; /// Includes everything important besides the chosen Display pub mod prelude { - pub use crate::color::{Color, TriColor}; + pub use crate::color::{Color, TriColor, OctColor}; pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay}; pub use crate::SPI_MODE; #[cfg(feature = "graphics")] - pub use crate::graphics::{Display, DisplayRotation}; + pub use crate::graphics::{OctDisplay, Display, DisplayRotation}; } /// Computes the needed buffer length. Takes care of rounding up in case width From 147eaf655d3a1ba2b819bb7816134e9303dfe12d Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Sun, 15 Nov 2020 18:01:45 -0800 Subject: [PATCH 04/80] Updated README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 0ce9a23..93e177d 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,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 | ✕ | ✔ | ✔ | ✔ | | [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 | ✕ | ✕ | ✔ | ✔ | | [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 | ✕ | ✕ | ✔ | ✔ | + ### [1]: 7.5 Inch B/W V2 (A) From e225464b62809ade7edd301d6daa30a557b5ae37 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Sun, 15 Nov 2020 18:11:58 -0800 Subject: [PATCH 05/80] Cargo fmt --- src/color.rs | 4 +- src/epd5in65f/command.rs | 2 +- src/epd5in65f/graphics.rs | 92 +++++++++++++++++++++++++++------------ src/epd5in65f/mod.rs | 7 ++- src/graphics.rs | 13 +++--- src/lib.rs | 6 +-- 6 files changed, 79 insertions(+), 45 deletions(-) diff --git a/src/color.rs b/src/color.rs index c8bd818..b9388c7 100644 --- a/src/color.rs +++ b/src/color.rs @@ -2,7 +2,7 @@ #[cfg(feature = "graphics")] use embedded_graphics::pixelcolor::BinaryColor; -#[cfg(feature = "graphics")] +#[cfg(feature = "graphics")] use embedded_graphics::pixelcolor::PixelColor; #[cfg(feature = "graphics")] @@ -83,7 +83,7 @@ impl OctColor { 0x05 => Ok(OctColor::Yellow), 0x06 => Ok(OctColor::Orange), 0x07 => Ok(OctColor::HiZ), - _ => Err(()) + _ => Err(()), } } ///Split the nibbles of a single byte and convert both to an OctColor if possible diff --git a/src/epd5in65f/command.rs b/src/epd5in65f/command.rs index 54c4ac2..5035bb8 100644 --- a/src/epd5in65f/command.rs +++ b/src/epd5in65f/command.rs @@ -66,7 +66,7 @@ pub(crate) enum Command { /// Image Process Command IMAGE_PROCESS_COMMAND = 0x13, - + /// This command builds the VCOM Look-Up Table (LUTC). LUT_FOR_VCOM = 0x20, /// This command builds the Black Look-Up Table (LUTB). diff --git a/src/epd5in65f/graphics.rs b/src/epd5in65f/graphics.rs index 9ec124c..2a52b15 100644 --- a/src/epd5in65f/graphics.rs +++ b/src/epd5in65f/graphics.rs @@ -1,7 +1,7 @@ +use crate::color::OctColor; use crate::epd5in65f::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; -use crate::graphics::{OctDisplay, DisplayRotation}; +use crate::graphics::{DisplayRotation, OctDisplay}; use embedded_graphics::prelude::*; -use crate::color::OctColor; /// Full size buffer for use with the 5in65f EPD /// @@ -56,14 +56,14 @@ impl OctDisplay for Display5in65f { mod tests { use super::*; use crate::epd5in65f; - use crate::graphics::{OctDisplay, DisplayRotation}; + use crate::graphics::{DisplayRotation, OctDisplay}; use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; // test buffer length #[test] fn graphics_size() { let display = Display5in65f::default(); - assert_eq!(display.buffer().len(), 448*600 / 2); + assert_eq!(display.buffer().len(), 448 * 600 / 2); } // test default background color on all bytes @@ -71,10 +71,13 @@ mod tests { fn graphics_default() { let display = Display5in65f::default(); for &byte in display.buffer() { - assert_eq!(byte, OctColor::colors_byte( - epd5in65f::DEFAULT_BACKGROUND_COLOR, - epd5in65f::DEFAULT_BACKGROUND_COLOR, - )); + assert_eq!( + byte, + OctColor::colors_byte( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR, + ) + ); } } @@ -87,15 +90,21 @@ mod tests { .draw(&mut display); let buffer = display.buffer(); - + for &byte in buffer.iter().take(1) { - assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + assert_eq!( + OctColor::split_byte(byte), + Ok((OctColor::Black, OctColor::Black)) + ); } for &byte in buffer.iter().skip(1) { assert_eq!( OctColor::split_byte(byte), - Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + Ok(( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR + )) ); } } @@ -105,20 +114,29 @@ mod tests { let mut display = Display5in65f::default(); display.set_rotation(DisplayRotation::Rotate90); - let _ = Line::new(Point::new(0, WIDTH as i32 - 2), Point::new(0, WIDTH as i32- 1)) - .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) - .draw(&mut display); + let _ = Line::new( + Point::new(0, WIDTH as i32 - 2), + Point::new(0, WIDTH as i32 - 1), + ) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); let buffer = display.buffer(); for &byte in buffer.iter().take(1) { - assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + assert_eq!( + OctColor::split_byte(byte), + Ok((OctColor::Black, OctColor::Black)) + ); } for &byte in buffer.iter().skip(1) { assert_eq!( OctColor::split_byte(byte), - Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + Ok(( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR + )) ); } } @@ -128,21 +146,29 @@ mod tests { let mut display = Display5in65f::default(); display.set_rotation(DisplayRotation::Rotate180); - let _ = Line::new(Point::new(WIDTH as i32 - 2, HEIGHT as i32 - 1), - Point::new(WIDTH as i32 - 1, HEIGHT as i32 - 1)) - .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) - .draw(&mut display); + let _ = Line::new( + Point::new(WIDTH as i32 - 2, HEIGHT as i32 - 1), + Point::new(WIDTH as i32 - 1, HEIGHT as i32 - 1), + ) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); let buffer = display.buffer(); - + for &byte in buffer.iter().take(1) { - assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + assert_eq!( + OctColor::split_byte(byte), + Ok((OctColor::Black, OctColor::Black)) + ); } for &byte in buffer.iter().skip(1) { assert_eq!( OctColor::split_byte(byte), - Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + Ok(( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR + )) ); } } @@ -152,21 +178,29 @@ mod tests { let mut display = Display5in65f::default(); display.set_rotation(DisplayRotation::Rotate270); - let _ = Line::new(Point::new(HEIGHT as i32 -1, 0), - Point::new(HEIGHT as i32 -1, 1)) - .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) - .draw(&mut display); + let _ = Line::new( + Point::new(HEIGHT as i32 - 1, 0), + Point::new(HEIGHT as i32 - 1, 1), + ) + .into_styled(PrimitiveStyle::with_stroke(OctColor::Black, 1)) + .draw(&mut display); let buffer = display.buffer(); for &byte in buffer.iter().take(1) { - assert_eq!(OctColor::split_byte(byte), Ok((OctColor::Black, OctColor::Black))); + assert_eq!( + OctColor::split_byte(byte), + Ok((OctColor::Black, OctColor::Black)) + ); } for &byte in buffer.iter().skip(1) { assert_eq!( OctColor::split_byte(byte), - Ok((epd5in65f::DEFAULT_BACKGROUND_COLOR, epd5in65f::DEFAULT_BACKGROUND_COLOR)) + Ok(( + epd5in65f::DEFAULT_BACKGROUND_COLOR, + epd5in65f::DEFAULT_BACKGROUND_COLOR + )) ); } } diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index fb80fb7..d10dddc 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -6,7 +6,6 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_5in65f.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd5in65f.py) - use embedded_hal::{ blocking::{delay::*, spi::Write}, digital::v2::{InputPin, OutputPin}, @@ -69,9 +68,9 @@ where self.send_resolution(spi)?; self.cmd_with_data(spi, Command::FLASH_MODE, &[0xAA])?; - + delay.delay_ms(100); - + self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; Ok(()) } @@ -159,7 +158,7 @@ where self.wait_busy_high(); self.send_resolution(spi)?; self.command(spi, Command::DATA_START_TRANSMISSION_1)?; - self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; + self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; self.display_frame(spi)?; Ok(()) } diff --git a/src/graphics.rs b/src/graphics.rs index 524e550..f9aac40 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,7 +1,7 @@ //! Graphics Support for EPDs use crate::buffer_len; -use crate::color::{OctColor, Color}; +use crate::color::{Color, OctColor}; use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; /// Displayrotation @@ -129,7 +129,8 @@ pub trait OctDisplay: DrawTarget { } // Give us index inside the buffer and the bit-position in that u8 which needs to be changed - let (index, upper) = find_oct_position(point.x as u32, point.y as u32, width, height, rotation); + let (index, upper) = + find_oct_position(point.x as u32, point.y as u32, width, height, rotation); let index = index as usize; // "Draw" the Pixel on that bit @@ -251,19 +252,19 @@ fn find_rotation(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotat DisplayRotation::Rotate0 => { nx = x; ny = y; - }, + } DisplayRotation::Rotate90 => { nx = width - 1 - y; ny = x; - } , + } DisplayRotation::Rotate180 => { nx = width - 1 - x; ny = height - 1 - y; - }, + } DisplayRotation::Rotate270 => { nx = y; ny = height - 1 - x; - }, + } } (nx, ny) } diff --git a/src/lib.rs b/src/lib.rs index 94f275e..175dc01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,21 +78,21 @@ pub mod epd2in13_v2; pub mod epd2in9; pub mod epd2in9bc; pub mod epd4in2; +pub mod epd5in65f; pub mod epd7in5; pub mod epd7in5_v2; -pub mod epd5in65f; pub(crate) mod type_a; /// Includes everything important besides the chosen Display pub mod prelude { - pub use crate::color::{Color, TriColor, OctColor}; + pub use crate::color::{Color, OctColor, TriColor}; pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay}; pub use crate::SPI_MODE; #[cfg(feature = "graphics")] - pub use crate::graphics::{OctDisplay, Display, DisplayRotation}; + pub use crate::graphics::{Display, DisplayRotation, OctDisplay}; } /// Computes the needed buffer length. Takes care of rounding up in case width From e49e144a348c055c2b335dc275b821d0d8637a54 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Thu, 19 Nov 2020 19:22:41 -0800 Subject: [PATCH 06/80] Minor fixups --- src/color.rs | 10 +++++++++ src/epd5in65f/graphics.rs | 44 +++++++++++++++++++++++++++++++++++++++ src/graphics.rs | 6 ++++-- 3 files changed, 58 insertions(+), 2 deletions(-) diff --git a/src/color.rs b/src/color.rs index b9388c7..6767673 100644 --- a/src/color.rs +++ b/src/color.rs @@ -185,4 +185,14 @@ mod tests { assert_eq!(Color::from(Color::White.get_bit_value()), Color::White); assert_eq!(Color::from(1u8).get_bit_value(), 1u8); } + + #[test] + fn test_oct() { + let left = OctColor::Red; + let right = OctColor::Green; + assert_eq!( + OctColor::split_byte(OctColor::colors_byte(left, right)), + Ok((left, right)) + ); + } } diff --git a/src/epd5in65f/graphics.rs b/src/epd5in65f/graphics.rs index 2a52b15..d21f8e8 100644 --- a/src/epd5in65f/graphics.rs +++ b/src/epd5in65f/graphics.rs @@ -204,4 +204,48 @@ mod tests { ); } } + + #[test] + fn graphics_colors() { + let mut display = Display5in65f::default(); + + const COLORS: [OctColor; 8] = [ + OctColor::HiZ, + OctColor::White, + OctColor::Black, + OctColor::Red, + OctColor::Green, + OctColor::Orange, + OctColor::Blue, + OctColor::Yellow, + ]; + for c in &COLORS { + display.clear_buffer(*c); + for b in display.buffer() { + assert_eq!(OctColor::split_byte(*b), Ok((*c, *c))); + } + } + + for (w, c) in (0..WIDTH).zip(COLORS.iter().cycle()) { + let _ = Line::new( + Point::new(w as i32, 0), + Point::new(w as i32, HEIGHT as i32 - 1), + ) + .into_styled(PrimitiveStyle::with_stroke(*c, 1)) + .draw(&mut display); + } + + COLORS + .chunks(2) + .cycle() + .take(WIDTH as usize * 2) + .cycle() + .zip(display.buffer()) + .for_each(|(window, b)| match (window, b) { + (&[c1, c2], b) => { + assert_eq!(OctColor::split_byte(*b), Ok((c1, c2))); + } + _ => panic!("unexpected pattern"), + }) + } } diff --git a/src/graphics.rs b/src/graphics.rs index f9aac40..c7b752e 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -93,9 +93,9 @@ pub trait Display: DrawTarget { /// - Clearing pub trait OctDisplay: DrawTarget { /// Clears the buffer of the display with the chosen background color - fn clear_buffer(&mut self, background_color: Color) { + fn clear_buffer(&mut self, background_color: OctColor) { for elem in self.get_mut_buffer().iter_mut() { - *elem = background_color.get_byte_value(); + *elem = OctColor::colors_byte(background_color, background_color); } } @@ -274,7 +274,9 @@ fn find_rotation(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotat fn find_oct_position(x: u32, y: u32, width: u32, height: u32, rotation: DisplayRotation) -> (u32, bool) { let (nx, ny) = find_rotation(x, y, width, height, rotation); ( + /* what byte address is this? */ nx / 2 + (width / 2) * ny, + /* is this the lower nibble (within byte)? */ (nx & 0x1) == 0, ) } From fb25c40fe2ebcd2f2ee7697e993361571a17e12f Mon Sep 17 00:00:00 2001 From: pjsier Date: Fri, 1 Jan 2021 09:51:30 -0600 Subject: [PATCH 07/80] add support for epd2in7b --- src/epd2in7b/command.rs | 138 ++++++++++++ src/epd2in7b/constants.rs | 55 +++++ src/epd2in7b/graphics.rs | 163 ++++++++++++++ src/epd2in7b/mod.rs | 456 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 5 files changed, 813 insertions(+) create mode 100644 src/epd2in7b/command.rs create mode 100644 src/epd2in7b/constants.rs create mode 100644 src/epd2in7b/graphics.rs create mode 100644 src/epd2in7b/mod.rs diff --git a/src/epd2in7b/command.rs b/src/epd2in7b/command.rs new file mode 100644 index 0000000..d478ce7 --- /dev/null +++ b/src/epd2in7b/command.rs @@ -0,0 +1,138 @@ +//! SPI Commands for the Waveshare 2.7" B 3 color E-Ink Display +use crate::traits; + +/// EPD2IN7B commands +/// +/// More information can be found in the [specification](https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf) +#[allow(dead_code)] +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset + PANEL_SETTING = 0x00, + /// Selecting internal and external power + POWER_SETTING = 0x01, + POWER_OFF = 0x02, + /// Setting Power OFF sequence + POWER_OFF_SEQUENCE_SETTING = 0x03, + POWER_ON = 0x04, + /// This command enables the internal bandgap, which will be cleared by the next POF. + POWER_ON_MEASURE = 0x05, + /// Starting data transmission + /// + /// ```ignore + /// self.send_data(&[0x07, 0x07, 0x17])?; + /// ``` + BOOSTER_SOFT_START = 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. + DEEP_SLEEP = 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. + DATA_START_TRANSMISSION_1 = 0x10, + /// Stopping data transmission + DATA_STOP = 0x11, + /// After this command is issued, driver will refresh display (data/VCOM) according to SRAM data and LUT. + DISPLAY_REFRESH = 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. + DATA_START_TRANSMISSION_2 = 0x13, + /// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission + /// complete, user must send command DSP (Data transmission Stop). Then 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. + PARTIAL_DATA_START_TRANSMISSION_1 = 0x14, + /// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission + /// complete, user must send command DSP (Data transmission Stop). Then 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. + PARTIAL_DATA_START_TRANSMISSION_2 = 0x15, + /// While user sent this command, driver will refresh display (data/VCOM) base on SRAM data and LUT. + /// + /// Only the area (X,Y, W, L) would update, the others pixel output would follow VCOM LUT + PARTIAL_DISPLAY_REFRESH = 0x16, + /// This command builds the Look-up table for VCOM + LUT_FOR_VCOM = 0x20, + LUT_WHITE_TO_WHITE = 0x21, + LUT_BLACK_TO_WHITE = 0x22, + LUT_WHITE_TO_BLACK = 0x23, + LUT_BLACK_TO_BLACK = 0x24, + /// The command controls the PLL clock frequency. + PLL_CONTROL = 0x30, + /// This command reads the temperature sensed by the temperature sensor. + /// + /// Doesn't work! Waveshare doesn't connect the read pin + TEMPERATURE_SENSOR_COMMAND = 0x40, + /// This command selects Internal or External temperature sensor. + TEMPERATURE_SENSOR_CALIBRATION = 0x41, + /// Write External Temperature Sensor + TEMPERATURE_SENSOR_WRITE = 0x42, + /// Read External Temperature Sensor + /// + /// Doesn't work! Waveshare doesn't connect the read pin + TEMPERATURE_SENSOR_READ = 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) + VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn the battery condition. + LOW_POWER_DETECTION = 0x51, + /// This command defines non-overlap period of Gate and Source. + TCON_SETTING = 0x60, + /// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR). + RESOLUTION_SETTING = 0x61, + SOURCE_AND_GATE_SETTING = 0x62, + /// This command reads the IC status. + /// + /// Doesn't work! Waveshare doesn't connect the read pin + GET_STATUS = 0x71, + /// Automatically measure VCOM. This command reads the IC status + AUTO_MEASUREMENT_VCOM = 0x80, + /// This command gets the VCOM value + /// + /// Doesn't work! Waveshare doesn't connect the read pin + READ_VCOM_VALUE = 0x81, + /// This command sets VCOM_DC value. + VCM_DC_SETTING = 0x82, + /// 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. + PROGRAM_MODE = 0xA0, + /// After this command is issued, the chip would enter the program mode. + ACTIVE_PROGRAMMING = 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. + READ_OTP = 0xA2, + /// Not shown in commands table, but used in init sequence + POWER_OPTIMIZATION = 0xf8, +} + +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::PANEL_SETTING.address(), 0x00); + assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + } +} diff --git a/src/epd2in7b/constants.rs b/src/epd2in7b/constants.rs new file mode 100644 index 0000000..f850f97 --- /dev/null +++ b/src/epd2in7b/constants.rs @@ -0,0 +1,55 @@ +#[rustfmt::skip] +pub(crate) const LUT_VCOM_DC: [u8; 44] = [ +0x00, 0x00, +0x00, 0x1A, 0x1A, 0x00, 0x00, 0x01, +0x00, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x00, 0x0E, 0x01, 0x0E, 0x01, 0x10, +0x00, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x00, 0x04, 0x10, 0x00, 0x00, 0x05, +0x00, 0x03, 0x0E, 0x00, 0x00, 0x0A, +0x00, 0x23, 0x00, 0x00, 0x00, 0x01, +]; + +#[rustfmt::skip] +pub(crate) const LUT_WW: [u8; 42] =[ +0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, +0x40, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, +0x80, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x00, 0x04, 0x10, 0x00, 0x00, 0x05, +0x00, 0x03, 0x0E, 0x00, 0x00, 0x0A, +0x00, 0x23, 0x00, 0x00, 0x00, 0x01, +]; + +#[rustfmt::skip] +pub(crate) const LUT_BW: [u8; 42] =[ +0xA0, 0x1A, 0x1A, 0x00, 0x00, 0x01, +0x00, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, +0x90, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0xB0, 0x04, 0x10, 0x00, 0x00, 0x05, +0xB0, 0x03, 0x0E, 0x00, 0x00, 0x0A, +0xC0, 0x23, 0x00, 0x00, 0x00, 0x01, +]; + +#[rustfmt::skip] +pub(crate) const LUT_BB: [u8; 42] =[ +0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, +0x40, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, +0x80, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x00, 0x04, 0x10, 0x00, 0x00, 0x05, +0x00, 0x03, 0x0E, 0x00, 0x00, 0x0A, +0x00, 0x23, 0x00, 0x00, 0x00, 0x01, +]; + +#[rustfmt::skip] +pub(crate) const LUT_WB: [u8; 42] =[ +0x90, 0x1A, 0x1A, 0x00, 0x00, 0x01, +0x20, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x84, 0x0E, 0x01, 0x0E, 0x01, 0x10, +0x10, 0x0A, 0x0A, 0x00, 0x00, 0x08, +0x00, 0x04, 0x10, 0x00, 0x00, 0x05, +0x00, 0x03, 0x0E, 0x00, 0x00, 0x0A, +0x00, 0x23, 0x00, 0x00, 0x00, 0x01, +]; diff --git a/src/epd2in7b/graphics.rs b/src/epd2in7b/graphics.rs new file mode 100644 index 0000000..1dcd7bf --- /dev/null +++ b/src/epd2in7b/graphics.rs @@ -0,0 +1,163 @@ +use crate::epd2in7b::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; +use crate::graphics::{Display, DisplayRotation}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::*; + +/// Full size buffer for use with the 2in7B EPD +/// +/// Can also be manuall constructed: +/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH * HEIGHT / 8]` +pub struct Display2in7b { + buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation, +} + +impl Default for Display2in7b { + fn default() -> Self { + Display2in7b { + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); + WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display2in7b { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl Display for Display2in7b { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::color::Black; + use crate::color::Color; + use crate::epd2in7b; + use crate::epd2in7b::{HEIGHT, WIDTH}; + use crate::graphics::{Display, DisplayRotation}; + use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + + // test buffer length + #[test] + fn graphics_size() { + let display = Display2in7b::default(); + assert_eq!(display.buffer().len(), 5808); + } + + // test default background color on all bytes + #[test] + fn graphics_default() { + let display = Display2in7b::default(); + for &byte in display.buffer() { + assert_eq!(byte, epd2in7b::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_0() { + let mut display = Display2in7b::default(); + let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd2in7b::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_90() { + let mut display = Display2in7b::default(); + display.set_rotation(DisplayRotation::Rotate90); + let _ = Line::new( + Point::new(0, WIDTH as i32 - 8), + Point::new(0, WIDTH as i32 - 1), + ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd2in7b::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_180() { + let mut display = Display2in7b::default(); + display.set_rotation(DisplayRotation::Rotate180); + + let _ = Line::new( + Point::new(WIDTH as i32 - 8, HEIGHT as i32 - 1), + Point::new(WIDTH as i32 - 1, HEIGHT as i32 - 1), + ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + extern crate std; + std::println!("{:?}", buffer); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd2in7b::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_270() { + let mut display = Display2in7b::default(); + display.set_rotation(DisplayRotation::Rotate270); + let _ = Line::new( + Point::new(HEIGHT as i32 - 1, 0), + Point::new(HEIGHT as i32 - 1, 7), + ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + extern crate std; + std::println!("{:?}", buffer); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd2in7b::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } +} diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs new file mode 100644 index 0000000..c93e9a4 --- /dev/null +++ b/src/epd2in7b/mod.rs @@ -0,0 +1,456 @@ +//! A simple Driver for the Waveshare 2.7" B Tri-Color E-Ink Display via SPI +//! +//! [Documentation](https://www.waveshare.com/wiki/2.7inch_e-Paper_HAT_(B)) + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +// The Lookup Tables for the Display +mod constants; +use crate::epd2in7b::constants::*; + +/// 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 = true; + +use crate::color::Color; + +pub(crate) mod command; +use self::command::Command; + +#[cfg(feature = "graphics")] +mod graphics; +#[cfg(feature = "graphics")] +pub use self::graphics::Display2in7b; + +/// EPD2in7b driver +pub struct EPD2in7b { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: Color, +} + +impl InternalWiAdditions + for EPD2in7b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn init>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + // reset the device + self.interface.reset(delay, 10); + + // power on + self.command(spi, Command::POWER_ON)?; + delay.delay_ms(5); + self.wait_until_idle(); + + // set panel settings, 0xbf is bw, 0xaf is multi-color + self.interface + .cmd_with_data(spi, Command::PANEL_SETTING, &[0xaf])?; + + // pll control + self.interface + .cmd_with_data(spi, Command::PLL_CONTROL, &[0x3a])?; + + // set the power settings + self.interface.cmd_with_data( + spi, + Command::POWER_SETTING, + &[0x03, 0x00, 0x2b, 0x2b, 0x09], + )?; + + // start the booster + self.interface + .cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x07, 0x07, 0x17])?; + + // power optimization + self.interface + .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x60, 0xa5])?; + self.interface + .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x89, 0xa5])?; + self.interface + .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x90, 0x00])?; + self.interface + .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x93, 0x2a])?; + self.interface + .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x73, 0x41])?; + + self.interface + .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + + self.interface + .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x87])?; + + self.set_lut(spi, None)?; + + self.interface + .cmd_with_data(spi, Command::PARTIAL_DISPLAY_REFRESH, &[0x00])?; + + self.wait_until_idle(); + Ok(()) + } +} + +impl WaveshareDisplay + for EPD2in7b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + type DisplayColor = Color; + fn new>( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = EPD2in7b { 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) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface + .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0xf7])?; + + self.command(spi, Command::POWER_OFF)?; + self.wait_until_idle(); + self.interface + .cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + Ok(()) + } + + fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.send_buffer_helper(spi, buffer)?; + + // Clear chromatic layer since we won't be using it here + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface + .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; + + self.interface.cmd(spi, Command::DATA_STOP)?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?; + + self.send_data(spi, &[(x >> 8) as u8])?; + self.send_data(spi, &[(x & 0xf8) as u8])?; + self.send_data(spi, &[(y >> 8) as u8])?; + self.send_data(spi, &[(y & 0xff) as u8])?; + self.send_data(spi, &[(width >> 8) as u8])?; + self.send_data(spi, &[(width & 0xf8) as u8])?; + self.send_data(spi, &[(height >> 8) as u8])?; + self.send_data(spi, &[(height & 0xff) as u8])?; + self.wait_until_idle(); + + self.send_buffer_helper(spi, buffer)?; + + self.interface.cmd(spi, Command::DATA_STOP) + } + + fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.command(spi, Command::DISPLAY_REFRESH)?; + self.wait_until_idle(); + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.command(spi, Command::DISPLAY_REFRESH)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); + + let color_value = self.color.get_byte_value(); + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.interface + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + + self.interface.cmd(spi, Command::DATA_STOP)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface + .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; + self.interface.cmd(spi, Command::DATA_STOP)?; + 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, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.cmd_with_data(spi, Command::LUT_FOR_VCOM, &LUT_VCOM_DC)?; + self.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, &LUT_WW)?; + self.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, &LUT_BW)?; + self.cmd_with_data(spi, Command::LUT_WHITE_TO_BLACK, &LUT_WB)?; + self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, &LUT_BB)?; + Ok(()) + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl WaveshareThreeColorDisplay + for EPD2in7b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, black)?; + self.update_chromatic_frame(spi, 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, + achromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + + self.send_buffer_helper(spi, achromatic)?; + + self.interface.cmd(spi, Command::DATA_STOP) + } + + /// 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, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + + self.send_buffer_helper(spi, chromatic)?; + + self.interface.cmd(spi, Command::DATA_STOP)?; + self.wait_until_idle(); + + Ok(()) + } +} + +impl EPD2in7b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + 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 send_buffer_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + // Based on the waveshare implementation, all data for color values is flipped. This helper + // method makes that transmission easier + for b in buffer.iter() { + self.send_data(spi, &[!b])?; + } + Ok(()) + } + + 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_until_idle(&mut self) { + self.interface.wait_until_idle(IS_BUSY_LOW) + } + + /// Refresh display for partial frame + pub fn display_partial_frame( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.command(spi, Command::PARTIAL_DISPLAY_REFRESH)?; + self.send_data(spi, &[(x >> 8) as u8])?; + self.send_data(spi, &[(x & 0xf8) as u8])?; + self.send_data(spi, &[(y >> 8) as u8])?; + self.send_data(spi, &[(y & 0xff) as u8])?; + self.send_data(spi, &[(width >> 8) as u8])?; + self.send_data(spi, &[(width & 0xf8) as u8])?; + self.send_data(spi, &[(height >> 8) as u8])?; + self.send_data(spi, &[(height & 0xff) as u8])?; + self.wait_until_idle(); + Ok(()) + } + + /// Update black/achromatic frame + pub fn update_partial_achromatic_frame( + &mut self, + spi: &mut SPI, + achromatic: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?; + self.send_data(spi, &[(x >> 8) as u8])?; + self.send_data(spi, &[(x & 0xf8) as u8])?; + self.send_data(spi, &[(y >> 8) as u8])?; + self.send_data(spi, &[(y & 0xff) as u8])?; + self.send_data(spi, &[(width >> 8) as u8])?; + self.send_data(spi, &[(width & 0xf8) as u8])?; + self.send_data(spi, &[(height >> 8) as u8])?; + self.send_data(spi, &[(height & 0xff) as u8])?; + self.wait_until_idle(); + + for b in achromatic.iter() { + // Flipping based on waveshare implementation + self.send_data(spi, &[!b])?; + } + + Ok(()) + } + + /// Update partial chromatic/red frame + pub fn update_partial_chromatic_frame( + &mut self, + spi: &mut SPI, + chromatic: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_2)?; + self.send_data(spi, &[(x >> 8) as u8])?; + self.send_data(spi, &[(x & 0xf8) as u8])?; + self.send_data(spi, &[(y >> 8) as u8])?; + self.send_data(spi, &[(y & 0xff) as u8])?; + self.send_data(spi, &[(width >> 8) as u8])?; + self.send_data(spi, &[(width & 0xf8) as u8])?; + self.send_data(spi, &[(height >> 8) as u8])?; + self.send_data(spi, &[(height & 0xff) as u8])?; + self.wait_until_idle(); + + for b in chromatic.iter() { + // Flipping based on waveshare implementation + self.send_data(spi, &[!b])?; + } + + Ok(()) + } +} + +#[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 175dc01..30a7cf2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -75,6 +75,7 @@ mod interface; pub mod epd1in54; pub mod epd1in54b; pub mod epd2in13_v2; +pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9bc; pub mod epd4in2; From 8630869186d3ebc60133d5ae614f1d7bd106c60e Mon Sep 17 00:00:00 2001 From: pjsier Date: Thu, 7 Jan 2021 12:44:16 -0500 Subject: [PATCH 08/80] add epd2in7b to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 93e177d..158c2f9 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ epd.update_and_display_frame(&mut spi, &display.buffer())?; | [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 | ✕ | ✕ | ✔ | ✔ | | [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]: 7.5 Inch B/W V2 (A) From 49cc823ccc04277f94a577f898e5937326394ab0 Mon Sep 17 00:00:00 2001 From: pjsier Date: Mon, 18 Jan 2021 13:20:58 -0600 Subject: [PATCH 09/80] fix epd2in7b reset delay --- src/epd2in7b/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index c93e9a4..666add7 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -57,7 +57,7 @@ where delay: &mut DELAY, ) -> Result<(), SPI::Error> { // reset the device - self.interface.reset(delay, 10); + self.interface.reset(delay, 2); // power on self.command(spi, Command::POWER_ON)?; From c30d213bc50e344b166f22aa666b93e72f568bfc Mon Sep 17 00:00:00 2001 From: David-OConnor Date: Thu, 21 Jan 2021 21:13:13 +0400 Subject: [PATCH 10/80] Added QuickRefresh trait, and implemented it for 4.2 display --- src/epd4in2/constants.rs | 146 +++++++++++++++++---------------- src/epd4in2/mod.rs | 170 ++++++++++++++++++++++++++++++++++++++- src/lib.rs | 4 +- src/traits.rs | 64 +++++++++++++++ 4 files changed, 312 insertions(+), 72 deletions(-) diff --git a/src/epd4in2/constants.rs b/src/epd4in2/constants.rs index 8ae34b9..a4c8037 100644 --- a/src/epd4in2/constants.rs +++ b/src/epd4in2/constants.rs @@ -1,109 +1,115 @@ +//! This file contains look-up-tables used to set voltages used during +//! various categories of pixel refreshes. + #[rustfmt::skip] pub(crate) const LUT_VCOM0: [u8; 44] = [ -0x00, 0x17, 0x00, 0x00, 0x00, 0x02, -0x00, 0x17, 0x17, 0x00, 0x00, 0x02, -0x00, 0x0A, 0x01, 0x00, 0x00, 0x01, -0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +// The commented-out line below was used in a Ben Krasnow video explaining +// partial refreshes. +// 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x00, 0x17, 0x17, 0x00, 0x00, 0x02, + 0x00, 0x0A, 0x01, 0x00, 0x00, 0x01, + 0x00, 0x0E, 0x0E, 0x00, 0x00, 0x02, + 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_VCOM0_QUICK: [u8; 44] = [ -0x00, 0x0E, 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, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x0E, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_WW: [u8; 42] =[ -0x40, 0x17, 0x00, 0x00, 0x00, 0x02, -0x90, 0x17, 0x17, 0x00, 0x00, 0x02, -0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, -0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, + 0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, + 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_WW_QUICK: [u8; 42] =[ -0xA0, 0x0E, 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, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA0, 0x0E, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_BW: [u8; 42] =[ -0x40, 0x17, 0x00, 0x00, 0x00, 0x02, -0x90, 0x17, 0x17, 0x00, 0x00, 0x02, -0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, -0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, + 0x40, 0x0A, 0x01, 0x00, 0x00, 0x01, + 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_BW_QUICK: [u8; 42] =[ -0xA0, 0x0E, 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, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xA0, 0x0E, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_BB: [u8; 42] =[ -0x80, 0x17, 0x00, 0x00, 0x00, 0x02, -0x90, 0x17, 0x17, 0x00, 0x00, 0x02, -0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, -0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, + 0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, + 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_BB_QUICK: [u8; 42] =[ -0x50, 0x0E, 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, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x0E, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_WB: [u8; 42] =[ -0x80, 0x17, 0x00, 0x00, 0x00, 0x02, -0x90, 0x17, 0x17, 0x00, 0x00, 0x02, -0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, -0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, + 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, + 0x80, 0x0A, 0x01, 0x00, 0x00, 0x01, + 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; #[rustfmt::skip] pub(crate) const LUT_WB_QUICK: [u8; 42] =[ -0x50, 0x0E, 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, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x50, 0x0E, 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, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, ]; diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index a3a972b..76ab7a6 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -55,7 +55,7 @@ use embedded_hal::{ }; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLUT, WaveshareDisplay}; //The Lookup Tables for the Display mod constants; @@ -407,6 +407,174 @@ where self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, lut_bb)?; Ok(()) } + + /// Helper function. Sets up the display to send pixel data to a custom + /// starting point. + pub fn shift_display( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.send_data(spi, &[(x >> 8) as u8])?; + let tmp = x & 0xf8; + self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored + let tmp = tmp + width - 1; + self.send_data(spi, &[(tmp >> 8) as u8])?; + self.send_data(spi, &[(tmp | 0x07) as u8])?; + + self.send_data(spi, &[(y >> 8) as u8])?; + self.send_data(spi, &[y as u8])?; + + self.send_data(spi, &[((y + height - 1) >> 8) as u8])?; + self.send_data(spi, &[(y + height - 1) as u8])?; + + self.send_data(spi, &[0x01])?; // Gates scan both inside and outside of the partial window. (default) + + Ok(()) + } +} + +impl QuickRefresh + for EPD4in2 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + /// To be followed immediately after by `update_old_frame`. + fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + + // todo: Eval if you need these 3 res setting items. + self.send_resolution(spi)?; + self.interface + .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 + self.interface + .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + + self.interface.data(spi, buffer)?; + + Ok(()) + } + + /// To be used immediately after `update_old_frame`. + fn update_new_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + // self.send_resolution(spi)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + + self.interface.data(spi, buffer)?; + + Ok(()) + } + + fn update_partial_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + + // todo: Eval if you need these 3 res setting items. + self.send_resolution(spi)?; + self.interface + .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 + self.interface + .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; + + if buffer.len() as u32 != width / 8 * height { + //TODO: panic!! or sth like that + //return Err("Wrong buffersize"); + } + + self.interface.cmd(spi, Command::PARTIAL_IN)?; + self.interface.cmd(spi, Command::PARTIAL_WINDOW)?; + + self.shift_display(spi, x, y, width, height)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + + self.interface.data(spi, buffer)?; + + Ok(()) + } + + /// Always call `update_partial_old_frame` before this, with buffer-updating code + /// between the calls. + fn update_partial_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + if buffer.len() as u32 != width / 8 * height { + //TODO: panic!! or sth like that + //return Err("Wrong buffersize"); + } + + self.shift_display(spi, x, y, width, height)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + + self.interface.data(spi, buffer)?; + + self.interface.cmd(spi, Command::PARTIAL_OUT)?; + Ok(()) + } + + fn clear_partial_frame( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.send_resolution(spi)?; + + let color_value = self.color.get_byte_value(); + + self.interface.cmd(spi, Command::PARTIAL_IN)?; + self.interface.cmd(spi, Command::PARTIAL_WINDOW)?; + + self.shift_display(spi, x, y, width, height)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.interface + .data_x_times(spi, color_value, width / 8 * height)?; + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface + .data_x_times(spi, color_value, width / 8 * height)?; + + self.interface.cmd(spi, Command::PARTIAL_OUT)?; + Ok(()) + } } #[cfg(test)] diff --git a/src/lib.rs b/src/lib.rs index 175dc01..dcbcf6a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -87,7 +87,9 @@ pub(crate) mod type_a; /// Includes everything important besides the chosen Display pub mod prelude { pub use crate::color::{Color, OctColor, TriColor}; - pub use crate::traits::{RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay}; + pub use crate::traits::{ + QuickRefresh, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + }; pub use crate::SPI_MODE; diff --git a/src/traits.rs b/src/traits.rs index 9b5aa01..0478874 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -229,3 +229,67 @@ where /// if the device is still busy fn is_busy(&self) -> bool; } + +/// Allows quick refresh support for displays that support it; lets you send both +/// old and new frame data to support this. +/// +/// When using the quick refresh look-up table, the display must receive separate display +/// buffer data marked as old, and new. This is used to determine which pixels need to change, +/// and how they will change. This isn't required when using full refreshes. +/// +/// Example: +/// epd.update_partial_old_frame(spi, disp.buffer(), x, y, frame_width, frame_height) +/// .ok(); +/// +/// disp.clear_buffer(Color::White); +/// // Execute drawing commands here. +/// +/// epd.update_partial_new_frame(spi, disp.buffer(), x, y, frame_width, frame_height) +/// .ok(); +pub trait QuickRefresh +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + /// Updates the old frame. + fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + + /// Updates the new frame. + fn update_new_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + + /// Updates the old frame for a portion of the display. + fn update_partial_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error>; + + /// Updates the new frame for a portion of the display. + fn update_partial_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error>; + + /// Clears the partial frame buffer on the EPD with the declared background color + /// The background color can be changed with [`WaveshareDisplay::set_background_color`] + fn clear_partial_frame( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error>; +} From 0695e9467089291076b9f596826e5c24458f7a91 Mon Sep 17 00:00:00 2001 From: David-OConnor Date: Thu, 21 Jan 2021 21:29:37 +0400 Subject: [PATCH 11/80] Removed example that broke CI --- Cargo.toml | 4 ++-- src/traits.rs | 10 +--------- 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5d69b64..c340fa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,8 +16,8 @@ edition = "2018" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics = { version = "0.6.1", optional = true} -embedded-hal = {version = "0.2.3", features = ["unproven"]} +embedded-graphics = { version = "0.6.2", optional = true} +embedded-hal = {version = "0.2.4", features = ["unproven"]} bit_field = "0.10.1" [dev-dependencies] diff --git a/src/traits.rs b/src/traits.rs index 0478874..044185a 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -237,15 +237,7 @@ where /// buffer data marked as old, and new. This is used to determine which pixels need to change, /// and how they will change. This isn't required when using full refreshes. /// -/// Example: -/// epd.update_partial_old_frame(spi, disp.buffer(), x, y, frame_width, frame_height) -/// .ok(); -/// -/// disp.clear_buffer(Color::White); -/// // Execute drawing commands here. -/// -/// epd.update_partial_new_frame(spi, disp.buffer(), x, y, frame_width, frame_height) -/// .ok(); +/// (todo: Example ommitted due to CI failures.) pub trait QuickRefresh where SPI: Write, From bccfc81b134090220b9339a0d2f91a6528c57c4f Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 23 Jan 2021 14:55:03 +0100 Subject: [PATCH 12/80] Improve Stuff mentioned by clippy: - use range.contains instead of >= && <= - Use better error type --- CHANGELOG.md | 13 +++++++++++++ src/color.rs | 15 ++++++++++++--- src/epd2in13_v2/command.rs | 14 +++++--------- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6fba5f..af0425f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + + +### Changed + - Use specific ParseColorError instead of () + +### Fixed + + +## [v0.5.0] + +TODO! + ## [v0.4.0] - 2020-04-06 ### Added diff --git a/src/color.rs b/src/color.rs index 6767673..c3092ca 100644 --- a/src/color.rs +++ b/src/color.rs @@ -10,6 +10,15 @@ pub use BinaryColor::Off as White; #[cfg(feature = "graphics")] pub use BinaryColor::On as Black; +/// When trying to parse u8 to one of the color types +#[derive(Debug)] +pub struct OutOfColorRangeParseError(u8); +impl core::fmt::Display for OutOfColorRangeParseError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Outside of possible Color Range: {}", self.0) + } +} + /// Only for the Black/White-Displays #[derive(Clone, Copy, PartialEq, Debug)] pub enum Color { @@ -73,7 +82,7 @@ impl OctColor { } ///Take the nibble (lower 4 bits) and convert to an OctColor if possible - pub fn from_nibble(nibble: u8) -> Result { + pub fn from_nibble(nibble: u8) -> Result { match nibble & 0xf { 0x00 => Ok(OctColor::Black), 0x01 => Ok(OctColor::White), @@ -83,11 +92,11 @@ impl OctColor { 0x05 => Ok(OctColor::Yellow), 0x06 => Ok(OctColor::Orange), 0x07 => Ok(OctColor::HiZ), - _ => Err(()), + e => Err(OutOfColorRangeParseError(e)), } } ///Split the nibbles of a single byte and convert both to an OctColor if possible - pub fn split_byte(byte: u8) -> Result<(OctColor, OctColor), ()> { + pub fn split_byte(byte: u8) -> Result<(OctColor, OctColor), OutOfColorRangeParseError> { let low = OctColor::from_nibble(byte & 0xf)?; let high = OctColor::from_nibble((byte >> 4) & 0xf)?; Ok((high, low)) diff --git a/src/epd2in13_v2/command.rs b/src/epd2in13_v2/command.rs index b7e1986..9ab4ddd 100644 --- a/src/epd2in13_v2/command.rs +++ b/src/epd2in13_v2/command.rs @@ -221,7 +221,7 @@ impl I32Ext for i32 { // This is really not very nice. Until I find something better, this will be // a placeholder. fn vcom(self) -> VCOM { - assert!(self >= -30 && self <= -2); + assert!((-30..=-2).contains(&self)); let u = match -self { 2 => 0x08, 3 => 0x0B, @@ -258,20 +258,16 @@ impl I32Ext for i32 { } fn gate_driving_decivolt(self) -> GateDrivingVoltage { - assert!(self >= 100 && self <= 210 && self % 5 == 0); + assert!((100..=210).contains(&self) && self % 5 == 0); GateDrivingVoltage(((self - 100) / 5 + 0x03) as u8) } fn source_driving_decivolt(self) -> SourceDrivingVoltage { - assert!( - (self >= 24 && self <= 88) - || (self >= 90 && self <= 180 && self % 5 == 0) - || (self >= -180 && self <= -90 && self % 5 == 0) - ); + assert!((24..=88).contains(&self) || (self % 5 == 0 && (90..=180).contains(&self.abs()))); - if self >= 24 && self <= 88 { + if (24..=88).contains(&self) { SourceDrivingVoltage(((self - 24) + 0x8E) as u8) - } else if self >= 90 && self <= 180 { + } else if (90..=180).contains(&self) { SourceDrivingVoltage(((self - 90) / 2 + 0x23) as u8) } else { SourceDrivingVoltage((((-self - 90) / 5) * 2 + 0x1A) as u8) From 1a612c92d3d864ff9af6fef54d6ddfbc21b41696 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 23 Jan 2021 16:23:36 +0100 Subject: [PATCH 13/80] Fix missing Eq for OutofColorRangeParseError --- src/color.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/color.rs b/src/color.rs index c3092ca..2c4435a 100644 --- a/src/color.rs +++ b/src/color.rs @@ -11,7 +11,7 @@ pub use BinaryColor::Off as White; pub use BinaryColor::On as Black; /// When trying to parse u8 to one of the color types -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq)] pub struct OutOfColorRangeParseError(u8); impl core::fmt::Display for OutOfColorRangeParseError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { From ca3eebecbe5e45269254591d8c7d8dcdaa3b27fe Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 23 Jan 2021 16:45:31 +0100 Subject: [PATCH 14/80] Try with codecov.yml --- codecov.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 codecov.yml diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 0000000..cf6c201 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,15 @@ +coverage: + status: + project: + default: + # basic + target: auto + threshold: 0% + base: auto + flags: + - unit + paths: + - "src" + if_ci_failed: ignore #success, failure, error, ignore + informational: false + only_pulls: false \ No newline at end of file From d572ef0f5dd5d869e5a35a287b7d9d14c7bea747 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 23 Jan 2021 16:50:55 +0100 Subject: [PATCH 15/80] test it --- src/color.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/color.rs b/src/color.rs index 2c4435a..754b411 100644 --- a/src/color.rs +++ b/src/color.rs @@ -19,6 +19,12 @@ impl core::fmt::Display for OutOfColorRangeParseError { } } +impl OutOfColorRangeParseError { + fn _new(size: u8) -> OutOfColorRangeParseError { + OutOfColorRangeParseError(size) + } +} + /// Only for the Black/White-Displays #[derive(Clone, Copy, PartialEq, Debug)] pub enum Color { From 463afa52c677a42468f5d08c5798fdad8095b228 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sat, 23 Jan 2021 17:01:11 +0100 Subject: [PATCH 16/80] delete travis + codecov --- .travis.yml | 49 ------------------------------------------------- codecov.yml | 15 --------------- 2 files changed, 64 deletions(-) delete mode 100644 .travis.yml delete mode 100644 codecov.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 5965444..0000000 --- a/.travis.yml +++ /dev/null @@ -1,49 +0,0 @@ -language: rust -rust: - - stable -sudo: required -env: TARGET=x86_64-unknown-linux-gnu - -before_install: - - set -e - - rustup self update - -# install: -# - cargo install cargo-update || echo "cargo-update already installed" -# - cargo install-update -a # update outdated cached binaries -# - cargo install cross || echo "cross already installed" - - #TODO: remove -A clippy::new_ret_no_self when new version of clippy gets released! -script: - - cargo check --all-features - - cargo test --all-features - -cache: cargo -before_cache: - # Travis can't cache files that are not readable by "others" - - chmod -R a+r $HOME/.cargo - - | - if [[ "$TRAVIS_RUST_VERSION" == stable ]]; then - cargo install cargo-tarpaulin - fi - -after_success: | - if [[ "$TRAVIS_RUST_VERSION" == stable ]]; then - # Uncomment the following line for coveralls.io - # cargo tarpaulin --ciserver travis-ci --coveralls $TRAVIS_JOB_ID - - # Uncomment the following two lines create and upload a report for codecov.io - cargo tarpaulin --all-features --out Xml - bash <(curl -s https://codecov.io/bash) -t "$CODECOV_TOKEN" - fi - - -branches: - only: - # release tags - - /^v\d+\.\d+\.\d+.*$/ - - main - -notifications: - email: - on_success: never diff --git a/codecov.yml b/codecov.yml deleted file mode 100644 index cf6c201..0000000 --- a/codecov.yml +++ /dev/null @@ -1,15 +0,0 @@ -coverage: - status: - project: - default: - # basic - target: auto - threshold: 0% - base: auto - flags: - - unit - paths: - - "src" - if_ci_failed: ignore #success, failure, error, ignore - informational: false - only_pulls: false \ No newline at end of file From 4ccbea56074d8aaeac81754357c16566393bda1d Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 17:34:39 +0100 Subject: [PATCH 17/80] Add Example to quick refresh trait --- src/traits.rs | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/traits.rs b/src/traits.rs index 044185a..d4877b5 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -238,6 +238,43 @@ where /// and how they will change. This isn't required when using full refreshes. /// /// (todo: Example ommitted due to CI failures.) +/// Example: +///```rust, no_run +///# use embedded_hal_mock::*; +///# fn main() -> Result<(), MockError> { +///# use embedded_graphics::{ +///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +///# }; +///# use epd_waveshare::{epd4in2::*, prelude::*}; +///# use epd_waveshare::graphics::VarDisplay; +///# +///# 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 = EPD4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +///let (x, y, frame_width, frame_height) = (20, 40, 80,80); +/// +///let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 80 / 8 * 80]; +///let mut display = VarDisplay::new(frame_width, frame_height, &mut buffer); +/// +///epd.update_partial_old_frame(&mut spi, display.buffer(), x, y, frame_width, frame_height) +/// .ok(); +/// +///display.clear_buffer(Color::White); +///// Execute drawing commands here. +/// +///epd.update_partial_new_frame(&mut spi, display.buffer(), x, y, frame_width, frame_height) +/// .ok(); +///# Ok(()) +///# } +///``` pub trait QuickRefresh where SPI: Write, From ad9574f355c5281637fe4478011097a270481264 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 17:35:03 +0100 Subject: [PATCH 18/80] Add David & the changes to Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af0425f..9b25ca6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added - + - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) ### Changed - Use specific ParseColorError instead of () From bcbef1e80544f40fc9e4ddba33f7885c65b8e734 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 20:29:23 +0100 Subject: [PATCH 19/80] "EPD4in2: Don't set the resolution (and some more) over and over again. If the resolution ever changes, something has horribly gone wrong." From @mgottschlag #48 --- src/epd4in2/mod.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 76ab7a6..098d085 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -132,6 +132,15 @@ where // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3A])?; + self.send_resolution(spi)?; + + self.interface + .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + + //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 + self.interface + .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; + self.set_lut(spi, None)?; self.wait_until_idle(); @@ -202,15 +211,6 @@ where self.wait_until_idle(); let color_value = self.color.get_byte_value(); - self.send_resolution(spi)?; - - self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; - - //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 - self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; - self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; self.interface From 788ddcab98519c29a272aec444564a2c030e630c Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 20:53:24 +0100 Subject: [PATCH 20/80] Apply #48 to QuickRefresh as well --- src/epd4in2/mod.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 098d085..636b254 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -450,14 +450,6 @@ where fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - // todo: Eval if you need these 3 res setting items. - self.send_resolution(spi)?; - self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; - //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 - self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; - self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; @@ -490,14 +482,6 @@ where ) -> Result<(), SPI::Error> { self.wait_until_idle(); - // todo: Eval if you need these 3 res setting items. - self.send_resolution(spi)?; - self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; - //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 - self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; - if buffer.len() as u32 != width / 8 * height { //TODO: panic!! or sth like that //return Err("Wrong buffersize"); From f9a09d9018bdaa88d2f0f36ec394d0a0b9d19c51 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 21:00:52 +0100 Subject: [PATCH 21/80] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b25ca6..dc08bc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed - Use specific ParseColorError instead of () + - EPD4in2: Don't set the resolution (and some more) over and over again (#48) ### Fixed From ce95d3d93f8b74b252f2853a8344d26dd58df425 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Wed, 27 Jan 2021 21:26:13 +0100 Subject: [PATCH 22/80] add auto_assign ymls --- .github/auto_assign-issues.yml | 8 ++++++++ .github/auto_assign.yml | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 .github/auto_assign-issues.yml create mode 100644 .github/auto_assign.yml diff --git a/.github/auto_assign-issues.yml b/.github/auto_assign-issues.yml new file mode 100644 index 0000000..6a6a4f9 --- /dev/null +++ b/.github/auto_assign-issues.yml @@ -0,0 +1,8 @@ +# If enabled, auto-assigns users when a new issue is created +# Defaults to true, allows you to install the app globally, and disable on a per-repo basis +addAssignees: true + +# The list of users to assign to new issues. +# If empty or not provided, the repository owner is assigned +assignees: + - caemor \ No newline at end of file diff --git a/.github/auto_assign.yml b/.github/auto_assign.yml new file mode 100644 index 0000000..5c151da --- /dev/null +++ b/.github/auto_assign.yml @@ -0,0 +1,17 @@ +# Set to true to add reviewers to pull requests +addReviewers: true + +# Set to true to add assignees to pull requests +addAssignees: true + +# A list of reviewers to be added to pull requests (GitHub user name) +reviewers: + - caemor + +# A list of keywords to be skipped the process that add reviewers if pull requests include it +#skipKeywords: +# - wip + +# A number of reviewers added to the pull request +# Set 0 to add all the reviewers (default: 0) +numberOfReviewers: 0 \ No newline at end of file From b4c3722eceaf29a4dcb79c811e839890ed9419c9 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Thu, 28 Jan 2021 12:08:13 +0100 Subject: [PATCH 23/80] Updated Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc08bc3..f3eeac2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) + - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) ### Changed - Use specific ParseColorError instead of () From d1b0ac185498b420fae69f1798e18c7baeb51b8b Mon Sep 17 00:00:00 2001 From: BuggStream Date: Sat, 6 Feb 2021 17:17:04 +0100 Subject: [PATCH 24/80] Add support for 1in54c EPD --- .gitignore | 3 + src/epd1in54c/command.rs | 39 +++++ src/epd1in54c/graphics.rs | 51 +++++++ src/epd1in54c/mod.rs | 300 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 5 files changed, 394 insertions(+) create mode 100644 src/epd1in54c/command.rs create mode 100644 src/epd1in54c/graphics.rs create mode 100644 src/epd1in54c/mod.rs diff --git a/.gitignore b/.gitignore index db7de4a..1f41f71 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,6 @@ Cargo.lock # vscode .vscode/* + +# intellij/clion +.idea/ diff --git a/src/epd1in54c/command.rs b/src/epd1in54c/command.rs new file mode 100644 index 0000000..830742f --- /dev/null +++ b/src/epd1in54c/command.rs @@ -0,0 +1,39 @@ +//! SPI Commands for the Waveshare 1.54" red E-Ink Display +use crate::traits; + +#[allow(dead_code)] +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + PANEL_SETTING = 0x00, + + POWER_SETTING = 0x01, + POWER_OFF = 0x02, + POWER_ON = 0x04, + BOOSTER_SOFT_START = 0x06, + DEEP_SLEEP = 0x07, + DATA_START_TRANSMISSION_1 = 0x10, + DISPLAY_REFRESH = 0x12, + DATA_START_TRANSMISSION_2 = 0x13, + + LUT_FOR_VCOM = 0x20, + LUT_WHITE_TO_WHITE = 0x21, + LUT_BLACK_TO_WHITE = 0x22, + LUT_WHITE_TO_BLACK = 0x23, + LUT_BLACK_TO_BLACK = 0x24, + + PLL_CONTROL = 0x30, + TEMPERATURE_SENSOR_COMMAND = 0x40, + TEMPERATURE_SENSOR_SELECTION = 0x41, + VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + RESOLUTION_SETTING = 0x61, + VCM_DC_SETTING = 0x82, + POWER_SAVING = 0xE3, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs new file mode 100644 index 0000000..2f636da --- /dev/null +++ b/src/epd1in54c/graphics.rs @@ -0,0 +1,51 @@ +use crate::epd1in54c::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH, NUM_DISPLAY_BITS}; +use crate::graphics::{Display, DisplayRotation}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::*; + +/// Full size buffer for use with the 1in54 EPD +/// +/// Can also be manually constructed and be used together with VarDisplay +pub struct Display1in54c { + buffer: [u8; NUM_DISPLAY_BITS as usize], + rotation: DisplayRotation, +} + +impl Default for Display1in54c { + fn default() -> Self { + Display1in54c { + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); NUM_DISPLAY_BITS as usize], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display1in54c { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl Display for Display1in54c { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs new file mode 100644 index 0000000..6ca626a --- /dev/null +++ b/src/epd1in54c/mod.rs @@ -0,0 +1,300 @@ +//! A simple Driver for the Waveshare 1.54" (C) E-Ink Display via SPI + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +/// Width of epd1in54 in pixels +pub const WIDTH: u32 = 152; +/// Height of epd1in54 in pixels +pub const HEIGHT: u32 = 152; +/// Default Background Color (white) +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; + +const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; + +const IS_BUSY_LOW: bool = true; + +use crate::color::Color; + +pub(crate) mod command; + +use self::command::Command; + +#[cfg(feature = "graphics")] +mod graphics; + +#[cfg(feature = "graphics")] +pub use self::graphics::Display1in54c; + +/// EPD1in54c driver +pub struct EPD1in54c { + interface: DisplayInterface, + color: Color, +} + +impl InternalWiAdditions + for EPD1in54c +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn init>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + // Based on Reference Program Code from: + // https://www.waveshare.com/w/upload/a/ac/1.54inch_e-Paper_Module_C_Specification.pdf + // and: + // https://github.com/waveshare/e-Paper/blob/master/STM32/STM32-F103ZET6/User/e-Paper/EPD_1in54c.c + self.interface.reset(delay, 2); + + // start the booster + self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?; + + // power on + self.command(spi, Command::POWER_ON)?; + delay.delay_ms(5); + self.wait_until_idle(); + + // set the panel settings + self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x0f, 0x0d])?; + + // set resolution + self.send_resolution(spi)?; + + self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x77])?; + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for EPD1in54c +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, black)?; + self.update_chromatic_frame(spi, chromatic) + } + + fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.interface.data(spi, black)?; + Ok(()) + } + + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface.data(spi, chromatic)?; + Ok(()) + } +} + +impl WaveshareDisplay + for EPD1in54c +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + type DisplayColor = Color; + fn new>( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = EPD1in54c { interface, color }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); + + self.command(spi, Command::POWER_OFF)?; + self.wait_until_idle(); + self.cmd_with_data(spi, Command::DEEP_SLEEP, &[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]) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, buffer)?; + + // Clear the chromatic layer + let color = self.color.get_byte_value(); + + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + Ok(()) + } + + #[allow(unused)] + fn update_partial_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + unimplemented!() + } + + fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.command(spi, Command::DISPLAY_REFRESH)?; + self.wait_until_idle(); + + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; + + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); + let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); + + // Clear the black + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + // Clear the red + self.interface + .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + Ok(()) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + Ok(()) + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl EPD1in54c +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + 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 wait_until_idle(&mut self) { + self.interface.wait_until_idle(IS_BUSY_LOW) + } + + fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.command(spi, Command::RESOLUTION_SETTING)?; + + // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | + // | HRES[7:3] | 0 | 0 | 0 | + self.send_data(spi, &[(w as u8) & 0b1111_1000])?; + // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | + // | - | - | - | - | - | - | - | VRES[8] | + self.send_data(spi, &[(w >> 8) as u8])?; + // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | + // | VRES[7:0] | + // Specification shows C/D is zero while sending the last byte, + // but upstream code does not implement it like that. So for now + // we follow upstream code. + self.send_data(spi, &[h as u8]) + } +} diff --git a/src/lib.rs b/src/lib.rs index 3757b19..60a816e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,6 +74,7 @@ mod interface; pub mod epd1in54; pub mod epd1in54b; +pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in7b; pub mod epd2in9; From 6c8ac87c7d649c1f403de198c24e345ae15be3fc Mon Sep 17 00:00:00 2001 From: BuggStream Date: Sun, 7 Feb 2021 01:19:30 +0100 Subject: [PATCH 25/80] Ensure device is ready to receive data when updating frame --- src/epd1in54c/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 6ca626a..d453bfe 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -99,6 +99,8 @@ where } fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; self.interface.data(spi, black)?; @@ -110,6 +112,8 @@ where spi: &mut SPI, chromatic: &[u8], ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface.data(spi, chromatic)?; From 6129723c416c31593b1623bfd8976d39c2b8b97f Mon Sep 17 00:00:00 2001 From: BuggStream Date: Sun, 7 Feb 2021 23:30:44 +0100 Subject: [PATCH 26/80] Clean up and simplify code --- src/epd1in54c/command.rs | 2 +- src/epd1in54c/graphics.rs | 2 +- src/epd1in54c/mod.rs | 24 +++++++----------------- 3 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/epd1in54c/command.rs b/src/epd1in54c/command.rs index 830742f..3715030 100644 --- a/src/epd1in54c/command.rs +++ b/src/epd1in54c/command.rs @@ -1,4 +1,4 @@ -//! SPI Commands for the Waveshare 1.54" red E-Ink Display +//! SPI Commands for the Waveshare 1.54" C red or yellow E-Ink Display use crate::traits; #[allow(dead_code)] diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs index 2f636da..dc66b7e 100644 --- a/src/epd1in54c/graphics.rs +++ b/src/epd1in54c/graphics.rs @@ -3,7 +3,7 @@ use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; -/// Full size buffer for use with the 1in54 EPD +/// Full size buffer for use with the 1in54c EPD /// /// Can also be manually constructed and be used together with VarDisplay pub struct Display1in54c { diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index d453bfe..f8bd54d 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -16,15 +16,12 @@ pub const WIDTH: u32 = 152; pub const HEIGHT: u32 = 152; /// Default Background Color (white) pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; - -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; - const IS_BUSY_LOW: bool = true; +const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; use crate::color::Color; pub(crate) mod command; - use self::command::Command; #[cfg(feature = "graphics")] @@ -100,10 +97,8 @@ where fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); + self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, black)?; - self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; - self.interface.data(spi, black)?; Ok(()) } @@ -113,10 +108,8 @@ where chromatic: &[u8], ) -> Result<(), SPI::Error> { self.wait_until_idle(); + self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, chromatic)?; - self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; - self.interface.data(spi, chromatic)?; Ok(()) } } @@ -189,8 +182,7 @@ where // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + self.command(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; Ok(()) @@ -228,13 +220,11 @@ where let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DATA_START_TRANSMISSION_1)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; - // Clear the red - self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + // Clear the chromatic + self.command(spi, Command::DATA_START_TRANSMISSION_2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; Ok(()) From b49dd6cd1fffabbe029b46b8d32335e23f477d0d Mon Sep 17 00:00:00 2001 From: BuggStream Date: Mon, 8 Feb 2021 00:26:31 +0100 Subject: [PATCH 27/80] Update documentation for 1in54c --- README.md | 1 + src/epd1in54c/command.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 158c2f9..200e601 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,7 @@ epd.update_and_display_frame(&mut spi, &display.buffer())?; | [2.13 Inch B/W (A) V2](https://www.waveshare.com/product/2.13inch-e-paper-hat.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [2.9 Inch B/W (A)](https://www.waveshare.com/product/2.9inch-e-paper-module.htm) | Black, White | ✕ | ✔ | ✔ | ✔ | | [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 | ✕ | ✔ | ✔ | ✔ | diff --git a/src/epd1in54c/command.rs b/src/epd1in54c/command.rs index 3715030..e0ad2f2 100644 --- a/src/epd1in54c/command.rs +++ b/src/epd1in54c/command.rs @@ -1,4 +1,4 @@ -//! SPI Commands for the Waveshare 1.54" C red or yellow E-Ink Display +//! SPI Commands for the Waveshare 1.54" C yellow E-Ink Display use crate::traits; #[allow(dead_code)] From b479edd1082b6ab3180905162a9852ec94f85456 Mon Sep 17 00:00:00 2001 From: BuggStream Date: Mon, 8 Feb 2021 00:40:07 +0100 Subject: [PATCH 28/80] Fix last rustfmt issue --- src/epd1in54c/graphics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs index dc66b7e..4475083 100644 --- a/src/epd1in54c/graphics.rs +++ b/src/epd1in54c/graphics.rs @@ -1,4 +1,4 @@ -use crate::epd1in54c::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH, NUM_DISPLAY_BITS}; +use crate::epd1in54c::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; From c27ffd507f35d2374dda66527efe451b368cdaf6 Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 31 Mar 2021 10:39:29 +0100 Subject: [PATCH 29/80] Added support for the 7.5 inch HD display --- src/epd7in5_hd/command.rs | 158 +++++++++++++++++++++ src/epd7in5_hd/graphics.rs | 149 ++++++++++++++++++++ src/epd7in5_hd/mod.rs | 275 +++++++++++++++++++++++++++++++++++++ src/interface.rs | 4 +- src/lib.rs | 1 + 5 files changed, 585 insertions(+), 2 deletions(-) create mode 100644 src/epd7in5_hd/command.rs create mode 100644 src/epd7in5_hd/graphics.rs create mode 100644 src/epd7in5_hd/mod.rs diff --git a/src/epd7in5_hd/command.rs b/src/epd7in5_hd/command.rs new file mode 100644 index 0000000..f656f9f --- /dev/null +++ b/src/epd7in5_hd/command.rs @@ -0,0 +1,158 @@ +//! SPI Commands for the Waveshare 7.5" 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)] +#[allow(non_camel_case_types)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + DRIVER_OUTPUT_CONTROL = 0x01, + + /// Set gate driving voltage + GATE_DRIVING_VOLTAGE_CONTROL = 0x03, + + /// Set source driving voltage + SOURCE_DRIVING_VOLTAGE_CONTROL = 0x04, + + SOFT_START = 0x0C, + + /// Set the scanning start position of the gate driver. + /// The valid range is from 0 to 679. + GATE_SCAN_START_POSITION = 0x0F, + + /// Deep sleep mode control + DEEP_SLEEP = 0x10, + + /// Define data entry sequence + DATA_ENTRY = 0x11, + + /// resets the commands and parameters to their S/W Reset default values except R10h-Deep Sleep Mode. + /// During operation, BUSY pad will output high. + /// Note: RAM are unaffected by this command. + SW_RESET = 0x12, + + /// After this command initiated, HV Ready detection starts. + /// BUSY pad will output high during detection. + /// The detection result can be read from the Status Bit Read (Command 0x2F). + HV_READY_DETECTION = 0x14, + + /// After this command initiated, VCI detection starts. + /// BUSY pad will output high during detection. + /// The detection result can be read from the Status Bit Read (Command 0x2F). + VCI_DETECTION = 0x15, + + /// Temperature Sensor Selection + TEMPERATURE_SENSOR_CONTROL = 0x18, + + /// Write to temperature register + TEMPERATURE_SENSOR_WRITE = 0x1A, + + /// Read from temperature register + TEMPERATURE_SENSOR_READ = 0x1B, + + /// Write Command to External temperature sensor. + TEMPERATURE_SENSOR_WRITE_EXTERNAL = 0x1C, + + /// Activate Display Update Sequence + MASTER_ACTIVATION = 0x20, + + /// RAM content option for Display Update + DISPLAY_UPDATE_CONTROL_1 = 0x21, + + /// Display Update Sequence Option + DISPLAY_UPDATE_CONTROL_2 = 0x22, + + /// After this command, data entries will be written into the BW RAM until another command is written + WRITE_RAM_BW = 0x24, + + /// After this command, data entries will be written into the RED RAM until another command is written + WRITE_RAM_RED = 0x26, + + /// Fetch data from RAM + READ_RAM = 0x27, + + /// Enter VCOM sensing conditions + VCOM_SENSE = 0x28, + + /// Enter VCOM sensing conditions + VCOM_SENSE_DURATION = 0x29, + + /// Program VCOM register into OTP + VCOM_PROGRAM_OTP = 0x2A, + + /// Reduces a glitch when ACVCOM is toggled + VCOM_CONTROL = 0x2B, + + /// Write VCOM register from MCU interface + VCOM_WRITE = 0x2C, + + /// Read Register for Display Option + OTP_READ = 0x2D, + + /// CRC calculation command for OTP content validation + CRC_CALCULATION = 0x34, + + /// CRC Status Read + CRC_READ = 0x35, + + /// Program OTP Selection according to the OTP Selection Control + PROGRAM_SELECTION = 0x36, + + /// Write Register for Display Option + DISPLAY_OPTION_WRITE = 0x37, + + /// Write register for User ID + USER_ID_WRITE = 0x38, + + /// Select border waveform for VBD + VBD_CONTROL = 0x3C, + + /// Read RAM Option + READ_RAM_OPTION = 0x41, + + /// Specify the start/end positions of the window address in the X direction by an address unit for RAM + SET_RAM_X_START_END = 0x44, + + /// Specify the start/end positions of the window address in the Y direction by an address unit for RAM + SET_RAM_Y_START_END = 0x45, + + /// Auto write RED RAM for regular pattern + AUTO_WRITE_RED = 0x46, + + /// Auto write B/W RAM for regular pattern + AUTO_WRITE_BW = 0x47, + + /// Make initial settings for the RAM X address in the address counter (AC) + SET_RAM_X_AC = 0x4E, + + /// Make initial settings for the RAM Y address in the address counter (AC) + SET_RAM_Y_AC = 0x4F, + + /// This command is an empty command; it does not have any effect on the display module. + /// However, it can be used to terminate Frame Memory Write or Read Commands. + NOP = 0x7F, +} + +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::PANEL_SETTING.address(), 0x00); + // assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + } +} diff --git a/src/epd7in5_hd/graphics.rs b/src/epd7in5_hd/graphics.rs new file mode 100644 index 0000000..1bee110 --- /dev/null +++ b/src/epd7in5_hd/graphics.rs @@ -0,0 +1,149 @@ +use crate::epd7in5_hd::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; +use crate::graphics::{Display, DisplayRotation}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::*; + +/// Full size buffer for use with the 7in5 EPD +/// +/// Can also be manually constructed: +/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 8 * HEIGHT]` +pub struct Display7in5 { + buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation, +} + +impl Default for Display7in5 { + fn default() -> Self { + Display7in5 { + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); + WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display7in5 { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl Display for Display7in5 { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::color::{Black, Color}; + use crate::epd7in5_hd; + use crate::graphics::{Display, DisplayRotation}; + use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + + // test buffer length + #[test] + fn graphics_size() { + let display = Display7in5::default(); + assert_eq!(display.buffer().len(), 58080); + } + + // test default background color on all bytes + #[test] + fn graphics_default() { + let display = Display7in5::default(); + for &byte in display.buffer() { + assert_eq!(byte, epd7in5_hd::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_0() { + let mut display = Display7in5::default(); + + let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd7in5_hd::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_90() { + let mut display = Display7in5::default(); + display.set_rotation(DisplayRotation::Rotate90); + + let _ = Line::new(Point::new(0, 792), Point::new(0, 799)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd7in5_hd::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_180() { + let mut display = Display7in5::default(); + display.set_rotation(DisplayRotation::Rotate180); + + let _ = Line::new(Point::new(792, 479), Point::new(799, 479)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd7in5_hd::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } + + #[test] + fn graphics_rotation_270() { + let mut display = Display7in5::default(); + display.set_rotation(DisplayRotation::Rotate270); + + let _ = Line::new(Point::new(479, 0), Point::new(479, 7)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + let buffer = display.buffer(); + + assert_eq!(buffer[0], Color::Black.get_byte_value()); + + for &byte in buffer.iter().skip(1) { + assert_eq!(byte, epd7in5_hd::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } +} diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs new file mode 100644 index 0000000..7e832b8 --- /dev/null +++ b/src/epd7in5_hd/mod.rs @@ -0,0 +1,275 @@ +//! A simple Driver for the Waveshare 7.5" E-Ink Display (HD) via SPI +//! +//! # References +//! +//! - [Datasheet](https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf) +//! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py) +//! +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::{InputPin, OutputPin}, +}; + +use crate::color::Color; +use crate::interface::DisplayInterface; +use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; + +pub(crate) mod command; +use self::command::Command; + +#[cfg(feature = "graphics")] +mod graphics; +#[cfg(feature = "graphics")] +pub use self::graphics::Display7in5; + +/// Width of the display +pub const WIDTH: u32 = 880; +/// Height of the display +pub const HEIGHT: u32 = 528; +/// Default Background Color +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::Black; // Inverted for HD (0xFF = White) +const IS_BUSY_LOW: bool = false; + +/// EPD7in5 (HD) driver +/// +pub struct EPD7in5 { + /// Connection Interface + interface: DisplayInterface, + /// Background Color + color: Color, +} + +impl InternalWiAdditions + for EPD7in5 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn init>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + // Reset the device + self.interface.reset(delay, 2); + + // HD procedure as described here: + // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd7in5_HD.py + // and as per specs: + // https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf + + self.wait_until_idle(); + self.command(spi, Command::SW_RESET)?; + self.wait_until_idle(); + + self.cmd_with_data(spi, Command::AUTO_WRITE_RED, &[0xF7])?; + self.wait_until_idle(); + self.cmd_with_data(spi, Command::AUTO_WRITE_BW, &[0xF7])?; + self.wait_until_idle(); + + self.cmd_with_data(spi, Command::SOFT_START, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40])?; + + self.cmd_with_data(spi, Command::DRIVER_OUTPUT_CONTROL, &[0xAF, 0x02, 0x01])?; + + self.cmd_with_data(spi, Command::DATA_ENTRY, &[0x01])?; + + self.cmd_with_data(spi, Command::SET_RAM_X_START_END, &[0x00, 0x00, 0x6F, 0x03])?; + self.cmd_with_data(spi, Command::SET_RAM_Y_START_END, &[0xAF, 0x02, 0x00, 0x00])?; + + self.cmd_with_data(spi, Command::VBD_CONTROL, &[0x05])?; + + self.cmd_with_data(spi, Command::TEMPERATURE_SENSOR_CONTROL, &[0x80])?; + + self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xB1])?; + + self.command(spi, Command::MASTER_ACTIVATION)?; + self.wait_until_idle(); + + self.cmd_with_data(spi, Command::SET_RAM_X_AC, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + + Ok(()) + } +} + +impl WaveshareDisplay + for EPD7in5 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + type DisplayColor = Color; + fn new>( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + 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) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0x01])?; + Ok(()) + } + + fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::WRITE_RAM_BW, buffer)?; + self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; + Ok(()) + } + + fn update_partial_frame( + &mut self, + _spi: &mut SPI, + _buffer: &[u8], + _x: u32, + _y: u32, + _width: u32, + _height: u32, + ) -> Result<(), SPI::Error> { + unimplemented!(); + } + + fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.command(spi, Command::MASTER_ACTIVATION)?; + self.wait_until_idle(); + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let pixel_count = WIDTH * HEIGHT / 8; + let blank_frame = [0xFF; (WIDTH * HEIGHT / 8) as usize]; + + // self.update_and_display_frame(spi, &blank_frame)?; + + self.wait_until_idle(); + self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + + for cmd in &[Command::WRITE_RAM_BW, Command::WRITE_RAM_RED] { + self.command(spi, *cmd)?; + self.interface.data_x_times(spi, 0xFF, pixel_count)?; + } + + self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; + self.command(spi, Command::MASTER_ACTIVATION)?; + self.wait_until_idle(); + 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, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + unimplemented!(); + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl EPD7in5 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + 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 wait_until_idle(&mut self) { + self.interface.wait_until_idle(IS_BUSY_LOW) + } + + // fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + // unimplemented!(); + // // let w = self.width(); + // // let h = self.height(); + + // // self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + + // // self.command(spi, Command::TCON_RESOLUTION)?; + // // 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, 880); + assert_eq!(HEIGHT, 528); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::Black); + } +} diff --git a/src/interface.rs b/src/interface.rs index 58fbebb..599e8f2 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -16,7 +16,7 @@ pub(crate) struct DisplayInterface { busy: BUSY, /// Data/Command Control Pin (High for data, Low for command) dc: DC, - /// Pin for Reseting + /// Pin for Resetting rst: RST, } @@ -107,7 +107,7 @@ where spi.write(data)?; } - // deativate spi with cs high + // deactivate spi with cs high let _ = self.cs.set_high(); Ok(()) diff --git a/src/lib.rs b/src/lib.rs index 60a816e..5885740 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,6 +82,7 @@ pub mod epd2in9bc; pub mod epd4in2; pub mod epd5in65f; pub mod epd7in5; +pub mod epd7in5_hd; pub mod epd7in5_v2; pub(crate) mod type_a; From ba432ccf910ca20398f37cdf9cc18edf66402dac Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 31 Mar 2021 11:09:32 +0100 Subject: [PATCH 30/80] Removed unused code --- src/epd7in5_hd/mod.rs | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 7e832b8..d0728b9 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -171,9 +171,6 @@ where fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let pixel_count = WIDTH * HEIGHT / 8; - let blank_frame = [0xFF; (WIDTH * HEIGHT / 8) as usize]; - - // self.update_and_display_frame(spi, &blank_frame)?; self.wait_until_idle(); self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; @@ -230,10 +227,6 @@ where 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, @@ -246,20 +239,6 @@ where fn wait_until_idle(&mut self) { self.interface.wait_until_idle(IS_BUSY_LOW) } - - // fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - // unimplemented!(); - // // let w = self.width(); - // // let h = self.height(); - - // // self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; - - // // self.command(spi, Command::TCON_RESOLUTION)?; - // // 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)] From 73c98d86e779343480a769e8355e12a6dadcb50f Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 31 Mar 2021 11:09:58 +0100 Subject: [PATCH 31/80] Added back tests for epd7in5_hd commands --- src/epd7in5_hd/command.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/epd7in5_hd/command.rs b/src/epd7in5_hd/command.rs index f656f9f..98ff4bb 100644 --- a/src/epd7in5_hd/command.rs +++ b/src/epd7in5_hd/command.rs @@ -152,7 +152,8 @@ mod tests { #[test] fn command_addr() { - // assert_eq!(Command::PANEL_SETTING.address(), 0x00); - // assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::MASTER_ACTIVATION.address(), 0x20); + assert_eq!(Command::SW_RESET.address(), 0x12); + assert_eq!(Command::DISPLAY_UPDATE_CONTROL_2.address(), 0x22); } } From 9a1575b2ec113489fe2221679a665ebec325b61c Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Sun, 4 Apr 2021 22:10:50 +0200 Subject: [PATCH 32/80] API change to partially fix #70 --- examples/epd1in54_no_graphics.rs | 14 +++--- examples/epd2in13_v2.rs | 14 +++--- examples/epd4in2.rs | 14 +++--- examples/epd4in2_variable_size.rs | 6 +-- src/epd1in54/mod.rs | 55 +++++++++++---------- src/epd1in54b/mod.rs | 62 +++++++++++++----------- src/epd1in54c/mod.rs | 62 +++++++++++++----------- src/epd2in13_v2/mod.rs | 59 ++++++++++++----------- src/epd2in7b/mod.rs | 60 ++++++++++++----------- src/epd2in9/mod.rs | 55 +++++++++++---------- src/epd2in9bc/mod.rs | 62 +++++++++++++----------- src/epd4in2/mod.rs | 60 ++++++++++++----------- src/epd5in65f/mod.rs | 61 +++++++++++++----------- src/epd7in5/mod.rs | 55 +++++++++++---------- src/epd7in5_v2/mod.rs | 79 ++++++++++++++++++------------- src/interface.rs | 39 +++++++++++---- src/traits.rs | 48 +++++++++++-------- 17 files changed, 451 insertions(+), 354 deletions(-) diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 7fd30ae..40931ae 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -61,8 +61,8 @@ fn main() -> Result<(), std::io::Error> { let mut epd = EPD1in54::new(&mut spi, cs_pin, busy, dc, rst, &mut delay)?; // Clear the full screen - epd.clear_frame(&mut spi)?; - epd.display_frame(&mut spi)?; + epd.clear_frame(&mut spi, &mut delay)?; + epd.display_frame(&mut spi, &mut delay)?; // Speeddemo epd.set_lut(&mut spi, Some(RefreshLUT::QUICK))?; @@ -71,12 +71,12 @@ fn main() -> Result<(), std::io::Error> { for i in 0..number_of_runs { let offset = i * 8 % 150; epd.update_partial_frame(&mut spi, &small_buffer, 25 + offset, 25 + offset, 16, 16)?; - epd.display_frame(&mut spi)?; + epd.display_frame(&mut spi, &mut delay)?; } // Clear the full screen - epd.clear_frame(&mut spi)?; - epd.display_frame(&mut spi)?; + epd.clear_frame(&mut spi, &mut delay)?; + epd.display_frame(&mut spi, &mut delay)?; // Draw some squares let small_buffer = [Color::Black.get_byte_value(); 3200]; //160x160 @@ -89,11 +89,11 @@ fn main() -> Result<(), std::io::Error> { epd.update_partial_frame(&mut spi, &small_buffer, 96, 96, 8, 8)?; // Display updated frame - epd.display_frame(&mut spi)?; + epd.display_frame(&mut spi, &mut delay)?; delay.delay_ms(5000u16); // Set the EPD to sleep - epd.sleep(&mut spi)?; + epd.sleep(&mut spi, &mut delay)?; Ok(()) } diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index ac509c3..b695993 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -80,9 +80,9 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd2in13.update_frame(&mut spi, &display.buffer())?; + epd2in13.update_frame(&mut spi, &display.buffer(), &mut delay)?; epd2in13 - .display_frame(&mut spi) + .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); delay.delay_ms(5000u16); @@ -123,7 +123,7 @@ fn main() -> Result<(), std::io::Error> { epd2in13 .set_refresh(&mut spi, &mut delay, RefreshLUT::QUICK) .unwrap(); - epd2in13.clear_frame(&mut spi).unwrap(); + epd2in13.clear_frame(&mut spi, &mut delay).unwrap(); // a moving `Hello World!` let limit = 10; @@ -131,7 +131,7 @@ fn main() -> Result<(), std::io::Error> { draw_text(&mut display, " Hello World! ", 5 + i * 12, 50); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer()) + .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) .expect("display frame new graphics"); delay.delay_ms(1_000u16); } @@ -140,7 +140,7 @@ fn main() -> Result<(), std::io::Error> { // the screen can refresh for this kind of change (small single character) display.clear_buffer(Color::White); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer()) + .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) .unwrap(); let spinner = ["|", "/", "-", "\\"]; @@ -148,12 +148,12 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); draw_text(&mut display, spinner[i % spinner.len()], 10, 100); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer()) + .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) .unwrap(); } println!("Finished tests - going to sleep"); - epd2in13.sleep(&mut spi) + epd2in13.sleep(&mut spi, &mut delay) } fn draw_text(display: &mut Display2in13, text: &str, x: i32, y: i32) { diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 04730ed..5ac80da 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -80,9 +80,9 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd4in2.update_frame(&mut spi, &display.buffer())?; + epd4in2.update_frame(&mut spi, &display.buffer(), &mut delay)?; epd4in2 - .display_frame(&mut spi) + .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); delay.delay_ms(5000u16); @@ -121,22 +121,24 @@ fn main() -> Result<(), std::io::Error> { // a moving `Hello World!` let limit = 10; epd4in2.set_lut(&mut spi, Some(RefreshLUT::QUICK)).unwrap(); - epd4in2.clear_frame(&mut spi).unwrap(); + epd4in2.clear_frame(&mut spi, &mut delay).unwrap(); for i in 0..limit { //println!("Moving Hello World. Loop {} from {}", (i + 1), limit); draw_text(&mut display, " Hello World! ", 5 + i * 12, 50); - epd4in2.update_frame(&mut spi, &display.buffer()).unwrap(); epd4in2 - .display_frame(&mut spi) + .update_frame(&mut spi, &display.buffer(), &mut delay) + .unwrap(); + epd4in2 + .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); delay.delay_ms(1_000u16); } println!("Finished tests - going to sleep"); - epd4in2.sleep(&mut spi) + epd4in2.sleep(&mut spi, &mut delay) } fn draw_text(display: &mut Display4in2, text: &str, x: i32, y: i32) { diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 6c03851..5fd8123 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -88,7 +88,7 @@ fn main() -> Result<(), std::io::Error> { .update_partial_frame(&mut spi, &display.buffer(), x, y, width, height) .unwrap(); epd4in2 - .display_frame(&mut spi) + .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); delay.delay_ms(5000u16); @@ -137,14 +137,14 @@ fn main() -> Result<(), std::io::Error> { .update_partial_frame(&mut spi, &display.buffer(), x, y, width, height) .unwrap(); epd4in2 - .display_frame(&mut spi) + .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); delay.delay_ms(1_000u16); } println!("Finished tests - going to sleep"); - epd4in2.sleep(&mut spi) + epd4in2.sleep(&mut spi, &mut delay) } fn draw_text(display: &mut VarDisplay, text: &str, x: i32, y: i32) { diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 66420ea..cd2e149 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -72,28 +72,25 @@ pub use crate::epd1in54::graphics::Display1in54; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10); // 3 Databytes: @@ -142,14 +139,15 @@ where } } -impl WaveshareDisplay - for EPD1in54 +impl WaveshareDisplay + for EPD1in54 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -160,7 +158,7 @@ where HEIGHT } - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -181,15 +179,11 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here or would 0x01 be even more efficient? @@ -198,7 +192,12 @@ where Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.use_full_frame(spi)?; self.interface @@ -225,7 +224,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) @@ -239,13 +238,18 @@ where Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.use_full_frame(spi)?; @@ -285,16 +289,17 @@ where } } -impl EPD1in54 +impl EPD1in54 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } pub(crate) fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index c14050e..c34efdc 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -33,25 +33,22 @@ mod graphics; pub use self::graphics::Display1in54b; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10); // set the power settings @@ -88,14 +85,15 @@ where } } -impl WaveshareThreeColorDisplay - for EPD1in54b +impl WaveshareThreeColorDisplay + for EPD1in54b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn update_color_frame( &mut self, @@ -133,17 +131,18 @@ where } } -impl WaveshareDisplay - for EPD1in54b +impl WaveshareDisplay + for EPD1in54b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -161,7 +160,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating @@ -181,11 +180,7 @@ where Ok(()) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } @@ -205,7 +200,12 @@ where HEIGHT } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.send_resolution(spi)?; @@ -245,19 +245,24 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.send_resolution(spi)?; @@ -307,13 +312,14 @@ where } } -impl EPD1in54b +impl EPD1in54b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -333,7 +339,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index f8bd54d..f226cfe 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -31,25 +31,22 @@ mod graphics; pub use self::graphics::Display1in54c; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Based on Reference Program Code from: // https://www.waveshare.com/w/upload/a/ac/1.54inch_e-Paper_Module_C_Specification.pdf // and: @@ -76,14 +73,15 @@ where } } -impl WaveshareThreeColorDisplay - for EPD1in54c +impl WaveshareThreeColorDisplay + for EPD1in54c where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn update_color_frame( &mut self, @@ -114,17 +112,18 @@ where } } -impl WaveshareDisplay - for EPD1in54c +impl WaveshareDisplay + for EPD1in54c where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -142,7 +141,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::POWER_OFF)?; @@ -152,11 +151,7 @@ where Ok(()) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } @@ -176,7 +171,12 @@ where HEIGHT } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.update_achromatic_frame(spi, buffer)?; // Clear the chromatic layer @@ -201,21 +201,26 @@ where unimplemented!() } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.command(spi, Command::DISPLAY_REFRESH)?; self.wait_until_idle(); Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -243,13 +248,14 @@ where } } -impl EPD1in54c +impl EPD1in54c where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -269,7 +275,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 704d262..fe661e5 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -45,9 +45,9 @@ const IS_BUSY_LOW: bool = false; /// EPD2in13 (V2) driver /// -pub struct EPD2in13 { +pub struct EPD2in13 { /// Connection Interface - interface: DisplayInterface, + interface: DisplayInterface, sleep_mode: DeepSleepMode, @@ -56,20 +56,17 @@ pub struct EPD2in13 { refresh: RefreshLUT, } -impl InternalWiAdditions - for EPD2in13 +impl InternalWiAdditions + for EPD2in13 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // HW reset self.interface.reset(delay, 10); @@ -157,17 +154,18 @@ where } } -impl WaveshareDisplay - for EPD2in13 +impl WaveshareDisplay + for EPD2in13 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -186,15 +184,11 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // All sample code enables and disables analog/clocks... @@ -212,7 +206,12 @@ where Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { assert!(buffer.len() == buffer_len(WIDTH as usize, HEIGHT as usize)); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; @@ -269,7 +268,7 @@ where /// Never use directly this function when using partial refresh, or also /// keep the base buffer in syncd using `set_partial_base_buffer` function. - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { if self.refresh == RefreshLUT::FULL { self.set_display_update_control_2( spi, @@ -289,9 +288,14 @@ where Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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)?; if self.refresh == RefreshLUT::QUICK { self.set_partial_base_buffer(spi, buffer)?; @@ -299,7 +303,7 @@ where Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { let color = self.background_color.get_byte_value(); self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; @@ -361,13 +365,14 @@ where } } -impl EPD2in13 +impl EPD2in13 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// When using partial refresh, the controller uses the provided buffer for /// comparison with new buffer. @@ -391,7 +396,7 @@ where /// Sets the refresh mode. When changing mode, the screen will be /// re-initialized accordingly. - pub fn set_refresh>( + pub fn set_refresh( &mut self, spi: &mut SPI, delay: &mut DELAY, @@ -559,7 +564,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 666add7..4a19aab 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -35,27 +35,24 @@ mod graphics; pub use self::graphics::Display2in7b; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device self.interface.reset(delay, 2); @@ -111,17 +108,18 @@ where } } -impl WaveshareDisplay - for EPD2in7b +impl WaveshareDisplay + for EPD2in7b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -139,15 +137,11 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0xf7])?; @@ -159,7 +153,12 @@ where Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; self.send_buffer_helper(spi, buffer)?; @@ -201,19 +200,24 @@ where self.interface.cmd(spi, Command::DATA_STOP) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.command(spi, Command::DISPLAY_REFRESH)?; self.wait_until_idle(); Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; + 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::DISPLAY_REFRESH)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); let color_value = self.color.get_byte_value(); @@ -267,14 +271,15 @@ where } } -impl WaveshareThreeColorDisplay - for EPD2in7b +impl WaveshareThreeColorDisplay + for EPD2in7b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn update_color_frame( &mut self, @@ -322,13 +327,14 @@ where } } -impl EPD2in7b +impl EPD2in7b where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -357,7 +363,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } /// Refresh display for partial frame diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index d2fbabb..4288562 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -72,28 +72,25 @@ pub use crate::epd2in9::graphics::Display2in9; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 10); self.wait_until_idle(); @@ -138,14 +135,15 @@ where } } -impl WaveshareDisplay - for EPD2in9 +impl WaveshareDisplay + for EPD2in9 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -156,7 +154,7 @@ where HEIGHT } - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -177,7 +175,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) @@ -186,17 +184,18 @@ where Ok(()) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.init(spi, delay)?; Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.use_full_frame(spi)?; @@ -224,7 +223,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) @@ -238,13 +237,18 @@ where Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.use_full_frame(spi)?; @@ -284,16 +288,17 @@ where } } -impl EPD2in9 +impl EPD2in9 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 300352c..6bfb6c4 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -90,25 +90,22 @@ mod graphics; pub use self::graphics::Display2in9bc; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Values taken from datasheet and sample code self.interface.reset(delay, 10); @@ -142,14 +139,15 @@ where } } -impl WaveshareThreeColorDisplay - for EPD2in9bc +impl WaveshareThreeColorDisplay + for EPD2in9bc where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn update_color_frame( &mut self, @@ -188,17 +186,18 @@ where } } -impl WaveshareDisplay - for EPD2in9bc +impl WaveshareDisplay + for EPD2in9bc where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -216,7 +215,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { // Section 8.2 from datasheet self.interface.cmd_with_data( spi, @@ -233,11 +232,7 @@ where Ok(()) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } @@ -257,7 +252,12 @@ where HEIGHT } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.interface .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; @@ -287,20 +287,25 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.command(spi, Command::DISPLAY_REFRESH)?; self.wait_until_idle(); Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.send_resolution(spi)?; let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); @@ -333,13 +338,14 @@ where } } -impl EPD2in9bc +impl EPD2in9bc where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -359,7 +365,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 636b254..e48a23c 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -81,29 +81,26 @@ pub use self::graphics::Display4in2; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // reset the device self.interface.reset(delay, 10); @@ -148,17 +145,18 @@ where } } -impl WaveshareDisplay - for EPD4in2 +impl WaveshareDisplay + for EPD4in2 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -180,15 +178,11 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating @@ -207,7 +201,12 @@ where Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); let color_value = self.color.get_byte_value(); @@ -267,19 +266,24 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; + 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::DISPLAY_REFRESH)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.send_resolution(spi)?; @@ -341,13 +345,14 @@ where } } -impl EPD4in2 +impl EPD4in2 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -367,7 +372,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { @@ -437,14 +442,15 @@ where } } -impl QuickRefresh - for EPD4in2 +impl QuickRefresh + for EPD4in2 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// To be followed immediately after by `update_old_frame`. fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index d10dddc..aefb3c3 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -33,27 +33,24 @@ const IS_BUSY_LOW: 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device self.interface.reset(delay, 2); @@ -76,17 +73,18 @@ where } } -impl WaveshareDisplay - for EPD5in65f +impl WaveshareDisplay + for EPD5in65f where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = OctColor; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -104,20 +102,21 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_busy_high(); self.send_resolution(spi)?; self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, buffer)?; @@ -136,7 +135,7 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_busy_high(); self.command(spi, Command::POWER_ON)?; self.wait_busy_high(); @@ -147,19 +146,24 @@ where Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let bg = OctColor::colors_byte(self.color, self.color); self.wait_busy_high(); self.send_resolution(spi)?; self.command(spi, Command::DATA_START_TRANSMISSION_1)?; self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; - self.display_frame(spi)?; + self.display_frame(spi, delay)?; Ok(()) } @@ -192,13 +196,14 @@ where } } -impl EPD5in65f +impl EPD5in65f where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -218,10 +223,10 @@ where } fn wait_busy_high(&mut self) { - self.interface.wait_until_idle(true) + let _ = self.interface.wait_until_idle(true, None); } fn wait_busy_low(&mut self) { - self.interface.wait_until_idle(false) + let _ = self.interface.wait_until_idle(false, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 883deb3..4e2c6c4 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -33,27 +33,24 @@ const IS_BUSY_LOW: bool = true; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device self.interface.reset(delay, 10); @@ -99,17 +96,18 @@ where } } -impl WaveshareDisplay - for EPD7in5 +impl WaveshareDisplay + for EPD7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -127,15 +125,11 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::POWER_OFF)?; self.wait_until_idle(); @@ -143,7 +137,12 @@ where Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::DATA_START_TRANSMISSION_1)?; for byte in buffer { @@ -172,19 +171,24 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; + 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::DISPLAY_REFRESH)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.send_resolution(spi)?; @@ -224,13 +228,14 @@ where } } -impl EPD7in5 +impl EPD7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -250,7 +255,7 @@ where } fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 67f9dab..8e81b90 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -37,27 +37,24 @@ const IS_BUSY_LOW: bool = true; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device self.interface.reset(delay, 2); @@ -69,29 +66,30 @@ where self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x27, 0x17])?; self.cmd_with_data(spi, Command::POWER_SETTING, &[0x07, 0x17, 0x3F, 0x3F])?; self.command(spi, Command::POWER_ON)?; - self.wait_until_idle(); + self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x1F])?; self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x06])?; self.cmd_with_data(spi, Command::TCON_RESOLUTION, &[0x03, 0x20, 0x01, 0xE0])?; self.cmd_with_data(spi, Command::DUAL_SPI, &[0x00])?; self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?; self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x10, 0x07])?; - self.wait_until_idle(); + self.wait_until_idle(spi, delay)?; Ok(()) } } -impl WaveshareDisplay - for EPD7in5 +impl WaveshareDisplay + for EPD7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -109,24 +107,25 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.wait_until_idle(); + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; self.command(spi, Command::POWER_OFF)?; - self.wait_until_idle(); + self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.wait_until_idle(); + 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::DATA_START_TRANSMISSION_2, buffer)?; Ok(()) } @@ -143,20 +142,25 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.wait_until_idle(); + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(spi, delay)?; self.command(spi, Command::DISPLAY_REFRESH)?; Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; + 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::DISPLAY_REFRESH)?; Ok(()) } - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.wait_until_idle(); + 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::DATA_START_TRANSMISSION_1)?; @@ -198,13 +202,14 @@ where } } -impl EPD7in5 +impl EPD7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) @@ -223,8 +228,16 @@ where self.interface.cmd_with_data(spi, command, data) } - fn wait_until_idle(&mut self) { - self.interface.wait_until_idle(IS_BUSY_LOW) + fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle( + IS_BUSY_LOW, + Some((spi, delay, |i, s, d| { + i.cmd(s, Command::GET_STATUS)?; + d.delay_ms(20); + Ok(()) + })), + )?; + Ok(()) } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/interface.rs b/src/interface.rs index 58fbebb..f8a7ee5 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -7,9 +7,11 @@ use embedded_hal::{ /// The Connection Interface of all (?) Waveshare EPD-Devices /// -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! @@ -20,17 +22,19 @@ pub(crate) struct DisplayInterface { rst: RST, } -impl DisplayInterface +impl DisplayInterface where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { pub fn new(cs: CS, busy: BUSY, dc: DC, rst: RST) -> Self { DisplayInterface { _spi: PhantomData::default(), + _delay: PhantomData::default(), cs, busy, dc, @@ -126,15 +130,32 @@ 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 wait_until_idle(&mut self, is_busy_low: bool) { - //tested: worked without the delay for all tested devices - //self.delay_ms(1); + pub(crate) fn wait_until_idle( + &mut self, + is_busy_low: bool, + mut task: Option<( + &mut SPI, + &mut DELAY, + fn(&mut Self, &mut SPI, &mut DELAY) -> Result<(), SPI::Error>, + )>, + ) -> Result<(), SPI::Error> { + // //tested: worked without the delay for all tested devices + // //self.delay_ms(1); + // Some displays need special treatment (Only 7.5"V2 known so far) + // In those cases, a "task" is provided and run here. If note, this + // just busy waits for the display. while self.is_busy(is_busy_low) { - //tested: REMOVAL of DELAY: it's only waiting for the signal anyway and should continue work asap - //old: shorten the time? it was 100 in the beginning - //self.delay_ms(5); + match task { + // TODO: Ignore this error? + Some((ref mut spi, ref mut delay, tcb)) => tcb(self, spi, delay)?, + None => {} + } + // //tested: REMOVAL of DELAY: it's only waiting for the signal anyway and should continue work asap + // //old: shorten the time? it was 100 in the beginning + // //self.delay_ms(5); } + Ok(()) } /// Checks if device is still busy @@ -162,7 +183,7 @@ where /// The timing of keeping the reset pin low seems to be important and different per device. /// Most displays seem to require keeping it low for 10ms, but the 7in5_v2 only seems to reset /// properly with 2ms - pub(crate) fn reset>(&mut self, delay: &mut DELAY, duration: u8) { + pub(crate) fn reset(&mut self, delay: &mut DELAY, duration: u8) { let _ = self.rst.set_high(); delay.delay_ms(10); diff --git a/src/traits.rs b/src/traits.rs index d4877b5..71de7b2 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -26,13 +26,14 @@ impl Default for RefreshLUT { } } -pub(crate) trait InternalWiAdditions +pub(crate) trait InternalWiAdditions where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// This initialises the EPD and powers it up /// @@ -44,22 +45,19 @@ where /// This function calls [reset](WaveshareDisplay::reset), /// so you don't need to call reset your self when trying to wake your device up /// after setting it to sleep. - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; } /// Functions to interact with three color panels -pub trait WaveshareThreeColorDisplay: - WaveshareDisplay +pub trait WaveshareThreeColorDisplay: + WaveshareDisplay where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// Transmit data to the SRAM of the EPD /// @@ -127,20 +125,21 @@ where ///# Ok(()) ///# } ///``` -pub trait WaveshareDisplay +pub trait WaveshareDisplay where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// The Color Type used by the Display type DisplayColor; /// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC /// /// This already initialises the device. - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -154,16 +153,12 @@ where /// Let the device enter deep-sleep mode to save power. /// /// The deep sleep mode returns to standby with a hardware reset. - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; + fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Wakes the device up from sleep /// /// Also reintialises the device if necessary. - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error>; + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame) fn set_background_color(&mut self, color: Self::DisplayColor); @@ -178,7 +173,12 @@ where fn height(&self) -> u32; /// Transmit a full frame to the SRAM of the EPD - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Transmits partial data to the SRAM of the EPD /// @@ -198,15 +198,20 @@ where /// Displays the frame data from SRAM /// /// This function waits until the device isn`t busy anymore - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Provide a combined update&display and save some time (skipping a busy check in between) - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Clears the frame buffer on the EPD with the declared background color /// /// The background color can be changed with [`WaveshareDisplay::set_background_color`] - fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error>; + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>; /// Trait for using various Waveforms from different LUTs /// E.g. for partial refreshes @@ -275,13 +280,14 @@ where ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// Updates the old frame. fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; From 04476e6671c620751a8f8cf3d4496ac440efafc0 Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Sun, 4 Apr 2021 22:26:50 +0200 Subject: [PATCH 33/80] fix tests --- src/epd1in54/mod.rs | 6 +++--- src/epd2in9/mod.rs | 6 +++--- src/epd2in9bc/mod.rs | 4 ++-- src/epd4in2/mod.rs | 6 +++--- src/lib.rs | 6 +++--- src/traits.rs | 8 ++++---- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index cd2e149..d82fe21 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -31,11 +31,11 @@ //! .draw(&mut display); //! //!// Display updated frame -//!epd.update_frame(&mut spi, &display.buffer())?; -//!epd.display_frame(&mut spi)?; +//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 4288562..881f32b 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -32,11 +32,11 @@ //! .draw(&mut display); //! //! // Display updated frame -//!epd.update_frame(&mut spi, &display.buffer())?; -//!epd.display_frame(&mut spi)?; +//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 6bfb6c4..2be3e57 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -46,10 +46,10 @@ //! &mono_display.buffer(), //! &chromatic_display.buffer() //!)?; -//!epd.display_frame(&mut spi)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index e48a23c..119edea 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -36,11 +36,11 @@ //! .draw(&mut display); //! //! // Display updated frame -//!epd.update_frame(&mut spi, &display.buffer())?; -//!epd.display_frame(&mut spi)?; +//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` diff --git a/src/lib.rs b/src/lib.rs index 60a816e..478acd3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,11 +39,11 @@ //! .draw(&mut display); //! //! // Display updated frame -//!epd.update_frame(&mut spi, &display.buffer())?; -//!epd.display_frame(&mut spi)?; +//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` diff --git a/src/traits.rs b/src/traits.rs index 71de7b2..f5c1f34 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -117,11 +117,11 @@ where /// .draw(&mut display); /// /// // Display updated frame -///epd.update_frame(&mut spi, &display.buffer())?; -///epd.display_frame(&mut spi)?; +///epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +///epd.display_frame(&mut spi, &mut delay)?; /// ///// Set the EPD to sleep -///epd.sleep(&mut spi)?; +///epd.sleep(&mut spi, &mut delay)?; ///# Ok(()) ///# } ///``` @@ -134,7 +134,7 @@ where RST: OutputPin, DELAY: DelayMs, { - /// The Color Type used by the Display + /// The Color Type used by the Display type DisplayColor; /// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC /// From c3a4cde81559d6c0d2c6c6aa1767a23bd0cabb61 Mon Sep 17 00:00:00 2001 From: Edwin Svensson Date: Sun, 11 Apr 2021 16:57:28 +0200 Subject: [PATCH 34/80] skip closure/task --- src/epd1in54/mod.rs | 2 +- src/epd1in54b/mod.rs | 2 +- src/epd1in54c/mod.rs | 2 +- src/epd2in13_v2/mod.rs | 2 +- src/epd2in7b/mod.rs | 2 +- src/epd2in9/mod.rs | 2 +- src/epd2in9bc/mod.rs | 2 +- src/epd4in2/mod.rs | 4 ++-- src/epd5in65f/mod.rs | 4 ++-- src/epd7in5/mod.rs | 2 +- src/epd7in5_v2/mod.rs | 12 ++++-------- src/interface.rs | 20 +------------------- src/traits.rs | 3 +-- 13 files changed, 18 insertions(+), 41 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index d82fe21..2666b5a 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -299,7 +299,7 @@ where DELAY: DelayMs, { fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } pub(crate) fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index c34efdc..57a390d 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -339,7 +339,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index f226cfe..df7d728 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -275,7 +275,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index fe661e5..0dd798f 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -564,7 +564,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 4a19aab..89a04e2 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -363,7 +363,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } /// Refresh display for partial frame diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 881f32b..9f2f9f1 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -298,7 +298,7 @@ where DELAY: DelayMs, { fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn use_full_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 2be3e57..663c8dc 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -365,7 +365,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 119edea..c87aa40 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -372,7 +372,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { @@ -442,7 +442,7 @@ where } } -impl QuickRefresh +impl QuickRefresh for EPD4in2 where SPI: Write, diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index aefb3c3..7731c3e 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -223,10 +223,10 @@ where } fn wait_busy_high(&mut self) { - let _ = self.interface.wait_until_idle(true, None); + let _ = self.interface.wait_until_idle(true); } fn wait_busy_low(&mut self) { - let _ = self.interface.wait_until_idle(false, None); + let _ = self.interface.wait_until_idle(false); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 4e2c6c4..ff8ada8 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -255,7 +255,7 @@ where } fn wait_until_idle(&mut self) { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW, None); + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 8e81b90..13f1716 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -229,14 +229,10 @@ where } fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - self.interface.wait_until_idle( - IS_BUSY_LOW, - Some((spi, delay, |i, s, d| { - i.cmd(s, Command::GET_STATUS)?; - d.delay_ms(20); - Ok(()) - })), - )?; + while self.interface.is_busy(IS_BUSY_LOW) { + self.interface.cmd(spi, Command::GET_STATUS)?; + delay.delay_ms(20); + } Ok(()) } diff --git a/src/interface.rs b/src/interface.rs index f8a7ee5..3ef967b 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -130,32 +130,14 @@ 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 wait_until_idle( - &mut self, - is_busy_low: bool, - mut task: Option<( - &mut SPI, - &mut DELAY, - fn(&mut Self, &mut SPI, &mut DELAY) -> Result<(), SPI::Error>, - )>, - ) -> Result<(), SPI::Error> { + pub(crate) fn wait_until_idle(&mut self, is_busy_low: bool) { // //tested: worked without the delay for all tested devices // //self.delay_ms(1); - - // Some displays need special treatment (Only 7.5"V2 known so far) - // In those cases, a "task" is provided and run here. If note, this - // just busy waits for the display. while self.is_busy(is_busy_low) { - match task { - // TODO: Ignore this error? - Some((ref mut spi, ref mut delay, tcb)) => tcb(self, spi, delay)?, - None => {} - } // //tested: REMOVAL of DELAY: it's only waiting for the signal anyway and should continue work asap // //old: shorten the time? it was 100 in the beginning // //self.delay_ms(5); } - Ok(()) } /// Checks if device is still busy diff --git a/src/traits.rs b/src/traits.rs index f5c1f34..5ad792a 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -280,14 +280,13 @@ where ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, - DELAY: DelayMs, { /// Updates the old frame. fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; From 0567da80c088d2c879f5541125fe34173176dde1 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 11 Apr 2021 20:28:46 +0200 Subject: [PATCH 35/80] Small impros to changelog and readme --- CHANGELOG.md | 59 +++++++++++++++++++++++++++++++++------------------- README.md | 47 +++++++++++++++++++++-------------------- 2 files changed, 63 insertions(+), 43 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3eeac2..9a4ae72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,15 +8,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added - - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) - - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) + +- Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) +- Added Epd 2in7 (B) support in #60 (thanks to @pjsier) ### Changed - - Use specific ParseColorError instead of () - - EPD4in2: Don't set the resolution (and some more) over and over again (#48) -### Fixed +- Use specific ParseColorError instead of () +- EPD4in2: Don't set the resolution (and some more) over and over again (#48) +- Removed `#[allow(non_camel_case_types)]` to fix various issues around it +### Fixed ## [v0.5.0] @@ -25,56 +27,65 @@ TODO! ## [v0.4.0] - 2020-04-06 ### Added - - New supported epds: epd7in5 (thanks to @str4d), epd7in5 v2 (thanks to @asaaki), epd1in54b (thanks to @jkristell) - - Added update_and_display_frame to WaveshareDisplay trait (fixes #38) - - also improve position of busy_wait (#30) once more - - More Documenation + +- New supported epds: epd7in5 (thanks to @str4d), epd7in5 v2 (thanks to @asaaki), epd1in54b (thanks to @jkristell) +- Added update_and_display_frame to WaveshareDisplay trait (fixes #38) +- also improve position of busy_wait (#30) once more +- More Documentation ### Changed - - Update embedded-graphics to 0.6 (changes Display Trait) (and to 0.5 before thanks to @dbr) - - Remove useless Featuregates (Doesn't change size) - - Update and integrate a few important examples and remove the others - - Use Embedded_hal:digital::v2 +- Update embedded-graphics to 0.6 (changes Display Trait) (and to 0.5 before thanks to @dbr) +- Remove useless feature gates (Doesn't change size) +- Update and integrate a few important examples and remove the others +- Use Embedded_hal:digital::v2 ### Fixed - - Doc Tests +- Doc Tests ## [v0.3.2] - 2019-06-17 ### Fixed - - Added some more missing wait_until_idle calls + +- Added some more missing wait_until_idle calls ## [v0.3.1] - 2019-04-06 ### Added - - Example for epd4in2 and BluePill-Board + +- Example for epd4in2 and BluePill-Board ### Changed - - Improved CI + +- Improved CI ### Fixed - - Timing issues in display_frame function: epd1in54 and epd2in9 were both missing a necessary wait_until_idle call at the end of their display_frame function which sometimes caused invalid/ignored commands/inputs afterwards - - Some CI Targets were not tested correctly before + +- Timing issues in display_frame function: epd1in54 and epd2in9 were both missing a necessary wait_until_idle call at + the end of their display_frame function which sometimes caused invalid/ignored commands/inputs afterwards +- Some CI Targets were not tested correctly before ## [v0.3.0] - 2019-04-04 ### Added + - added eink to keywords - added reference to previous crate-name - improved readme/docs e.g. added reference to a few great arduino display libs for these epds - Added is_busy to Waveshare_Interface - Added IS_BUSY_LOW const for all supported epds - Added is_busy to DisplayInterface -- Added VarDisplay (a variable buffersize display/graphic driver) +- Added VarDisplay (a variable buffer-size display/graphic driver) - Updated and added more examples - add a feature gated alternative full lut for type_a displays ### Removed + - Removed all Buffers (Buffer1in54,...) and instead made specialised Displays (Display1in54,...) with included Buffers ### Changed + - Switch to 2018 edition - "cargo fix --edition" for the library - Use cargo fix edition-idioms and remove the internal renaming from embedded_hal to hal @@ -87,19 +98,25 @@ TODO! Initial release with Changelog ### Added + - Uses embedded-graphics now - Tested and fixed 1.54 inch, 2.9 inch and 4.2 inch display ### Removed + - Old included Graphics Library ### Changed + - Lots of internal changes - Renamed to `epd-waveshare` - [Unreleased]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.4.0...HEAD + [v0.4.0]: https://github.com/Caemor/eink-waveshare-rs/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.1]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.3.0...v0.3.1 + [v0.3.0]: https://github.com/Caemor/eink-waveshare-rs/compare/v0.2.0...v0.3.0 diff --git a/README.md b/README.md index 200e601..99fcb1b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,14 @@ [![Build Status](https://travis-ci.com/caemor/epd-waveshare.svg?branch=master)](https://travis-ci.com/caemor/epd-waveshare) -This library contains a driver for E-Paper Modules from Waveshare (which are basically the same as the Dalian Good Display ones). +This library contains a driver for E-Paper Modules from Waveshare (which are basically the same as the Dalian Good +Display ones). It uses the [embedded graphics](https://crates.io/crates/embedded-graphics) library for the optional graphics support. A 2018-edition compatible version (Rust 1.31+) is needed. -Other similiar libraries with support for much more displays are [u8g2](https://github.com/olikraus/u8g2) and [GxEPD](https://github.com/ZinggJM/GxEPD) for arduino. +Other similar libraries with support for much more displays are [u8g2](https://github.com/olikraus/u8g2) +and [GxEPD](https://github.com/ZinggJM/GxEPD) for arduino. ## Examples @@ -14,24 +16,24 @@ 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 epd = EPD4in2::new( & mut spi, cs, busy, dc, rst, & mut delay) ?; // Setup the graphics -let mut display = Display4in2::default(); +let mut display = Display4in2::default (); // Draw some text display.draw( - let _ = Text::new("Hello Rust!", Point::new(x, y)) - .into_styled(text_style!( +let _ = Text::new("Hello Rust!", Point::new(x, y)) +.into_styled(text_style!( font = Font12x16, text_color = Black, background_color = White )) - .draw(display); +.draw(display); ); // Transfer the frame data to the epd and display it -epd.update_and_display_frame(&mut spi, &display.buffer())?; +epd.update_and_display_frame( & mut spi, & display.buffer()) ?; ``` ## (Supported) Devices @@ -50,11 +52,10 @@ epd.update_and_display_frame(&mut spi, &display.buffer())?; | [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]: 7.5 Inch B/W V2 (A) -Since November 2019 Waveshare sells their updated version of these displays. -They should have a "V2" marking sticker on the backside of the panel. +Since November 2019 Waveshare sells their updated version of these displays. They should have a "V2" marking sticker on +the backside of the panel. Use `epd7in5_v2` instead of `epd7in5`, because the protocol changed. @@ -69,21 +70,23 @@ It's possible with this driver but might lead to ghosting / burn-in effects ther | Interface | Description | | :---: | :--- | -| VCC | 3.3V | -| GND | GND | -| DIN | SPI MOSI | -| CLK | SPI SCK | -| CS | SPI chip select (Low active) | -| DC | Data/Command control pin (High for data, and low for command) | -| RST | External reset pin (Low for reset) | -| BUSY | Busy state output pin (Low for busy) | +| VCC | 3.3V | +| GND | GND | +| DIN | SPI MOSI | +| CLK | SPI SCK | +| CS | SPI chip select (Low active) | +| DC | Data/Command control pin (High for data, and low for command) | +| RST | External reset pin (Low for reset) | +| BUSY | Busy state output pin (Low for busy) | ### Display Configs -There are two types of Display Configurations used in Wavedshare EPDs, which also needs to be set on the "new" E-Paper Driver HAT. -They are also called A and B, but you shouldn't get confused and mix it with the Type A,B,C and D of the various Displays, which just describe different types (colored variants) or new versions. In the Display Config the seperation is most likely due to included fast partial refresh of the displays. In a Tabular form: +There are two types of Display Configurations used in Waveshare EPDs, which also needs to be set on the "new" E-Paper +Driver HAT. They are also called A and B, but you shouldn't get confused and mix it with the Type A,B,C and D of the +various Displays, which just describe different types (colored variants) or new versions. In the Display Config the +separation is most likely due to included fast partial refresh of the displays. In a Tabular form: -| Type A | Tybe B | +| Type A | Type B | | :---: | :---: | | 1.54in (A) | 1.54in (B) | | 2.13in (A) | 1.54in (C) | From ba1b90e2f3b32237d0cbe1f00d29289b1776c464 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 11 Apr 2021 20:31:24 +0200 Subject: [PATCH 36/80] Removed #[allow(non_camel_case_types)] to fix issues --- src/epd1in54/mod.rs | 34 +++++------ src/epd1in54b/command.rs | 47 ++++++++------- src/epd1in54b/mod.rs | 54 +++++++++--------- src/epd1in54c/command.rs | 43 +++++++------- src/epd1in54c/mod.rs | 26 ++++----- src/epd2in13_v2/command.rs | 113 ++++++++++++++++++------------------- src/epd2in13_v2/mod.rs | 64 ++++++++++----------- src/epd2in7b/command.rs | 81 +++++++++++++------------- src/epd2in7b/mod.rs | 78 ++++++++++++------------- src/epd2in9/mod.rs | 34 +++++------ src/epd2in9bc/command.rs | 43 +++++++------- src/epd2in9bc/mod.rs | 36 ++++++------ src/epd4in2/command.rs | 83 ++++++++++++++------------- src/epd4in2/mod.rs | 84 +++++++++++++-------------- src/epd5in65f/command.rs | 77 +++++++++++++------------ src/epd5in65f/mod.rs | 34 +++++------ src/epd7in5/command.rs | 77 +++++++++++++------------ src/epd7in5/mod.rs | 34 +++++------ src/epd7in5_v2/command.rs | 79 +++++++++++++------------- src/epd7in5_v2/mod.rs | 36 ++++++------ src/type_a/command.rs | 47 ++++++++------- 21 files changed, 593 insertions(+), 611 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 66420ea..1edac11 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -103,7 +103,7 @@ where // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) self.interface.cmd_with_data( spi, - Command::DRIVER_OUTPUT_CONTROL, + Command::DriverOutputControl, &[HEIGHT as u8, (HEIGHT >> 8) as u8, 0x00], )?; @@ -114,26 +114,26 @@ where //TODO: test self.interface.cmd_with_data( spi, - Command::BOOSTER_SOFT_START_CONTROL, + Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D], )?; // One Databyte with value 0xA8 for 7V VCOM self.interface - .cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[0xA8])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?; // One Databyte with default value 0x1A for 4 dummy lines per gate self.interface - .cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[0x1A])?; + .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?; // One Databyte with default value 0x08 for 2us per line self.interface - .cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[0x08])?; + .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?; // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction self.interface - .cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; self.set_lut(spi, None)?; @@ -194,7 +194,7 @@ where // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here or would 0x01 be even more efficient? self.interface - .cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?; Ok(()) } @@ -202,7 +202,7 @@ where self.wait_until_idle(); self.use_full_frame(spi)?; self.interface - .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer)?; Ok(()) } @@ -221,7 +221,7 @@ where self.set_ram_counter(spi, x, y)?; self.interface - .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer)?; Ok(()) } @@ -230,9 +230,9 @@ where // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface - .cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; - self.interface.cmd(spi, Command::MASTER_ACTIVATION)?; + self.interface.cmd(spi, Command::MasterActivation)?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send self.interface.cmd(spi, Command::NOP)?; @@ -252,7 +252,7 @@ where // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WRITE_RAM)?; + self.interface.cmd(spi, Command::WriteRam)?; self.interface .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; Ok(()) @@ -321,14 +321,14 @@ where // aren't relevant self.interface.cmd_with_data( spi, - Command::SET_RAM_X_ADDRESS_START_END_POSITION, + Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], )?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end self.interface.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_START_END_POSITION, + Command::SetRamYAddressStartEndPosition, &[ start_y as u8, (start_y >> 8) as u8, @@ -349,12 +349,12 @@ where // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; // 2 Databytes: A[7:0] & 0..A[8] self.interface.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_COUNTER, + Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], )?; Ok(()) @@ -365,7 +365,7 @@ where assert!(buffer.len() == 30); self.interface - .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; Ok(()) } } diff --git a/src/epd1in54b/command.rs b/src/epd1in54b/command.rs index 6c150e0..392fd19 100644 --- a/src/epd1in54b/command.rs +++ b/src/epd1in54b/command.rs @@ -2,35 +2,34 @@ use crate::traits; #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { - PANEL_SETTING = 0x00, + PanelSetting = 0x00, - POWER_SETTING = 0x01, - POWER_OFF = 0x02, - POWER_ON = 0x04, - BOOSTER_SOFT_START = 0x06, - DATA_START_TRANSMISSION_1 = 0x10, - DISPLAY_REFRESH = 0x12, - DATA_START_TRANSMISSION_2 = 0x13, + PowerSetting = 0x01, + PowerOff = 0x02, + PowerOn = 0x04, + BoosterSoftStart = 0x06, + DataStartTransmission1 = 0x10, + DisplayRefresh = 0x12, + DataStartTransmission2 = 0x13, - LUT_FOR_VCOM = 0x20, - LUT_WHITE_TO_WHITE = 0x21, - LUT_BLACK_TO_WHITE = 0x22, - LUT_G0 = 0x23, - LUT_G1 = 0x24, - LUT_RED_VCOM = 0x25, - LUT_RED0 = 0x26, - LUT_RED1 = 0x27, + LutForVcom = 0x20, + LutWhiteToWhite = 0x21, + LutBlackToWhite = 0x22, + LutG0 = 0x23, + LutG1 = 0x24, + LutRedVcom = 0x25, + LutRed0 = 0x26, + LutRed1 = 0x27, - PLL_CONTROL = 0x30, - TEMPERATURE_SENSOR_COMMAND = 0x40, - TEMPERATURE_SENSOR_SELECTION = 0x41, - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, - RESOLUTION_SETTING = 0x61, - VCM_DC_SETTING = 0x82, - POWER_SAVING = 0xE3, + PllControl = 0x30, + TemperatureSensorCommand = 0x40, + TemperatureSensorSelection = 0x41, + VcomAndDataIntervalSetting = 0x50, + ResolutionSetting = 0x61, + VcmDcSetting = 0x82, + PowerSaving = 0xE3, } impl traits::Command for Command { diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index c14050e..8441508 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -56,29 +56,29 @@ where // set the power settings self.interface - .cmd_with_data(spi, Command::POWER_SETTING, &[0x07, 0x00, 0x08, 0x00])?; + .cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x00, 0x08, 0x00])?; // start the booster self.interface - .cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x07, 0x07, 0x07])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x07])?; // power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // set the panel settings - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xCF])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xCF])?; - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; // PLL - self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x39])?; + self.cmd_with_data(spi, Command::PllControl, &[0x39])?; // set resolution self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x0E])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0E])?; self.set_lut(spi, None)?; @@ -112,7 +112,7 @@ where self.send_resolution(spi)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; for b in black { let expanded = expand_bits(*b); @@ -127,7 +127,7 @@ where chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; Ok(()) } @@ -164,19 +164,19 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x00])?; // VCOM to 0V + .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // VCOM to 0V self.interface - .cmd_with_data(spi, Command::POWER_SETTING, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast + .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast self.wait_until_idle(); //NOTE: The example code has a 1s delay here - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; Ok(()) } @@ -210,7 +210,7 @@ where self.send_resolution(spi)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; for b in buffer { // Two bits per pixel @@ -225,7 +225,7 @@ where let nbits = WIDTH * (HEIGHT / 8); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, nbits)?; //NOTE: Example code has a delay here @@ -247,7 +247,7 @@ where fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -265,7 +265,7 @@ where // Clear the black self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; // Uses 2 bits per pixel self.interface @@ -273,7 +273,7 @@ where // Clear the red self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; Ok(()) @@ -285,19 +285,19 @@ where _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.interface - .cmd_with_data(spi, Command::LUT_FOR_VCOM, LUT_VCOM0)?; + .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?; self.interface - .cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, LUT_WHITE_TO_WHITE)?; + .cmd_with_data(spi, Command::LutWhiteToWhite, LUT_WHITE_TO_WHITE)?; self.interface - .cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, LUT_BLACK_TO_WHITE)?; - self.interface.cmd_with_data(spi, Command::LUT_G0, LUT_G1)?; - self.interface.cmd_with_data(spi, Command::LUT_G1, LUT_G2)?; + .cmd_with_data(spi, Command::LutBlackToWhite, LUT_BLACK_TO_WHITE)?; + self.interface.cmd_with_data(spi, Command::LutG0, LUT_G1)?; + self.interface.cmd_with_data(spi, Command::LutG1, LUT_G2)?; self.interface - .cmd_with_data(spi, Command::LUT_RED_VCOM, LUT_RED_VCOM)?; + .cmd_with_data(spi, Command::LutRedVcom, LUT_RED_VCOM)?; self.interface - .cmd_with_data(spi, Command::LUT_RED0, LUT_RED0)?; + .cmd_with_data(spi, Command::LutRed0, LUT_RED0)?; self.interface - .cmd_with_data(spi, Command::LUT_RED1, LUT_RED1)?; + .cmd_with_data(spi, Command::LutRed1, LUT_RED1)?; Ok(()) } @@ -340,7 +340,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::RESOLUTION_SETTING)?; + self.command(spi, Command::ResolutionSetting)?; self.send_data(spi, &[w as u8])?; self.send_data(spi, &[(h >> 8) as u8])?; diff --git a/src/epd1in54c/command.rs b/src/epd1in54c/command.rs index e0ad2f2..eef7aec 100644 --- a/src/epd1in54c/command.rs +++ b/src/epd1in54c/command.rs @@ -2,33 +2,32 @@ use crate::traits; #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { - PANEL_SETTING = 0x00, + PanelSetting = 0x00, - POWER_SETTING = 0x01, - POWER_OFF = 0x02, - POWER_ON = 0x04, - BOOSTER_SOFT_START = 0x06, - DEEP_SLEEP = 0x07, - DATA_START_TRANSMISSION_1 = 0x10, - DISPLAY_REFRESH = 0x12, - DATA_START_TRANSMISSION_2 = 0x13, + PowerSetting = 0x01, + PowerOff = 0x02, + PowerOn = 0x04, + BoosterSoftStart = 0x06, + DeepSleep = 0x07, + DataStartTransmission1 = 0x10, + DisplayRefresh = 0x12, + DataStartTransmission2 = 0x13, - LUT_FOR_VCOM = 0x20, - LUT_WHITE_TO_WHITE = 0x21, - LUT_BLACK_TO_WHITE = 0x22, - LUT_WHITE_TO_BLACK = 0x23, - LUT_BLACK_TO_BLACK = 0x24, + LutForVcom = 0x20, + LutWhiteToWhite = 0x21, + LutBlackToWhite = 0x22, + LutWhiteToBlack = 0x23, + LutBlackToBlack = 0x24, - PLL_CONTROL = 0x30, - TEMPERATURE_SENSOR_COMMAND = 0x40, - TEMPERATURE_SENSOR_SELECTION = 0x41, - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, - RESOLUTION_SETTING = 0x61, - VCM_DC_SETTING = 0x82, - POWER_SAVING = 0xE3, + PllControl = 0x30, + TemperatureSensorCommand = 0x40, + TemperatureSensorSelection = 0x41, + VcomAndDataIntervalSetting = 0x50, + ResolutionSetting = 0x61, + VcmDcSetting = 0x82, + PowerSaving = 0xE3, } impl traits::Command for Command { diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index f8bd54d..77b5325 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -57,20 +57,20 @@ where self.interface.reset(delay, 2); // start the booster - self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; // power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // set the panel settings - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x0f, 0x0d])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0f, 0x0d])?; // set resolution self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x77])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?; Ok(()) } @@ -97,7 +97,7 @@ where fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, black)?; + self.cmd_with_data(spi, Command::DataStartTransmission1, black)?; Ok(()) } @@ -108,7 +108,7 @@ where chromatic: &[u8], ) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, chromatic)?; + self.cmd_with_data(spi, Command::DataStartTransmission2, chromatic)?; Ok(()) } @@ -145,9 +145,9 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xa5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xa5])?; Ok(()) } @@ -182,7 +182,7 @@ where // Clear the chromatic layer let color = self.color.get_byte_value(); - self.command(spi, Command::DATA_START_TRANSMISSION_2)?; + self.command(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; Ok(()) @@ -202,7 +202,7 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(); Ok(()) @@ -220,11 +220,11 @@ where let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; // Clear the chromatic - self.command(spi, Command::DATA_START_TRANSMISSION_2)?; + self.command(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; Ok(()) @@ -276,7 +276,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::RESOLUTION_SETTING)?; + self.command(spi, Command::ResolutionSetting)?; // | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 | // | HRES[7:3] | 0 | 0 | 0 | diff --git a/src/epd2in13_v2/command.rs b/src/epd2in13_v2/command.rs index 9ab4ddd..e94c43e 100644 --- a/src/epd2in13_v2/command.rs +++ b/src/epd2in13_v2/command.rs @@ -9,51 +9,50 @@ use bit_field::BitField; /// /// For more infos about the addresses and what they are doing look into the pdfs #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { - DRIVER_OUTPUT_CONTROL = 0x01, - GATE_DRIVING_VOLTAGE_CTRL = 0x03, - SOURCE_DRIVING_VOLTAGE_CTRL = 0x04, - BOOSTER_SOFT_START_CONTROL = 0x0C, - GATE_SCAN_START_POSITION = 0x0F, - DEEP_SLEEP_MODE = 0x10, - DATA_ENTRY_MODE_SETTING = 0x11, - SW_RESET = 0x12, - HV_READY_DETECTION = 0x14, - VCI_DETECTION = 0x15, - TEMPERATURE_SENSOR_CONTROL_WRITE = 0x1A, - TEMPERATURE_SENSOR_CONTROL_READ = 0x1B, - TEMPERATURE_SENSOR_EXT_CONTROL_WRITE = 0x1C, - MASTER_ACTIVATION = 0x20, - DISPLAY_UPDATE_CONTROL_1 = 0x21, - DISPLAY_UPDATE_CONTROL_2 = 0x22, - WRITE_RAM = 0x24, - WRITE_RAM_RED = 0x26, - READ_RAM = 0x27, - VCOM_SENSE = 0x28, - VCOM_SENSE_DURATION = 0x29, - PROGRAM_VCOM_OPT = 0x2A, - WRITE_VCOM_REGISTER = 0x2C, - OTP_REGISTER_READ = 0x2D, - STATUS_BIT_READ = 0x2F, - PROGRAM_WS_OTP = 0x30, - LOAD_WS_OTP = 0x31, - WRITE_LUT_REGISTER = 0x32, - PROGRAM_OTP_SELECTION = 0x36, - WRITE_OTP_SELECTION = 0x37, - SET_DUMMY_LINE_PERIOD = 0x3A, - SET_GATE_LINE_WIDTH = 0x3B, - BORDER_WAVEFORM_CONTROL = 0x3C, - READ_RAM_OPTION = 0x41, - SET_RAM_X_ADDRESS_START_END_POSITION = 0x44, - SET_RAM_Y_ADDRESS_START_END_POSITION = 0x45, - AUTO_WRITE_RED_RAM_REGULAR_PATTERN = 0x46, - AUTO_WRITE_BW_RAM_REGULAR_PATTERN = 0x47, - SET_RAM_X_ADDRESS_COUNTER = 0x4E, - SET_RAM_Y_ADDRESS_COUNTER = 0x4F, - SET_ANALOG_BLOCK_CONTROL = 0x74, - SET_DIGITAL_BLOCK_CONTROL = 0x7E, + DriverOutputControl = 0x01, + GateDrivingVoltageCtrl = 0x03, + SourceDrivingVoltageCtrl = 0x04, + BoosterSoftStartControl = 0x0C, + GateScanStartPosition = 0x0F, + DeepSleepMode = 0x10, + DataEntryModeSetting = 0x11, + SwReset = 0x12, + HvReadyDetection = 0x14, + VciDetection = 0x15, + TemperatureSensorControlWrite = 0x1A, + TemperatureSensorControlRead = 0x1B, + TemperatureSensorExtControlWrite = 0x1C, + MasterActivation = 0x20, + DisplayUpdateControl1 = 0x21, + DisplayUpdateControl2 = 0x22, + WriteRam = 0x24, + WriteRamRed = 0x26, + ReadRam = 0x27, + VcomSense = 0x28, + VcomSenseDuration = 0x29, + ProgramVcomOpt = 0x2A, + WriteVcomRegister = 0x2C, + OtpRegisterRead = 0x2D, + StatusBitRead = 0x2F, + ProgramWsOtp = 0x30, + LoadWsOtp = 0x31, + WriteLutRegister = 0x32, + ProgramOtpSelection = 0x36, + WriteOtpSelection = 0x37, + SetDummyLinePeriod = 0x3A, + SetGateLineWidth = 0x3B, + BorderWaveformControl = 0x3C, + ReadRamOption = 0x41, + SetRamXAddressStartEndPosition = 0x44, + SetRamYAddressStartEndPosition = 0x45, + AutoWriteRedRamRegularPattern = 0x46, + AutoWriteBwRamRegularPattern = 0x47, + SetRamXAddressCounter = 0x4E, + SetRamYAddressCounter = 0x4F, + SetAnalogBlockControl = 0x74, + SetDigitalBlockControl = 0x7E, NOP = 0x7F, } @@ -135,32 +134,30 @@ impl DisplayUpdateControl2 { } #[allow(dead_code)] -#[allow(non_camel_case_types)] + pub(crate) enum DataEntryModeIncr { - X_DECR_Y_DECR = 0x0, - X_INCR_Y_DECR = 0x1, - X_DECR_Y_INCR = 0x2, - X_INCR_Y_INCR = 0x3, + XDecrYDecr = 0x0, + XIncrYDecr = 0x1, + XDecrYIncr = 0x2, + XIncrYIncr = 0x3, } #[allow(dead_code)] -#[allow(non_camel_case_types)] + pub(crate) enum DataEntryModeDir { - X_DIR = 0x0, - Y_DIR = 0x4, + XDir = 0x0, + YDir = 0x4, } #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum BorderWaveFormVBD { GS = 0x0, - FIX_LEVEL = 0x1, + FixLevel = 0x1, VCOM = 0x2, } #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum BorderWaveFormFixLevel { VSS = 0x0, @@ -170,7 +167,6 @@ pub(crate) enum BorderWaveFormFixLevel { } #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum BorderWaveFormGS { LUT0 = 0x0, @@ -194,17 +190,16 @@ impl BorderWaveForm { } #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub enum DeepSleepMode { // Sleeps and keeps access to RAM and controller - NORMAL = 0x00, + Normal = 0x00, // Sleeps without access to RAM/controller but keeps RAM content - MODE_1 = 0x01, + Mode1 = 0x01, // Same as MODE_1 but RAM content is not kept - MODE_2 = 0x11, + Mode2 = 0x11, } pub(crate) struct GateDrivingVoltage(pub u8); diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index 704d262..cd5481d 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -80,7 +80,7 @@ where self.set_lut(spi, Some(self.refresh))?; // Python code does this, not sure why - // self.cmd_with_data(spi, Command::WRITE_OTP_SELECTION, &[0, 0, 0, 0, 0x40, 0, 0])?; + // self.cmd_with_data(spi, Command::WriteOtpSelection, &[0, 0, 0, 0, 0x40, 0, 0])?; // During partial update, clock/analog are not disabled between 2 // updates. @@ -88,7 +88,7 @@ where spi, DisplayUpdateControl2::new().enable_analog().enable_clock(), )?; - self.command(spi, Command::MASTER_ACTIVATION)?; + self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); self.set_border_waveform( @@ -101,7 +101,7 @@ where )?; } else { self.wait_until_idle(); - self.command(spi, Command::SW_RESET)?; + self.command(spi, Command::SwReset)?; self.wait_until_idle(); self.set_driver_output( @@ -118,11 +118,7 @@ where self.set_dummy_line_period(spi, 0x30)?; self.set_gate_scan_start_position(spi, 0)?; - self.set_data_entry_mode( - spi, - DataEntryModeIncr::X_INCR_Y_INCR, - DataEntryModeDir::X_DIR, - )?; + 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)?; @@ -177,7 +173,7 @@ where ) -> Result { let mut epd = EPD2in13 { interface: DisplayInterface::new(cs, busy, dc, rst), - sleep_mode: DeepSleepMode::MODE_1, + sleep_mode: DeepSleepMode::Mode1, background_color: DEFAULT_BACKGROUND_COLOR, refresh: RefreshLUT::FULL, }; @@ -206,7 +202,7 @@ where .disable_analog() .disable_clock(), )?; - self.command(spi, Command::MASTER_ACTIVATION)?; + self.command(spi, Command::MasterActivation)?; self.set_sleep_mode(spi, self.sleep_mode)?; Ok(()) @@ -217,14 +213,14 @@ where self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; - self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer)?; if self.refresh == RefreshLUT::FULL { // Always keep the base buffer equal to current if not doing partial refresh. self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; - self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; } Ok(()) } @@ -254,14 +250,14 @@ where self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_address_counters(spi, x, y)?; - self.cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + self.cmd_with_data(spi, Command::WriteRam, buffer)?; if self.refresh == RefreshLUT::FULL { // Always keep the base buffer equals to current if not doing partial refresh. self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_address_counters(spi, x, y)?; - self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; } Ok(()) @@ -283,7 +279,7 @@ where } else { self.set_display_update_control_2(spi, DisplayUpdateControl2::new().display())?; } - self.command(spi, Command::MASTER_ACTIVATION)?; + self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) @@ -305,7 +301,7 @@ where self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; - self.command(spi, Command::WRITE_RAM)?; + self.command(spi, Command::WriteRam)?; self.interface.data_x_times( spi, color, @@ -317,7 +313,7 @@ where self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; - self.command(spi, Command::WRITE_RAM_RED)?; + self.command(spi, Command::WriteRamRed)?; self.interface.data_x_times( spi, color, @@ -353,7 +349,7 @@ where Some(RefreshLUT::QUICK) => &LUT_PARTIAL_UPDATE, }; - self.cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer) + self.cmd_with_data(spi, Command::WriteLutRegister, buffer) } fn is_busy(&self) -> bool { @@ -380,7 +376,7 @@ where self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; - self.cmd_with_data(spi, Command::WRITE_RAM_RED, buffer)?; + self.cmd_with_data(spi, Command::WriteRamRed, buffer)?; Ok(()) } @@ -412,7 +408,7 @@ where assert!(start <= 295); self.cmd_with_data( spi, - Command::GATE_SCAN_START_POSITION, + Command::GateScanStartPosition, &[(start & 0xFF) as u8, ((start >> 8) & 0x1) as u8], ) } @@ -424,13 +420,13 @@ where ) -> Result<(), SPI::Error> { self.cmd_with_data( spi, - Command::BORDER_WAVEFORM_CONTROL, + Command::BorderWaveformControl, &[borderwaveform.to_u8()], ) } fn set_vcom_register(&mut self, spi: &mut SPI, vcom: VCOM) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[vcom.0]) + self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) } fn set_gate_driving_voltage( @@ -438,7 +434,7 @@ where spi: &mut SPI, voltage: GateDrivingVoltage, ) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::GATE_DRIVING_VOLTAGE_CTRL, &[voltage.0]) + self.cmd_with_data(spi, Command::GateDrivingVoltageCtrl, &[voltage.0]) } fn set_dummy_line_period( @@ -447,11 +443,11 @@ where number_of_lines: u8, ) -> Result<(), SPI::Error> { assert!(number_of_lines <= 127); - self.cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[number_of_lines]) + self.cmd_with_data(spi, Command::SetDummyLinePeriod, &[number_of_lines]) } fn set_gate_line_width(&mut self, spi: &mut SPI, width: u8) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[width & 0x0F]) + self.cmd_with_data(spi, Command::SetGateLineWidth, &[width & 0x0F]) } /// Sets the source driving voltage value @@ -464,7 +460,7 @@ where ) -> Result<(), SPI::Error> { self.cmd_with_data( spi, - Command::SOURCE_DRIVING_VOLTAGE_CTRL, + Command::SourceDrivingVoltageCtrl, &[vsh1.0, vsh2.0, vsl.0], ) } @@ -476,16 +472,16 @@ where spi: &mut SPI, value: DisplayUpdateControl2, ) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[value.0]) + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[value.0]) } /// Triggers the deep sleep mode fn set_sleep_mode(&mut self, spi: &mut SPI, mode: DeepSleepMode) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[mode as u8]) + 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::DRIVER_OUTPUT_CONTROL, &output.to_bytes()) + self.cmd_with_data(spi, Command::DriverOutputControl, &output.to_bytes()) } /// Sets the data entry mode (ie. how X and Y positions changes when writing @@ -497,7 +493,7 @@ where counter_direction: DataEntryModeDir, ) -> Result<(), SPI::Error> { let mode = counter_incr_mode as u8 | counter_direction as u8; - self.cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[mode]) + self.cmd_with_data(spi, Command::DataEntryModeSetting, &[mode]) } /// Sets both X and Y pixels ranges @@ -511,13 +507,13 @@ where ) -> Result<(), SPI::Error> { self.cmd_with_data( spi, - Command::SET_RAM_X_ADDRESS_START_END_POSITION, + Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], )?; self.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_START_END_POSITION, + Command::SetRamYAddressStartEndPosition, &[ start_y as u8, (start_y >> 8) as u8, @@ -535,11 +531,11 @@ where y: u32, ) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?; + self.cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; self.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_COUNTER, + Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], )?; Ok(()) diff --git a/src/epd2in7b/command.rs b/src/epd2in7b/command.rs index d478ce7..b228d22 100644 --- a/src/epd2in7b/command.rs +++ b/src/epd2in7b/command.rs @@ -5,117 +5,116 @@ use crate::traits; /// /// More information can be found in the [specification](https://www.waveshare.com/w/upload/d/d8/2.7inch-e-paper-b-specification.pdf) #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset - PANEL_SETTING = 0x00, + PanelSetting = 0x00, /// Selecting internal and external power - POWER_SETTING = 0x01, - POWER_OFF = 0x02, + PowerSetting = 0x01, + PowerOff = 0x02, /// Setting Power OFF sequence - POWER_OFF_SEQUENCE_SETTING = 0x03, - POWER_ON = 0x04, + PowerOffSequenceSetting = 0x03, + PowerOn = 0x04, /// This command enables the internal bandgap, which will be cleared by the next POF. - POWER_ON_MEASURE = 0x05, + PowerOnMeasure = 0x05, /// Starting data transmission /// /// ```ignore /// self.send_data(&[0x07, 0x07, 0x17])?; /// ``` - BOOSTER_SOFT_START = 0x06, + 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. - DEEP_SLEEP = 0x07, + 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. - DATA_START_TRANSMISSION_1 = 0x10, + DataStartTransmission1 = 0x10, /// Stopping data transmission - DATA_STOP = 0x11, + DataStop = 0x11, /// After this command is issued, driver will refresh display (data/VCOM) according to SRAM data and LUT. - DISPLAY_REFRESH = 0x12, + 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. - DATA_START_TRANSMISSION_2 = 0x13, + DataStartTransmission2 = 0x13, /// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission /// complete, user must send command DSP (Data transmission Stop). Then 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. - PARTIAL_DATA_START_TRANSMISSION_1 = 0x14, + PartialDataStartTransmission1 = 0x14, /// The command define as follows: The register is indicates that user start to transmit data, then write to SRAM. While data transmission /// complete, user must send command DSP (Data transmission Stop). Then 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. - PARTIAL_DATA_START_TRANSMISSION_2 = 0x15, + PartialDataStartTransmission2 = 0x15, /// While user sent this command, driver will refresh display (data/VCOM) base on SRAM data and LUT. /// /// Only the area (X,Y, W, L) would update, the others pixel output would follow VCOM LUT - PARTIAL_DISPLAY_REFRESH = 0x16, + PartialDisplayRefresh = 0x16, /// This command builds the Look-up table for VCOM - LUT_FOR_VCOM = 0x20, - LUT_WHITE_TO_WHITE = 0x21, - LUT_BLACK_TO_WHITE = 0x22, - LUT_WHITE_TO_BLACK = 0x23, - LUT_BLACK_TO_BLACK = 0x24, + LutForVcom = 0x20, + LutWhiteToWhite = 0x21, + LutBlackToWhite = 0x22, + LutWhiteToBlack = 0x23, + LutBlackToBlack = 0x24, /// The command controls the PLL clock frequency. - PLL_CONTROL = 0x30, + PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. /// /// Doesn't work! Waveshare doesn't connect the read pin - TEMPERATURE_SENSOR_COMMAND = 0x40, + TemperatureSensorCommand = 0x40, /// This command selects Internal or External temperature sensor. - TEMPERATURE_SENSOR_CALIBRATION = 0x41, + TemperatureSensorCalibration = 0x41, /// Write External Temperature Sensor - TEMPERATURE_SENSOR_WRITE = 0x42, + TemperatureSensorWrite = 0x42, /// Read External Temperature Sensor /// /// Doesn't work! Waveshare doesn't connect the read pin - TEMPERATURE_SENSOR_READ = 0x43, + 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) - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + VcomAndDataIntervalSetting = 0x50, /// This command indicates the input power condition. Host can read this flag to learn the battery condition. - LOW_POWER_DETECTION = 0x51, + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. - TCON_SETTING = 0x60, + TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR). - RESOLUTION_SETTING = 0x61, - SOURCE_AND_GATE_SETTING = 0x62, + ResolutionSetting = 0x61, + SourceAndGateSetting = 0x62, /// This command reads the IC status. /// /// Doesn't work! Waveshare doesn't connect the read pin - GET_STATUS = 0x71, + GetStatus = 0x71, /// Automatically measure VCOM. This command reads the IC status - AUTO_MEASUREMENT_VCOM = 0x80, + AutoMeasurementVcom = 0x80, /// This command gets the VCOM value /// /// Doesn't work! Waveshare doesn't connect the read pin - READ_VCOM_VALUE = 0x81, + ReadVcomValue = 0x81, /// This command sets VCOM_DC value. - VCM_DC_SETTING = 0x82, + VcmDcSetting = 0x82, /// 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. - PROGRAM_MODE = 0xA0, + ProgramMode = 0xA0, /// After this command is issued, the chip would enter the program mode. - ACTIVE_PROGRAMMING = 0xA1, + 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. - READ_OTP = 0xA2, + ReadOtp = 0xA2, /// Not shown in commands table, but used in init sequence - POWER_OPTIMIZATION = 0xf8, + PowerOptimization = 0xf8, } impl traits::Command for Command { @@ -132,7 +131,7 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::PANEL_SETTING.address(), 0x00); - assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); } } diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 666add7..fc85eab 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -60,51 +60,51 @@ where self.interface.reset(delay, 2); // power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // set panel settings, 0xbf is bw, 0xaf is multi-color self.interface - .cmd_with_data(spi, Command::PANEL_SETTING, &[0xaf])?; + .cmd_with_data(spi, Command::PanelSetting, &[0xaf])?; // pll control self.interface - .cmd_with_data(spi, Command::PLL_CONTROL, &[0x3a])?; + .cmd_with_data(spi, Command::PllControl, &[0x3a])?; // set the power settings self.interface.cmd_with_data( spi, - Command::POWER_SETTING, + Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0x09], )?; // start the booster self.interface - .cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x07, 0x07, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x07, 0x07, 0x17])?; // power optimization self.interface - .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x60, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x60, 0xa5])?; self.interface - .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x89, 0xa5])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x89, 0xa5])?; self.interface - .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x90, 0x00])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x90, 0x00])?; self.interface - .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x93, 0x2a])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x93, 0x2a])?; self.interface - .cmd_with_data(spi, Command::POWER_OPTIMIZATION, &[0x73, 0x41])?; + .cmd_with_data(spi, Command::PowerOptimization, &[0x73, 0x41])?; self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x87])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x87])?; self.set_lut(spi, None)?; self.interface - .cmd_with_data(spi, Command::PARTIAL_DISPLAY_REFRESH, &[0x00])?; + .cmd_with_data(spi, Command::PartialDisplayRefresh, &[0x00])?; self.wait_until_idle(); Ok(()) @@ -150,27 +150,27 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0xf7])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0xf7])?; - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_until_idle(); self.interface - .cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, buffer)?; // Clear chromatic layer since we won't be using it here self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DATA_STOP)?; + self.interface.cmd(spi, Command::DataStop)?; Ok(()) } @@ -184,7 +184,7 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::PartialDataStartTransmission1)?; self.send_data(spi, &[(x >> 8) as u8])?; self.send_data(spi, &[(x & 0xf8) as u8])?; @@ -198,18 +198,18 @@ where self.send_buffer_helper(spi, buffer)?; - self.interface.cmd(spi, Command::DATA_STOP) + self.interface.cmd(spi, Command::DataStop) } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(); Ok(()) } fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.update_frame(spi, buffer)?; - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -218,17 +218,17 @@ where let color_value = self.color.get_byte_value(); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DATA_STOP)?; + self.interface.cmd(spi, Command::DataStop)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; - self.interface.cmd(spi, Command::DATA_STOP)?; + self.interface.cmd(spi, Command::DataStop)?; Ok(()) } @@ -254,11 +254,11 @@ where _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::LUT_FOR_VCOM, &LUT_VCOM_DC)?; - self.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, &LUT_WW)?; - self.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, &LUT_BW)?; - self.cmd_with_data(spi, Command::LUT_WHITE_TO_BLACK, &LUT_WB)?; - self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, &LUT_BB)?; + self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC)?; + self.cmd_with_data(spi, Command::LutWhiteToWhite, &LUT_WW)?; + self.cmd_with_data(spi, Command::LutBlackToWhite, &LUT_BW)?; + self.cmd_with_data(spi, Command::LutWhiteToBlack, &LUT_WB)?; + self.cmd_with_data(spi, Command::LutBlackToBlack, &LUT_BB)?; Ok(()) } @@ -295,11 +295,11 @@ where achromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, achromatic)?; - self.interface.cmd(spi, Command::DATA_STOP) + self.interface.cmd(spi, Command::DataStop) } /// Update only chromatic data of the display. @@ -311,11 +311,11 @@ where chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.send_buffer_helper(spi, chromatic)?; - self.interface.cmd(spi, Command::DATA_STOP)?; + self.interface.cmd(spi, Command::DataStop)?; self.wait_until_idle(); Ok(()) @@ -369,7 +369,7 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { - self.command(spi, Command::PARTIAL_DISPLAY_REFRESH)?; + self.command(spi, Command::PartialDisplayRefresh)?; self.send_data(spi, &[(x >> 8) as u8])?; self.send_data(spi, &[(x & 0xf8) as u8])?; self.send_data(spi, &[(y >> 8) as u8])?; @@ -393,7 +393,7 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::PartialDataStartTransmission1)?; self.send_data(spi, &[(x >> 8) as u8])?; self.send_data(spi, &[(x & 0xf8) as u8])?; self.send_data(spi, &[(y >> 8) as u8])?; @@ -423,7 +423,7 @@ where height: u32, ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::PARTIAL_DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::PartialDataStartTransmission2)?; self.send_data(spi, &[(x >> 8) as u8])?; self.send_data(spi, &[(x & 0xf8) as u8])?; self.send_data(spi, &[(y >> 8) as u8])?; diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index d2fbabb..0f25b7b 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -104,7 +104,7 @@ where // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) self.interface - .cmd_with_data(spi, Command::DRIVER_OUTPUT_CONTROL, &[0x27, 0x01, 0x00])?; + .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; // 3 Databytes: (and default values from datasheet and arduino) // 1 .. A[6:0] = 0xCF | 0xD7 @@ -113,26 +113,26 @@ where //TODO: test self.interface.cmd_with_data( spi, - Command::BOOSTER_SOFT_START_CONTROL, + Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D], )?; // One Databyte with value 0xA8 for 7V VCOM self.interface - .cmd_with_data(spi, Command::WRITE_VCOM_REGISTER, &[0xA8])?; + .cmd_with_data(spi, Command::WriteVcomRegister, &[0xA8])?; // One Databyte with default value 0x1A for 4 dummy lines per gate self.interface - .cmd_with_data(spi, Command::SET_DUMMY_LINE_PERIOD, &[0x1A])?; + .cmd_with_data(spi, Command::SetDummyLinePeriod, &[0x1A])?; // One Databyte with default value 0x08 for 2us per line self.interface - .cmd_with_data(spi, Command::SET_GATE_LINE_WIDTH, &[0x08])?; + .cmd_with_data(spi, Command::SetGateLineWidth, &[0x08])?; // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction self.interface - .cmd_with_data(spi, Command::DATA_ENTRY_MODE_SETTING, &[0x03])?; + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; self.set_lut(spi, None) } @@ -182,7 +182,7 @@ where // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode //TODO: is 0x00 needed here? (see also epd1in54) self.interface - .cmd_with_data(spi, Command::DEEP_SLEEP_MODE, &[0x00])?; + .cmd_with_data(spi, Command::DeepSleepMode, &[0x00])?; Ok(()) } @@ -201,7 +201,7 @@ where self.use_full_frame(spi)?; self.interface - .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer)?; Ok(()) } @@ -220,7 +220,7 @@ where self.set_ram_counter(spi, x, y)?; self.interface - .cmd_with_data(spi, Command::WRITE_RAM, buffer)?; + .cmd_with_data(spi, Command::WriteRam, buffer)?; Ok(()) } @@ -229,9 +229,9 @@ where // enable clock signal, enable cp, display pattern -> 0xC4 (tested with the arduino version) //TODO: test control_1 or control_2 with default value 0xFF (from the datasheet) self.interface - .cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xC4])?; + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xC4])?; - self.interface.cmd(spi, Command::MASTER_ACTIVATION)?; + self.interface.cmd(spi, Command::MasterActivation)?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send self.interface.cmd(spi, Command::NOP)?; @@ -251,7 +251,7 @@ where // clear the ram with the background color let color = self.background_color.get_byte_value(); - self.interface.cmd(spi, Command::WRITE_RAM)?; + self.interface.cmd(spi, Command::WriteRam)?; self.interface .data_x_times(spi, color, WIDTH / 8 * HEIGHT)?; Ok(()) @@ -319,14 +319,14 @@ where // aren't relevant self.interface.cmd_with_data( spi, - Command::SET_RAM_X_ADDRESS_START_END_POSITION, + Command::SetRamXAddressStartEndPosition, &[(start_x >> 3) as u8, (end_x >> 3) as u8], )?; // 2 Databytes: A[7:0] & 0..A[8] for each - start and end self.interface.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_START_END_POSITION, + Command::SetRamYAddressStartEndPosition, &[ start_y as u8, (start_y >> 8) as u8, @@ -341,12 +341,12 @@ where // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram // aren't relevant self.interface - .cmd_with_data(spi, Command::SET_RAM_X_ADDRESS_COUNTER, &[(x >> 3) as u8])?; + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[(x >> 3) as u8])?; // 2 Databytes: A[7:0] & 0..A[8] self.interface.cmd_with_data( spi, - Command::SET_RAM_Y_ADDRESS_COUNTER, + Command::SetRamYAddressCounter, &[y as u8, (y >> 8) as u8], )?; Ok(()) @@ -357,7 +357,7 @@ where self.wait_until_idle(); assert!(buffer.len() == 30); self.interface - .cmd_with_data(spi, Command::WRITE_LUT_REGISTER, buffer)?; + .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; Ok(()) } } diff --git a/src/epd2in9bc/command.rs b/src/epd2in9bc/command.rs index a389a6f..9414c5a 100644 --- a/src/epd2in9bc/command.rs +++ b/src/epd2in9bc/command.rs @@ -2,33 +2,32 @@ use crate::traits; #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { - PANEL_SETTING = 0x00, + PanelSetting = 0x00, - POWER_SETTING = 0x01, - POWER_OFF = 0x02, - POWER_ON = 0x04, - BOOSTER_SOFT_START = 0x06, - DEEP_SLEEP = 0x07, - DATA_START_TRANSMISSION_1 = 0x10, - DISPLAY_REFRESH = 0x12, - DATA_START_TRANSMISSION_2 = 0x13, + PowerSetting = 0x01, + PowerOff = 0x02, + PowerOn = 0x04, + BoosterSoftStart = 0x06, + DeepSleep = 0x07, + DataStartTransmission1 = 0x10, + DisplayRefresh = 0x12, + DataStartTransmission2 = 0x13, - LUT_FOR_VCOM = 0x20, - LUT_WHITE_TO_WHITE = 0x21, - LUT_BLACK_TO_WHITE = 0x22, - LUT_WHITE_TO_BLACK = 0x23, - LUT_BLACK_TO_BLACK = 0x24, + LutForVcom = 0x20, + LutWhiteToWhite = 0x21, + LutBlackToWhite = 0x22, + LutWhiteToBlack = 0x23, + LutBlackToBlack = 0x24, - PLL_CONTROL = 0x30, - TEMPERATURE_SENSOR_COMMAND = 0x40, - TEMPERATURE_SENSOR_SELECTION = 0x41, - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, - RESOLUTION_SETTING = 0x61, - VCM_DC_SETTING = 0x82, - POWER_SAVING = 0xE3, + PllControl = 0x30, + TemperatureSensorCommand = 0x40, + TemperatureSensorSelection = 0x41, + VcomAndDataIntervalSetting = 0x50, + ResolutionSetting = 0x61, + VcmDcSetting = 0x82, + PowerSaving = 0xE3, } impl traits::Command for Command { diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 300352c..5a81342 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -115,26 +115,26 @@ where // start the booster self.interface - .cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; // power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // set the panel settings - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x8F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?; self.cmd_with_data( spi, - Command::VCOM_AND_DATA_INTERVAL_SETTING, + Command::VcomAndDataIntervalSetting, &[WHITE_BORDER | VCOM_DATA_INTERVAL], )?; // set resolution self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x0A])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?; self.wait_until_idle(); @@ -166,7 +166,7 @@ where /// Finish by calling `update_chromatic_frame`. fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, black)?; Ok(()) } @@ -180,7 +180,7 @@ where chromatic: &[u8], ) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; self.wait_until_idle(); @@ -220,15 +220,15 @@ where // Section 8.2 from datasheet self.interface.cmd_with_data( spi, - Command::VCOM_AND_DATA_INTERVAL_SETTING, + Command::VcomAndDataIntervalSetting, &[FLOATING_BORDER | VCOM_DATA_INTERVAL], )?; - self.command(spi, Command::POWER_OFF)?; - // The example STM code from Github has a wait after POWER_OFF + self.command(spi, Command::PowerOff)?; + // The example STM code from Github has a wait after PowerOff self.wait_until_idle(); - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } @@ -259,7 +259,7 @@ where fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, &buffer)?; @@ -267,7 +267,7 @@ where let color = self.color.get_byte_value(); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; self.wait_until_idle(); @@ -288,7 +288,7 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; self.wait_until_idle(); Ok(()) @@ -307,13 +307,13 @@ where // Clear the black self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; // Clear the chromatic self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; self.wait_until_idle(); @@ -366,7 +366,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::RESOLUTION_SETTING)?; + self.command(spi, Command::ResolutionSetting)?; self.send_data(spi, &[w as u8])?; self.send_data(spi, &[(h >> 8) as u8])?; @@ -382,7 +382,7 @@ where }; self.cmd_with_data( spi, - Command::VCOM_AND_DATA_INTERVAL_SETTING, + Command::VcomAndDataIntervalSetting, &[border | VCOM_DATA_INTERVAL], ) } diff --git a/src/epd4in2/command.rs b/src/epd4in2/command.rs index 0d220b1..3a31a69 100644 --- a/src/epd4in2/command.rs +++ b/src/epd4in2/command.rs @@ -8,7 +8,6 @@ use crate::traits; /// /// The description of the single commands is mostly taken from IL0398.pdf #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift direction, booster switch, soft reset @@ -17,101 +16,101 @@ pub(crate) enum Command { /// 0x1F B/W Mode, LUT from OTP /// 0x2F Red Mode, LUT set by registers /// 0x3F B/W Mode, LUT set by registers - PANEL_SETTING = 0x00, + 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 - POWER_SETTING = 0x01, + 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. - POWER_OFF = 0x02, + PowerOff = 0x02, /// Setting Power OFF sequence - POWER_OFF_SEQUENCE_SETTING = 0x03, + PowerOffSequenceSetting = 0x03, /// Turning On the Power - POWER_ON = 0x04, + PowerOn = 0x04, /// This command enables the internal bandgap, which will be cleared by the next POF. - POWER_ON_MEASURE = 0x05, + PowerOnMeasure = 0x05, /// Starting data transmission /// 3-times: self.send_data(0x17)?; //07 0f 17 1f 27 2F 37 2f - BOOSTER_SOFT_START = 0x06, + 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. - DEEP_SLEEP = 0x07, + 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. - DATA_START_TRANSMISSION_1 = 0x10, + DataStartTransmission1 = 0x10, /// Stopping data transmission - DATA_STOP = 0x11, + 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. - DISPLAY_REFRESH = 0x12, + 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. - DATA_START_TRANSMISSION_2 = 0x13, + 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 - LUT_FOR_VCOM = 0x20, + 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 - LUT_WHITE_TO_WHITE = 0x21, + 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 - LUT_BLACK_TO_WHITE = 0x22, + 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 - LUT_WHITE_TO_BLACK = 0x23, + 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 - LUT_BLACK_TO_BLACK = 0x24, + LutBlackToBlack = 0x24, /// The command controls the PLL clock frequency. - PLL_CONTROL = 0x30, + PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. /// /// Doesn't work! Waveshare doesn't connect the read pin - TEMPERATURE_SENSOR_COMMAND = 0x40, + TemperatureSensorCommand = 0x40, /// Selects the Internal or External temperature sensor and offset - TEMPERATURE_SENSOR_SELECTION = 0x41, + TemperatureSensorSelection = 0x41, /// Write External Temperature Sensor - TEMPERATURE_SENSOR_WRITE = 0x42, + TemperatureSensorWrite = 0x42, /// Read External Temperature Sensor /// /// Doesn't work! Waveshare doesn't connect the read pin - TEMPERATURE_SENSOR_READ = 0x43, + 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) - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + VcomAndDataIntervalSetting = 0x50, /// This command indicates the input power condition. Host can read this flag to learn the battery condition. - LOW_POWER_DETECTION = 0x51, + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. - TCON_SETTING = 0x60, + TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority than the RES\[1:0\] in R00H (PSR). - RESOLUTION_SETTING = 0x61, + ResolutionSetting = 0x61, /// This command defines the Fist Active Gate and First Active Source of active channels. - GSST_SETTING = 0x65, + GsstSetting = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 0x001. /// /// Doesn't work! Waveshare doesn't connect the read pin @@ -120,39 +119,39 @@ pub(crate) enum Command { /// PTL, I2C_ERR, I2C_BUSY, DATA, PON, POF, BUSY /// /// Doesn't work! Waveshare doesn't connect the read pin - GET_STATUS = 0x71, + GetStatus = 0x71, /// Automatically measure VCOM. This command reads the IC status - AUTO_MEASUREMENT_VCOM = 0x80, + AutoMeasurementVcom = 0x80, /// This command gets the VCOM value /// /// Doesn't work! Waveshare doesn't connect the read pin - READ_VCOM_VALUE = 0x81, + ReadVcomValue = 0x81, /// Set VCM_DC - VCM_DC_SETTING = 0x82, + VcmDcSetting = 0x82, /// This command sets partial window - PARTIAL_WINDOW = 0x90, + PartialWindow = 0x90, /// This command makes the display enter partial mode - PARTIAL_IN = 0x91, + PartialIn = 0x91, /// This command makes the display exit partial mode and enter normal mode - PARTIAL_OUT = 0x92, + 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. - PROGRAM_MODE = 0xA0, + 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. - ACTIVE_PROGRAMMING = 0xA1, + 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. - READ_OTP = 0xA2, + 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. - POWER_SAVING = 0xE3, + PowerSaving = 0xE3, } impl traits::Command for Command { @@ -169,10 +168,10 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::POWER_SAVING.address(), 0xE3); + assert_eq!(Command::PowerSaving.address(), 0xE3); - assert_eq!(Command::PANEL_SETTING.address(), 0x00); + assert_eq!(Command::PanelSetting.address(), 0x00); - assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::DisplayRefresh.address(), 0x12); } } diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 636b254..73e46e0 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -110,36 +110,36 @@ where // set the power settings self.interface.cmd_with_data( spi, - Command::POWER_SETTING, + Command::PowerSetting, &[0x03, 0x00, 0x2b, 0x2b, 0xff], )?; // start the booster self.interface - .cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0x17, 0x17, 0x17])?; + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; // power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // set the panel settings - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x3F])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x3F])?; // Set Frequency, 200 Hz didn't work on my board // 150Hz and 171Hz wasn't tested yet // TODO: Test these other frequencies // 3A 100HZ 29 150Hz 39 200HZ 31 171HZ DEFAULT: 3c 50Hz - self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3A])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3A])?; self.send_resolution(spi)?; self.interface - .cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x12])?; + .cmd_with_data(spi, Command::VcmDcSetting, &[0x12])?; //VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x97])?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x97])?; self.set_lut(spi, None)?; @@ -191,19 +191,19 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface - .cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x17])?; //border floating - self.command(spi, Command::VCM_DC_SETTING)?; // VCOM to 0V - self.command(spi, Command::PANEL_SETTING)?; + .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating + self.command(spi, Command::VcmDcSetting)?; // VCOM to 0V + self.command(spi, Command::PanelSetting)?; - self.command(spi, Command::POWER_SETTING)?; //VG&VS to 0V fast + self.command(spi, Command::PowerSetting)?; //VG&VS to 0V fast for _ in 0..4 { self.send_data(spi, &[0x00])?; } - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_until_idle(); self.interface - .cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + .cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } @@ -212,12 +212,12 @@ where let color_value = self.color.get_byte_value(); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; self.interface - .cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?; + .cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; Ok(()) } @@ -236,8 +236,8 @@ where //return Err("Wrong buffersize"); } - self.command(spi, Command::PARTIAL_IN)?; - self.command(spi, Command::PARTIAL_WINDOW)?; + self.command(spi, Command::PartialIn)?; + self.command(spi, Command::PartialWindow)?; self.send_data(spi, &[(x >> 8) as u8])?; let tmp = x & 0xf8; self.send_data(spi, &[tmp as u8])?; // x should be the multiple of 8, the last 3 bit will always be ignored @@ -256,26 +256,26 @@ where //TODO: handle dtm somehow let is_dtm1 = false; if is_dtm1 { - self.command(spi, Command::DATA_START_TRANSMISSION_1)? //TODO: check if data_start transmission 1 also needs "old"/background data here + self.command(spi, Command::DataStartTransmission1)? //TODO: check if data_start transmission 1 also needs "old"/background data here } else { - self.command(spi, Command::DATA_START_TRANSMISSION_2)? + self.command(spi, Command::DataStartTransmission2)? } self.send_data(spi, buffer)?; - self.command(spi, Command::PARTIAL_OUT)?; + self.command(spi, Command::PartialOut)?; Ok(()) } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.update_frame(spi, buffer)?; - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -286,12 +286,12 @@ where let color_value = self.color.get_byte_value(); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; Ok(()) @@ -374,7 +374,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::RESOLUTION_SETTING)?; + self.command(spi, Command::ResolutionSetting)?; self.send_data(spi, &[(w >> 8) as u8])?; self.send_data(spi, &[w as u8])?; self.send_data(spi, &[(h >> 8) as u8])?; @@ -392,19 +392,19 @@ where ) -> Result<(), SPI::Error> { self.wait_until_idle(); // LUT VCOM - self.cmd_with_data(spi, Command::LUT_FOR_VCOM, lut_vcom)?; + self.cmd_with_data(spi, Command::LutForVcom, lut_vcom)?; // LUT WHITE to WHITE - self.cmd_with_data(spi, Command::LUT_WHITE_TO_WHITE, lut_ww)?; + self.cmd_with_data(spi, Command::LutWhiteToWhite, lut_ww)?; // LUT BLACK to WHITE - self.cmd_with_data(spi, Command::LUT_BLACK_TO_WHITE, lut_bw)?; + self.cmd_with_data(spi, Command::LutBlackToWhite, lut_bw)?; // LUT WHITE to BLACK - self.cmd_with_data(spi, Command::LUT_WHITE_TO_BLACK, lut_wb)?; + self.cmd_with_data(spi, Command::LutWhiteToBlack, lut_wb)?; // LUT BLACK to BLACK - self.cmd_with_data(spi, Command::LUT_BLACK_TO_BLACK, lut_bb)?; + self.cmd_with_data(spi, Command::LutBlackToBlack, lut_bb)?; Ok(()) } @@ -451,7 +451,7 @@ where self.wait_until_idle(); self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -464,7 +464,7 @@ where // self.send_resolution(spi)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, buffer)?; @@ -487,13 +487,13 @@ where //return Err("Wrong buffersize"); } - self.interface.cmd(spi, Command::PARTIAL_IN)?; - self.interface.cmd(spi, Command::PARTIAL_WINDOW)?; + self.interface.cmd(spi, Command::PartialIn)?; + self.interface.cmd(spi, Command::PartialWindow)?; self.shift_display(spi, x, y, width, height)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -520,11 +520,11 @@ where self.shift_display(spi, x, y, width, height)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, buffer)?; - self.interface.cmd(spi, Command::PARTIAL_OUT)?; + self.interface.cmd(spi, Command::PartialOut)?; Ok(()) } @@ -541,22 +541,22 @@ where let color_value = self.color.get_byte_value(); - self.interface.cmd(spi, Command::PARTIAL_IN)?; - self.interface.cmd(spi, Command::PARTIAL_WINDOW)?; + self.interface.cmd(spi, Command::PartialIn)?; + self.interface.cmd(spi, Command::PartialWindow)?; self.shift_display(spi, x, y, width, height)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_1)?; + .cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, width / 8 * height)?; self.interface - .cmd(spi, Command::DATA_START_TRANSMISSION_2)?; + .cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, width / 8 * height)?; - self.interface.cmd(spi, Command::PARTIAL_OUT)?; + self.interface.cmd(spi, Command::PartialOut)?; Ok(()) } } diff --git a/src/epd5in65f/command.rs b/src/epd5in65f/command.rs index 5035bb8..89af89e 100644 --- a/src/epd5in65f/command.rs +++ b/src/epd5in65f/command.rs @@ -8,127 +8,126 @@ use crate::traits; /// /// For more infos about the addresses and what they are doing look into the PDFs. #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift /// direction, booster switch, soft reset. - PANEL_SETTING = 0x00, + PanelSetting = 0x00, /// Selecting internal and external power - POWER_SETTING = 0x01, + 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. - POWER_OFF = 0x02, + PowerOff = 0x02, /// Setting Power OFF sequence - POWER_OFF_SEQUENCE_SETTING = 0x03, + 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". - POWER_ON = 0x04, + PowerOn = 0x04, /// Starting data transmission - BOOSTER_SOFT_START = 0x06, + 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. - DEEP_SLEEP = 0x07, + 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 - DATA_START_TRANSMISSION_1 = 0x10, + 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. - DATA_STOP = 0x11, + 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. - DISPLAY_REFRESH = 0x12, + DisplayRefresh = 0x12, /// Image Process Command - IMAGE_PROCESS_COMMAND = 0x13, + ImageProcessCommand = 0x13, /// This command builds the VCOM Look-Up Table (LUTC). - LUT_FOR_VCOM = 0x20, + LutForVcom = 0x20, /// This command builds the Black Look-Up Table (LUTB). - LUT_BLACK = 0x21, + LutBlack = 0x21, /// This command builds the White Look-Up Table (LUTW). - LUT_WHITE = 0x22, + LutWhite = 0x22, /// This command builds the Gray1 Look-Up Table (LUTG1). - LUT_GRAY_1 = 0x23, + LutGray1 = 0x23, /// This command builds the Gray2 Look-Up Table (LUTG2). - LUT_GRAY_2 = 0x24, + LutGray2 = 0x24, /// This command builds the Red0 Look-Up Table (LUTR0). - LUT_RED_0 = 0x25, + LutRed0 = 0x25, /// This command builds the Red1 Look-Up Table (LUTR1). - LUT_RED_1 = 0x26, + LutRed1 = 0x26, /// This command builds the Red2 Look-Up Table (LUTR2). - LUT_RED_2 = 0x27, + LutRed2 = 0x27, /// This command builds the Red3 Look-Up Table (LUTR3). - LUT_RED_3 = 0x28, + LutRed3 = 0x28, /// This command builds the XON Look-Up Table (LUTXON). - LUT_XON = 0x29, + LutXon = 0x29, /// The command controls the PLL clock frequency. - PLL_CONTROL = 0x30, + PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TEMPERATURE_SENSOR_COMMAND = 0x40, + TemperatureSensorCommand = 0x40, /// This command selects the Internal or External temperature sensor. - TEMPERATURE_CALIBRATION = 0x41, + TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. - TEMPERATURE_SENSOR_WRITE = 0x42, + TemperatureSensorWrite = 0x42, /// This command could read data from the external temperature sensor. - TEMPERATURE_SENSOR_READ = 0x43, + 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). - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + VcomAndDataIntervalSetting = 0x50, /// This command indicates the input power condition. Host can read this flag to learn /// the battery condition. - LOW_POWER_DETECTION = 0x51, + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. - TCON_SETTING = 0x60, + TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority /// than the RES\[1:0\] in R00H (PSR). - TCON_RESOLUTION = 0x61, + TconResolution = 0x61, /// This command defines MCU host direct access external memory mode. - //SPI_FLASH_CONTROL = 0x65, + //SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. //REVISION = 0x70, /// This command reads the IC status. - GET_STATUS = 0x71, + GetStatus = 0x71, /// This command implements related VCOM sensing setting. - //AUTO_MEASUREMENT_VCOM = 0x80, + //AutoMeasurementVcom = 0x80, /// This command gets the VCOM value. - READ_VCOM_VALUE = 0x81, + ReadVcomValue = 0x81, /// This command sets `VCOM_DC` value. - VCM_DC_SETTING = 0x82, + VcmDcSetting = 0x82, // /// This is in all the Waveshare controllers for EPD6in65f, but it's not documented // /// anywhere in the datasheet `¯\_(ツ)_/¯` - FLASH_MODE = 0xE3, + FlashMode = 0xE3, } impl traits::Command for Command { @@ -145,7 +144,7 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::PANEL_SETTING.address(), 0x00); - assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); } } diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index d10dddc..6e8e7b4 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -57,21 +57,21 @@ where // Reset the device self.interface.reset(delay, 2); - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xEF, 0x08])?; - self.cmd_with_data(spi, Command::POWER_SETTING, &[0x37, 0x00, 0x23, 0x23])?; - self.cmd_with_data(spi, Command::POWER_OFF_SEQUENCE_SETTING, &[0x00])?; - self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0xC7, 0xC7, 0x1D])?; - self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3C])?; - self.cmd_with_data(spi, Command::TEMPERATURE_SENSOR_COMMAND, &[0x00])?; - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; - self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xEF, 0x08])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00, 0x23, 0x23])?; + self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; + self.cmd_with_data(spi, Command::TemperatureSensorCommand, &[0x00])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::FLASH_MODE, &[0xAA])?; + self.cmd_with_data(spi, Command::FlashMode, &[0xAA])?; delay.delay_ms(100); - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x37])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; Ok(()) } } @@ -113,14 +113,14 @@ where } fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_busy_high(); self.send_resolution(spi)?; - self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_1, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; Ok(()) } @@ -138,11 +138,11 @@ where fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_busy_high(); - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; self.wait_busy_high(); - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; self.wait_busy_high(); - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_busy_low(); Ok(()) } @@ -157,7 +157,7 @@ where let bg = OctColor::colors_byte(self.color, self.color); self.wait_busy_high(); self.send_resolution(spi)?; - self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; self.display_frame(spi)?; Ok(()) @@ -227,7 +227,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::TCON_RESOLUTION)?; + 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])?; diff --git a/src/epd7in5/command.rs b/src/epd7in5/command.rs index 064a5ee..cb1aa1c 100644 --- a/src/epd7in5/command.rs +++ b/src/epd7in5/command.rs @@ -8,130 +8,129 @@ use crate::traits; /// /// For more infos about the addresses and what they are doing look into the PDFs. #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift /// direction, booster switch, soft reset. - PANEL_SETTING = 0x00, + PanelSetting = 0x00, /// Selecting internal and external power - POWER_SETTING = 0x01, + 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. - POWER_OFF = 0x02, + PowerOff = 0x02, /// Setting Power OFF sequence - POWER_OFF_SEQUENCE_SETTING = 0x03, + 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". - POWER_ON = 0x04, + PowerOn = 0x04, /// Starting data transmission - BOOSTER_SOFT_START = 0x06, + 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. - DEEP_SLEEP = 0x07, + 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. - DATA_START_TRANSMISSION_1 = 0x10, + 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. - DATA_STOP = 0x11, + 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. - DISPLAY_REFRESH = 0x12, + DisplayRefresh = 0x12, /// After this command is issued, image process engine will find thin lines/pixels /// from frame SRAM and update the frame SRAM for applying new gray level waveform. /// /// After "Image Process Command", BUSY_N signal will become "0" until image process /// is finished. - IMAGE_PROCESS = 0x13, + ImageProcess = 0x13, /// This command builds the VCOM Look-Up Table (LUTC). - LUT_FOR_VCOM = 0x20, + LutForVcom = 0x20, /// This command builds the Black Look-Up Table (LUTB). - LUT_BLACK = 0x21, + LutBlack = 0x21, /// This command builds the White Look-Up Table (LUTW). - LUT_WHITE = 0x22, + LutWhite = 0x22, /// This command builds the Gray1 Look-Up Table (LUTG1). - LUT_GRAY_1 = 0x23, + LutGray1 = 0x23, /// This command builds the Gray2 Look-Up Table (LUTG2). - LUT_GRAY_2 = 0x24, + LutGray2 = 0x24, /// This command builds the Red0 Look-Up Table (LUTR0). - LUT_RED_0 = 0x25, + LutRed0 = 0x25, /// This command builds the Red1 Look-Up Table (LUTR1). - LUT_RED_1 = 0x26, + LutRed1 = 0x26, /// This command builds the Red2 Look-Up Table (LUTR2). - LUT_RED_2 = 0x27, + LutRed2 = 0x27, /// This command builds the Red3 Look-Up Table (LUTR3). - LUT_RED_3 = 0x28, + LutRed3 = 0x28, /// This command builds the XON Look-Up Table (LUTXON). - LUT_XON = 0x29, + LutXon = 0x29, /// The command controls the PLL clock frequency. - PLL_CONTROL = 0x30, + PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TEMPERATURE_SENSOR_COMMAND = 0x40, + TemperatureSensorCommand = 0x40, /// This command selects the Internal or External temperature sensor. - TEMPERATURE_CALIBRATION = 0x41, + TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. - TEMPERATURE_SENSOR_WRITE = 0x42, + TemperatureSensorWrite = 0x42, /// This command could read data from the external temperature sensor. - TEMPERATURE_SENSOR_READ = 0x43, + 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). - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + VcomAndDataIntervalSetting = 0x50, /// This command indicates the input power condition. Host can read this flag to learn /// the battery condition. - LOW_POWER_DETECTION = 0x51, + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. - TCON_SETTING = 0x60, + TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority /// than the RES\[1:0\] in R00H (PSR). - TCON_RESOLUTION = 0x61, + TconResolution = 0x61, /// This command defines MCU host direct access external memory mode. - SPI_FLASH_CONTROL = 0x65, + SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. REVISION = 0x70, /// This command reads the IC status. - GET_STATUS = 0x71, + GetStatus = 0x71, /// This command implements related VCOM sensing setting. - AUTO_MEASUREMENT_VCOM = 0x80, + AutoMeasurementVcom = 0x80, /// This command gets the VCOM value. - READ_VCOM_VALUE = 0x81, + ReadVcomValue = 0x81, /// This command sets `VCOM_DC` value. - VCM_DC_SETTING = 0x82, + VcmDcSetting = 0x82, /// This is in all the Waveshare controllers for EPD7in5, but it's not documented /// anywhere in the datasheet `¯\_(ツ)_/¯` - FLASH_MODE = 0xE5, + FlashMode = 0xE5, } impl traits::Command for Command { @@ -148,7 +147,7 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::PANEL_SETTING.address(), 0x00); - assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); } } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 883deb3..16d902a 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -58,41 +58,41 @@ where self.interface.reset(delay, 10); // Set the power settings - self.cmd_with_data(spi, Command::POWER_SETTING, &[0x37, 0x00])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x37, 0x00])?; // Set the panel settings: // - 600 x 448 // - Using LUT from external flash - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0xCF, 0x08])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0xCF, 0x08])?; // Start the booster - self.cmd_with_data(spi, Command::BOOSTER_SOFT_START, &[0xC7, 0xCC, 0x28])?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xCC, 0x28])?; // Power on - self.command(spi, Command::POWER_ON)?; + self.command(spi, Command::PowerOn)?; delay.delay_ms(5); self.wait_until_idle(); // Set the clock frequency to 50Hz (default) - self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x3C])?; + self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; // Select internal temperature sensor (default) - self.cmd_with_data(spi, Command::TEMPERATURE_CALIBRATION, &[0x00])?; + self.cmd_with_data(spi, Command::TemperatureCalibration, &[0x00])?; // Set Vcom and data interval to 10 (default), border output to white - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x77])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x77])?; // Set S2G and G2S non-overlap periods to 12 (default) - self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; // Set the real resolution self.send_resolution(spi)?; // Set VCOM_DC to -1.5V - self.cmd_with_data(spi, Command::VCM_DC_SETTING, &[0x1E])?; + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x1E])?; // This is in all the Waveshare controllers for EPD7in5 - self.cmd_with_data(spi, Command::FLASH_MODE, &[0x03])?; + self.cmd_with_data(spi, Command::FlashMode, &[0x03])?; self.wait_until_idle(); Ok(()) @@ -137,15 +137,15 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DataStartTransmission1)?; for byte in buffer { let mut temp = *byte; for _ in 0..4 { @@ -174,13 +174,13 @@ where fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.update_frame(spi, buffer)?; - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -189,7 +189,7 @@ where self.send_resolution(spi)?; // The Waveshare controllers all implement clear using 0x33 - self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, 0x33, WIDTH / 8 * HEIGHT * 4)?; Ok(()) @@ -257,7 +257,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::TCON_RESOLUTION)?; + 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])?; diff --git a/src/epd7in5_v2/command.rs b/src/epd7in5_v2/command.rs index c239eda..599c080 100644 --- a/src/epd7in5_v2/command.rs +++ b/src/epd7in5_v2/command.rs @@ -8,130 +8,129 @@ use crate::traits; /// /// For more infos about the addresses and what they are doing look into the PDFs. #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Set Resolution, LUT selection, BWR pixels, gate scan direction, source shift /// direction, booster switch, soft reset. - PANEL_SETTING = 0x00, + PanelSetting = 0x00, /// Selecting internal and external power - POWER_SETTING = 0x01, + 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. - POWER_OFF = 0x02, + PowerOff = 0x02, /// Setting Power OFF sequence - POWER_OFF_SEQUENCE_SETTING = 0x03, + 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". - POWER_ON = 0x04, + PowerOn = 0x04, /// Starting data transmission - BOOSTER_SOFT_START = 0x06, + 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. - DEEP_SLEEP = 0x07, + 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 - DATA_START_TRANSMISSION_1 = 0x10, + 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. - DATA_STOP = 0x11, + 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. - DISPLAY_REFRESH = 0x12, + DisplayRefresh = 0x12, /// RED or NEW_DATA - DATA_START_TRANSMISSION_2 = 0x13, + DataStartTransmission2 = 0x13, /// Dual SPI - what for? - DUAL_SPI = 0x15, + DualSpi = 0x15, /// This command builds the VCOM Look-Up Table (LUTC). - LUT_FOR_VCOM = 0x20, + LutForVcom = 0x20, /// This command builds the Black Look-Up Table (LUTB). - LUT_BLACK = 0x21, + LutBlack = 0x21, /// This command builds the White Look-Up Table (LUTW). - LUT_WHITE = 0x22, + LutWhite = 0x22, /// This command builds the Gray1 Look-Up Table (LUTG1). - LUT_GRAY_1 = 0x23, + LutGray1 = 0x23, /// This command builds the Gray2 Look-Up Table (LUTG2). - LUT_GRAY_2 = 0x24, + LutGray2 = 0x24, /// This command builds the Red0 Look-Up Table (LUTR0). - LUT_RED_0 = 0x25, + LutRed0 = 0x25, /// This command builds the Red1 Look-Up Table (LUTR1). - LUT_RED_1 = 0x26, + LutRed1 = 0x26, /// This command builds the Red2 Look-Up Table (LUTR2). - LUT_RED_2 = 0x27, + LutRed2 = 0x27, /// This command builds the Red3 Look-Up Table (LUTR3). - LUT_RED_3 = 0x28, + LutRed3 = 0x28, /// This command builds the XON Look-Up Table (LUTXON). - LUT_XON = 0x29, + LutXon = 0x29, /// The command controls the PLL clock frequency. - PLL_CONTROL = 0x30, + PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TEMPERATURE_SENSOR_COMMAND = 0x40, + TemperatureSensorCommand = 0x40, /// This command selects the Internal or External temperature sensor. - TEMPERATURE_CALIBRATION = 0x41, + TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. - TEMPERATURE_SENSOR_WRITE = 0x42, + TemperatureSensorWrite = 0x42, /// This command could read data from the external temperature sensor. - TEMPERATURE_SENSOR_READ = 0x43, + 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). - VCOM_AND_DATA_INTERVAL_SETTING = 0x50, + VcomAndDataIntervalSetting = 0x50, /// This command indicates the input power condition. Host can read this flag to learn /// the battery condition. - LOW_POWER_DETECTION = 0x51, + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. - TCON_SETTING = 0x60, + TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority /// than the RES\[1:0\] in R00H (PSR). - TCON_RESOLUTION = 0x61, + TconResolution = 0x61, /// This command defines MCU host direct access external memory mode. - SPI_FLASH_CONTROL = 0x65, + SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. REVISION = 0x70, /// This command reads the IC status. - GET_STATUS = 0x71, + GetStatus = 0x71, /// This command implements related VCOM sensing setting. - AUTO_MEASUREMENT_VCOM = 0x80, + AutoMeasurementVcom = 0x80, /// This command gets the VCOM value. - READ_VCOM_VALUE = 0x81, + ReadVcomValue = 0x81, /// This command sets `VCOM_DC` value. - VCM_DC_SETTING = 0x82, + VcmDcSetting = 0x82, // /// This is in all the Waveshare controllers for EPD7in5, but it's not documented // /// anywhere in the datasheet `¯\_(ツ)_/¯` - // FLASH_MODE = 0xE5, + // FlashMode = 0xE5, } impl traits::Command for Command { @@ -148,7 +147,7 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::PANEL_SETTING.address(), 0x00); - assert_eq!(Command::DISPLAY_REFRESH.address(), 0x12); + assert_eq!(Command::PanelSetting.address(), 0x00); + assert_eq!(Command::DisplayRefresh.address(), 0x12); } } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 67f9dab..e4c60e0 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -66,16 +66,16 @@ where // 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::BOOSTER_SOFT_START, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::POWER_SETTING, &[0x07, 0x17, 0x3F, 0x3F])?; - self.command(spi, Command::POWER_ON)?; + self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F])?; + self.command(spi, Command::PowerOn)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::PANEL_SETTING, &[0x1F])?; - self.cmd_with_data(spi, Command::PLL_CONTROL, &[0x06])?; - self.cmd_with_data(spi, Command::TCON_RESOLUTION, &[0x03, 0x20, 0x01, 0xE0])?; - self.cmd_with_data(spi, Command::DUAL_SPI, &[0x00])?; - self.cmd_with_data(spi, Command::TCON_SETTING, &[0x22])?; - self.cmd_with_data(spi, Command::VCOM_AND_DATA_INTERVAL_SETTING, &[0x10, 0x07])?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; + self.cmd_with_data(spi, Command::PllControl, &[0x06])?; + self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; + self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; + self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?; self.wait_until_idle(); Ok(()) } @@ -119,15 +119,15 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::POWER_OFF)?; + self.command(spi, Command::PowerOff)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0xA5])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::DATA_START_TRANSMISSION_2, buffer)?; + self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; Ok(()) } @@ -145,13 +145,13 @@ where fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.update_frame(spi, buffer)?; - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -159,13 +159,13 @@ where self.wait_until_idle(); self.send_resolution(spi)?; - self.command(spi, Command::DATA_START_TRANSMISSION_1)?; + self.command(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; - self.command(spi, Command::DATA_START_TRANSMISSION_2)?; + self.command(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, 0x00, WIDTH * HEIGHT / 8)?; - self.command(spi, Command::DISPLAY_REFRESH)?; + self.command(spi, Command::DisplayRefresh)?; Ok(()) } @@ -231,7 +231,7 @@ where let w = self.width(); let h = self.height(); - self.command(spi, Command::TCON_RESOLUTION)?; + 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])?; diff --git a/src/type_a/command.rs b/src/type_a/command.rs index e966aa9..d12dd2c 100644 --- a/src/type_a/command.rs +++ b/src/type_a/command.rs @@ -8,7 +8,6 @@ use crate::traits; /// /// For more infos about the addresses and what they are doing look into the pdfs #[allow(dead_code)] -#[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { /// Driver Output control @@ -17,56 +16,56 @@ pub(crate) enum Command { /// 0.. A[8] /// 0.. B[2:0] /// Default: Set A[8:0] = 0x127 and B[2:0] = 0x0 - DRIVER_OUTPUT_CONTROL = 0x01, + DriverOutputControl = 0x01, /// Booster Soft start control /// 3 Databytes: /// 1.. A[6:0] /// 1.. B[6:0] /// 1.. C[6:0] /// Default: A[7:0] = 0xCF, B[7:0] = 0xCE, C[7:0] = 0x8D - BOOSTER_SOFT_START_CONTROL = 0x0C, - GATE_SCAN_START_POSITION = 0x0F, + BoosterSoftStartControl = 0x0C, + GateScanStartPosition = 0x0F, //TODO: useful? - // GATE_SCAN_START_POSITION = 0x0F, + // GateScanStartPosition = 0x0F, /// Deep Sleep Mode Control /// 1 Databyte: /// 0.. A[0] /// Values: /// A[0] = 0: Normal Mode (POR) /// A[0] = 1: Enter Deep Sleep Mode - DEEP_SLEEP_MODE = 0x10, + DeepSleepMode = 0x10, // /// Data Entry mode setting - DATA_ENTRY_MODE_SETTING = 0x11, + DataEntryModeSetting = 0x11, - SW_RESET = 0x12, + SwReset = 0x12, - TEMPERATURE_SENSOR_CONTROL = 0x1A, + TemperatureSensorControl = 0x1A, - MASTER_ACTIVATION = 0x20, + MasterActivation = 0x20, - DISPLAY_UPDATE_CONTROL_1 = 0x21, + DisplayUpdateControl1 = 0x21, - DISPLAY_UPDATE_CONTROL_2 = 0x22, + DisplayUpdateControl2 = 0x22, - WRITE_RAM = 0x24, + WriteRam = 0x24, - WRITE_VCOM_REGISTER = 0x2C, + WriteVcomRegister = 0x2C, - WRITE_LUT_REGISTER = 0x32, + WriteLutRegister = 0x32, - SET_DUMMY_LINE_PERIOD = 0x3A, + SetDummyLinePeriod = 0x3A, - SET_GATE_LINE_WIDTH = 0x3B, + SetGateLineWidth = 0x3B, - BORDER_WAVEFORM_CONTROL = 0x3C, + BorderWaveformControl = 0x3C, - SET_RAM_X_ADDRESS_START_END_POSITION = 0x44, + SetRamXAddressStartEndPosition = 0x44, - SET_RAM_Y_ADDRESS_START_END_POSITION = 0x45, + SetRamYAddressStartEndPosition = 0x45, - SET_RAM_X_ADDRESS_COUNTER = 0x4E, + SetRamXAddressCounter = 0x4E, - SET_RAM_Y_ADDRESS_COUNTER = 0x4F, + SetRamYAddressCounter = 0x4F, NOP = 0xFF, } @@ -85,9 +84,9 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::DRIVER_OUTPUT_CONTROL.address(), 0x01); + assert_eq!(Command::DriverOutputControl.address(), 0x01); - assert_eq!(Command::SET_RAM_X_ADDRESS_COUNTER.address(), 0x4E); + assert_eq!(Command::SetRamXAddressCounter.address(), 0x4E); assert_eq!(Command::NOP.address(), 0xFF); } From 9d95eeb64b6bbff747b2583e21362d76489a0ef3 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 11 Apr 2021 20:38:03 +0200 Subject: [PATCH 37/80] cargo fmt --- src/epd1in54/mod.rs | 7 ++----- src/epd1in54b/mod.rs | 18 ++++++------------ src/epd2in7b/mod.rs | 18 ++++++------------ src/epd2in9/mod.rs | 7 ++----- src/epd2in9bc/mod.rs | 18 ++++++------------ src/epd4in2/mod.rs | 27 +++++++++------------------ 6 files changed, 31 insertions(+), 64 deletions(-) diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 1edac11..99f0d4c 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -112,11 +112,8 @@ where // 1 .. B[6:0] = 0xCE | 0xD6 // 1 .. C[6:0] = 0x8D | 0x9D //TODO: test - self.interface.cmd_with_data( - spi, - Command::BoosterSoftStartControl, - &[0xD7, 0xD6, 0x9D], - )?; + self.interface + .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D])?; // One Databyte with value 0xA8 for 7V VCOM self.interface diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 8441508..25a5b48 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -111,8 +111,7 @@ where self.wait_until_idle(); self.send_resolution(spi)?; - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; for b in black { let expanded = expand_bits(*b); @@ -126,8 +125,7 @@ where spi: &mut SPI, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; Ok(()) } @@ -209,8 +207,7 @@ where self.wait_until_idle(); self.send_resolution(spi)?; - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; for b in buffer { // Two bits per pixel @@ -224,8 +221,7 @@ where let color = self.color.get_byte_value(); let nbits = WIDTH * (HEIGHT / 8); - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, nbits)?; //NOTE: Example code has a delay here @@ -264,16 +260,14 @@ where let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; // Uses 2 bits per pixel self.interface .data_x_times(spi, color, 2 * (WIDTH * HEIGHT / 8))?; // Clear the red - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color, WIDTH * HEIGHT / 8)?; Ok(()) diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index fc85eab..37ae3b5 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -160,13 +160,11 @@ where } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, buffer)?; // Clear chromatic layer since we won't be using it here - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, !self.color.get_byte_value(), WIDTH * HEIGHT / 8)?; @@ -217,15 +215,13 @@ where self.wait_until_idle(); let color_value = self.color.get_byte_value(); - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; self.interface.cmd(spi, Command::DataStop)?; - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, WIDTH * HEIGHT / 8)?; self.interface.cmd(spi, Command::DataStop)?; @@ -294,8 +290,7 @@ where spi: &mut SPI, achromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.send_buffer_helper(spi, achromatic)?; @@ -310,8 +305,7 @@ where spi: &mut SPI, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.send_buffer_helper(spi, chromatic)?; diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 0f25b7b..99d003c 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -111,11 +111,8 @@ where // 1 .. B[6:0] = 0xCE | 0xD6 // 1 .. C[6:0] = 0x8D | 0x9D //TODO: test - self.interface.cmd_with_data( - spi, - Command::BoosterSoftStartControl, - &[0xD7, 0xD6, 0x9D], - )?; + self.interface + .cmd_with_data(spi, Command::BoosterSoftStartControl, &[0xD7, 0xD6, 0x9D])?; // One Databyte with value 0xA8 for 7V VCOM self.interface diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 5a81342..6f76602 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -165,8 +165,7 @@ where /// /// Finish by calling `update_chromatic_frame`. fn update_achromatic_frame(&mut self, spi: &mut SPI, black: &[u8]) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, black)?; Ok(()) } @@ -179,8 +178,7 @@ where spi: &mut SPI, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, chromatic)?; self.wait_until_idle(); @@ -258,16 +256,14 @@ where } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, &buffer)?; // Clear the chromatic layer let color = self.color.get_byte_value(); - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; self.wait_until_idle(); @@ -306,14 +302,12 @@ where let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); // Clear the black - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; // Clear the chromatic - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; self.wait_until_idle(); diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 73e46e0..4e155a5 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -211,8 +211,7 @@ where self.wait_until_idle(); let color_value = self.color.get_byte_value(); - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; @@ -285,13 +284,11 @@ where let color_value = self.color.get_byte_value(); - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, WIDTH / 8 * HEIGHT)?; Ok(()) @@ -450,8 +447,7 @@ where fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -463,8 +459,7 @@ where self.wait_until_idle(); // self.send_resolution(spi)?; - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, buffer)?; @@ -492,8 +487,7 @@ where self.shift_display(spi, x, y, width, height)?; - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface.data(spi, buffer)?; @@ -519,8 +513,7 @@ where self.shift_display(spi, x, y, width, height)?; - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface.data(spi, buffer)?; @@ -546,13 +539,11 @@ where self.shift_display(spi, x, y, width, height)?; - self.interface - .cmd(spi, Command::DataStartTransmission1)?; + self.interface.cmd(spi, Command::DataStartTransmission1)?; self.interface .data_x_times(spi, color_value, width / 8 * height)?; - self.interface - .cmd(spi, Command::DataStartTransmission2)?; + self.interface.cmd(spi, Command::DataStartTransmission2)?; self.interface .data_x_times(spi, color_value, width / 8 * height)?; From 15e557951f09d3e0eab186643b7d1603645432f5 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 11 Apr 2021 21:21:39 +0200 Subject: [PATCH 38/80] Further improvements around acronym lowercases,... --- CHANGELOG.md | 4 +-- README.md | 2 +- examples/epd1in54_no_graphics.rs | 6 ++-- examples/epd2in13_v2.rs | 6 ++-- examples/epd4in2.rs | 6 ++-- examples/epd4in2_variable_size.rs | 4 +-- src/epd1in54/mod.rs | 28 +++++++-------- src/epd1in54b/command.rs | 2 +- src/epd1in54b/mod.rs | 20 +++++------ src/epd1in54c/command.rs | 2 +- src/epd1in54c/mod.rs | 18 +++++----- src/epd2in13_v2/command.rs | 40 ++++++++++----------- src/epd2in13_v2/mod.rs | 58 +++++++++++++++---------------- src/epd2in7b/command.rs | 2 +- src/epd2in7b/mod.rs | 18 +++++----- src/epd2in9/mod.rs | 26 +++++++------- src/epd2in9bc/command.rs | 2 +- src/epd2in9bc/mod.rs | 20 +++++------ src/epd4in2/command.rs | 4 +-- src/epd4in2/mod.rs | 28 +++++++-------- src/epd5in65f/command.rs | 6 ++-- src/epd5in65f/mod.rs | 18 +++++----- src/epd7in5/command.rs | 8 ++--- src/epd7in5/mod.rs | 18 +++++----- src/epd7in5_v2/command.rs | 8 ++--- src/epd7in5_v2/mod.rs | 16 ++++----- src/interface.rs | 4 +-- src/lib.rs | 4 +-- src/traits.rs | 16 ++++----- src/type_a/command.rs | 6 ++-- 30 files changed, 200 insertions(+), 200 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a4ae72..37fbb31 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,13 +9,13 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added -- Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) +- Added QuickRefresh Trait and implemented it for Epd4in2 in #62 (thanks to @David-OConnor) - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) ### Changed - Use specific ParseColorError instead of () -- EPD4in2: Don't set the resolution (and some more) over and over again (#48) +- Epd4in2: Don't set the resolution (and some more) over and over again (#48) - Removed `#[allow(non_camel_case_types)]` to fix various issues around it ### Fixed diff --git a/README.md b/README.md index 99fcb1b..1b72247 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ 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 epd = Epd4in2::new( & mut spi, cs, busy, dc, rst, & mut delay) ?; // Setup the graphics let mut display = Display4in2::default (); diff --git a/examples/epd1in54_no_graphics.rs b/examples/epd1in54_no_graphics.rs index 7fd30ae..4782622 100644 --- a/examples/epd1in54_no_graphics.rs +++ b/examples/epd1in54_no_graphics.rs @@ -1,7 +1,7 @@ #![deny(warnings)] use embedded_hal::prelude::*; -use epd_waveshare::{epd1in54::EPD1in54, prelude::*}; +use epd_waveshare::{epd1in54::Epd1in54, prelude::*}; use linux_embedded_hal::{ spidev::{self, SpidevOptions}, sysfs_gpio::Direction, @@ -58,14 +58,14 @@ 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)?; + let mut epd = Epd1in54::new(&mut spi, cs_pin, busy, dc, rst, &mut delay)?; // Clear the full screen epd.clear_frame(&mut spi)?; epd.display_frame(&mut spi)?; // Speeddemo - epd.set_lut(&mut spi, Some(RefreshLUT::QUICK))?; + epd.set_lut(&mut spi, Some(RefreshLut::Quick))?; let small_buffer = [Color::Black.get_byte_value(); 32]; //16x16 let number_of_runs = 1; for i in 0..number_of_runs { diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index ac509c3..3fc7472 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -10,7 +10,7 @@ use embedded_graphics::{ use embedded_hal::prelude::*; use epd_waveshare::{ color::*, - epd2in13_v2::{Display2in13, EPD2in13}, + epd2in13_v2::{Display2in13, Epd2in13}, graphics::{Display, DisplayRotation}, prelude::*, }; @@ -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).expect("eink initalize error"); + Epd2in13::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); //println!("Test all the rotations"); let mut display = Display2in13::default(); @@ -121,7 +121,7 @@ fn main() -> Result<(), std::io::Error> { // Demonstrating how to use the partial refresh feature of the screen. // Real animations can be used. epd2in13 - .set_refresh(&mut spi, &mut delay, RefreshLUT::QUICK) + .set_refresh(&mut spi, &mut delay, RefreshLut::Quick) .unwrap(); epd2in13.clear_frame(&mut spi).unwrap(); diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 04730ed..b986828 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -10,7 +10,7 @@ use embedded_graphics::{ use embedded_hal::prelude::*; use epd_waveshare::{ color::*, - epd4in2::{Display4in2, EPD4in2}, + epd4in2::{Display4in2, Epd4in2}, graphics::{Display, DisplayRotation}, prelude::*, }; @@ -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).expect("eink initalize error"); + Epd4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); //println!("Test all the rotations"); let mut display = Display4in2::default(); @@ -120,7 +120,7 @@ fn main() -> Result<(), std::io::Error> { // a moving `Hello World!` let limit = 10; - epd4in2.set_lut(&mut spi, Some(RefreshLUT::QUICK)).unwrap(); + epd4in2.set_lut(&mut spi, Some(RefreshLut::Quick)).unwrap(); epd4in2.clear_frame(&mut spi).unwrap(); for i in 0..limit { //println!("Moving Hello World. Loop {} from {}", (i + 1), limit); diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 6c03851..554c707 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -11,7 +11,7 @@ use embedded_graphics::{ use embedded_hal::prelude::*; use epd_waveshare::{ color::*, - epd4in2::{self, EPD4in2}, + epd4in2::{self, Epd4in2}, graphics::{Display, DisplayRotation, VarDisplay}, prelude::*, }; @@ -64,7 +64,7 @@ fn main() -> Result<(), std::io::Error> { let mut delay = Delay {}; let mut epd4in2 = - EPD4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); + Epd4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); println!("Test all the rotations"); diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index 99f0d4c..315899b 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -20,7 +20,7 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = EPD1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); @@ -61,7 +61,7 @@ use crate::type_a::{ use crate::color::Color; -use crate::traits::{RefreshLUT, WaveshareDisplay}; +use crate::traits::{RefreshLut, WaveshareDisplay}; use crate::interface::DisplayInterface; @@ -70,18 +70,18 @@ mod graphics; #[cfg(feature = "graphics")] pub use crate::epd1in54::graphics::Display1in54; -/// EPD1in54 driver +/// Epd1in54 driver /// -pub struct EPD1in54 { +pub struct Epd1in54 { /// SPI interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT - refresh: RefreshLUT, + refresh: RefreshLut, } -impl EPD1in54 +impl Epd1in54 where SPI: Write, CS: OutputPin, @@ -140,7 +140,7 @@ where } impl WaveshareDisplay - for EPD1in54 + for Epd1in54 where SPI: Write, CS: OutputPin, @@ -167,10 +167,10 @@ where ) -> Result { let interface = DisplayInterface::new(cs, busy, dc, rst); - let mut epd = EPD1in54 { + let mut epd = Epd1in54 { interface, background_color: DEFAULT_BACKGROUND_COLOR, - refresh: RefreshLUT::FULL, + refresh: RefreshLut::Full, }; epd.init(spi, delay)?; @@ -232,7 +232,7 @@ where self.interface.cmd(spi, Command::MasterActivation)?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::NOP)?; + self.interface.cmd(spi, Command::Nop)?; Ok(()) } @@ -266,14 +266,14 @@ where fn set_lut( &mut self, spi: &mut SPI, - refresh_rate: Option, + refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLUT::FULL => self.set_lut_helper(spi, &LUT_FULL_UPDATE), - RefreshLUT::QUICK => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE), + RefreshLut::Full => self.set_lut_helper(spi, &LUT_FULL_UPDATE), + RefreshLut::Quick => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE), } } @@ -282,7 +282,7 @@ where } } -impl EPD1in54 +impl Epd1in54 where SPI: Write, CS: OutputPin, diff --git a/src/epd1in54b/command.rs b/src/epd1in54b/command.rs index 392fd19..fd1e35d 100644 --- a/src/epd1in54b/command.rs +++ b/src/epd1in54b/command.rs @@ -24,7 +24,7 @@ pub(crate) enum Command { LutRed1 = 0x27, PllControl = 0x30, - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, TemperatureSensorSelection = 0x41, VcomAndDataIntervalSetting = 0x50, ResolutionSetting = 0x61, diff --git a/src/epd1in54b/mod.rs b/src/epd1in54b/mod.rs index 25a5b48..0f871ba 100644 --- a/src/epd1in54b/mod.rs +++ b/src/epd1in54b/mod.rs @@ -7,7 +7,7 @@ use embedded_hal::{ use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; //The Lookup Tables for the Display @@ -32,14 +32,14 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display1in54b; -/// EPD1in54b driver -pub struct EPD1in54b { +/// Epd1in54b driver +pub struct Epd1in54b { interface: DisplayInterface, color: Color, } impl InternalWiAdditions - for EPD1in54b + for Epd1in54b where SPI: Write, CS: OutputPin, @@ -89,7 +89,7 @@ where } impl WaveshareThreeColorDisplay - for EPD1in54b + for Epd1in54b where SPI: Write, CS: OutputPin, @@ -132,7 +132,7 @@ where } impl WaveshareDisplay - for EPD1in54b + for Epd1in54b where SPI: Write, CS: OutputPin, @@ -152,7 +152,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD1in54b { interface, color }; + let mut epd = Epd1in54b { interface, color }; epd.init(spi, delay)?; @@ -165,7 +165,7 @@ where .cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17])?; //border floating self.interface - .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // VCOM to 0V + .cmd_with_data(spi, Command::VcmDcSetting, &[0x00])?; // Vcom to 0V self.interface .cmd_with_data(spi, Command::PowerSetting, &[0x02, 0x00, 0x00, 0x00])?; //VG&VS to 0V fast @@ -276,7 +276,7 @@ where fn set_lut( &mut self, spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.interface .cmd_with_data(spi, Command::LutForVcom, LUT_VCOM0)?; @@ -301,7 +301,7 @@ where } } -impl EPD1in54b +impl Epd1in54b where SPI: Write, CS: OutputPin, diff --git a/src/epd1in54c/command.rs b/src/epd1in54c/command.rs index eef7aec..5913986 100644 --- a/src/epd1in54c/command.rs +++ b/src/epd1in54c/command.rs @@ -22,7 +22,7 @@ pub(crate) enum Command { LutBlackToBlack = 0x24, PllControl = 0x30, - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, TemperatureSensorSelection = 0x41, VcomAndDataIntervalSetting = 0x50, ResolutionSetting = 0x61, diff --git a/src/epd1in54c/mod.rs b/src/epd1in54c/mod.rs index 77b5325..6ff0508 100644 --- a/src/epd1in54c/mod.rs +++ b/src/epd1in54c/mod.rs @@ -7,7 +7,7 @@ use embedded_hal::{ use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; /// Width of epd1in54 in pixels @@ -30,14 +30,14 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display1in54c; -/// EPD1in54c driver -pub struct EPD1in54c { +/// Epd1in54c driver +pub struct Epd1in54c { interface: DisplayInterface, color: Color, } impl InternalWiAdditions - for EPD1in54c + for Epd1in54c where SPI: Write, CS: OutputPin, @@ -77,7 +77,7 @@ where } impl WaveshareThreeColorDisplay - for EPD1in54c + for Epd1in54c where SPI: Write, CS: OutputPin, @@ -115,7 +115,7 @@ where } impl WaveshareDisplay - for EPD1in54c + for Epd1in54c where SPI: Write, CS: OutputPin, @@ -135,7 +135,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD1in54c { interface, color }; + let mut epd = Epd1in54c { interface, color }; epd.init(spi, delay)?; @@ -233,7 +233,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { Ok(()) } @@ -243,7 +243,7 @@ where } } -impl EPD1in54c +impl Epd1in54c where SPI: Write, CS: OutputPin, diff --git a/src/epd2in13_v2/command.rs b/src/epd2in13_v2/command.rs index e94c43e..850fd16 100644 --- a/src/epd2in13_v2/command.rs +++ b/src/epd2in13_v2/command.rs @@ -5,7 +5,7 @@ use crate::traits; extern crate bit_field; use bit_field::BitField; -/// EPD2in13 v2 +/// Epd2in13 v2 /// /// For more infos about the addresses and what they are doing look into the pdfs #[allow(dead_code)] @@ -54,7 +54,7 @@ pub(crate) enum Command { SetAnalogBlockControl = 0x74, SetDigitalBlockControl = 0x7E, - NOP = 0x7F, + Nop = 0x7F, } pub(crate) struct DriverOutput { @@ -151,34 +151,34 @@ pub(crate) enum DataEntryModeDir { #[allow(dead_code)] #[derive(Copy, Clone)] -pub(crate) enum BorderWaveFormVBD { - GS = 0x0, +pub(crate) enum BorderWaveFormVbd { + Gs = 0x0, FixLevel = 0x1, - VCOM = 0x2, + Vcom = 0x2, } #[allow(dead_code)] #[derive(Copy, Clone)] pub(crate) enum BorderWaveFormFixLevel { - VSS = 0x0, - VSH1 = 0x1, - VSL = 0x2, - VSH2 = 0x3, + 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) enum BorderWaveFormGs { + Lut0 = 0x0, + Lut1 = 0x1, + Lut2 = 0x2, + Lut3 = 0x3, } pub(crate) struct BorderWaveForm { - pub vbd: BorderWaveFormVBD, + pub vbd: BorderWaveFormVbd, pub fix_level: BorderWaveFormFixLevel, - pub gs_trans: BorderWaveFormGS, + pub gs_trans: BorderWaveFormGs, } impl BorderWaveForm { @@ -204,10 +204,10 @@ pub enum DeepSleepMode { pub(crate) struct GateDrivingVoltage(pub u8); pub(crate) struct SourceDrivingVoltage(pub u8); -pub(crate) struct VCOM(pub u8); +pub(crate) struct Vcom(pub u8); pub(crate) trait I32Ext { - fn vcom(self) -> VCOM; + fn vcom(self) -> Vcom; fn gate_driving_decivolt(self) -> GateDrivingVoltage; fn source_driving_decivolt(self) -> SourceDrivingVoltage; } @@ -215,7 +215,7 @@ pub(crate) trait I32Ext { impl I32Ext for i32 { // This is really not very nice. Until I find something better, this will be // a placeholder. - fn vcom(self) -> VCOM { + fn vcom(self) -> Vcom { assert!((-30..=-2).contains(&self)); let u = match -self { 2 => 0x08, @@ -249,7 +249,7 @@ impl I32Ext for i32 { 30 => 0x78, _ => 0, }; - VCOM(u) + Vcom(u) } fn gate_driving_decivolt(self) -> GateDrivingVoltage { diff --git a/src/epd2in13_v2/mod.rs b/src/epd2in13_v2/mod.rs index cd5481d..4705c1f 100644 --- a/src/epd2in13_v2/mod.rs +++ b/src/epd2in13_v2/mod.rs @@ -16,13 +16,13 @@ use embedded_hal::{ use crate::buffer_len; use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::{ - BorderWaveForm, BorderWaveFormFixLevel, BorderWaveFormGS, BorderWaveFormVBD, Command, + BorderWaveForm, BorderWaveFormFixLevel, BorderWaveFormGs, BorderWaveFormVbd, Command, DataEntryModeDir, DataEntryModeIncr, DeepSleepMode, DisplayUpdateControl2, DriverOutput, - GateDrivingVoltage, I32Ext, SourceDrivingVoltage, VCOM, + GateDrivingVoltage, I32Ext, SourceDrivingVoltage, Vcom, }; pub(crate) mod constants; @@ -43,9 +43,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) driver /// -pub struct EPD2in13 { +pub struct Epd2in13 { /// Connection Interface interface: DisplayInterface, @@ -53,11 +53,11 @@ pub struct EPD2in13 { /// Background Color background_color: Color, - refresh: RefreshLUT, + refresh: RefreshLut, } impl InternalWiAdditions - for EPD2in13 + for Epd2in13 where SPI: Write, CS: OutputPin, @@ -73,7 +73,7 @@ where // HW reset self.interface.reset(delay, 10); - if self.refresh == RefreshLUT::QUICK { + if self.refresh == RefreshLut::Quick { self.set_vcom_register(spi, (-9).vcom())?; self.wait_until_idle(); @@ -94,9 +94,9 @@ where self.set_border_waveform( spi, BorderWaveForm { - vbd: BorderWaveFormVBD::GS, - fix_level: BorderWaveFormFixLevel::VSS, - gs_trans: BorderWaveFormGS::LUT1, + vbd: BorderWaveFormVbd::Gs, + fix_level: BorderWaveFormFixLevel::Vss, + gs_trans: BorderWaveFormGs::Lut1, }, )?; } else { @@ -127,9 +127,9 @@ where self.set_border_waveform( spi, BorderWaveForm { - vbd: BorderWaveFormVBD::GS, - fix_level: BorderWaveFormFixLevel::VSS, - gs_trans: BorderWaveFormGS::LUT3, + vbd: BorderWaveFormVbd::Gs, + fix_level: BorderWaveFormFixLevel::Vss, + gs_trans: BorderWaveFormGs::Lut3, }, )?; @@ -154,7 +154,7 @@ where } impl WaveshareDisplay - for EPD2in13 + for Epd2in13 where SPI: Write, CS: OutputPin, @@ -171,11 +171,11 @@ where rst: RST, delay: &mut DELAY, ) -> Result { - let mut epd = EPD2in13 { + let mut epd = Epd2in13 { interface: DisplayInterface::new(cs, busy, dc, rst), sleep_mode: DeepSleepMode::Mode1, background_color: DEFAULT_BACKGROUND_COLOR, - refresh: RefreshLUT::FULL, + refresh: RefreshLut::Full, }; epd.init(spi, delay)?; @@ -215,7 +215,7 @@ where self.cmd_with_data(spi, Command::WriteRam, buffer)?; - if self.refresh == RefreshLUT::FULL { + if self.refresh == RefreshLut::Full { // Always keep the base buffer equal to current if not doing partial refresh. self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; @@ -245,14 +245,14 @@ where // RAM content). Using this function will most probably make the actual // display incorrect as the controler will compare with something // incorrect. - assert!(self.refresh == RefreshLUT::FULL); + assert!(self.refresh == RefreshLut::Full); self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_address_counters(spi, x, y)?; self.cmd_with_data(spi, Command::WriteRam, buffer)?; - if self.refresh == RefreshLUT::FULL { + if self.refresh == RefreshLut::Full { // Always keep the base buffer equals to current if not doing partial refresh. self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_address_counters(spi, x, y)?; @@ -266,7 +266,7 @@ where /// Never use directly this function when using partial refresh, or also /// keep the base buffer in syncd using `set_partial_base_buffer` function. fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - if self.refresh == RefreshLUT::FULL { + if self.refresh == RefreshLut::Full { self.set_display_update_control_2( spi, DisplayUpdateControl2::new() @@ -289,7 +289,7 @@ where self.update_frame(spi, buffer)?; self.display_frame(spi)?; - if self.refresh == RefreshLUT::QUICK { + if self.refresh == RefreshLut::Quick { self.set_partial_base_buffer(spi, buffer)?; } Ok(()) @@ -309,7 +309,7 @@ where )?; // Always keep the base buffer equals to current if not doing partial refresh. - if self.refresh == RefreshLUT::FULL { + if self.refresh == RefreshLut::Full { self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; self.set_ram_address_counters(spi, 0, 0)?; @@ -342,11 +342,11 @@ where fn set_lut( &mut self, spi: &mut SPI, - refresh_rate: Option, + refresh_rate: Option, ) -> Result<(), SPI::Error> { let buffer = match refresh_rate { - Some(RefreshLUT::FULL) | None => &LUT_FULL_UPDATE, - Some(RefreshLUT::QUICK) => &LUT_PARTIAL_UPDATE, + Some(RefreshLut::Full) | None => &LUT_FULL_UPDATE, + Some(RefreshLut::Quick) => &LUT_PARTIAL_UPDATE, }; self.cmd_with_data(spi, Command::WriteLutRegister, buffer) @@ -357,7 +357,7 @@ where } } -impl EPD2in13 +impl Epd2in13 where SPI: Write, CS: OutputPin, @@ -391,7 +391,7 @@ where &mut self, spi: &mut SPI, delay: &mut DELAY, - refresh: RefreshLUT, + refresh: RefreshLut, ) -> Result<(), SPI::Error> { if self.refresh != refresh { self.refresh = refresh; @@ -425,7 +425,7 @@ where ) } - fn set_vcom_register(&mut self, spi: &mut SPI, vcom: VCOM) -> Result<(), SPI::Error> { + fn set_vcom_register(&mut self, spi: &mut SPI, vcom: Vcom) -> Result<(), SPI::Error> { self.cmd_with_data(spi, Command::WriteVcomRegister, &[vcom.0]) } diff --git a/src/epd2in7b/command.rs b/src/epd2in7b/command.rs index b228d22..e32365c 100644 --- a/src/epd2in7b/command.rs +++ b/src/epd2in7b/command.rs @@ -71,7 +71,7 @@ pub(crate) enum Command { /// This command reads the temperature sensed by the temperature sensor. /// /// Doesn't work! Waveshare doesn't connect the read pin - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, /// This command selects Internal or External temperature sensor. TemperatureSensorCalibration = 0x41, /// Write External Temperature Sensor diff --git a/src/epd2in7b/mod.rs b/src/epd2in7b/mod.rs index 37ae3b5..cbe07fe 100644 --- a/src/epd2in7b/mod.rs +++ b/src/epd2in7b/mod.rs @@ -9,7 +9,7 @@ use embedded_hal::{ use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; // The Lookup Tables for the Display @@ -34,8 +34,8 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display2in7b; -/// EPD2in7b driver -pub struct EPD2in7b { +/// Epd2in7b driver +pub struct Epd2in7b { /// Connection Interface interface: DisplayInterface, /// Background Color @@ -43,7 +43,7 @@ pub struct EPD2in7b { } impl InternalWiAdditions - for EPD2in7b + for Epd2in7b where SPI: Write, CS: OutputPin, @@ -112,7 +112,7 @@ where } impl WaveshareDisplay - for EPD2in7b + for Epd2in7b where SPI: Write, CS: OutputPin, @@ -132,7 +132,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD2in7b { interface, color }; + let mut epd = Epd2in7b { interface, color }; epd.init(spi, delay)?; @@ -247,7 +247,7 @@ where fn set_lut( &mut self, spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.cmd_with_data(spi, Command::LutForVcom, &LUT_VCOM_DC)?; @@ -264,7 +264,7 @@ where } impl WaveshareThreeColorDisplay - for EPD2in7b + for Epd2in7b where SPI: Write, CS: OutputPin, @@ -316,7 +316,7 @@ where } } -impl EPD2in7b +impl Epd2in7b where SPI: Write, CS: OutputPin, diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 99d003c..8658789 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -21,7 +21,7 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = EPD2in9::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd2in9::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display2in9::default(); @@ -70,18 +70,18 @@ mod graphics; #[cfg(feature = "graphics")] pub use crate::epd2in9::graphics::Display2in9; -/// EPD2in9 driver +/// Epd2in9 driver /// -pub struct EPD2in9 { +pub struct Epd2in9 { /// SPI interface: DisplayInterface, /// Color background_color: Color, /// Refresh LUT - refresh: RefreshLUT, + refresh: RefreshLut, } -impl EPD2in9 +impl Epd2in9 where SPI: Write, CS: OutputPin, @@ -136,7 +136,7 @@ where } impl WaveshareDisplay - for EPD2in9 + for Epd2in9 where SPI: Write, CS: OutputPin, @@ -163,10 +163,10 @@ where ) -> Result { let interface = DisplayInterface::new(cs, busy, dc, rst); - let mut epd = EPD2in9 { + let mut epd = Epd2in9 { interface, background_color: DEFAULT_BACKGROUND_COLOR, - refresh: RefreshLUT::FULL, + refresh: RefreshLut::Full, }; epd.init(spi, delay)?; @@ -231,7 +231,7 @@ where self.interface.cmd(spi, Command::MasterActivation)?; // MASTER Activation should not be interupted to avoid currption of panel images // therefore a terminate command is send - self.interface.cmd(spi, Command::NOP)?; + self.interface.cmd(spi, Command::Nop)?; Ok(()) } @@ -265,14 +265,14 @@ where fn set_lut( &mut self, spi: &mut SPI, - refresh_rate: Option, + refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLUT::FULL => self.set_lut_helper(spi, &LUT_FULL_UPDATE), - RefreshLUT::QUICK => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE), + RefreshLut::Full => self.set_lut_helper(spi, &LUT_FULL_UPDATE), + RefreshLut::Quick => self.set_lut_helper(spi, &LUT_PARTIAL_UPDATE), } } @@ -281,7 +281,7 @@ where } } -impl EPD2in9 +impl Epd2in9 where SPI: Write, CS: OutputPin, diff --git a/src/epd2in9bc/command.rs b/src/epd2in9bc/command.rs index 9414c5a..7121c50 100644 --- a/src/epd2in9bc/command.rs +++ b/src/epd2in9bc/command.rs @@ -22,7 +22,7 @@ pub(crate) enum Command { LutBlackToBlack = 0x24, PllControl = 0x30, - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, TemperatureSensorSelection = 0x41, VcomAndDataIntervalSetting = 0x50, ResolutionSetting = 0x61, diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 6f76602..ff8face 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -20,7 +20,7 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = EPD2in9bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd2in9bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white pixels @@ -60,7 +60,7 @@ use embedded_hal::{ use crate::interface::DisplayInterface; use crate::traits::{ - InternalWiAdditions, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; /// Width of epd2in9bc in pixels @@ -89,14 +89,14 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display2in9bc; -/// EPD2in9bc driver -pub struct EPD2in9bc { +/// Epd2in9bc driver +pub struct Epd2in9bc { interface: DisplayInterface, color: Color, } impl InternalWiAdditions - for EPD2in9bc + for Epd2in9bc where SPI: Write, CS: OutputPin, @@ -143,7 +143,7 @@ where } impl WaveshareThreeColorDisplay - for EPD2in9bc + for Epd2in9bc where SPI: Write, CS: OutputPin, @@ -187,7 +187,7 @@ where } impl WaveshareDisplay - for EPD2in9bc + for Epd2in9bc where SPI: Write, CS: OutputPin, @@ -207,7 +207,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD2in9bc { interface, color }; + let mut epd = Epd2in9bc { interface, color }; epd.init(spi, delay)?; @@ -317,7 +317,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { Ok(()) } @@ -327,7 +327,7 @@ where } } -impl EPD2in9bc +impl Epd2in9bc where SPI: Write, CS: OutputPin, diff --git a/src/epd4in2/command.rs b/src/epd4in2/command.rs index 3a31a69..4d3a9fe 100644 --- a/src/epd4in2/command.rs +++ b/src/epd4in2/command.rs @@ -92,7 +92,7 @@ pub(crate) enum Command { /// This command reads the temperature sensed by the temperature sensor. /// /// Doesn't work! Waveshare doesn't connect the read pin - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, /// Selects the Internal or External temperature sensor and offset TemperatureSensorSelection = 0x41, /// Write External Temperature Sensor @@ -114,7 +114,7 @@ pub(crate) enum Command { /// The LUT_REV / Chip Revision is read from OTP address = 0x001. /// /// Doesn't work! Waveshare doesn't connect the read pin - REVISION = 0x70, + Revision = 0x70, /// Read Flags. This command reads the IC status /// PTL, I2C_ERR, I2C_BUSY, DATA, PON, POF, BUSY /// diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 4e155a5..2f75539 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -25,7 +25,7 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = EPD4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display4in2::default(); @@ -55,7 +55,7 @@ use embedded_hal::{ }; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, QuickRefresh, RefreshLut, WaveshareDisplay}; //The Lookup Tables for the Display mod constants; @@ -79,19 +79,19 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display4in2; -/// EPD4in2 driver +/// Epd4in2 driver /// -pub struct EPD4in2 { +pub struct Epd4in2 { /// Connection Interface interface: DisplayInterface, /// Background Color color: Color, /// Refresh LUT - refresh: RefreshLUT, + refresh: RefreshLut, } impl InternalWiAdditions - for EPD4in2 + for Epd4in2 where SPI: Write, CS: OutputPin, @@ -149,7 +149,7 @@ where } impl WaveshareDisplay - for EPD4in2 + for Epd4in2 where SPI: Write, CS: OutputPin, @@ -169,10 +169,10 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD4in2 { + let mut epd = Epd4in2 { interface, color, - refresh: RefreshLUT::FULL, + refresh: RefreshLut::Full, }; epd.init(spi, delay)?; @@ -313,16 +313,16 @@ where fn set_lut( &mut self, spi: &mut SPI, - refresh_rate: Option, + refresh_rate: Option, ) -> Result<(), SPI::Error> { if let Some(refresh_lut) = refresh_rate { self.refresh = refresh_lut; } match self.refresh { - RefreshLUT::FULL => { + RefreshLut::Full => { self.set_lut_helper(spi, &LUT_VCOM0, &LUT_WW, &LUT_BW, &LUT_WB, &LUT_BB) } - RefreshLUT::QUICK => self.set_lut_helper( + RefreshLut::Quick => self.set_lut_helper( spi, &LUT_VCOM0_QUICK, &LUT_WW_QUICK, @@ -338,7 +338,7 @@ where } } -impl EPD4in2 +impl Epd4in2 where SPI: Write, CS: OutputPin, @@ -435,7 +435,7 @@ where } impl QuickRefresh - for EPD4in2 + for Epd4in2 where SPI: Write, CS: OutputPin, diff --git a/src/epd5in65f/command.rs b/src/epd5in65f/command.rs index 89af89e..23d2246 100644 --- a/src/epd5in65f/command.rs +++ b/src/epd5in65f/command.rs @@ -64,7 +64,7 @@ pub(crate) enum Command { DisplayRefresh = 0x12, /// Image Process Command - ImageProcessCommand = 0x13, + ImageProcess = 0x13, /// This command builds the VCOM Look-Up Table (LUTC). LutForVcom = 0x20, @@ -91,7 +91,7 @@ pub(crate) enum Command { PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, /// This command selects the Internal or External temperature sensor. TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. @@ -115,7 +115,7 @@ pub(crate) enum Command { //SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. - //REVISION = 0x70, + //Revision = 0x70, /// This command reads the IC status. GetStatus = 0x71, diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 6e8e7b4..9f94930 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -13,7 +13,7 @@ use embedded_hal::{ use crate::color::OctColor; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -31,9 +31,9 @@ pub const HEIGHT: u32 = 448; pub const DEFAULT_BACKGROUND_COLOR: OctColor = OctColor::White; const IS_BUSY_LOW: bool = true; -/// EPD5in65f driver +/// Epd5in65f driver /// -pub struct EPD5in65f { +pub struct Epd5in65f { /// Connection Interface interface: DisplayInterface, /// Background Color @@ -41,7 +41,7 @@ pub struct EPD5in65f { } impl InternalWiAdditions - for EPD5in65f + for Epd5in65f where SPI: Write, CS: OutputPin, @@ -62,7 +62,7 @@ where self.cmd_with_data(spi, Command::PowerOffSequenceSetting, &[0x00])?; self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?; self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; - self.cmd_with_data(spi, Command::TemperatureSensorCommand, &[0x00])?; + self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00])?; self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; self.send_resolution(spi)?; @@ -77,7 +77,7 @@ where } impl WaveshareDisplay - for EPD5in65f + for Epd5in65f where SPI: Write, CS: OutputPin, @@ -97,7 +97,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD5in65f { interface, color }; + let mut epd = Epd5in65f { interface, color }; epd.init(spi, delay)?; @@ -182,7 +182,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); } @@ -192,7 +192,7 @@ where } } -impl EPD5in65f +impl Epd5in65f where SPI: Write, CS: OutputPin, diff --git a/src/epd7in5/command.rs b/src/epd7in5/command.rs index cb1aa1c..8615269 100644 --- a/src/epd7in5/command.rs +++ b/src/epd7in5/command.rs @@ -2,7 +2,7 @@ use crate::traits; -/// EPD7in5 commands +/// Epd7in5 commands /// /// Should rarely (never?) be needed directly. /// @@ -93,7 +93,7 @@ pub(crate) enum Command { PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, /// This command selects the Internal or External temperature sensor. TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. @@ -117,7 +117,7 @@ pub(crate) enum Command { SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. - REVISION = 0x70, + Revision = 0x70, /// This command reads the IC status. GetStatus = 0x71, @@ -128,7 +128,7 @@ pub(crate) enum Command { /// This command sets `VCOM_DC` value. VcmDcSetting = 0x82, - /// This is in all the Waveshare controllers for EPD7in5, but it's not documented + /// This is in all the Waveshare controllers for Epd7in5, but it's not documented /// anywhere in the datasheet `¯\_(ツ)_/¯` FlashMode = 0xE5, } diff --git a/src/epd7in5/mod.rs b/src/epd7in5/mod.rs index 16d902a..c93bf1e 100644 --- a/src/epd7in5/mod.rs +++ b/src/epd7in5/mod.rs @@ -13,7 +13,7 @@ use embedded_hal::{ use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -31,9 +31,9 @@ pub const HEIGHT: u32 = 384; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; -/// EPD7in5 driver +/// Epd7in5 driver /// -pub struct EPD7in5 { +pub struct Epd7in5 { /// Connection Interface interface: DisplayInterface, /// Background Color @@ -41,7 +41,7 @@ pub struct EPD7in5 { } impl InternalWiAdditions - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -91,7 +91,7 @@ where // Set VCOM_DC to -1.5V self.cmd_with_data(spi, Command::VcmDcSetting, &[0x1E])?; - // This is in all the Waveshare controllers for EPD7in5 + // This is in all the Waveshare controllers for Epd7in5 self.cmd_with_data(spi, Command::FlashMode, &[0x03])?; self.wait_until_idle(); @@ -100,7 +100,7 @@ where } impl WaveshareDisplay - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -120,7 +120,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD7in5 { interface, color }; + let mut epd = Epd7in5 { interface, color }; epd.init(spi, delay)?; @@ -214,7 +214,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); } @@ -224,7 +224,7 @@ where } } -impl EPD7in5 +impl Epd7in5 where SPI: Write, CS: OutputPin, diff --git a/src/epd7in5_v2/command.rs b/src/epd7in5_v2/command.rs index 599c080..95292d3 100644 --- a/src/epd7in5_v2/command.rs +++ b/src/epd7in5_v2/command.rs @@ -2,7 +2,7 @@ use crate::traits; -/// EPD7in5 commands +/// Epd7in5 commands /// /// Should rarely (never?) be needed directly. /// @@ -94,7 +94,7 @@ pub(crate) enum Command { PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. - TemperatureSensorCommand = 0x40, + TemperatureSensor = 0x40, /// This command selects the Internal or External temperature sensor. TemperatureCalibration = 0x41, /// This command could write data to the external temperature sensor. @@ -118,7 +118,7 @@ pub(crate) enum Command { SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. - REVISION = 0x70, + Revision = 0x70, /// This command reads the IC status. GetStatus = 0x71, @@ -128,7 +128,7 @@ pub(crate) enum Command { ReadVcomValue = 0x81, /// This command sets `VCOM_DC` value. VcmDcSetting = 0x82, - // /// This is in all the Waveshare controllers for EPD7in5, but it's not documented + // /// This is in all the Waveshare controllers for Epd7in5, but it's not documented // /// anywhere in the datasheet `¯\_(ツ)_/¯` // FlashMode = 0xE5, } diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index e4c60e0..b3ab5de 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -17,7 +17,7 @@ use embedded_hal::{ use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -35,9 +35,9 @@ pub const HEIGHT: u32 = 480; pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; -/// EPD7in5 (V2) driver +/// Epd7in5 (V2) driver /// -pub struct EPD7in5 { +pub struct Epd7in5 { /// Connection Interface interface: DisplayInterface, /// Background Color @@ -45,7 +45,7 @@ pub struct EPD7in5 { } impl InternalWiAdditions - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -82,7 +82,7 @@ where } impl WaveshareDisplay - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -102,7 +102,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD7in5 { interface, color }; + let mut epd = Epd7in5 { interface, color }; epd.init(spi, delay)?; @@ -188,7 +188,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); } @@ -198,7 +198,7 @@ where } } -impl EPD7in5 +impl Epd7in5 where SPI: Write, CS: OutputPin, diff --git a/src/interface.rs b/src/interface.rs index 58fbebb..4ba1eb3 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -51,7 +51,7 @@ where /// Basic function for sending an array of u8-values of data over spi /// - /// Enables direct interaction with the device with the help of [command()](EPD4in2::command()) + /// Enables direct interaction with the device with the help of [command()](Epd4in2::command()) pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { // high for data let _ = self.dc.set_high(); @@ -157,7 +157,7 @@ where /// Resets the device. /// - /// Often used to awake the module from deep sleep. See [EPD4in2::sleep()](EPD4in2::sleep()) + /// Often used to awake the module from deep sleep. See [Epd4in2::sleep()](Epd4in2::sleep()) /// /// The timing of keeping the reset pin low seems to be important and different per device. /// Most displays seem to require keeping it low for 10ms, but the 7in5_v2 only seems to reset diff --git a/src/lib.rs b/src/lib.rs index 60a816e..b96e6fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,7 +28,7 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = EPD1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd1in54::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!let mut display = Display1in54::default(); @@ -90,7 +90,7 @@ pub(crate) mod type_a; pub mod prelude { pub use crate::color::{Color, OctColor, TriColor}; pub use crate::traits::{ - QuickRefresh, RefreshLUT, WaveshareDisplay, WaveshareThreeColorDisplay, + QuickRefresh, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; pub use crate::SPI_MODE; diff --git a/src/traits.rs b/src/traits.rs index d4877b5..7c21c10 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -12,17 +12,17 @@ pub(crate) trait Command { /// Seperates the different LUT for the Display Refresh process #[derive(Debug, Clone, PartialEq, Eq, Copy)] -pub enum RefreshLUT { +pub enum RefreshLut { /// The "normal" full Lookuptable for the Refresh-Sequence - FULL, + Full, /// The quick LUT where not the full refresh sequence is followed. /// This might lead to some - QUICK, + Quick, } -impl Default for RefreshLUT { +impl Default for RefreshLut { fn default() -> Self { - RefreshLUT::FULL + RefreshLut::Full } } @@ -108,7 +108,7 @@ where ///# let mut delay = delay::MockNoop::new(); /// ///// Setup EPD -///let mut epd = EPD4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +///let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; /// ///// Use display graphics from embedded-graphics ///let mut display = Display4in2::default(); @@ -219,7 +219,7 @@ where fn set_lut( &mut self, spi: &mut SPI, - refresh_rate: Option, + refresh_rate: Option, ) -> Result<(), SPI::Error>; /// Checks if the display is busy transmitting data @@ -258,7 +258,7 @@ where ///# let mut delay = delay::MockNoop::new(); ///# ///# // Setup EPD -///# let mut epd = EPD4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +///# let mut epd = Epd4in2::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; ///let (x, y, frame_width, frame_height) = (20, 40, 80,80); /// ///let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 80 / 8 * 80]; diff --git a/src/type_a/command.rs b/src/type_a/command.rs index d12dd2c..71a106b 100644 --- a/src/type_a/command.rs +++ b/src/type_a/command.rs @@ -2,7 +2,7 @@ use crate::traits; -/// EPD1in54 and EPD2IN9 commands +/// Epd1in54 and EPD2IN9 commands /// /// Should rarely (never?) be needed directly. /// @@ -67,7 +67,7 @@ pub(crate) enum Command { SetRamYAddressCounter = 0x4F, - NOP = 0xFF, + Nop = 0xFF, } impl traits::Command for Command { @@ -88,6 +88,6 @@ mod tests { assert_eq!(Command::SetRamXAddressCounter.address(), 0x4E); - assert_eq!(Command::NOP.address(), 0xFF); + assert_eq!(Command::Nop.address(), 0xFF); } } From ba1243137d70d149a210d05b2b6ca6b119bdc146 Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 14 Apr 2021 14:59:23 +0100 Subject: [PATCH 39/80] EPD 7in5 HD: Added more documentation Updated README to include the driver. Updated CHANGELOG. Added note about the default background color of the HD driver --- CHANGELOG.md | 1 + README.md | 1 + src/epd7in5_hd/mod.rs | 11 ++++++++--- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3eeac2..73104ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) + - Added Epd 7in5 HD support ### Changed - Use specific ParseColorError instead of () diff --git a/README.md b/README.md index 200e601..e2a83b4 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ epd.update_and_display_frame(&mut spi, &display.buffer())?; | Device (with Link) | Colors | Flexible Display | Partial Refresh | Supported | Tested | | :---: | --- | :---: | :---: | :---: | :---: | +| [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 | ✕ | ✕ | ✔ | ✔ | | [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)] | ✔ | ✔ | diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index d0728b9..90eb746 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -1,5 +1,9 @@ //! A simple Driver for the Waveshare 7.5" E-Ink Display (HD) via SPI //! +//! Color values for this driver are inverted compared to the [EPD 7in5 V2 driver](crate::epd7in5_v2) +//! *EPD 7in5 HD:* White = 1/0xFF, Black = 0/0x00 +//! *EPD 7in5 V2:* White = 0/0x00, Black = 1/0xFF +//! //! # References //! //! - [Datasheet](https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf) @@ -27,7 +31,7 @@ pub const WIDTH: u32 = 880; /// Height of the display pub const HEIGHT: u32 = 528; /// Default Background Color -pub const DEFAULT_BACKGROUND_COLOR: Color = Color::Black; // Inverted for HD (0xFF = White) +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; /// EPD7in5 (HD) driver @@ -171,13 +175,14 @@ where fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let pixel_count = WIDTH * HEIGHT / 8; + let background_color_byte = self.color.get_byte_value(); self.wait_until_idle(); self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; for cmd in &[Command::WRITE_RAM_BW, Command::WRITE_RAM_RED] { self.command(spi, *cmd)?; - self.interface.data_x_times(spi, 0xFF, pixel_count)?; + self.interface.data_x_times(spi, background_color_byte, pixel_count)?; } self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; @@ -249,6 +254,6 @@ mod tests { fn epd_size() { assert_eq!(WIDTH, 880); assert_eq!(HEIGHT, 528); - assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::Black); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); } } From 72e6b82b2d553bfee8ff96690b23d5ea93a6c743 Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 14 Apr 2021 15:22:33 +0100 Subject: [PATCH 40/80] epd7in5 HD: Formatted with cargo fmt --- src/epd7in5_hd/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 90eb746..4b0d04c 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -182,7 +182,8 @@ where for cmd in &[Command::WRITE_RAM_BW, Command::WRITE_RAM_RED] { self.command(spi, *cmd)?; - self.interface.data_x_times(spi, background_color_byte, pixel_count)?; + self.interface + .data_x_times(spi, background_color_byte, pixel_count)?; } self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; From a1e9c17b53447a710a635238947ac1a3229e1408 Mon Sep 17 00:00:00 2001 From: pi Date: Wed, 14 Apr 2021 15:30:41 +0100 Subject: [PATCH 41/80] epd7in5 HD: Corrected import of `RefreshLut` trait --- src/epd7in5_hd/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 4b0d04c..e9ab1f3 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -16,7 +16,7 @@ use embedded_hal::{ use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLUT, WaveshareDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -211,7 +211,7 @@ where fn set_lut( &mut self, _spi: &mut SPI, - _refresh_rate: Option, + _refresh_rate: Option, ) -> Result<(), SPI::Error> { unimplemented!(); } From 989a236fb1cacd37175b8ce1b004eeab53491051 Mon Sep 17 00:00:00 2001 From: pi Date: Thu, 15 Apr 2021 10:20:52 +0100 Subject: [PATCH 42/80] epd7in5 HD: Rename Command enums for Clippy check --- src/epd7in5_hd/command.rs | 86 +++++++++++++++++++-------------------- src/epd7in5_hd/mod.rs | 46 ++++++++++----------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/epd7in5_hd/command.rs b/src/epd7in5_hd/command.rs index 98ff4bb..946ace8 100644 --- a/src/epd7in5_hd/command.rs +++ b/src/epd7in5_hd/command.rs @@ -11,131 +11,131 @@ use crate::traits; #[allow(non_camel_case_types)] #[derive(Copy, Clone)] pub(crate) enum Command { - DRIVER_OUTPUT_CONTROL = 0x01, + DriverOutputControl = 0x01, /// Set gate driving voltage - GATE_DRIVING_VOLTAGE_CONTROL = 0x03, + GateDrivingVoltageControl = 0x03, /// Set source driving voltage - SOURCE_DRIVING_VOLTAGE_CONTROL = 0x04, + SourceDrivingVoltageControl = 0x04, - SOFT_START = 0x0C, + SoftStart = 0x0C, /// Set the scanning start position of the gate driver. /// The valid range is from 0 to 679. - GATE_SCAN_START_POSITION = 0x0F, + GateScanStartPosition = 0x0F, /// Deep sleep mode control - DEEP_SLEEP = 0x10, + DeepSleep = 0x10, /// Define data entry sequence - DATA_ENTRY = 0x11, + DataEntry = 0x11, /// resets the commands and parameters to their S/W Reset default values except R10h-Deep Sleep Mode. /// During operation, BUSY pad will output high. /// Note: RAM are unaffected by this command. - SW_RESET = 0x12, + SwReset = 0x12, /// After this command initiated, HV Ready detection starts. /// BUSY pad will output high during detection. /// The detection result can be read from the Status Bit Read (Command 0x2F). - HV_READY_DETECTION = 0x14, + HvReadyDetection = 0x14, /// After this command initiated, VCI detection starts. /// BUSY pad will output high during detection. /// The detection result can be read from the Status Bit Read (Command 0x2F). - VCI_DETECTION = 0x15, + VciDetection = 0x15, /// Temperature Sensor Selection - TEMPERATURE_SENSOR_CONTROL = 0x18, + TemperatureSensorControl = 0x18, /// Write to temperature register - TEMPERATURE_SENSOR_WRITE = 0x1A, + TemperatureSensorWrite = 0x1A, /// Read from temperature register - TEMPERATURE_SENSOR_READ = 0x1B, + TemperatureSensorRead = 0x1B, /// Write Command to External temperature sensor. - TEMPERATURE_SENSOR_WRITE_EXTERNAL = 0x1C, + TemperatureSensorWriteExternal = 0x1C, /// Activate Display Update Sequence - MASTER_ACTIVATION = 0x20, + MasterActivation = 0x20, /// RAM content option for Display Update - DISPLAY_UPDATE_CONTROL_1 = 0x21, + DisplayUpdateControl1 = 0x21, /// Display Update Sequence Option - DISPLAY_UPDATE_CONTROL_2 = 0x22, + DisplayUpdateControl2 = 0x22, /// After this command, data entries will be written into the BW RAM until another command is written - WRITE_RAM_BW = 0x24, + WriteRamBw = 0x24, /// After this command, data entries will be written into the RED RAM until another command is written - WRITE_RAM_RED = 0x26, + WriteRamRed = 0x26, /// Fetch data from RAM - READ_RAM = 0x27, + ReadRam = 0x27, /// Enter VCOM sensing conditions - VCOM_SENSE = 0x28, + VcomSense = 0x28, /// Enter VCOM sensing conditions - VCOM_SENSE_DURATION = 0x29, + VcomSenseDuration = 0x29, /// Program VCOM register into OTP - VCOM_PROGRAM_OTP = 0x2A, + VcomProgramOtp = 0x2A, /// Reduces a glitch when ACVCOM is toggled - VCOM_CONTROL = 0x2B, + VcomControl = 0x2B, /// Write VCOM register from MCU interface - VCOM_WRITE = 0x2C, + VcomWrite = 0x2C, /// Read Register for Display Option - OTP_READ = 0x2D, + OtpRead = 0x2D, /// CRC calculation command for OTP content validation - CRC_CALCULATION = 0x34, + CrcCalculation = 0x34, /// CRC Status Read - CRC_READ = 0x35, + CrcRead = 0x35, /// Program OTP Selection according to the OTP Selection Control - PROGRAM_SELECTION = 0x36, + ProgramSelection = 0x36, /// Write Register for Display Option - DISPLAY_OPTION_WRITE = 0x37, + DisplayOptionWrite = 0x37, /// Write register for User ID - USER_ID_WRITE = 0x38, + UserIdWrite = 0x38, /// Select border waveform for VBD - VBD_CONTROL = 0x3C, + VbdControl = 0x3C, /// Read RAM Option - READ_RAM_OPTION = 0x41, + ReadRamOption = 0x41, /// Specify the start/end positions of the window address in the X direction by an address unit for RAM - SET_RAM_X_START_END = 0x44, + SetRamXStartEnd = 0x44, /// Specify the start/end positions of the window address in the Y direction by an address unit for RAM - SET_RAM_Y_START_END = 0x45, + SetRamYStartEnd = 0x45, /// Auto write RED RAM for regular pattern - AUTO_WRITE_RED = 0x46, + AutoWriteRed = 0x46, /// Auto write B/W RAM for regular pattern - AUTO_WRITE_BW = 0x47, + AutoWriteBw = 0x47, /// Make initial settings for the RAM X address in the address counter (AC) - SET_RAM_X_AC = 0x4E, + SetRamXAc = 0x4E, /// Make initial settings for the RAM Y address in the address counter (AC) - SET_RAM_Y_AC = 0x4F, + SetRamYAc = 0x4F, /// This command is an empty command; it does not have any effect on the display module. /// However, it can be used to terminate Frame Memory Write or Read Commands. - NOP = 0x7F, + Nop = 0x7F, } impl traits::Command for Command { @@ -152,8 +152,8 @@ mod tests { #[test] fn command_addr() { - assert_eq!(Command::MASTER_ACTIVATION.address(), 0x20); - assert_eq!(Command::SW_RESET.address(), 0x12); - assert_eq!(Command::DISPLAY_UPDATE_CONTROL_2.address(), 0x22); + assert_eq!(Command::MasterActivation.address(), 0x20); + assert_eq!(Command::SwReset.address(), 0x12); + assert_eq!(Command::DisplayUpdateControl2.address(), 0x22); } } diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index e9ab1f3..799d184 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -66,34 +66,34 @@ where // https://www.waveshare.com/w/upload/2/27/7inch_HD_e-Paper_Specification.pdf self.wait_until_idle(); - self.command(spi, Command::SW_RESET)?; + self.command(spi, Command::SwReset)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::AUTO_WRITE_RED, &[0xF7])?; + self.cmd_with_data(spi, Command::AutoWriteRed, &[0xF7])?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::AUTO_WRITE_BW, &[0xF7])?; + self.cmd_with_data(spi, Command::AutoWriteBw, &[0xF7])?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::SOFT_START, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40])?; + self.cmd_with_data(spi, Command::SoftStart, &[0xAE, 0xC7, 0xC3, 0xC0, 0x40])?; - self.cmd_with_data(spi, Command::DRIVER_OUTPUT_CONTROL, &[0xAF, 0x02, 0x01])?; + self.cmd_with_data(spi, Command::DriverOutputControl, &[0xAF, 0x02, 0x01])?; - self.cmd_with_data(spi, Command::DATA_ENTRY, &[0x01])?; + self.cmd_with_data(spi, Command::DataEntry, &[0x01])?; - self.cmd_with_data(spi, Command::SET_RAM_X_START_END, &[0x00, 0x00, 0x6F, 0x03])?; - self.cmd_with_data(spi, Command::SET_RAM_Y_START_END, &[0xAF, 0x02, 0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamXStartEnd, &[0x00, 0x00, 0x6F, 0x03])?; + self.cmd_with_data(spi, Command::SetRamYStartEnd, &[0xAF, 0x02, 0x00, 0x00])?; - self.cmd_with_data(spi, Command::VBD_CONTROL, &[0x05])?; + self.cmd_with_data(spi, Command::VbdControl, &[0x05])?; - self.cmd_with_data(spi, Command::TEMPERATURE_SENSOR_CONTROL, &[0x80])?; + self.cmd_with_data(spi, Command::TemperatureSensorControl, &[0x80])?; - self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xB1])?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xB1])?; - self.command(spi, Command::MASTER_ACTIVATION)?; + self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); - self.cmd_with_data(spi, Command::SET_RAM_X_AC, &[0x00, 0x00])?; - self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamXAc, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; Ok(()) } @@ -137,15 +137,15 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::DEEP_SLEEP, &[0x01])?; + self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?; Ok(()) } fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; - self.cmd_with_data(spi, Command::WRITE_RAM_BW, buffer)?; - self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::WriteRamBw, buffer)?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; Ok(()) } @@ -162,7 +162,7 @@ where } fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - self.command(spi, Command::MASTER_ACTIVATION)?; + self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) } @@ -178,16 +178,16 @@ where let background_color_byte = self.color.get_byte_value(); self.wait_until_idle(); - self.cmd_with_data(spi, Command::SET_RAM_Y_AC, &[0x00, 0x00])?; + self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; - for cmd in &[Command::WRITE_RAM_BW, Command::WRITE_RAM_RED] { + for cmd in &[Command::WriteRamBw, Command::WriteRamRed] { self.command(spi, *cmd)?; self.interface .data_x_times(spi, background_color_byte, pixel_count)?; } - self.cmd_with_data(spi, Command::DISPLAY_UPDATE_CONTROL_2, &[0xF7])?; - self.command(spi, Command::MASTER_ACTIVATION)?; + self.cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; + self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) } From c94f6c44341bf44fa2722307460c33d0c4603ebc Mon Sep 17 00:00:00 2001 From: pi Date: Thu, 15 Apr 2021 10:27:30 +0100 Subject: [PATCH 43/80] epd7in5 HD: Renamed epd7in5 struct for Clippy --- src/epd7in5_hd/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index 799d184..ab36a70 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -36,7 +36,7 @@ const IS_BUSY_LOW: bool = false; /// EPD7in5 (HD) driver /// -pub struct EPD7in5 { +pub struct Epd7in5 { /// Connection Interface interface: DisplayInterface, /// Background Color @@ -44,7 +44,7 @@ pub struct EPD7in5 { } impl InternalWiAdditions - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -100,7 +100,7 @@ where } impl WaveshareDisplay - for EPD7in5 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -120,7 +120,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = EPD7in5 { interface, color }; + let mut epd = Epd7in5 { interface, color }; epd.init(spi, delay)?; @@ -221,7 +221,7 @@ where } } -impl EPD7in5 +impl Epd7in5 where SPI: Write, CS: OutputPin, From 3141865b62b9d6c1478cab4bd30837cd4a5ef01a Mon Sep 17 00:00:00 2001 From: pi Date: Thu, 15 Apr 2021 10:49:39 +0100 Subject: [PATCH 44/80] epd7in5 HD: Fixed graphics tests --- src/epd7in5_hd/graphics.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/epd7in5_hd/graphics.rs b/src/epd7in5_hd/graphics.rs index 1bee110..60c36dc 100644 --- a/src/epd7in5_hd/graphics.rs +++ b/src/epd7in5_hd/graphics.rs @@ -98,7 +98,7 @@ mod tests { let mut display = Display7in5::default(); display.set_rotation(DisplayRotation::Rotate90); - let _ = Line::new(Point::new(0, 792), Point::new(0, 799)) + let _ = Line::new(Point::new(0, 872), Point::new(0, 879)) .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); @@ -116,7 +116,7 @@ mod tests { let mut display = Display7in5::default(); display.set_rotation(DisplayRotation::Rotate180); - let _ = Line::new(Point::new(792, 479), Point::new(799, 479)) + let _ = Line::new(Point::new(872, 527), Point::new(879, 527)) .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); @@ -134,7 +134,7 @@ mod tests { let mut display = Display7in5::default(); display.set_rotation(DisplayRotation::Rotate270); - let _ = Line::new(Point::new(479, 0), Point::new(479, 7)) + let _ = Line::new(Point::new(527, 0), Point::new(527, 7)) .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); From 8ef83eb88aaa710b10f50530980b0f7672b1929f Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 18 Apr 2021 18:49:23 +0200 Subject: [PATCH 45/80] Fix missing parts of merge of #71 --- src/epd7in5_hd/mod.rs | 55 +++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 25 deletions(-) diff --git a/src/epd7in5_hd/mod.rs b/src/epd7in5_hd/mod.rs index ab36a70..d4f4983 100644 --- a/src/epd7in5_hd/mod.rs +++ b/src/epd7in5_hd/mod.rs @@ -36,27 +36,24 @@ const IS_BUSY_LOW: 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device self.interface.reset(delay, 2); @@ -99,17 +96,18 @@ where } } -impl WaveshareDisplay - for Epd7in5 +impl WaveshareDisplay + for Epd7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -127,21 +125,22 @@ where Ok(epd) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); self.cmd_with_data(spi, Command::DeepSleep, &[0x01])?; Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.cmd_with_data(spi, Command::SetRamYAc, &[0x00, 0x00])?; self.cmd_with_data(spi, Command::WriteRamBw, buffer)?; @@ -161,19 +160,24 @@ where unimplemented!(); } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.command(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { let pixel_count = WIDTH * HEIGHT / 8; let background_color_byte = self.color.get_byte_value(); @@ -221,13 +225,14 @@ where } } -impl Epd7in5 +impl Epd7in5 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> { self.interface.cmd(spi, command) From 64e1b6ded0e2dbc36dffd926036c7a939b9bbc32 Mon Sep 17 00:00:00 2001 From: Andreas Date: Sun, 18 Apr 2021 12:05:54 +0200 Subject: [PATCH 46/80] Added epd2in9_v2 support --- CHANGELOG.md | 1 + README.md | 1 + src/epd2in9_v2/graphics.rs | 74 +++++++ src/epd2in9_v2/mod.rs | 438 +++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/type_a/command.rs | 4 + 6 files changed, 519 insertions(+) create mode 100644 src/epd2in9_v2/graphics.rs create mode 100644 src/epd2in9_v2/mod.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index bb7d21c..983d17a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) - Added Epd 7in5 HD support +- Added Epd 2in9 V2 support ### Changed diff --git a/README.md b/README.md index 5ee6012..59b9f41 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [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.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 | ✕ | ✔ | ✔ | ✔ | | [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 | ✕ | ✕ | ✔ | ✔ | diff --git a/src/epd2in9_v2/graphics.rs b/src/epd2in9_v2/graphics.rs new file mode 100644 index 0000000..fb1154e --- /dev/null +++ b/src/epd2in9_v2/graphics.rs @@ -0,0 +1,74 @@ +use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; +use crate::graphics::{Display, DisplayRotation}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::*; + +/// Display with Fullsize buffer for use with the 2in9 EPD +/// +/// Can also be manuall constructed: +/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 8 * HEIGHT]` +pub struct Display2in9 { + buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation, +} + +impl Default for Display2in9 { + fn default() -> Self { + Display2in9 { + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); + WIDTH as usize * HEIGHT as usize / 8], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display2in9 { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl Display for Display2in9 { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} + +#[cfg(test)] +mod tests { + use super::*; + + // test buffer length + #[test] + fn graphics_size() { + let display = Display2in9::default(); + assert_eq!(display.buffer().len(), 4736); + } + + // test default background color on all bytes + #[test] + fn graphics_default() { + let display = Display2in9::default(); + for &byte in display.buffer() { + assert_eq!(byte, DEFAULT_BACKGROUND_COLOR.get_byte_value()); + } + } +} diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs new file mode 100644 index 0000000..3fc27f0 --- /dev/null +++ b/src/epd2in9_v2/mod.rs @@ -0,0 +1,438 @@ +//! A simple Driver for the Waveshare 2.9" E-Ink Display V2 via SPI +//! +//! Specification: https://www.waveshare.com/w/upload/7/79/2.9inch-e-paper-v2-specification.pdf +//! +//! # Example for the 2.9 in E-Ink Display V2 +//! +//!```rust, no_run +//!# use embedded_hal_mock::*; +//!# fn main() -> Result<(), MockError> { +//!use embedded_graphics::{ +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//!}; +//!use epd_waveshare::{epd2in9_v2::*, 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 = Epd2in9::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//! +//!// Use display graphics from embedded-graphics +//!let mut display = Display2in9::default(); +//! +//!// Use embedded graphics for drawing a line +//!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) +//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .draw(&mut display); +//! +//! // Display updated frame +//!epd.update_frame(&mut spi, &display.buffer())?; +//!epd.display_frame(&mut spi)?; +//! +//!// Set the EPD to sleep +//!epd.sleep(&mut spi)?; +//!# Ok(()) +//!# } +//!``` + +/// Width of epd2in9 in pixels +pub const WIDTH: u32 = 128; +/// Height of epd2in9 in pixels +pub const HEIGHT: u32 = 296; +/// Default Background Color (white) +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; +const IS_BUSY_LOW: bool = false; + +const LUT_PARTIAL_2IN9: [u8; 153] = [ + 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, + 0x0A,0x0,0x0,0x0,0x0,0x0,0x2, + 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, +]; + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::type_a::{ + command::Command, +}; + +use crate::color::Color; + +use crate::traits::*; + +use crate::interface::DisplayInterface; +use crate::traits::QuickRefresh; + +#[cfg(feature = "graphics")] +mod graphics; +#[cfg(feature = "graphics")] +pub use crate::epd2in9_v2::graphics::Display2in9; + +/// Epd2in9 driver +/// +pub struct Epd2in9 { + /// SPI + interface: DisplayInterface, + /// Color + background_color: Color, + /// Refresh LUT + refresh: RefreshLut, +} + +impl Epd2in9 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn init>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.interface.reset(delay, 2); + + self.wait_until_idle(); + self.interface.cmd(spi, Command::SwReset)?; + self.wait_until_idle(); + + // 3 Databytes: + // A[7:0] + // 0.. A[8] + // 0.. B[2:0] + // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) + self.interface.cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; + + // One Databyte with default value 0x03 + // -> address: x increment, y increment, address counter is updated in x direction + self.interface.cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + + self.set_ram_area(spi, 0, 0, WIDTH-1, HEIGHT-1)?; + + self.interface.cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80])?; + + self.set_ram_counter(spi, 0, 0)?; + + self.wait_until_idle(); + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in9 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + 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, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + + let mut epd = Epd2in9 { + interface, + background_color: DEFAULT_BACKGROUND_COLOR, + refresh: RefreshLut::Full, + }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); + // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode + self.interface.cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + Ok(()) + } + + fn wake_up>( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.init(spi, delay)?; + Ok(()) + } + + fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface.cmd_with_data(spi, Command::WriteRam, buffer) + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.set_ram_area(spi, x, y, x + width, y + height)?; + self.set_ram_counter(spi, x, y)?; + + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; + Ok(()) + } + + fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + 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])?; + self.interface.cmd(spi, Command::MasterActivation)?; + self.wait_until_idle(); + Ok(()) + } + + fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer)?; + self.display_frame(spi)?; + Ok(()) + } + + fn clear_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + self.wait_until_idle(); + + // clear the ram with the background color + let color = self.background_color.get_byte_value(); + + self.interface.cmd(spi, Command::WriteRam)?; + self.interface.data_x_times(spi, color, WIDTH / 8 * HEIGHT) + } + + fn set_background_color(&mut self, background_color: Color) { + self.background_color = background_color; + } + + fn background_color(&self) -> &Color { + &self.background_color + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + refresh_rate: Option, + ) -> Result<(), SPI::Error> { + if let Some(refresh_lut) = refresh_rate { + self.refresh = refresh_lut; + } + Ok(()) + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl Epd2in9 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + fn wait_until_idle(&mut self) { + self.interface.wait_until_idle(IS_BUSY_LOW); + } + + fn use_full_frame(&mut self, spi: &mut SPI) -> 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, 0, 0) + } + + 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); + + // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram + // aren't relevant + self.interface.cmd_with_data( + spi, + Command::SetRamXAddressStartEndPosition, + &[(start_x >> 3) as u8, (end_x >> 3) as u8], + )?; + + // 2 Databytes: A[7:0] & 0..A[8] for each - start and end + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressStartEndPosition, + &[ + start_y as u8, + (start_y >> 8) as u8, + end_y as u8, + (end_y >> 8) as u8, + ], + ) + } + + fn set_ram_counter(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + self.wait_until_idle(); + // x is positioned in bytes, so the last 3 bits which show the position inside a byte in the ram + // aren't relevant + self.interface + .cmd_with_data(spi, Command::SetRamXAddressCounter, &[x as u8])?; + + // 2 Databytes: A[7:0] & 0..A[8] + self.interface.cmd_with_data( + spi, + Command::SetRamYAddressCounter, + &[y as u8, (y >> 8) as u8], + )?; + Ok(()) + } + + /// Set your own LUT, this function is also used internally for set_lut + fn set_lut_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface.cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + self.wait_until_idle(); + Ok(()) + } +} + +impl QuickRefresh + for Epd2in9 +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, +{ + /// To be followed immediately by `update_new_frame`. + fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + self.interface.cmd_with_data(spi, Command::WriteRam, buffer)?; + 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]) -> Result<(), SPI::Error> { + self.wait_until_idle(); + //TODO original waveshare library has a hardware reset for 2 ms. But it works without reset apparently. + + self.set_lut_helper(spi, &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(); + + self.use_full_frame(spi)?; + + self.interface.cmd_with_data(spi, Command::WriteRam, buffer)?; + Ok(()) + } + + #[allow(unused)] + fn update_partial_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + //TODO supported by display? + unimplemented!() + } + + #[allow(unused)] + fn update_partial_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + //TODO supported by display? + unimplemented!() + } + + #[allow(unused)] + fn clear_partial_frame( + &mut self, + spi: &mut SPI, + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + //TODO supported by display? + unimplemented!() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn epd_size() { + assert_eq!(WIDTH, 128); + assert_eq!(HEIGHT, 296); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); + } +} diff --git a/src/lib.rs b/src/lib.rs index 0c140a8..9d43e31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in7b; pub mod epd2in9; +pub mod epd2in9_v2; pub mod epd2in9bc; pub mod epd4in2; pub mod epd5in65f; diff --git a/src/type_a/command.rs b/src/type_a/command.rs index 71a106b..ebdddb1 100644 --- a/src/type_a/command.rs +++ b/src/type_a/command.rs @@ -49,9 +49,13 @@ pub(crate) enum Command { WriteRam = 0x24, + WriteRam2 = 0x26, + WriteVcomRegister = 0x2C, WriteLutRegister = 0x32, + + WriteOtpSelection = 0x37, SetDummyLinePeriod = 0x3A, From 1cd1c3921db21011d6025018bf692a81c9906738 Mon Sep 17 00:00:00 2001 From: Andreas Date: Mon, 19 Apr 2021 16:59:54 +0200 Subject: [PATCH 47/80] fixed documentation and formatting --- src/epd2in9_v2/graphics.rs | 2 +- src/epd2in9_v2/mod.rs | 101 ++++++++++++++++++++----------------- src/type_a/command.rs | 2 +- 3 files changed, 56 insertions(+), 49 deletions(-) diff --git a/src/epd2in9_v2/graphics.rs b/src/epd2in9_v2/graphics.rs index fb1154e..df1cd2e 100644 --- a/src/epd2in9_v2/graphics.rs +++ b/src/epd2in9_v2/graphics.rs @@ -3,7 +3,7 @@ use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; -/// Display with Fullsize buffer for use with the 2in9 EPD +/// Display with Fullsize buffer for use with the 2in9 EPD V2 /// /// Can also be manuall constructed: /// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 8 * HEIGHT]` diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 3fc27f0..6797d3d 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -1,5 +1,5 @@ //! A simple Driver for the Waveshare 2.9" E-Ink Display V2 via SPI -//! +//! //! Specification: https://www.waveshare.com/w/upload/7/79/2.9inch-e-paper-v2-specification.pdf //! //! # Example for the 2.9 in E-Ink Display V2 @@ -51,24 +51,15 @@ pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = false; const LUT_PARTIAL_2IN9: [u8; 153] = [ - 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, - 0x0A,0x0,0x0,0x0,0x0,0x0,0x2, - 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, + 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, 0x0A, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 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, ]; use embedded_hal::{ @@ -76,9 +67,7 @@ use embedded_hal::{ digital::v2::*, }; -use crate::type_a::{ - command::Command, -}; +use crate::type_a::command::Command; use crate::color::Color; @@ -121,24 +110,27 @@ where self.wait_until_idle(); self.interface.cmd(spi, Command::SwReset)?; self.wait_until_idle(); - + // 3 Databytes: // A[7:0] // 0.. A[8] // 0.. B[2:0] // Default Values: A = Height of Screen (0x127), B = 0x00 (GD, SM and TB=0?) - self.interface.cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; - + self.interface + .cmd_with_data(spi, Command::DriverOutputControl, &[0x27, 0x01, 0x00])?; + // One Databyte with default value 0x03 // -> address: x increment, y increment, address counter is updated in x direction - self.interface.cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; - - self.set_ram_area(spi, 0, 0, WIDTH-1, HEIGHT-1)?; - - self.interface.cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80])?; + self.interface + .cmd_with_data(spi, Command::DataEntryModeSetting, &[0x03])?; + + self.set_ram_area(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl1, &[0x00, 0x80])?; self.set_ram_counter(spi, 0, 0)?; - + self.wait_until_idle(); Ok(()) } @@ -186,7 +178,8 @@ where fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode - self.interface.cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; + self.interface + .cmd_with_data(spi, Command::DeepSleepMode, &[0x01])?; Ok(()) } @@ -203,7 +196,7 @@ where self.wait_until_idle(); self.interface.cmd_with_data(spi, Command::WriteRam, buffer) } - + fn update_partial_frame( &mut self, spi: &mut SPI, @@ -225,7 +218,8 @@ where fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { 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])?; + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0xF7])?; self.interface.cmd(spi, Command::MasterActivation)?; self.wait_until_idle(); Ok(()) @@ -342,7 +336,8 @@ where /// Set your own LUT, this function is also used internally for set_lut fn set_lut_helper(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.interface.cmd_with_data(spi, Command::WriteLutRegister, buffer)?; + self.interface + .cmd_with_data(spi, Command::WriteLutRegister, buffer)?; self.wait_until_idle(); Ok(()) } @@ -360,29 +355,39 @@ where /// To be followed immediately by `update_new_frame`. fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { self.wait_until_idle(); - self.interface.cmd_with_data(spi, Command::WriteRam, buffer)?; - self.interface.cmd_with_data(spi, Command::WriteRam2, buffer) + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; + 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]) -> Result<(), SPI::Error> { self.wait_until_idle(); //TODO original waveshare library has a hardware reset for 2 ms. But it works without reset apparently. - + self.set_lut_helper(spi, &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_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(); - + self.use_full_frame(spi)?; - - self.interface.cmd_with_data(spi, Command::WriteRam, buffer)?; + + self.interface + .cmd_with_data(spi, Command::WriteRam, buffer)?; Ok(()) } + /// Partial quick refresh not supported yet #[allow(unused)] fn update_partial_old_frame( &mut self, @@ -396,7 +401,8 @@ where //TODO supported by display? unimplemented!() } - + + /// Partial quick refresh not supported yet #[allow(unused)] fn update_partial_new_frame( &mut self, @@ -410,7 +416,8 @@ where //TODO supported by display? unimplemented!() } - + + /// Partial quick refresh not supported yet #[allow(unused)] fn clear_partial_frame( &mut self, diff --git a/src/type_a/command.rs b/src/type_a/command.rs index ebdddb1..97af56a 100644 --- a/src/type_a/command.rs +++ b/src/type_a/command.rs @@ -54,7 +54,7 @@ pub(crate) enum Command { WriteVcomRegister = 0x2C, WriteLutRegister = 0x32, - + WriteOtpSelection = 0x37, SetDummyLinePeriod = 0x3A, From ae25129ada5f834a9ec016577b46b3363c30a6e9 Mon Sep 17 00:00:00 2001 From: Andreas Date: Mon, 19 Apr 2021 18:00:41 +0200 Subject: [PATCH 48/80] Merge branch 'fix-70' --- src/epd2in9_v2/mod.rs | 64 +++++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 6797d3d..01dcfcc 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -33,11 +33,11 @@ //! .draw(&mut display); //! //! // Display updated frame -//!epd.update_frame(&mut spi, &display.buffer())?; -//!epd.display_frame(&mut spi)?; +//!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; //! //!// Set the EPD to sleep -//!epd.sleep(&mut spi)?; +//!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) //!# } //!``` @@ -83,28 +83,25 @@ pub use crate::epd2in9_v2::graphics::Display2in9; /// 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, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { - fn init>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.interface.reset(delay, 2); self.wait_until_idle(); @@ -136,14 +133,15 @@ where } } -impl WaveshareDisplay - for Epd2in9 +impl WaveshareDisplay + for Epd2in9 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { type DisplayColor = Color; fn width(&self) -> u32 { @@ -154,7 +152,7 @@ where HEIGHT } - fn new>( + fn new( spi: &mut SPI, cs: CS, busy: BUSY, @@ -175,7 +173,7 @@ where Ok(epd) } - fn sleep(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // 0x00 for Normal mode (Power on Reset), 0x01 for Deep Sleep Mode self.interface @@ -183,16 +181,17 @@ where Ok(()) } - fn wake_up>( - &mut self, - spi: &mut SPI, - delay: &mut DELAY, - ) -> Result<(), SPI::Error> { + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.init(spi, delay)?; Ok(()) } - fn update_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface.cmd_with_data(spi, Command::WriteRam, buffer) } @@ -215,7 +214,7 @@ where Ok(()) } - fn display_frame(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // Enable clock signal, Enable Analog, Load temperature value, DISPLAY with DISPLAY Mode 1, Disable Analog, Disable OSC self.interface @@ -225,13 +224,18 @@ where Ok(()) } - fn update_and_display_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { - self.update_frame(spi, buffer)?; - self.display_frame(spi)?; + 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) -> Result<(), SPI::Error> { + fn clear_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { self.wait_until_idle(); // clear the ram with the background color @@ -265,13 +269,14 @@ where } } -impl Epd2in9 +impl Epd2in9 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { fn wait_until_idle(&mut self) { self.interface.wait_until_idle(IS_BUSY_LOW); @@ -343,14 +348,15 @@ where } } -impl QuickRefresh - for Epd2in9 +impl QuickRefresh + for Epd2in9 where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// To be followed immediately by `update_new_frame`. fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { From dc93687a8647b66e6d29bea86994e288bfd36d60 Mon Sep 17 00:00:00 2001 From: Andreas Date: Tue, 27 Apr 2021 17:35:15 +0200 Subject: [PATCH 49/80] Fixed epd2in9 quick refresh --- src/epd2in9_v2/mod.rs | 55 +++++++++++++++++++++++++++++++++++++++---- src/epd4in2/mod.rs | 33 +++++++++++++++++++++++--- src/traits.rs | 28 +++++++++++++++++++--- 3 files changed, 105 insertions(+), 11 deletions(-) diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 01dcfcc..354cc32 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -32,10 +32,22 @@ //! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) //! .draw(&mut display); //! -//! // Display updated frame +//!// Display updated frame //!epd.update_frame(&mut spi, &display.buffer(), &mut delay)?; //!epd.display_frame(&mut spi, &mut delay)?; //! +//!// Draw something new here +//! +//!// Display new image as a base image for further quick refreshes +//!epd.update_old_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_frame(&mut spi, &mut delay)?; +//! +//!// Update image here +//! +//!// quick refresh of updated pixels +//!epd.update_new_frame(&mut spi, &display.buffer(), &mut delay)?; +//!epd.display_new_frame(&mut spi, &mut delay)?; +//! //!// Set the EPD to sleep //!epd.sleep(&mut spi, &mut delay)?; //!# Ok(()) @@ -205,6 +217,7 @@ where width: u32, height: u32, ) -> Result<(), SPI::Error> { + //TODO This is copied from epd2in9 but it seems not working. Partial refresh supported by version 2? self.wait_until_idle(); self.set_ram_area(spi, x, y, x + width, y + height)?; self.set_ram_counter(spi, x, y)?; @@ -348,7 +361,7 @@ where } } -impl QuickRefresh +impl QuickRefresh for Epd2in9 where SPI: Write, @@ -359,7 +372,12 @@ where DELAY: DelayMs, { /// To be followed immediately by `update_new_frame`. - fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface .cmd_with_data(spi, Command::WriteRam, buffer)?; @@ -368,9 +386,14 @@ where } /// To be used immediately after `update_old_frame`. - fn update_new_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); - //TODO original waveshare library has a hardware reset for 2 ms. But it works without reset apparently. + self.interface.reset(delay, 2); self.set_lut_helper(spi, &LUT_PARTIAL_2IN9)?; self.interface.cmd_with_data( @@ -393,6 +416,28 @@ where 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(); + self.interface + .cmd_with_data(spi, Command::DisplayUpdateControl2, &[0x0F])?; + self.interface.cmd(spi, Command::MasterActivation)?; + self.wait_until_idle(); + 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( diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 983172f..b39ee5e 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -439,7 +439,7 @@ where } } -impl QuickRefresh +impl QuickRefresh for Epd4in2 where SPI: Write, @@ -450,7 +450,12 @@ where DELAY: DelayMs, { /// To be followed immediately after by `update_old_frame`. - fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); self.interface.cmd(spi, Command::DataStartTransmission1)?; @@ -461,7 +466,12 @@ where } /// To be used immediately after `update_old_frame`. - fn update_new_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error> { + fn update_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + _delay: &mut DELAY, + ) -> Result<(), SPI::Error> { self.wait_until_idle(); // self.send_resolution(spi)?; @@ -472,6 +482,23 @@ where Ok(()) } + /// This function is not needed for this display + #[allow(unused)] + fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + unimplemented!() + } + + /// This function is not needed for this display + #[allow(unused)] + fn update_and_display_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + unimplemented!() + } + fn update_partial_old_frame( &mut self, spi: &mut SPI, diff --git a/src/traits.rs b/src/traits.rs index 94446f2..abdb919 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -280,19 +280,41 @@ where ///# Ok(()) ///# } ///``` -pub trait QuickRefresh +pub trait QuickRefresh where SPI: Write, CS: OutputPin, BUSY: InputPin, DC: OutputPin, RST: OutputPin, + DELAY: DelayMs, { /// Updates the old frame. - fn update_old_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + fn update_old_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Updates the new frame. - fn update_new_frame(&mut self, spi: &mut SPI, buffer: &[u8]) -> Result<(), SPI::Error>; + fn update_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error>; + + /// Displays the new frame + fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error>; + + /// Updates and displays the new frame. + fn update_and_display_new_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error>; /// Updates the old frame for a portion of the display. fn update_partial_old_frame( From d9254a68a29da3c2eb982328c89f104f3bfeb939 Mon Sep 17 00:00:00 2001 From: Chris <11088935+caemor@users.noreply.github.com> Date: Tue, 27 Apr 2021 21:09:40 +0200 Subject: [PATCH 50/80] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 983d17a..423beb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,16 +10,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Added - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) -- Added Epd 7in5 HD support -- Added Epd 2in9 V2 support +- Added Epd 7in5 HD support (thanks to @whiite) +- Added Epd 2in9 V2 support in #73 & #74 (thanks to @andber1) ### Changed - Use specific ParseColorError instead of () - Epd4in2: Don't set the resolution (and some more) over and over again (#48) - Removed `#[allow(non_camel_case_types)]` to fix various issues around it +- Added Delay to QuickRefresh Trait due to #74 (thanks to @andber1) + -### Fixed ## [v0.5.0] From 6679869bc3828cecc9eb833c15750b26b38512fa Mon Sep 17 00:00:00 2001 From: Chris <11088935+caemor@users.noreply.github.com> Date: Sun, 16 May 2021 14:26:51 +0200 Subject: [PATCH 51/80] Update rust.yml Fix ci only running for main-branch stuff --- .github/workflows/rust.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 18fc9a3..62031c1 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -1,13 +1,7 @@ name: Rust -on: - push: - branches: - - main - pull_request: - branches: - - main +on: [push, pull_request] jobs: build: From e1aada3b38fee8ebb6658f7b002bfad30e96e2b8 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sat, 8 May 2021 14:43:51 +0200 Subject: [PATCH 52/80] use epd2in9bc as base for implementing support epd2in13bc --- src/epd2in13bc/command.rs | 38 ++++ src/epd2in13bc/graphics.rs | 51 +++++ src/epd2in13bc/mod.rs | 389 +++++++++++++++++++++++++++++++++++++ 3 files changed, 478 insertions(+) create mode 100644 src/epd2in13bc/command.rs create mode 100644 src/epd2in13bc/graphics.rs create mode 100644 src/epd2in13bc/mod.rs diff --git a/src/epd2in13bc/command.rs b/src/epd2in13bc/command.rs new file mode 100644 index 0000000..7121c50 --- /dev/null +++ b/src/epd2in13bc/command.rs @@ -0,0 +1,38 @@ +//! SPI Commands for the Waveshare 2.9" (B/C) E-Ink Display +use crate::traits; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + PanelSetting = 0x00, + + PowerSetting = 0x01, + PowerOff = 0x02, + PowerOn = 0x04, + BoosterSoftStart = 0x06, + DeepSleep = 0x07, + DataStartTransmission1 = 0x10, + DisplayRefresh = 0x12, + DataStartTransmission2 = 0x13, + + LutForVcom = 0x20, + LutWhiteToWhite = 0x21, + LutBlackToWhite = 0x22, + LutWhiteToBlack = 0x23, + LutBlackToBlack = 0x24, + + PllControl = 0x30, + TemperatureSensor = 0x40, + TemperatureSensorSelection = 0x41, + VcomAndDataIntervalSetting = 0x50, + ResolutionSetting = 0x61, + VcmDcSetting = 0x82, + PowerSaving = 0xE3, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs new file mode 100644 index 0000000..16d12d1 --- /dev/null +++ b/src/epd2in13bc/graphics.rs @@ -0,0 +1,51 @@ +use crate::epd2in9bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; +use crate::graphics::{Display, DisplayRotation}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics::prelude::*; + +/// Full size buffer for use with the 2in9b/c EPD +/// +/// Can also be manually constructed and be used together with VarDisplay +pub struct Display2in9bc { + buffer: [u8; NUM_DISPLAY_BITS as usize], + rotation: DisplayRotation, +} + +impl Default for Display2in9bc { + fn default() -> Self { + Display2in9bc { + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); NUM_DISPLAY_BITS as usize], + rotation: DisplayRotation::default(), + } + } +} + +impl DrawTarget for Display2in9bc { + type Error = core::convert::Infallible; + + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper(WIDTH, HEIGHT, pixel) + } + + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + +impl Display for Display2in9bc { + fn buffer(&self) -> &[u8] { + &self.buffer + } + + fn get_mut_buffer(&mut self) -> &mut [u8] { + &mut self.buffer + } + + fn set_rotation(&mut self, rotation: DisplayRotation) { + self.rotation = rotation; + } + + fn rotation(&self) -> DisplayRotation { + self.rotation + } +} diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs new file mode 100644 index 0000000..37280f3 --- /dev/null +++ b/src/epd2in13bc/mod.rs @@ -0,0 +1,389 @@ +//! A simple Driver for the Waveshare 2.9" (B/C) E-Ink Display via SPI +//! +//! # Example for the 2.9" E-Ink Display +//! +//!```rust, no_run +//!# use embedded_hal_mock::*; +//!# fn main() -> Result<(), MockError> { +//!use embedded_graphics::{ +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//!}; +//!use epd_waveshare::{epd2in9bc::*, 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 = Epd2in9bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//! +//!// Use display graphics from embedded-graphics +//!// This display is for the black/white pixels +//!let mut mono_display = Display2in9bc::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(Black, 1)) +//! .draw(&mut mono_display); +//! +//!// Use a second display for red/yellow +//!let mut chromatic_display = Display2in9bc::default(); +//! +//!// We use `Black` but it will be shown as red/yellow +//!let _ = Line::new(Point::new(15, 120), Point::new(15, 200)) +//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .draw(&mut chromatic_display); +//! +//!// Display updated frame +//!epd.update_color_frame( +//! &mut spi, +//! &mono_display.buffer(), +//! &chromatic_display.buffer() +//!)?; +//!epd.display_frame(&mut spi, &mut delay)?; +//! +//!// Set the EPD to sleep +//!epd.sleep(&mut spi, &mut delay)?; +//!# Ok(()) +//!# } +//!``` +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +/// Width of epd2in9bc in pixels +pub const WIDTH: u32 = 128; +/// Height of epd2in9bc in pixels +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 IS_BUSY_LOW: bool = true; +const VCOM_DATA_INTERVAL: u8 = 0x07; +const WHITE_BORDER: u8 = 0x70; +const BLACK_BORDER: u8 = 0x30; +const CHROMATIC_BORDER: u8 = 0xb0; +const FLOATING_BORDER: u8 = 0xF0; + +use crate::color::{Color, TriColor}; + +pub(crate) mod command; +use self::command::Command; + +#[cfg(feature = "graphics")] +mod graphics; +#[cfg(feature = "graphics")] +pub use self::graphics::Display2in9bc; + +/// Epd2in9bc driver +pub struct Epd2in9bc { + interface: DisplayInterface, + color: Color, +} + +impl InternalWiAdditions + for Epd2in9bc +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // Values taken from datasheet and sample code + + self.interface.reset(delay, 10); + + // start the booster + self.interface + .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?; + + // power on + self.command(spi, Command::PowerOn)?; + delay.delay_ms(5); + self.wait_until_idle(); + + // set the panel settings + self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?; + + self.cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[WHITE_BORDER | VCOM_DATA_INTERVAL], + )?; + + // set resolution + self.send_resolution(spi)?; + + self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?; + + self.wait_until_idle(); + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for Epd2in9bc +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, black)?; + self.update_chromatic_frame(spi, 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, 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, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.data(spi, chromatic)?; + + self.wait_until_idle(); + Ok(()) + } +} + +impl WaveshareDisplay + for Epd2in9bc +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, +{ + type DisplayColor = Color; + fn new( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + ) -> Result { + let interface = DisplayInterface::new(cs, busy, dc, rst); + let color = DEFAULT_BACKGROUND_COLOR; + + let mut epd = Epd2in9bc { interface, color }; + + epd.init(spi, delay)?; + + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + // Section 8.2 from datasheet + self.interface.cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[FLOATING_BORDER | VCOM_DATA_INTERVAL], + )?; + + self.command(spi, Command::PowerOff)?; + // The example STM code from Github has a wait after PowerOff + self.wait_until_idle(); + + 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.interface.cmd(spi, Command::DataStartTransmission1)?; + + 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(); + Ok(()) + } + + #[allow(unused)] + fn update_partial_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + Ok(()) + } + + fn display_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.command(spi, Command::DisplayRefresh)?; + + self.wait_until_idle(); + 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.send_resolution(spi)?; + + let color = DEFAULT_BACKGROUND_COLOR.get_byte_value(); + + // Clear the black + self.interface.cmd(spi, Command::DataStartTransmission1)?; + + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + // Clear the chromatic + self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + self.wait_until_idle(); + Ok(()) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + Ok(()) + } + + fn is_busy(&self) -> bool { + self.interface.is_busy(IS_BUSY_LOW) + } +} + +impl Epd2in9bc +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayMs, +{ + 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 wait_until_idle(&mut self) { + let _ = self.interface.wait_until_idle(IS_BUSY_LOW); + } + + fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let w = self.width(); + let h = self.height(); + + self.command(spi, Command::ResolutionSetting)?; + + self.send_data(spi, &[w as u8])?; + self.send_data(spi, &[(h >> 8) as u8])?; + self.send_data(spi, &[h as u8]) + } + + /// Set the outer border of the display to the chosen color. + pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> { + let border = match color { + TriColor::Black => BLACK_BORDER, + TriColor::White => WHITE_BORDER, + TriColor::Chromatic => CHROMATIC_BORDER, + }; + self.cmd_with_data( + spi, + Command::VcomAndDataIntervalSetting, + &[border | VCOM_DATA_INTERVAL], + ) + } +} From 9dedf76c57348238af16572ade128af7f7512dfd Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sat, 8 May 2021 15:01:14 +0200 Subject: [PATCH 53/80] bring copy into 2in13bc namespace --- src/epd2in13bc/command.rs | 2 +- src/epd2in13bc/graphics.rs | 12 ++++++------ src/epd2in13bc/mod.rs | 30 +++++++++++++++--------------- src/lib.rs | 1 + 4 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/epd2in13bc/command.rs b/src/epd2in13bc/command.rs index 7121c50..48c7541 100644 --- a/src/epd2in13bc/command.rs +++ b/src/epd2in13bc/command.rs @@ -1,4 +1,4 @@ -//! SPI Commands for the Waveshare 2.9" (B/C) E-Ink Display +//! SPI Commands for the Waveshare 2.13" (B/C) E-Ink Display use crate::traits; #[allow(dead_code)] diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs index 16d12d1..64eea72 100644 --- a/src/epd2in13bc/graphics.rs +++ b/src/epd2in13bc/graphics.rs @@ -1,4 +1,4 @@ -use crate::epd2in9bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; +use crate::epd2in13bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; @@ -6,21 +6,21 @@ use embedded_graphics::prelude::*; /// Full size buffer for use with the 2in9b/c EPD /// /// Can also be manually constructed and be used together with VarDisplay -pub struct Display2in9bc { +pub struct Display2in13bc { buffer: [u8; NUM_DISPLAY_BITS as usize], rotation: DisplayRotation, } -impl Default for Display2in9bc { +impl Default for Display2in13bc { fn default() -> Self { - Display2in9bc { + Display2in13bc { buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); NUM_DISPLAY_BITS as usize], rotation: DisplayRotation::default(), } } } -impl DrawTarget for Display2in9bc { +impl DrawTarget for Display2in13bc { type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { @@ -32,7 +32,7 @@ impl DrawTarget for Display2in9bc { } } -impl Display for Display2in9bc { +impl Display for Display2in13bc { fn buffer(&self) -> &[u8] { &self.buffer } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 37280f3..d3db78e 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -1,6 +1,6 @@ -//! A simple Driver for the Waveshare 2.9" (B/C) E-Ink Display via SPI +//! A simple Driver for the Waveshare 2.13" (B/C) E-Ink Display via SPI //! -//! # Example for the 2.9" E-Ink Display +//! # Example for the 2.13" E-Ink Display //! //!```rust, no_run //!# use embedded_hal_mock::*; @@ -8,7 +8,7 @@ //!use embedded_graphics::{ //! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, //!}; -//!use epd_waveshare::{epd2in9bc::*, prelude::*}; +//!use epd_waveshare::{epd2in13bc::*, prelude::*}; //!# //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); @@ -20,11 +20,11 @@ //!# let mut delay = delay::MockNoop::new(); //! //!// Setup EPD -//!let mut epd = Epd2in9bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; +//!let mut epd = Epd2in13bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics //!// This display is for the black/white pixels -//!let mut mono_display = Display2in9bc::default(); +//!let mut mono_display = Display2in13bc::default(); //! //!// Use embedded graphics for drawing //!// A black line @@ -33,7 +33,7 @@ //! .draw(&mut mono_display); //! //!// Use a second display for red/yellow -//!let mut chromatic_display = Display2in9bc::default(); +//!let mut chromatic_display = Display2in13bc::default(); //! //!// We use `Black` but it will be shown as red/yellow //!let _ = Line::new(Point::new(15, 120), Point::new(15, 200)) @@ -63,9 +63,9 @@ use crate::traits::{ InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, }; -/// Width of epd2in9bc in pixels +/// Width of epd2in13bc in pixels pub const WIDTH: u32 = 128; -/// Height of epd2in9bc in pixels +/// Height of epd2in13bc in pixels pub const HEIGHT: u32 = 296; /// Default background color (white) of epd2in9bc display pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; @@ -87,16 +87,16 @@ use self::command::Command; #[cfg(feature = "graphics")] mod graphics; #[cfg(feature = "graphics")] -pub use self::graphics::Display2in9bc; +pub use self::graphics::Display2in13bc; /// Epd2in9bc driver -pub struct Epd2in9bc { +pub struct Epd2in13bc { interface: DisplayInterface, color: Color, } impl InternalWiAdditions - for Epd2in9bc + for Epd2in13bc where SPI: Write, CS: OutputPin, @@ -140,7 +140,7 @@ where } impl WaveshareThreeColorDisplay - for Epd2in9bc + for Epd2in13bc where SPI: Write, CS: OutputPin, @@ -185,7 +185,7 @@ where } impl WaveshareDisplay - for Epd2in9bc + for Epd2in13bc where SPI: Write, CS: OutputPin, @@ -206,7 +206,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = Epd2in9bc { interface, color }; + let mut epd = Epd2in13bc { interface, color }; epd.init(spi, delay)?; @@ -332,7 +332,7 @@ where } } -impl Epd2in9bc +impl Epd2in13bc where SPI: Write, CS: OutputPin, diff --git a/src/lib.rs b/src/lib.rs index 9d43e31..50ee2d2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,6 +76,7 @@ pub mod epd1in54; pub mod epd1in54b; pub mod epd1in54c; pub mod epd2in13_v2; +pub mod epd2in13bc; pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; From c552111ae888edde3c270a9a651eb6524cecfba6 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 16 May 2021 11:15:16 +0200 Subject: [PATCH 54/80] add support for Waveshare e-Paper 2.13 inch tri-color screen datasheet is same as the 2.9" version, except resolution --- src/epd2in13bc/graphics.rs | 2 +- src/epd2in13bc/mod.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs index 64eea72..10ca19a 100644 --- a/src/epd2in13bc/graphics.rs +++ b/src/epd2in13bc/graphics.rs @@ -3,7 +3,7 @@ use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; -/// Full size buffer for use with the 2in9b/c EPD +/// Full size buffer for use with the 2in13b/c EPD /// /// Can also be manually constructed and be used together with VarDisplay pub struct Display2in13bc { diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index d3db78e..e055acb 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -64,9 +64,9 @@ use crate::traits::{ }; /// Width of epd2in13bc in pixels -pub const WIDTH: u32 = 128; +pub const WIDTH: u32 = 104; /// Height of epd2in13bc in pixels -pub const HEIGHT: u32 = 296; +pub const HEIGHT: u32 = 212; /// Default background color (white) of epd2in9bc display pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; From 199c5ed298cd45a8fbff7a89d54743aeeba4a8b9 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 16 May 2021 12:11:52 +0200 Subject: [PATCH 55/80] add example for epd2in13bc using chromatic color besides black and white --- examples/epd2in13bc.rs | 148 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 examples/epd2in13bc.rs diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs new file mode 100644 index 0000000..b7d9a04 --- /dev/null +++ b/examples/epd2in13bc.rs @@ -0,0 +1,148 @@ +#![deny(warnings)] + +use embedded_graphics::{ + fonts::{Font12x16, Font6x8, Text}, + prelude::*, + primitives::{Circle, Line}, + style::PrimitiveStyle, + text_style, +}; +use embedded_hal::prelude::*; +use epd_waveshare::{ + color::*, + epd2in13bc::{Display2in13bc, Epd2in13bc}, + graphics::{Display, DisplayRotation}, + prelude::*, +}; +use linux_embedded_hal::{ + spidev::{self, SpidevOptions}, + sysfs_gpio::Direction, + Delay, Pin, Spidev, +}; + +// 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> { + let busy = Pin::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 + 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 + 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 + 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"); + + // Configure SPI + // Settings are taken from + let mut spi = Spidev::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 mut delay = Delay {}; + + let mut epd2in13 = + Epd2in13bc::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); + + println!("Test all the rotations"); + let mut display = Display2in13bc::default(); + let mut display_chromatic = Display2in13bc::default(); + + display.set_rotation(DisplayRotation::Rotate0); + draw_text(&mut display, "Rotation 0!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate90); + draw_text(&mut display, "Rotation 90!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate180); + draw_text(&mut display, "Rotation 180!", 5, 50); + + display.set_rotation(DisplayRotation::Rotate270); + draw_text(&mut display, "Rotation 270!", 5, 50); + + epd2in13.update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + .expect("display frame new graphics"); + + println!("First frame done. Waiting 5s"); + delay.delay_ms(5000u16); + + println!("Now test new graphics with default rotation:"); + display.clear_buffer(Color::White); + display_chromatic.clear_buffer(Color::White); + // keep both displays on same rotation + display_chromatic.set_rotation(DisplayRotation::Rotate270); + + // draw a analog clock + let _ = Circle::new(Point::new(64, 64), 40) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) + .into_styled(PrimitiveStyle::with_stroke(Black, 4)) + .draw(&mut display); + let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .draw(&mut display); + + // draw white on Red background + let _ = Text::new("It's working-WoB!", Point::new(90, 10)) + .into_styled(text_style!( + font = Font6x8, + text_color = White, + background_color = Black + )) + .draw(&mut display_chromatic); + + // use bigger/different font + let _ = Text::new("It's working-WoB!", Point::new(90, 40)) + .into_styled(text_style!( + font = Font12x16, + text_color = White, + background_color = Black + )) + .draw(&mut display_chromatic); + + epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?; + epd2in13 + .display_frame(&mut spi, &mut delay) + .expect("display frame new graphics"); + println!("Second frame done. Waiting 5s"); + delay.delay_ms(5000u16); + + display.clear_buffer(Color::White); + display_chromatic.clear_buffer(Color::White); + epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?; + epd2in13.display_frame(&mut spi, &mut delay)?; + + println!("Finished tests - going to sleep"); + epd2in13.sleep(&mut spi, &mut delay) +} + +fn draw_text(display: &mut Display2in13bc, text: &str, x: i32, y: i32) { + let _ = Text::new(text, Point::new(x, y)) + .into_styled(text_style!( + font = Font6x8, + text_color = Black, + background_color = White + )) + .draw(display); +} From a4b8f5768ee445576b0497080da25996aa6f5bff Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 16 May 2021 12:24:39 +0200 Subject: [PATCH 56/80] run cargo fmt --- examples/epd2in13bc.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index b7d9a04..a7c4709 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -45,7 +45,7 @@ fn main() -> Result<(), std::io::Error> { // 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 cs.export().expect("cs export"); - while !cs.is_exported() { } + while !cs.is_exported() {} cs.set_direction(Direction::Out).expect("CS Direction"); cs.set_value(1).expect("CS Value set to 1"); @@ -80,7 +80,8 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotation 270!", 5, 50); - epd2in13.update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + epd2in13 + .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) .expect("display frame new graphics"); println!("First frame done. Waiting 5s"); @@ -90,10 +91,10 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); display_chromatic.clear_buffer(Color::White); // keep both displays on same rotation - display_chromatic.set_rotation(DisplayRotation::Rotate270); + display_chromatic.set_rotation(DisplayRotation::Rotate270); // draw a analog clock - let _ = Circle::new(Point::new(64, 64), 40) + let _ = Circle::new(Point::new(64, 64), 40) .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) @@ -133,7 +134,7 @@ fn main() -> Result<(), std::io::Error> { epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?; epd2in13.display_frame(&mut spi, &mut delay)?; - println!("Finished tests - going to sleep"); + println!("Finished tests - going to sleep"); epd2in13.sleep(&mut spi, &mut delay) } From f7d86d8bfeea9fa142f8ad8a1114475f667fb317 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 16 May 2021 15:47:00 +0200 Subject: [PATCH 57/80] add epd2in13bc to README and add some comments to example --- README.md | 1 + examples/epd2in13bc.rs | 14 +++++++++++++- src/epd2in13bc/mod.rs | 4 +++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 59b9f41..ce37369 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [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 (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 | ✕ | ✔ | ✔ | ✔ | | [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 | ✕ | ✕ | ✔ | ✔ | diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index a7c4709..45a48a3 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -23,6 +23,17 @@ use linux_embedded_hal::{ // 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 +// +// This example first setups SPI communication using the pin layout found +// at https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B). This example uses the layout for the +// Raspberry Pi Zero (RPI Zero). The Chip Select (CS) was taken from the ep2in9 example since CE0 (GPIO8) did +// not seem to work on RPI Zero with 2.13" HAT +// +// The first frame is filled with four texts at different rotations (black on white) +// The second frame uses a buffer for black/white and a seperate buffer for chromatic/white (i.e. red or yellow) +// This example draws a sample clock in black on white and two texts using white on red. +// +// after finishing, put the display to sleep fn main() -> Result<(), std::io::Error> { let busy = Pin::new(24); // GPIO 24, board J-18 @@ -104,7 +115,8 @@ fn main() -> Result<(), std::io::Error> { .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); - // draw white on Red background + // draw text white on Red background by using the chromatic buffer + let _ = Text::new("It's working-WoB!", Point::new(90, 10)) .into_styled(text_style!( font = Font6x8, diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index e055acb..a9265e2 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -1,4 +1,6 @@ //! A simple Driver for the Waveshare 2.13" (B/C) E-Ink Display via SPI +//! More information on this display can be found at the [Waveshare Wiki]:(https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B)) +//! This driver was build and tested for 212x104, 2.13inch E-Ink display HAT for Raspberry Pi, three-color, SPI interface //! //! # Example for the 2.13" E-Ink Display //! @@ -67,7 +69,7 @@ use crate::traits::{ pub const WIDTH: u32 = 104; /// Height of epd2in13bc in pixels pub const HEIGHT: u32 = 212; -/// Default background color (white) of epd2in9bc display +/// Default background color (white) of epd2in13bc display pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; From c25d9f18d323cb689b26594410c390632045f03e Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 30 May 2021 14:20:02 +0200 Subject: [PATCH 58/80] Enable drawing in three colors for epd2in13 Move from BinaryColor to TriColor: use one Display fo drawing --- examples/epd2in13bc.rs | 53 +++++++++++++----------- src/color.rs | 22 ++++++++++ src/epd2in13bc/graphics.rs | 33 +++++++++++---- src/epd2in13bc/mod.rs | 15 +++---- src/graphics.rs | 85 +++++++++++++++++++++++++++++++++++++- 5 files changed, 166 insertions(+), 42 deletions(-) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 45a48a3..69a7ffc 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -11,7 +11,7 @@ use embedded_hal::prelude::*; use epd_waveshare::{ color::*, epd2in13bc::{Display2in13bc, Epd2in13bc}, - graphics::{Display, DisplayRotation}, + graphics::{DisplayRotation, TriDisplay}, prelude::*, }; use linux_embedded_hal::{ @@ -77,7 +77,7 @@ fn main() -> Result<(), std::io::Error> { println!("Test all the rotations"); let mut display = Display2in13bc::default(); - let mut display_chromatic = Display2in13bc::default(); + display.clear_buffer(TriColor::White); display.set_rotation(DisplayRotation::Rotate0); draw_text(&mut display, "Rotation 0!", 5, 50); @@ -91,59 +91,62 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotation 270!", 5, 50); + // Since we only used black and white, we can resort to updating only + // the bw-buffer of this tri-color screen + epd2in13 - .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + .update_and_display_frame(&mut spi, &display.bw_buffer(), &mut delay) .expect("display frame new graphics"); println!("First frame done. Waiting 5s"); delay.delay_ms(5000u16); - println!("Now test new graphics with default rotation:"); - display.clear_buffer(Color::White); - display_chromatic.clear_buffer(Color::White); - // keep both displays on same rotation - display_chromatic.set_rotation(DisplayRotation::Rotate270); + println!("Now test new graphics with default rotation and three colors:"); + display.clear_buffer(TriColor::White); - // draw a analog clock + // draw a analog clock in black let _ = Circle::new(Point::new(64, 64), 40) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) - .into_styled(PrimitiveStyle::with_stroke(Black, 4)) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 4)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) .draw(&mut display); - // draw text white on Red background by using the chromatic buffer + // draw text white on chromatic (red or yellow) background let _ = Text::new("It's working-WoB!", Point::new(90, 10)) .into_styled(text_style!( font = Font6x8, - text_color = White, - background_color = Black + text_color = TriColor::White, + background_color = TriColor::Chromatic )) - .draw(&mut display_chromatic); + .draw(&mut display); // use bigger/different font let _ = Text::new("It's working-WoB!", Point::new(90, 40)) .into_styled(text_style!( font = Font12x16, - text_color = White, - background_color = Black + text_color = TriColor::White, + background_color = TriColor::Chromatic )) - .draw(&mut display_chromatic); + .draw(&mut display); - epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?; + // we used three colors, so we need to update both bw-buffer and chromatic-buffer + + epd2in13.update_color_frame(&mut spi, display.bw_buffer(), display.chromatic_buffer())?; epd2in13 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); + println!("Second frame done. Waiting 5s"); delay.delay_ms(5000u16); - display.clear_buffer(Color::White); - display_chromatic.clear_buffer(Color::White); - epd2in13.update_color_frame(&mut spi, &display.buffer(), &display_chromatic.buffer())?; + // clear both bw buffer and chromatic buffer + display.clear_buffer(TriColor::White); + epd2in13.update_color_frame(&mut spi, display.bw_buffer(), display.chromatic_buffer())?; epd2in13.display_frame(&mut spi, &mut delay)?; println!("Finished tests - going to sleep"); @@ -154,8 +157,8 @@ fn draw_text(display: &mut Display2in13bc, text: &str, x: i32, y: i32) { let _ = Text::new(text, Point::new(x, y)) .into_styled(text_style!( font = Font6x8, - text_color = Black, - background_color = White + text_color = TriColor::Black, + background_color = TriColor::White )) .draw(display); } diff --git a/src/color.rs b/src/color.rs index 754b411..6918dcb 100644 --- a/src/color.rs +++ b/src/color.rs @@ -169,6 +169,28 @@ impl From for Color { } } +impl TriColor { + /// Get the color encoding of the color for one bit + pub fn get_bit_value(self) -> u8 { + match self { + TriColor::White => 1u8, + TriColor::Black | TriColor::Chromatic => 0u8, + } + } + + /// Gets a full byte of black or white pixels + pub fn get_byte_value(self) -> u8 { + match self { + TriColor::White => 0xff, + TriColor::Black | TriColor::Chromatic => 0x00, + } + } +} + +impl PixelColor for TriColor { + type Raw = (); +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs index 10ca19a..80ce6d1 100644 --- a/src/epd2in13bc/graphics.rs +++ b/src/epd2in13bc/graphics.rs @@ -1,30 +1,33 @@ +use crate::color::TriColor; use crate::epd2in13bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; -use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use crate::graphics::{DisplayRotation, TriDisplay}; use embedded_graphics::prelude::*; -/// Full size buffer for use with the 2in13b/c EPD +/// Full size buffer for use with the 2.13" b/c EPD /// /// Can also be manually constructed and be used together with VarDisplay pub struct Display2in13bc { - buffer: [u8; NUM_DISPLAY_BITS as usize], + // one buffer for both b/w and for chromatic: + // * &buffer[0..NUM_DISPLAY_BITS] for b/w buffer and + // * &buffer[NUM_DISPLAY_BITS..2*NUM_DISPLAY_BITS] for chromatic buffer + buffer: [u8; 2 * NUM_DISPLAY_BITS as usize], rotation: DisplayRotation, } impl Default for Display2in13bc { fn default() -> Self { Display2in13bc { - buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); NUM_DISPLAY_BITS as usize], + buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 2 * NUM_DISPLAY_BITS as usize], rotation: DisplayRotation::default(), } } } -impl DrawTarget for Display2in13bc { +impl DrawTarget for Display2in13bc { type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { + self.draw_helper_tri(WIDTH, HEIGHT, pixel) } fn size(&self) -> Size { @@ -32,7 +35,7 @@ impl DrawTarget for Display2in13bc { } } -impl Display for Display2in13bc { +impl TriDisplay for Display2in13bc { fn buffer(&self) -> &[u8] { &self.buffer } @@ -48,4 +51,16 @@ impl Display for Display2in13bc { fn rotation(&self) -> DisplayRotation { self.rotation } + + fn chromatic_offset(&self) -> usize { + NUM_DISPLAY_BITS as usize + } + + fn bw_buffer(&self) -> &[u8] { + &self.buffer[0..self.chromatic_offset()] + } + + fn chromatic_buffer(&self) -> &[u8] { + &self.buffer[self.chromatic_offset()..] + } } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index a9265e2..9c11cbf 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -70,8 +70,9 @@ pub const WIDTH: u32 = 104; /// Height of epd2in13bc in pixels pub const HEIGHT: u32 = 212; /// Default background color (white) of epd2in13bc display -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; @@ -81,7 +82,7 @@ const BLACK_BORDER: u8 = 0x30; const CHROMATIC_BORDER: u8 = 0xb0; const FLOATING_BORDER: u8 = 0xF0; -use crate::color::{Color, TriColor}; +use crate::color::TriColor; pub(crate) mod command; use self::command::Command; @@ -91,10 +92,10 @@ mod graphics; #[cfg(feature = "graphics")] pub use self::graphics::Display2in13bc; -/// Epd2in9bc driver +/// Epd2in13bc driver pub struct Epd2in13bc { interface: DisplayInterface, - color: Color, + color: TriColor, } impl InternalWiAdditions @@ -196,7 +197,7 @@ where RST: OutputPin, DELAY: DelayMs, { - type DisplayColor = Color; + type DisplayColor = TriColor; fn new( spi: &mut SPI, cs: CS, @@ -236,11 +237,11 @@ where self.init(spi, delay) } - fn set_background_color(&mut self, color: Color) { + fn set_background_color(&mut self, color: TriColor) { self.color = color; } - fn background_color(&self) -> &Color { + fn background_color(&self) -> &TriColor { &self.color } diff --git a/src/graphics.rs b/src/graphics.rs index c7b752e..a752e58 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,7 +1,7 @@ //! Graphics Support for EPDs use crate::buffer_len; -use crate::color::{Color, OctColor}; +use crate::color::{Color, OctColor, TriColor}; use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; /// Displayrotation @@ -85,6 +85,89 @@ pub trait Display: DrawTarget { } } +/// Necessary traits for all displays to implement for drawing +/// +/// Adds support for: +/// - Drawing (With the help of DrawTarget/Embedded Graphics) +/// - Rotations +/// - Clearing +pub trait TriDisplay: DrawTarget { + /// Clears the buffer of the display with the chosen background color + fn clear_buffer(&mut self, background_color: TriColor) { + for elem in self.get_mut_buffer().iter_mut() { + *elem = background_color.get_byte_value(); + } + } + + /// Returns the buffer + fn buffer(&self) -> &[u8]; + + /// Returns a mutable buffer + fn get_mut_buffer(&mut self) -> &mut [u8]; + + /// Sets the rotation of the display + fn set_rotation(&mut self, rotation: DisplayRotation); + + /// Get the current rotation of the display + fn rotation(&self) -> DisplayRotation; + + /// Get the offset into buffer where chromatic data starts + fn chromatic_offset(&self) -> usize; + + /// return the b/w part of the buffer + fn bw_buffer(&self) -> &[u8]; + + /// return the chromatic part of the buffer + fn chromatic_buffer(&self) -> &[u8]; + + /// Helperfunction for the Embedded Graphics draw trait + /// + /// Becomes uneccesary when const_generics become stablised + fn draw_helper_tri( + &mut self, + width: u32, + height: u32, + pixel: Pixel, + ) -> Result<(), Self::Error> { + let rotation = self.rotation(); + + let Pixel(point, color) = pixel; + if outside_display(point, width, height, rotation) { + return Ok(()); + } + + // Give us index inside the buffer and the bit-position in that u8 which needs to be changed + let (index, bit) = find_position(point.x as u32, point.y as u32, width, height, rotation); + let index = index as usize; + let offset = self.chromatic_offset(); + + let buffer = self.get_mut_buffer(); + + // "Draw" the Pixel on that bit + match color { + TriColor::Black => { + // clear bit in bw-buffer -> black + buffer[index] &= !bit; + // set bit in chromatic-buffer -> white + buffer[index+offset] |= bit; + } + TriColor::White => { + // set bit in bw-buffer -> white + buffer[index] |= bit; + // set bit in chromatic-buffer -> white + buffer[index+offset] |= bit; + } + TriColor::Chromatic => { + // set bit in b/w buffer (white) + buffer[index] |= bit; + // clear bit in chromatic buffer -> chromatic + buffer[index+offset] &= !bit; + } + } + Ok(()) + } +} + /// Necessary traits for all displays to implement for drawing /// /// Adds support for: From a55a9970a5c3d770c31a17d868f84aee2e4a8778 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sun, 30 May 2021 14:28:09 +0200 Subject: [PATCH 59/80] cargo fmt --- examples/epd2in13bc.rs | 2 +- src/graphics.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 69a7ffc..603f3bf 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -91,7 +91,7 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotation 270!", 5, 50); - // Since we only used black and white, we can resort to updating only + // Since we only used black and white, we can resort to updating only // the bw-buffer of this tri-color screen epd2in13 diff --git a/src/graphics.rs b/src/graphics.rs index a752e58..17ea4ec 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -116,7 +116,7 @@ pub trait TriDisplay: DrawTarget { /// return the b/w part of the buffer fn bw_buffer(&self) -> &[u8]; - + /// return the chromatic part of the buffer fn chromatic_buffer(&self) -> &[u8]; @@ -130,12 +130,12 @@ pub trait TriDisplay: DrawTarget { pixel: Pixel, ) -> Result<(), Self::Error> { let rotation = self.rotation(); - + let Pixel(point, color) = pixel; if outside_display(point, width, height, rotation) { return Ok(()); } - + // Give us index inside the buffer and the bit-position in that u8 which needs to be changed let (index, bit) = find_position(point.x as u32, point.y as u32, width, height, rotation); let index = index as usize; @@ -149,19 +149,19 @@ pub trait TriDisplay: DrawTarget { // clear bit in bw-buffer -> black buffer[index] &= !bit; // set bit in chromatic-buffer -> white - buffer[index+offset] |= bit; + buffer[index + offset] |= bit; } TriColor::White => { // set bit in bw-buffer -> white buffer[index] |= bit; // set bit in chromatic-buffer -> white - buffer[index+offset] |= bit; + buffer[index + offset] |= bit; } TriColor::Chromatic => { // set bit in b/w buffer (white) buffer[index] |= bit; // clear bit in chromatic buffer -> chromatic - buffer[index+offset] &= !bit; + buffer[index + offset] &= !bit; } } Ok(()) From 076b3a2d072dd00cfd03fb5639d545930b969cc1 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 9 Jun 2021 11:41:25 +0200 Subject: [PATCH 60/80] Update example to use TriColor --- src/color.rs | 1 + src/epd2in13bc/mod.rs | 30 ++++++++++++------------------ src/lib.rs | 2 +- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/color.rs b/src/color.rs index 6918dcb..8867978 100644 --- a/src/color.rs +++ b/src/color.rs @@ -187,6 +187,7 @@ impl TriColor { } } +#[cfg(feature = "graphics")] impl PixelColor for TriColor { type Raw = (); } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 9c11cbf..27c034b 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -7,10 +7,8 @@ //!```rust, no_run //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { -//!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, -//!}; -//!use epd_waveshare::{epd2in13bc::*, prelude::*}; +//!use embedded_graphics::{prelude::*, primitives::Line, style::PrimitiveStyle}; +//!use epd_waveshare::{epd2in13bc::*, prelude::*, color::TriColor}; //!# //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); @@ -25,28 +23,24 @@ //!let mut epd = Epd2in13bc::new(&mut spi, cs_pin, busy_in, dc, rst, &mut delay)?; //! //!// Use display graphics from embedded-graphics -//!// This display is for the black/white pixels -//!let mut mono_display = Display2in13bc::default(); +//!// This display is for the black/white/chromatic pixels +//!let mut tricolor_display = Display2in13bc::default(); //! -//!// Use embedded graphics for drawing -//!// A black line +//!// Use embedded graphics for drawing a black line //!let _ = Line::new(Point::new(0, 120), Point::new(0, 200)) -//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) -//! .draw(&mut mono_display); +//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) +//! .draw(&mut tricolor_display); //! -//!// Use a second display for red/yellow -//!let mut chromatic_display = Display2in13bc::default(); -//! -//!// We use `Black` but it will be shown as red/yellow +//!// 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(Black, 1)) -//! .draw(&mut chromatic_display); +//! .into_styled(PrimitiveStyle::with_stroke(TriColor::Chromatic, 1)) +//! .draw(&mut tricolor_display); //! //!// Display updated frame //!epd.update_color_frame( //! &mut spi, -//! &mono_display.buffer(), -//! &chromatic_display.buffer() +//! &tricolor_display.bw_buffer(), +//! &tricolor_display.chromatic_buffer() //!)?; //!epd.display_frame(&mut spi, &mut delay)?; //! diff --git a/src/lib.rs b/src/lib.rs index 50ee2d2..39abc82 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,7 +99,7 @@ pub mod prelude { pub use crate::SPI_MODE; #[cfg(feature = "graphics")] - pub use crate::graphics::{Display, DisplayRotation, OctDisplay}; + pub use crate::graphics::{Display, TriDisplay, DisplayRotation, OctDisplay}; } /// Computes the needed buffer length. Takes care of rounding up in case width From 35ac1325309b20c2e6131edc43bda0f04eb66b94 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 9 Jun 2021 11:46:59 +0200 Subject: [PATCH 61/80] fix fmt --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 39abc82..bfd34bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,7 +99,7 @@ pub mod prelude { pub use crate::SPI_MODE; #[cfg(feature = "graphics")] - pub use crate::graphics::{Display, TriDisplay, DisplayRotation, OctDisplay}; + pub use crate::graphics::{Display, DisplayRotation, OctDisplay, TriDisplay}; } /// Computes the needed buffer length. Takes care of rounding up in case width From 78ffda673e263ae9faeb843196f1a8bc2c0caa69 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Sat, 12 Jun 2021 15:59:08 +0200 Subject: [PATCH 62/80] migrate minimum set of drivers to make tests pass --- Cargo.toml | 5 ++- examples/epd2in13_v2.rs | 63 +++++++++++++++++------------- examples/epd2in13bc.rs | 64 +++++++++++++++++------------- examples/epd4in2.rs | 65 ++++++++++++++++++------------- examples/epd4in2_variable_size.rs | 62 ++++++++++++++++------------- src/epd1in54/graphics.rs | 51 +++++++++++++++++++----- src/epd1in54/mod.rs | 8 +++- src/epd1in54b/graphics.rs | 3 +- src/epd1in54c/graphics.rs | 3 +- src/epd2in13_v2/graphics.rs | 50 +++++++++++++++++++----- src/epd2in13bc/graphics.rs | 20 +++++++--- src/epd2in13bc/mod.rs | 4 +- src/epd2in7b/graphics.rs | 3 +- src/epd2in9/graphics.rs | 18 ++++++--- src/epd2in9/mod.rs | 8 +++- src/epd2in9_v2/graphics.rs | 4 +- src/epd2in9bc/graphics.rs | 4 +- src/epd4in2/graphics.rs | 51 +++++++++++++++++++----- src/epd4in2/mod.rs | 8 +++- src/epd5in65f/graphics.rs | 3 +- src/epd7in5/graphics.rs | 3 +- src/epd7in5_hd/graphics.rs | 3 +- src/epd7in5_v2/graphics.rs | 16 ++++++-- src/graphics.rs | 53 ++++++++++++++++++------- src/lib.rs | 28 +++++++------ src/traits.rs | 12 ++++-- 26 files changed, 411 insertions(+), 201 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c340fa8..05df967 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,8 @@ edition = "2018" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics = { version = "0.6.2", optional = true} +embedded-graphics = { version = "0.7.0", optional = true} +embedded-graphics-core = { version = "0.3.2", optional = true} embedded-hal = {version = "0.2.4", features = ["unproven"]} bit_field = "0.10.1" @@ -27,7 +28,7 @@ embedded-hal-mock = "0.7" [features] default = ["graphics"] -graphics = ["embedded-graphics"] +graphics = ["embedded-graphics","embedded-graphics-core"] # Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking type_a_alternative_faster_lut = [] diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index 3ee0e8c..fef4b6c 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -1,17 +1,16 @@ #![deny(warnings)] use embedded_graphics::{ - fonts::{Font12x16, Font6x8, Text}, + mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line}, - style::PrimitiveStyle, - text_style, + primitives::{Circle, Line, PrimitiveStyleBuilder}, + text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; use epd_waveshare::{ color::*, epd2in13_v2::{Display2in13, Epd2in13}, - graphics::{Display, DisplayRotation}, + graphics::DisplayRotation, prelude::*, }; use linux_embedded_hal::{ @@ -90,32 +89,40 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); // draw a analog clock + let style = PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(); + let _ = Circle::new(Point::new(64, 64), 40) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) - .into_styled(PrimitiveStyle::with_stroke(Black, 4)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); // draw white on black background - let _ = Text::new("It's working-WoB!", Point::new(90, 10)) - .into_styled(text_style!( - font = Font6x8, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_color(Black) + .build(); + let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); + + let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 10), style, text_style) .draw(&mut display); // use bigger/different font - let _ = Text::new("It's working-WoB!", Point::new(90, 40)) - .into_styled(text_style!( - font = Font12x16, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_10X20) + .text_color(White) + .background_color(Black) + .build(); + + let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 40), style, text_style) .draw(&mut display); // Demonstrating how to use the partial refresh feature of the screen. @@ -157,11 +164,13 @@ fn main() -> Result<(), std::io::Error> { } fn draw_text(display: &mut Display2in13, text: &str, x: i32, y: i32) { - let _ = Text::new(text, Point::new(x, y)) - .into_styled(text_style!( - font = Font6x8, - text_color = Black, - background_color = White - )) - .draw(display); + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_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); } diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 603f3bf..68c72a0 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -1,11 +1,10 @@ #![deny(warnings)] use embedded_graphics::{ - fonts::{Font12x16, Font6x8, Text}, + mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line}, - style::PrimitiveStyle, - text_style, + primitives::{Circle, Line, PrimitiveStyleBuilder}, + text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; use epd_waveshare::{ @@ -104,34 +103,41 @@ fn main() -> Result<(), std::io::Error> { println!("Now test new graphics with default rotation and three colors:"); display.clear_buffer(TriColor::White); - // draw a analog clock in black + // draw a analog clock + let style = PrimitiveStyleBuilder::new() + .stroke_color(TriColor::Black) + .stroke_width(1) + .build(); + let _ = Circle::new(Point::new(64, 64), 40) - .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) - .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 4)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) - .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) + .into_styled(style) .draw(&mut display); - // draw text white on chromatic (red or yellow) background + // draw text white on Red background by using the chromatic buffer + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(TriColor::White) + .background_color(TriColor::Chromatic) + .build(); + let text_style = TextStyleBuilder::new().baseline(Baseline::Top).build(); - let _ = Text::new("It's working-WoB!", Point::new(90, 10)) - .into_styled(text_style!( - font = Font6x8, - text_color = TriColor::White, - background_color = TriColor::Chromatic - )) + let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 10), style, text_style) .draw(&mut display); // use bigger/different font - let _ = Text::new("It's working-WoB!", Point::new(90, 40)) - .into_styled(text_style!( - font = Font12x16, - text_color = TriColor::White, - background_color = TriColor::Chromatic - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_10X20) + .text_color(TriColor::White) + .background_color(TriColor::Chromatic) + .build(); + + let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 40), style, text_style) .draw(&mut display); // we used three colors, so we need to update both bw-buffer and chromatic-buffer @@ -154,11 +160,13 @@ fn main() -> Result<(), std::io::Error> { } fn draw_text(display: &mut Display2in13bc, text: &str, x: i32, y: i32) { - let _ = Text::new(text, Point::new(x, y)) - .into_styled(text_style!( - font = Font6x8, - text_color = TriColor::Black, - background_color = TriColor::White - )) - .draw(display); + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(TriColor::White) + .background_color(TriColor::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); } diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index dffc083..400ec83 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -1,17 +1,16 @@ #![deny(warnings)] use embedded_graphics::{ - fonts::{Font12x16, Font6x8, Text}, + mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line}, - style::PrimitiveStyle, - text_style, + primitives::{Circle, Line, PrimitiveStyleBuilder}, + text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; use epd_waveshare::{ color::*, epd4in2::{Display4in2, Epd4in2}, - graphics::{Display, DisplayRotation}, + graphics::DisplayRotation, prelude::*, }; use linux_embedded_hal::{ @@ -90,32 +89,40 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); // draw a analog clock - let _ = Circle::new(Point::new(64, 64), 64) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + let style = PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(); + + let _ = Circle::new(Point::new(64, 64), 40) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(0, 64)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 80)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); // draw white on black background - let _ = Text::new("It's working-WoB!", Point::new(175, 250)) - .into_styled(text_style!( - font = Font6x8, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_color(Black) + .build(); + 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); // use bigger/different font - let _ = Text::new("It's working-WoB!", Point::new(50, 200)) - .into_styled(text_style!( - font = Font12x16, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_10X20) + .text_color(White) + .background_color(Black) + .build(); + + let _ = Text::with_text_style("It's working-WoB!", Point::new(50, 200), style, text_style) .draw(&mut display); // a moving `Hello World!` @@ -142,11 +149,13 @@ fn main() -> Result<(), std::io::Error> { } fn draw_text(display: &mut Display4in2, text: &str, x: i32, y: i32) { - let _ = Text::new(text, Point::new(x, y)) - .into_styled(text_style!( - font = Font6x8, - text_color = Black, - background_color = White - )) - .draw(display); + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_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); } diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index fe36f7e..6faf287 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -2,11 +2,10 @@ #![deny(warnings)] use embedded_graphics::{ - fonts::{Font12x16, Font6x8, Text}, + mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line}, - style::PrimitiveStyle, - text_style, + primitives::{Circle, Line, PrimitiveStyleBuilder}, + text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; use epd_waveshare::{ @@ -97,33 +96,40 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); // draw a analog clock - // draw a analog clock + let style = PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(); + let _ = Circle::new(Point::new(64, 64), 64) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(0, 64)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 80)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled(style) .draw(&mut display); // draw white on black background - let _ = Text::new("It's working-WoB!", Point::new(175, 250)) - .into_styled(text_style!( - font = Font6x8, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_color(Black) + .build(); + 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); // use bigger/different font - let _ = Text::new("It's working-WoB!", Point::new(50, 200)) - .into_styled(text_style!( - font = Font12x16, - text_color = White, - background_color = Black - )) + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_10X20) + .text_color(White) + .background_color(Black) + .build(); + + let _ = Text::with_text_style("It's working-WoB!", Point::new(50, 200), style, text_style) .draw(&mut display); // a moving `Hello World!` @@ -148,11 +154,13 @@ fn main() -> Result<(), std::io::Error> { } fn draw_text(display: &mut VarDisplay, text: &str, x: i32, y: i32) { - let _ = Text::new(text, Point::new(x, y)) - .into_styled(text_style!( - font = Font6x8, - text_color = Black, - background_color = White - )) - .draw(display); + let style = MonoTextStyleBuilder::new() + .font(&embedded_graphics::mono_font::ascii::FONT_6X10) + .text_color(White) + .background_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); } diff --git a/src/epd1in54/graphics.rs b/src/epd1in54/graphics.rs index 2cdc1d2..6bc08d7 100644 --- a/src/epd1in54/graphics.rs +++ b/src/epd1in54/graphics.rs @@ -1,7 +1,7 @@ use crate::epd1in54::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54 EPD /// @@ -22,13 +22,21 @@ impl Default for Display1in54 { } } -impl DrawTarget for Display1in54 { +impl DrawTarget for Display1in54 { + type Color = BinaryColor; type Error = core::convert::Infallible; - - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display1in54 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -57,7 +65,10 @@ mod tests { use super::*; use crate::color::{Black, Color}; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyleBuilder}, + }; // test buffer length #[test] @@ -79,7 +90,12 @@ mod tests { fn graphics_rotation_0() { let mut display = Display1in54::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -96,7 +112,12 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 192), Point::new(0, 199)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -113,7 +134,12 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate180); let _ = Line::new(Point::new(192, 199), Point::new(199, 199)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -133,7 +159,12 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate270); let _ = Line::new(Point::new(199, 0), Point::new(199, 7)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd1in54/mod.rs b/src/epd1in54/mod.rs index e5d97bd..ae7f542 100644 --- a/src/epd1in54/mod.rs +++ b/src/epd1in54/mod.rs @@ -6,7 +6,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, //!}; //!use epd_waveshare::{epd1in54::*, prelude::*}; //!# @@ -26,8 +26,12 @@ //!let mut display = Display1in54::default(); //! //!// Use embedded graphics for drawing a line +//!let style = PrimitiveStyleBuilder::new() +//! .stroke_color(Black) +//! .stroke_width(1) +//! .build(); //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .into_styled(style) //! .draw(&mut display); //! //!// Display updated frame diff --git a/src/epd1in54b/graphics.rs b/src/epd1in54b/graphics.rs index 617d697..53aca36 100644 --- a/src/epd1in54b/graphics.rs +++ b/src/epd1in54b/graphics.rs @@ -21,7 +21,8 @@ impl Default for Display1in54b { } } -impl DrawTarget for Display1in54b { +impl DrawTarget for Display1in54b { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs index 4475083..476793c 100644 --- a/src/epd1in54c/graphics.rs +++ b/src/epd1in54c/graphics.rs @@ -20,7 +20,8 @@ impl Default for Display1in54c { } } -impl DrawTarget for Display1in54c { +impl DrawTarget for Display1in54c { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd2in13_v2/graphics.rs b/src/epd2in13_v2/graphics.rs index 1c77a3e..1f01982 100644 --- a/src/epd2in13_v2/graphics.rs +++ b/src/epd2in13_v2/graphics.rs @@ -2,7 +2,7 @@ use crate::buffer_len; use crate::epd2in13_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in13 v2 EPD /// @@ -23,13 +23,22 @@ impl Default for Display2in13 { } } -impl DrawTarget for Display2in13 { +impl DrawTarget for Display2in13 { + type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display2in13 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -59,7 +68,10 @@ mod tests { use crate::color::{Black, Color}; use crate::epd2in13_v2; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyleBuilder}, + }; // test buffer length #[test] @@ -82,7 +94,12 @@ mod tests { let mut display = Display2in13::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -103,7 +120,12 @@ mod tests { Point::new(0, (WIDTH - 8) as i32), Point::new(0, (WIDTH - 1) as i32), ) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -124,7 +146,12 @@ mod tests { Point::new((WIDTH - 8) as i32, (HEIGHT - 1) as i32), Point::new((WIDTH - 1) as i32, (HEIGHT - 1) as i32), ) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -145,7 +172,12 @@ mod tests { Point::new((HEIGHT - 1) as i32, 0), Point::new((HEIGHT - 1) as i32, 7), ) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs index 80ce6d1..30e9460 100644 --- a/src/epd2in13bc/graphics.rs +++ b/src/epd2in13bc/graphics.rs @@ -1,7 +1,7 @@ use crate::color::TriColor; use crate::epd2in13bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; -use crate::graphics::{DisplayRotation, TriDisplay}; -use embedded_graphics::prelude::*; +use crate::graphics::{TriDisplay, DisplayRotation}; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2.13" b/c EPD /// @@ -23,13 +23,21 @@ impl Default for Display2in13bc { } } -impl DrawTarget for Display2in13bc { +impl DrawTarget for Display2in13bc { + type Color = TriColor; type Error = core::convert::Infallible; - - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper_tri(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper_tri(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display2in13bc { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 27c034b..ef5a044 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -7,8 +7,8 @@ //!```rust, no_run //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { -//!use embedded_graphics::{prelude::*, primitives::Line, style::PrimitiveStyle}; -//!use epd_waveshare::{epd2in13bc::*, prelude::*, color::TriColor}; +//!use embedded_graphics::{prelude::*, primitives::{Line, PrimitiveStyle, PrimitiveStyleBuilder}}; +//!use epd_waveshare::{epd2in13bc::*, prelude::*}; //!# //!# let expectations = []; //!# let mut spi = spi::Mock::new(&expectations); diff --git a/src/epd2in7b/graphics.rs b/src/epd2in7b/graphics.rs index 1dcd7bf..ca193cf 100644 --- a/src/epd2in7b/graphics.rs +++ b/src/epd2in7b/graphics.rs @@ -22,7 +22,8 @@ impl Default for Display2in7b { } } -impl DrawTarget for Display2in7b { +impl DrawTarget for Display2in7b { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd2in9/graphics.rs b/src/epd2in9/graphics.rs index fb1154e..0e29253 100644 --- a/src/epd2in9/graphics.rs +++ b/src/epd2in9/graphics.rs @@ -1,7 +1,7 @@ use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Display with Fullsize buffer for use with the 2in9 EPD /// @@ -22,13 +22,21 @@ impl Default for Display2in9 { } } -impl DrawTarget for Display2in9 { +impl DrawTarget for Display2in9 { + type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } - +} +impl OriginDimensions for Display2in9 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index 0feec3d..a139289 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -7,7 +7,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, //!}; //!use epd_waveshare::{epd2in9::*, prelude::*}; //!# @@ -27,8 +27,12 @@ //!let mut display = Display2in9::default(); //! //!// Use embedded graphics for drawing a line +//!let style = PrimitiveStyleBuilder::new() +//! .stroke_color(Black) +//! .stroke_width(1) +//! .build(); //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .into_styled(style) //! .draw(&mut display); //! //! // Display updated frame diff --git a/src/epd2in9_v2/graphics.rs b/src/epd2in9_v2/graphics.rs index df1cd2e..9edf34f 100644 --- a/src/epd2in9_v2/graphics.rs +++ b/src/epd2in9_v2/graphics.rs @@ -1,6 +1,5 @@ use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; /// Display with Fullsize buffer for use with the 2in9 EPD V2 @@ -22,7 +21,8 @@ impl Default for Display2in9 { } } -impl DrawTarget for Display2in9 { +impl DrawTarget for Display2in9 { + type Color = BinaryColor type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd2in9bc/graphics.rs b/src/epd2in9bc/graphics.rs index 16d12d1..ed021b7 100644 --- a/src/epd2in9bc/graphics.rs +++ b/src/epd2in9bc/graphics.rs @@ -1,6 +1,5 @@ use crate::epd2in9bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; /// Full size buffer for use with the 2in9b/c EPD @@ -20,7 +19,8 @@ impl Default for Display2in9bc { } } -impl DrawTarget for Display2in9bc { +impl DrawTarget for Display2in9bc { + type Color = BinaryColor type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd4in2/graphics.rs b/src/epd4in2/graphics.rs index 101501e..d45c17d 100644 --- a/src/epd4in2/graphics.rs +++ b/src/epd4in2/graphics.rs @@ -1,7 +1,7 @@ use crate::epd4in2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 4in2 EPD /// @@ -22,13 +22,21 @@ impl Default for Display4in2 { } } -impl DrawTarget for Display4in2 { +impl DrawTarget for Display4in2 { + type Color = BinaryColor; type Error = core::convert::Infallible; - - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display4in2 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -59,7 +67,10 @@ mod tests { use crate::color::Color; use crate::epd4in2; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyleBuilder}, + }; // test buffer length #[test] @@ -81,7 +92,12 @@ mod tests { fn graphics_rotation_0() { let mut display = Display4in2::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -98,7 +114,12 @@ mod tests { let mut display = Display4in2::default(); display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 392), Point::new(0, 399)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -116,7 +137,12 @@ mod tests { display.set_rotation(DisplayRotation::Rotate180); let _ = Line::new(Point::new(392, 299), Point::new(399, 299)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -136,7 +162,12 @@ mod tests { let mut display = Display4in2::default(); display.set_rotation(DisplayRotation::Rotate270); let _ = Line::new(Point::new(299, 0), Point::new(299, 7)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index b39ee5e..5570f5a 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -11,7 +11,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, //!}; //!use epd_waveshare::{epd4in2::*, prelude::*}; //!# @@ -31,8 +31,12 @@ //!let mut display = Display4in2::default(); //! //!// Use embedded graphics for drawing a line +//!let style = PrimitiveStyleBuilder::new() +//! .stroke_color(Black) +//! .stroke_width(1) +//! .build(); //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .into_styled(style) //! .draw(&mut display); //! //! // Display updated frame diff --git a/src/epd5in65f/graphics.rs b/src/epd5in65f/graphics.rs index d21f8e8..0287d38 100644 --- a/src/epd5in65f/graphics.rs +++ b/src/epd5in65f/graphics.rs @@ -22,7 +22,8 @@ impl Default for Display5in65f { } } -impl DrawTarget for Display5in65f { +impl DrawTarget for Display5in65f { + type Color = OctColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd7in5/graphics.rs b/src/epd7in5/graphics.rs index 62d1563..82bf712 100644 --- a/src/epd7in5/graphics.rs +++ b/src/epd7in5/graphics.rs @@ -22,7 +22,8 @@ impl Default for Display7in5 { } } -impl DrawTarget for Display7in5 { +impl DrawTarget for Display7in5 { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd7in5_hd/graphics.rs b/src/epd7in5_hd/graphics.rs index 60c36dc..0497009 100644 --- a/src/epd7in5_hd/graphics.rs +++ b/src/epd7in5_hd/graphics.rs @@ -22,7 +22,8 @@ impl Default for Display7in5 { } } -impl DrawTarget for Display7in5 { +impl DrawTarget for Display7in5 { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { diff --git a/src/epd7in5_v2/graphics.rs b/src/epd7in5_v2/graphics.rs index 8c3211f..2d8642a 100644 --- a/src/epd7in5_v2/graphics.rs +++ b/src/epd7in5_v2/graphics.rs @@ -2,6 +2,7 @@ use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; use embedded_graphics::prelude::*; +use embedded_graphics_core::OriginDimension; /// Full size buffer for use with the 7in5 EPD /// @@ -22,16 +23,17 @@ impl Default for Display7in5 { } } -impl DrawTarget for Display7in5 { +impl DrawTarget for Display7in5 { + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { self.draw_helper(WIDTH, HEIGHT, pixel) } - fn size(&self) -> Size { - Size::new(WIDTH, HEIGHT) - } +// fn size(&self) -> Size { +// Size::new(WIDTH, HEIGHT) +// } } impl Display for Display7in5 { @@ -52,6 +54,12 @@ impl Display for Display7in5 { } } +impl OriginDimension for Display7in5 { + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/graphics.rs b/src/graphics.rs index 17ea4ec..e347259 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -2,7 +2,8 @@ use crate::buffer_len; use crate::color::{Color, OctColor, TriColor}; -use embedded_graphics::{pixelcolor::BinaryColor, prelude::*}; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::prelude::*; /// Displayrotation #[derive(Clone, Copy)] @@ -29,7 +30,7 @@ impl Default for DisplayRotation { /// - Drawing (With the help of DrawTarget/Embedded Graphics) /// - Rotations /// - Clearing -pub trait Display: DrawTarget { +pub trait Display: DrawTarget { /// Clears the buffer of the display with the chosen background color fn clear_buffer(&mut self, background_color: Color) { for elem in self.get_mut_buffer().iter_mut() { @@ -91,7 +92,7 @@ pub trait Display: DrawTarget { /// - Drawing (With the help of DrawTarget/Embedded Graphics) /// - Rotations /// - Clearing -pub trait TriDisplay: DrawTarget { +pub trait TriDisplay: DrawTarget { /// Clears the buffer of the display with the chosen background color fn clear_buffer(&mut self, background_color: TriColor) { for elem in self.get_mut_buffer().iter_mut() { @@ -174,7 +175,7 @@ pub trait TriDisplay: DrawTarget { /// - Drawing (With the help of DrawTarget/Embedded Graphics) /// - Rotations /// - Clearing -pub trait OctDisplay: DrawTarget { +pub trait OctDisplay: DrawTarget { /// Clears the buffer of the display with the chosen background color fn clear_buffer(&mut self, background_color: OctColor) { for elem in self.get_mut_buffer().iter_mut() { @@ -240,8 +241,7 @@ pub trait OctDisplay: DrawTarget { /// # use epd_waveshare::graphics::VarDisplay; /// # use epd_waveshare::color::Black; /// # use embedded_graphics::prelude::*; -/// # use embedded_graphics::primitives::{Circle, Line}; -/// # use embedded_graphics::style::PrimitiveStyle; +/// # use embedded_graphics::primitives::{Circle, Line, PrimitiveStyleBuilder}; /// let width = 128; /// let height = 296; /// @@ -250,8 +250,13 @@ pub trait OctDisplay: DrawTarget { /// /// display.set_rotation(DisplayRotation::Rotate90); /// +///let style = PrimitiveStyleBuilder::new() +/// .stroke_color(Black) +/// .stroke_width(1) +/// .build(); +/// /// let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -/// .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +/// .into_styled(style) /// .draw(&mut display); /// ``` pub struct VarDisplay<'a> { @@ -277,13 +282,22 @@ impl<'a> VarDisplay<'a> { } } -impl<'a> DrawTarget for VarDisplay<'a> { +impl<'a> DrawTarget for VarDisplay<'a> { + type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(self.width, self.height, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(self.width, self.height, pixel)?; + } + Ok(()) } +} +impl<'a> OriginDimensions for VarDisplay<'a> { fn size(&self) -> Size { Size::new(self.width, self.height) } @@ -379,7 +393,10 @@ mod tests { use super::{buffer_len, find_position, outside_display, Display, DisplayRotation, VarDisplay}; use crate::color::Black; use crate::color::Color; - use embedded_graphics::{prelude::*, primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyleBuilder}, + }; #[test] fn buffer_clear() { @@ -436,7 +453,12 @@ mod tests { let mut display = VarDisplay::new(width, height, &mut buffer); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); @@ -460,7 +482,12 @@ mod tests { display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) - .into_styled(PrimitiveStyle::with_stroke(Black, 1)) + .into_styled( + PrimitiveStyleBuilder::new() + .stroke_color(Black) + .stroke_width(1) + .build(), + ) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/lib.rs b/src/lib.rs index bfd34bf..0e00d8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, //!}; //!use epd_waveshare::{epd1in54::*, prelude::*}; //!# @@ -34,8 +34,14 @@ //!let mut display = Display1in54::default(); //! //!// Use embedded graphics for drawing a line +//! +//!let style = PrimitiveStyleBuilder::new() +//! .stroke_color(Black) +//! .stroke_width(1) +//! .build(); +//! //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +//! .into_styled(style) //! .draw(&mut display); //! //! // Display updated frame @@ -73,19 +79,19 @@ pub mod color; mod interface; pub mod epd1in54; -pub mod epd1in54b; -pub mod epd1in54c; +//pub mod epd1in54b; +//pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in13bc; -pub mod epd2in7b; +//pub mod epd2in7b; pub mod epd2in9; -pub mod epd2in9_v2; -pub mod epd2in9bc; +//pub mod epd2in9_v2; +//pub mod epd2in9bc; pub mod epd4in2; -pub mod epd5in65f; -pub mod epd7in5; -pub mod epd7in5_hd; -pub mod epd7in5_v2; +//pub mod epd5in65f; +//pub mod epd7in5; +//pub mod epd7in5_hd; +//pub mod epd7in5_v2; pub(crate) mod type_a; diff --git a/src/traits.rs b/src/traits.rs index abdb919..19ab914 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -92,7 +92,7 @@ where ///# use embedded_hal_mock::*; ///# fn main() -> Result<(), MockError> { ///use embedded_graphics::{ -/// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +/// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, ///}; ///use epd_waveshare::{epd4in2::*, prelude::*}; ///# @@ -112,8 +112,14 @@ where ///let mut display = Display4in2::default(); /// ///// Use embedded graphics for drawing a line +/// +///let style = PrimitiveStyleBuilder::new() +/// .stroke_color(Black) +/// .stroke_width(1) +/// .build(); +/// ///let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -/// .into_styled(PrimitiveStyle::with_stroke(Black, 1)) +/// .into_styled(style) /// .draw(&mut display); /// /// // Display updated frame @@ -248,7 +254,7 @@ where ///# use embedded_hal_mock::*; ///# fn main() -> Result<(), MockError> { ///# use embedded_graphics::{ -///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, ///# }; ///# use epd_waveshare::{epd4in2::*, prelude::*}; ///# use epd_waveshare::graphics::VarDisplay; From 21428ff82fb4e90d86dde1543f5c78e1c29aa8d6 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 16 Jun 2021 13:49:59 +0200 Subject: [PATCH 63/80] fix fmt after rebase --- src/epd2in13bc/graphics.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in13bc/graphics.rs b/src/epd2in13bc/graphics.rs index 30e9460..9d29a40 100644 --- a/src/epd2in13bc/graphics.rs +++ b/src/epd2in13bc/graphics.rs @@ -1,6 +1,6 @@ use crate::color::TriColor; use crate::epd2in13bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; -use crate::graphics::{TriDisplay, DisplayRotation}; +use crate::graphics::{DisplayRotation, TriDisplay}; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2.13" b/c EPD From dd9a09aff4d28ccb4b8f7b32c6a879abba758267 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 16 Jun 2021 14:17:18 +0200 Subject: [PATCH 64/80] use PrimitiveStyle::with_stroke, not PrimitiveStyleBuilder --- examples/epd2in13_v2.rs | 13 ++++--------- examples/epd2in13bc.rs | 13 ++++--------- src/epd1in54/graphics.rs | 30 +++++------------------------- src/epd7in5_v2/graphics.rs | 4 ---- 4 files changed, 13 insertions(+), 47 deletions(-) diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index fef4b6c..5eab890 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -3,7 +3,7 @@ use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line, PrimitiveStyleBuilder}, + primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; @@ -89,19 +89,14 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); // draw a analog clock - let style = PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(); - let _ = Circle::new(Point::new(64, 64), 40) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(Black, 4)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); // draw white on black background diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 68c72a0..8110d79 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -3,7 +3,7 @@ use embedded_graphics::{ mono_font::MonoTextStyleBuilder, prelude::*, - primitives::{Circle, Line, PrimitiveStyleBuilder}, + primitives::{Circle, Line, PrimitiveStyle}, text::{Baseline, Text, TextStyleBuilder}, }; use embedded_hal::prelude::*; @@ -104,19 +104,14 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(TriColor::White); // draw a analog clock - let style = PrimitiveStyleBuilder::new() - .stroke_color(TriColor::Black) - .stroke_width(1) - .build(); - let _ = Circle::new(Point::new(64, 64), 40) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 4)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(80, 40)) - .into_styled(style) + .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) .draw(&mut display); // draw text white on Red background by using the chromatic buffer diff --git a/src/epd1in54/graphics.rs b/src/epd1in54/graphics.rs index 6bc08d7..644ae0f 100644 --- a/src/epd1in54/graphics.rs +++ b/src/epd1in54/graphics.rs @@ -67,7 +67,7 @@ mod tests { use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::{ prelude::*, - primitives::{Line, PrimitiveStyleBuilder}, + primitives::{Line, PrimitiveStyle}, }; // test buffer length @@ -90,12 +90,7 @@ mod tests { fn graphics_rotation_0() { let mut display = Display1in54::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -112,12 +107,7 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 192), Point::new(0, 199)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -134,12 +124,7 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate180); let _ = Line::new(Point::new(192, 199), Point::new(199, 199)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -159,12 +144,7 @@ mod tests { let mut display = Display1in54::default(); display.set_rotation(DisplayRotation::Rotate270); let _ = Line::new(Point::new(199, 0), Point::new(199, 7)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd7in5_v2/graphics.rs b/src/epd7in5_v2/graphics.rs index 2d8642a..e9a6ad5 100644 --- a/src/epd7in5_v2/graphics.rs +++ b/src/epd7in5_v2/graphics.rs @@ -30,10 +30,6 @@ impl DrawTarget for Display7in5 { fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { self.draw_helper(WIDTH, HEIGHT, pixel) } - -// fn size(&self) -> Size { -// Size::new(WIDTH, HEIGHT) -// } } impl Display for Display7in5 { From 5622627c1f7f4a885b5df5ee01624ed57da8befc Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 16 Jun 2021 14:53:12 +0200 Subject: [PATCH 65/80] fix remaining PrimitiveStyleBuilder conversions --- Cargo.toml | 2 +- src/epd2in13_v2/graphics.rs | 30 +++++------------------------- src/epd2in9/mod.rs | 8 ++------ src/epd4in2/graphics.rs | 30 +++++------------------------- src/epd4in2/mod.rs | 8 ++------ src/graphics.rs | 25 +++++-------------------- src/lib.rs | 9 ++------- src/traits.rs | 11 +++-------- 8 files changed, 25 insertions(+), 98 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 05df967..d3c0a05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ edition = "2018" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics = { version = "0.7.0", optional = true} +embedded-graphics = { version = "0.7.1", optional = true} embedded-graphics-core = { version = "0.3.2", optional = true} embedded-hal = {version = "0.2.4", features = ["unproven"]} bit_field = "0.10.1" diff --git a/src/epd2in13_v2/graphics.rs b/src/epd2in13_v2/graphics.rs index 1f01982..0d04bf7 100644 --- a/src/epd2in13_v2/graphics.rs +++ b/src/epd2in13_v2/graphics.rs @@ -70,7 +70,7 @@ mod tests { use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::{ prelude::*, - primitives::{Line, PrimitiveStyleBuilder}, + primitives::{Line, PrimitiveStyle}, }; // test buffer length @@ -94,12 +94,7 @@ mod tests { let mut display = Display2in13::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -120,12 +115,7 @@ mod tests { Point::new(0, (WIDTH - 8) as i32), Point::new(0, (WIDTH - 1) as i32), ) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -146,12 +136,7 @@ mod tests { Point::new((WIDTH - 8) as i32, (HEIGHT - 1) as i32), Point::new((WIDTH - 1) as i32, (HEIGHT - 1) as i32), ) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -172,12 +157,7 @@ mod tests { Point::new((HEIGHT - 1) as i32, 0), Point::new((HEIGHT - 1) as i32, 7), ) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd2in9/mod.rs b/src/epd2in9/mod.rs index a139289..fc1ed54 100644 --- a/src/epd2in9/mod.rs +++ b/src/epd2in9/mod.rs @@ -7,7 +7,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; //!use epd_waveshare::{epd2in9::*, prelude::*}; //!# @@ -27,12 +27,8 @@ //!let mut display = Display2in9::default(); //! //!// Use embedded graphics for drawing a line -//!let style = PrimitiveStyleBuilder::new() -//! .stroke_color(Black) -//! .stroke_width(1) -//! .build(); //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(style) +//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) //! .draw(&mut display); //! //! // Display updated frame diff --git a/src/epd4in2/graphics.rs b/src/epd4in2/graphics.rs index d45c17d..cc98590 100644 --- a/src/epd4in2/graphics.rs +++ b/src/epd4in2/graphics.rs @@ -69,7 +69,7 @@ mod tests { use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::{ prelude::*, - primitives::{Line, PrimitiveStyleBuilder}, + primitives::{Line, PrimitiveStyle}, }; // test buffer length @@ -92,12 +92,7 @@ mod tests { fn graphics_rotation_0() { let mut display = Display4in2::default(); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -114,12 +109,7 @@ mod tests { let mut display = Display4in2::default(); display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 392), Point::new(0, 399)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -137,12 +127,7 @@ mod tests { display.set_rotation(DisplayRotation::Rotate180); let _ = Line::new(Point::new(392, 299), Point::new(399, 299)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -162,12 +147,7 @@ mod tests { let mut display = Display4in2::default(); display.set_rotation(DisplayRotation::Rotate270); let _ = Line::new(Point::new(299, 0), Point::new(299, 7)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 5570f5a..3ab7e6e 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -11,7 +11,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; //!use epd_waveshare::{epd4in2::*, prelude::*}; //!# @@ -31,12 +31,8 @@ //!let mut display = Display4in2::default(); //! //!// Use embedded graphics for drawing a line -//!let style = PrimitiveStyleBuilder::new() -//! .stroke_color(Black) -//! .stroke_width(1) -//! .build(); //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(style) +//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) //! .draw(&mut display); //! //! // Display updated frame diff --git a/src/graphics.rs b/src/graphics.rs index e347259..abdf88f 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -241,7 +241,7 @@ pub trait OctDisplay: DrawTarget { /// # use epd_waveshare::graphics::VarDisplay; /// # use epd_waveshare::color::Black; /// # use embedded_graphics::prelude::*; -/// # use embedded_graphics::primitives::{Circle, Line, PrimitiveStyleBuilder}; +/// # use embedded_graphics::primitives::{Circle, Line, PrimitiveStyle}; /// let width = 128; /// let height = 296; /// @@ -250,13 +250,8 @@ pub trait OctDisplay: DrawTarget { /// /// display.set_rotation(DisplayRotation::Rotate90); /// -///let style = PrimitiveStyleBuilder::new() -/// .stroke_color(Black) -/// .stroke_width(1) -/// .build(); -/// /// let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -/// .into_styled(style) +/// .into_styled(PrimitiveStyle::with_stroke(Black, 1)) /// .draw(&mut display); /// ``` pub struct VarDisplay<'a> { @@ -395,7 +390,7 @@ mod tests { use crate::color::Color; use embedded_graphics::{ prelude::*, - primitives::{Line, PrimitiveStyleBuilder}, + primitives::{Line, PrimitiveStyle}, }; #[test] @@ -453,12 +448,7 @@ mod tests { let mut display = VarDisplay::new(width, height, &mut buffer); let _ = Line::new(Point::new(0, 0), Point::new(7, 0)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); @@ -482,12 +472,7 @@ mod tests { display.set_rotation(DisplayRotation::Rotate90); let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) - .into_styled( - PrimitiveStyleBuilder::new() - .stroke_color(Black) - .stroke_width(1) - .build(), - ) + .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let buffer = display.buffer(); diff --git a/src/lib.rs b/src/lib.rs index 0e00d8d..a41c7d3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; //!use epd_waveshare::{epd1in54::*, prelude::*}; //!# @@ -35,13 +35,8 @@ //! //!// Use embedded graphics for drawing a line //! -//!let style = PrimitiveStyleBuilder::new() -//! .stroke_color(Black) -//! .stroke_width(1) -//! .build(); -//! //!let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -//! .into_styled(style) +//! .into_styled(PrimitiveStyle::with_stroke(Black, 1)) //! .draw(&mut display); //! //! // Display updated frame diff --git a/src/traits.rs b/src/traits.rs index 19ab914..a74c2a2 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -92,7 +92,7 @@ where ///# use embedded_hal_mock::*; ///# fn main() -> Result<(), MockError> { ///use embedded_graphics::{ -/// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, +/// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, ///}; ///use epd_waveshare::{epd4in2::*, prelude::*}; ///# @@ -113,13 +113,8 @@ where /// ///// Use embedded graphics for drawing a line /// -///let style = PrimitiveStyleBuilder::new() -/// .stroke_color(Black) -/// .stroke_width(1) -/// .build(); -/// ///let _ = Line::new(Point::new(0, 120), Point::new(0, 295)) -/// .into_styled(style) +/// .into_styled(PrimitiveStyle::with_stroke(Black, 1)) /// .draw(&mut display); /// /// // Display updated frame @@ -254,7 +249,7 @@ where ///# use embedded_hal_mock::*; ///# fn main() -> Result<(), MockError> { ///# use embedded_graphics::{ -///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyleBuilder}, +///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, ///# }; ///# use epd_waveshare::{epd4in2::*, prelude::*}; ///# use epd_waveshare::graphics::VarDisplay; From feac908558d275de01f43fc4931db869a4384f95 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 16 Jun 2021 16:48:00 +0200 Subject: [PATCH 66/80] fix example for epd 2.13" * use Circle::with_center * the large text does not fit on this screen, add newline --- examples/epd2in13bc.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 8110d79..6d8d8b8 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -104,7 +104,7 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(TriColor::White); // draw a analog clock - let _ = Circle::new(Point::new(64, 64), 40) + let _ = Circle::with_center(Point::new(64, 64), 80) .into_styled(PrimitiveStyle::with_stroke(TriColor::Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) @@ -132,7 +132,7 @@ fn main() -> Result<(), std::io::Error> { .background_color(TriColor::Chromatic) .build(); - let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 40), style, text_style) + let _ = Text::with_text_style("It's working\nWoB!", Point::new(90, 40), style, text_style) .draw(&mut display); // we used three colors, so we need to update both bw-buffer and chromatic-buffer From 6a10e0cb96cd64f1e7859773c8553423c6164261 Mon Sep 17 00:00:00 2001 From: Reinier Balt Date: Wed, 16 Jun 2021 17:36:12 +0200 Subject: [PATCH 67/80] Migrate remaining drivers --- examples/epd2in13_v2.rs | 4 ++-- examples/epd4in2.rs | 6 +++--- examples/epd4in2_variable_size.rs | 2 +- src/epd1in54/graphics.rs | 1 + src/epd1in54b/graphics.rs | 14 +++++++++++--- src/epd1in54c/graphics.rs | 14 +++++++++++--- src/epd2in7b/graphics.rs | 19 +++++++++++++++---- src/epd2in9/graphics.rs | 1 + src/epd2in9_v2/graphics.rs | 17 +++++++++++++---- src/epd2in9_v2/mod.rs | 2 +- src/epd2in9bc/graphics.rs | 17 +++++++++++++---- src/epd2in9bc/mod.rs | 2 +- src/epd5in65f/graphics.rs | 19 +++++++++++++++---- src/epd7in5/graphics.rs | 19 +++++++++++++++---- src/epd7in5_hd/graphics.rs | 19 +++++++++++++++---- src/epd7in5_v2/graphics.rs | 30 +++++++++++++++++++----------- src/lib.rs | 18 +++++++++--------- 17 files changed, 146 insertions(+), 58 deletions(-) diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index 5eab890..f245bae 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -89,7 +89,7 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); // draw a analog clock - let _ = Circle::new(Point::new(64, 64), 40) + let _ = Circle::with_center(Point::new(64, 64), 80) .into_styled(PrimitiveStyle::with_stroke(Black, 1)) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(30, 40)) @@ -117,7 +117,7 @@ fn main() -> Result<(), std::io::Error> { .background_color(Black) .build(); - let _ = Text::with_text_style("It's working-WoB!", Point::new(90, 40), style, text_style) + let _ = Text::with_text_style("It's working\nWoB!", Point::new(90, 40), style, text_style) .draw(&mut display); // Demonstrating how to use the partial refresh feature of the screen. diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 400ec83..08464b5 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -64,7 +64,7 @@ fn main() -> Result<(), std::io::Error> { let mut epd4in2 = Epd4in2::new(&mut spi, cs, busy, dc, rst, &mut delay).expect("eink initalize error"); - //println!("Test all the rotations"); + println!("Test all the rotations"); let mut display = Display4in2::default(); display.set_rotation(DisplayRotation::Rotate0); @@ -85,7 +85,7 @@ fn main() -> Result<(), std::io::Error> { .expect("display frame new graphics"); delay.delay_ms(5000u16); - //println!("Now test new graphics with default rotation and some special stuff:"); + println!("Now test new graphics with default rotation and some special stuff"); display.clear_buffer(Color::White); // draw a analog clock @@ -94,7 +94,7 @@ fn main() -> Result<(), std::io::Error> { .stroke_width(1) .build(); - let _ = Circle::new(Point::new(64, 64), 40) + 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)) diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index 6faf287..a388fcd 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -101,7 +101,7 @@ fn main() -> Result<(), std::io::Error> { .stroke_width(1) .build(); - let _ = Circle::new(Point::new(64, 64), 64) + let _ = Circle::with_center(Point::new(64, 64), 128) .into_styled(style) .draw(&mut display); let _ = Line::new(Point::new(64, 64), Point::new(0, 64)) diff --git a/src/epd1in54/graphics.rs b/src/epd1in54/graphics.rs index 644ae0f..8c4a9ec 100644 --- a/src/epd1in54/graphics.rs +++ b/src/epd1in54/graphics.rs @@ -25,6 +25,7 @@ impl Default for Display1in54 { impl DrawTarget for Display1in54 { type Color = BinaryColor; type Error = core::convert::Infallible; + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> where I: IntoIterator>, diff --git a/src/epd1in54b/graphics.rs b/src/epd1in54b/graphics.rs index 53aca36..9fca3ef 100644 --- a/src/epd1in54b/graphics.rs +++ b/src/epd1in54b/graphics.rs @@ -1,7 +1,7 @@ use crate::epd1in54b::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54 EPD /// @@ -25,10 +25,18 @@ impl DrawTarget for Display1in54b { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display1in54b { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs index 476793c..d08a7ff 100644 --- a/src/epd1in54c/graphics.rs +++ b/src/epd1in54c/graphics.rs @@ -1,7 +1,7 @@ use crate::epd1in54c::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54c EPD /// @@ -24,10 +24,18 @@ impl DrawTarget for Display1in54c { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display1in54c { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd2in7b/graphics.rs b/src/epd2in7b/graphics.rs index ca193cf..c460a9c 100644 --- a/src/epd2in7b/graphics.rs +++ b/src/epd2in7b/graphics.rs @@ -1,7 +1,7 @@ use crate::epd2in7b::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in7B EPD /// @@ -26,10 +26,18 @@ impl DrawTarget for Display2in7b { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display2in7b { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -61,7 +69,10 @@ mod tests { use crate::epd2in7b; use crate::epd2in7b::{HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyle}, + }; // test buffer length #[test] diff --git a/src/epd2in9/graphics.rs b/src/epd2in9/graphics.rs index 0e29253..5dba792 100644 --- a/src/epd2in9/graphics.rs +++ b/src/epd2in9/graphics.rs @@ -36,6 +36,7 @@ impl DrawTarget for Display2in9 { Ok(()) } } + impl OriginDimensions for Display2in9 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) diff --git a/src/epd2in9_v2/graphics.rs b/src/epd2in9_v2/graphics.rs index 9edf34f..6fc6308 100644 --- a/src/epd2in9_v2/graphics.rs +++ b/src/epd2in9_v2/graphics.rs @@ -1,6 +1,7 @@ use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::prelude::*; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::prelude::*; /// Display with Fullsize buffer for use with the 2in9 EPD V2 /// @@ -22,13 +23,21 @@ impl Default for Display2in9 { } impl DrawTarget for Display2in9 { - type Color = BinaryColor + type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display2in9 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 354cc32..1c94e46 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -8,7 +8,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; //!use epd_waveshare::{epd2in9_v2::*, prelude::*}; //!# diff --git a/src/epd2in9bc/graphics.rs b/src/epd2in9bc/graphics.rs index ed021b7..1044aee 100644 --- a/src/epd2in9bc/graphics.rs +++ b/src/epd2in9bc/graphics.rs @@ -1,6 +1,7 @@ use crate::epd2in9bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::prelude::*; +use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in9b/c EPD /// @@ -20,13 +21,21 @@ impl Default for Display2in9bc { } impl DrawTarget for Display2in9bc { - type Color = BinaryColor + type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display2in9bc { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index 37280f3..d76ce8e 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -6,7 +6,7 @@ //!# use embedded_hal_mock::*; //!# fn main() -> Result<(), MockError> { //!use embedded_graphics::{ -//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::Line, style::PrimitiveStyle, +//! pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle}, //!}; //!use epd_waveshare::{epd2in9bc::*, prelude::*}; //!# diff --git a/src/epd5in65f/graphics.rs b/src/epd5in65f/graphics.rs index 0287d38..d58cd31 100644 --- a/src/epd5in65f/graphics.rs +++ b/src/epd5in65f/graphics.rs @@ -1,7 +1,7 @@ use crate::color::OctColor; use crate::epd5in65f::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{DisplayRotation, OctDisplay}; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 5in65f EPD /// @@ -26,10 +26,18 @@ impl DrawTarget for Display5in65f { type Color = OctColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display5in65f { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -58,7 +66,10 @@ mod tests { use super::*; use crate::epd5in65f; use crate::graphics::{DisplayRotation, OctDisplay}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyle}, + }; // test buffer length #[test] diff --git a/src/epd7in5/graphics.rs b/src/epd7in5/graphics.rs index 82bf712..4c7896e 100644 --- a/src/epd7in5/graphics.rs +++ b/src/epd7in5/graphics.rs @@ -1,7 +1,7 @@ use crate::epd7in5::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD /// @@ -26,10 +26,18 @@ impl DrawTarget for Display7in5 { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display7in5 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -60,7 +68,10 @@ mod tests { use crate::color::Color; use crate::epd7in5; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyle}, + }; // test buffer length #[test] diff --git a/src/epd7in5_hd/graphics.rs b/src/epd7in5_hd/graphics.rs index 0497009..1b13ec2 100644 --- a/src/epd7in5_hd/graphics.rs +++ b/src/epd7in5_hd/graphics.rs @@ -1,7 +1,7 @@ use crate::epd7in5_hd::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD /// @@ -26,10 +26,18 @@ impl DrawTarget for Display7in5 { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) } +} +impl OriginDimensions for Display7in5 { fn size(&self) -> Size { Size::new(WIDTH, HEIGHT) } @@ -59,7 +67,10 @@ mod tests { use crate::color::{Black, Color}; use crate::epd7in5_hd; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyle}, + }; // test buffer length #[test] diff --git a/src/epd7in5_v2/graphics.rs b/src/epd7in5_v2/graphics.rs index e9a6ad5..4cc905f 100644 --- a/src/epd7in5_v2/graphics.rs +++ b/src/epd7in5_v2/graphics.rs @@ -1,8 +1,7 @@ use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::pixelcolor::BinaryColor; -use embedded_graphics::prelude::*; -use embedded_graphics_core::OriginDimension; +use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD /// @@ -27,8 +26,20 @@ impl DrawTarget for Display7in5 { type Color = BinaryColor; type Error = core::convert::Infallible; - fn draw_pixel(&mut self, pixel: Pixel) -> Result<(), Self::Error> { - self.draw_helper(WIDTH, HEIGHT, pixel) + fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> + where + I: IntoIterator>, + { + for pixel in pixels { + self.draw_helper(WIDTH, HEIGHT, pixel)?; + } + Ok(()) + } +} + +impl OriginDimensions for Display7in5 { + fn size(&self) -> Size { + Size::new(WIDTH, HEIGHT) } } @@ -50,19 +61,16 @@ impl Display for Display7in5 { } } -impl OriginDimension for Display7in5 { - fn size(&self) -> Size { - Size::new(WIDTH, HEIGHT) - } -} - #[cfg(test)] mod tests { use super::*; use crate::color::{Black, Color}; use crate::epd7in5_v2; use crate::graphics::{Display, DisplayRotation}; - use embedded_graphics::{primitives::Line, style::PrimitiveStyle}; + use embedded_graphics::{ + prelude::*, + primitives::{Line, PrimitiveStyle}, + }; // test buffer length #[test] diff --git a/src/lib.rs b/src/lib.rs index a41c7d3..0319c0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,19 +74,19 @@ pub mod color; mod interface; pub mod epd1in54; -//pub mod epd1in54b; -//pub mod epd1in54c; +pub mod epd1in54b; +pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in13bc; -//pub mod epd2in7b; +pub mod epd2in7b; pub mod epd2in9; -//pub mod epd2in9_v2; -//pub mod epd2in9bc; +pub mod epd2in9_v2; +pub mod epd2in9bc; pub mod epd4in2; -//pub mod epd5in65f; -//pub mod epd7in5; -//pub mod epd7in5_hd; -//pub mod epd7in5_v2; +pub mod epd5in65f; +pub mod epd7in5; +pub mod epd7in5_hd; +pub mod epd7in5_v2; pub(crate) mod type_a; From 3edeac413dc6e1621de9e32f26b60df6a00e8cd8 Mon Sep 17 00:00:00 2001 From: Christian Meusel Date: Wed, 14 Jul 2021 23:06:29 +0200 Subject: [PATCH 68/80] Provide full QuickRefresh interface for 4in2 too This display needs no special commands for displaying the new frame. But it will come in handy to support the full QuickRefresh trait when it comes to supporting different quick refresh capable displays from an application. --- src/epd4in2/mod.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 3ab7e6e..9560206 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -482,21 +482,24 @@ where Ok(()) } - /// This function is not needed for this display - #[allow(unused)] + /// This is wrapper around `display_frame` for using this device as a true + /// `QuickRefresh` device. fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { - unimplemented!() + self.display_frame(spi, delay) } - /// This function is not needed for this display - #[allow(unused)] + /// This is wrapper around `update_new_frame` and `display_frame` for using + /// this device as a true `QuickRefresh` device. + /// + /// To be used immediately after `update_old_frame`. fn update_and_display_new_frame( &mut self, spi: &mut SPI, buffer: &[u8], delay: &mut DELAY, ) -> Result<(), SPI::Error> { - unimplemented!() + self.update_new_frame(spi, buffer, delay)?; + self.display_frame(spi, delay) } fn update_partial_old_frame( From 1a09b81ab6ba6b54afd977d082b9810434c9a59f Mon Sep 17 00:00:00 2001 From: Christian Meusel Date: Wed, 14 Jul 2021 23:19:28 +0200 Subject: [PATCH 69/80] Clean up some warnings from 'cargo doc' --- src/epd2in13bc/mod.rs | 2 +- src/epd2in9_v2/mod.rs | 2 +- src/lib.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index ef5a044..12d6972 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -1,5 +1,5 @@ //! A simple Driver for the Waveshare 2.13" (B/C) E-Ink Display via SPI -//! More information on this display can be found at the [Waveshare Wiki]:(https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B)) +//! More information on this display can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/2.13inch_e-Paper_HAT_(B)) //! This driver was build and tested for 212x104, 2.13inch E-Ink display HAT for Raspberry Pi, three-color, SPI interface //! //! # Example for the 2.13" E-Ink Display diff --git a/src/epd2in9_v2/mod.rs b/src/epd2in9_v2/mod.rs index 1c94e46..5158627 100644 --- a/src/epd2in9_v2/mod.rs +++ b/src/epd2in9_v2/mod.rs @@ -1,6 +1,6 @@ //! A simple Driver for the Waveshare 2.9" E-Ink Display V2 via SPI //! -//! Specification: https://www.waveshare.com/w/upload/7/79/2.9inch-e-paper-v2-specification.pdf +//! Specification: //! //! # Example for the 2.9 in E-Ink Display V2 //! diff --git a/src/lib.rs b/src/lib.rs index 0319c0e..2fe9c5f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -109,9 +109,9 @@ pub mod prelude { /// unused /// bits width /// <----><------------------------> -/// [XXXXX210][76543210]...[76543210] ^ -/// [XXXXX210][76543210]...[76543210] | height -/// [XXXXX210][76543210]...[76543210] v +/// \[XXXXX210\]\[76543210\]...\[76543210\] ^ +/// \[XXXXX210\]\[76543210\]...\[76543210\] | height +/// \[XXXXX210\]\[76543210\]...\[76543210\] v pub const fn buffer_len(width: usize, height: usize) -> usize { (width + 7) / 8 * height } From b84531977152e17e37cc09f0f9e263552c1c1cd2 Mon Sep 17 00:00:00 2001 From: Chris <11088935+caemor@users.noreply.github.com> Date: Thu, 15 Jul 2021 07:54:13 +0200 Subject: [PATCH 70/80] Update src/epd4in2/mod.rs --- src/epd4in2/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd4in2/mod.rs b/src/epd4in2/mod.rs index 9560206..900d20d 100644 --- a/src/epd4in2/mod.rs +++ b/src/epd4in2/mod.rs @@ -482,7 +482,7 @@ where Ok(()) } - /// This is wrapper around `display_frame` for using this device as a true + /// This is a wrapper around `display_frame` for using this device as a true /// `QuickRefresh` device. fn display_new_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { self.display_frame(spi, delay) From 247a78acb7c7455afedb196b54162d1b04da5af1 Mon Sep 17 00:00:00 2001 From: Kaleb Elwert Date: Fri, 13 Aug 2021 01:14:07 +0100 Subject: [PATCH 71/80] Write data over SPI 1 byte at a time Fixes #82 --- src/interface.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index ef011d3..76993f0 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -57,11 +57,15 @@ where /// /// Enables direct interaction with the device with the help of [command()](Epd4in2::command()) pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - // high for data - let _ = self.dc.set_high(); + for val in data.iter().copied() { + // high for data + let _ = self.dc.set_high(); - // Transfer data (u8-array) over spi - self.write(spi, data) + // Transfer data one u8 at a time over spi + self.write(spi, &[val])?; + } + + Ok(()) } /// Basic function for sending [Commands](Command) and the data belonging to it. @@ -86,11 +90,9 @@ where val: u8, repetitions: u32, ) -> Result<(), SPI::Error> { - // high for data - let _ = self.dc.set_high(); // Transfer data (u8) over spi for _ in 0..repetitions { - self.write(spi, &[val])?; + self.data(spi, &[val])?; } Ok(()) } From f3e7dad83d1540204483d1751c632aa8643cf419 Mon Sep 17 00:00:00 2001 From: Kaleb Elwert Date: Fri, 13 Aug 2021 07:54:04 +0100 Subject: [PATCH 72/80] Address PR feedback --- src/interface.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/interface.rs b/src/interface.rs index 76993f0..c977db4 100644 --- a/src/interface.rs +++ b/src/interface.rs @@ -57,10 +57,10 @@ where /// /// Enables direct interaction with the device with the help of [command()](Epd4in2::command()) pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> { - for val in data.iter().copied() { - // high for data - let _ = self.dc.set_high(); + // 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])?; } @@ -90,9 +90,11 @@ where val: u8, repetitions: u32, ) -> Result<(), SPI::Error> { + // high for data + let _ = self.dc.set_high(); // Transfer data (u8) over spi for _ in 0..repetitions { - self.data(spi, &[val])?; + self.write(spi, &[val])?; } Ok(()) } From a92eac02a4f870b11e92ba5c166fa7c8ae15ec6f Mon Sep 17 00:00:00 2001 From: James Waples Date: Fri, 20 Aug 2021 18:10:59 +0100 Subject: [PATCH 73/80] Make embedded-graphics a dev dependency e-g-core should be the only e-g dependency required for the driver itself, so this PR changes a few of the imports to reflect that. --- Cargo.toml | 4 ++-- src/color.rs | 4 ++-- src/epd1in54/graphics.rs | 2 +- src/epd1in54b/graphics.rs | 2 +- src/epd1in54c/graphics.rs | 2 +- src/epd2in13_v2/graphics.rs | 2 +- src/epd2in7b/graphics.rs | 2 +- src/epd2in9/graphics.rs | 2 +- src/epd2in9_v2/graphics.rs | 2 +- src/epd2in9bc/graphics.rs | 2 +- src/epd4in2/graphics.rs | 2 +- src/epd7in5/graphics.rs | 2 +- src/epd7in5_hd/graphics.rs | 2 +- src/epd7in5_v2/graphics.rs | 2 +- src/graphics.rs | 2 +- 15 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d3c0a05..5b9ea43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,19 +16,19 @@ edition = "2018" # travis-ci = { repository = "caemor/epd-waveshare" } [dependencies] -embedded-graphics = { version = "0.7.1", optional = true} embedded-graphics-core = { version = "0.3.2", optional = true} embedded-hal = {version = "0.2.4", features = ["unproven"]} bit_field = "0.10.1" [dev-dependencies] +embedded-graphics = "0.7.1" linux-embedded-hal = "0.3" embedded-hal-mock = "0.7" [features] default = ["graphics"] -graphics = ["embedded-graphics","embedded-graphics-core"] +graphics = ["embedded-graphics-core"] # Offers an alternative fast full lut for type_a displays, but the refreshed screen isnt as clean looking type_a_alternative_faster_lut = [] diff --git a/src/color.rs b/src/color.rs index 8867978..bff5739 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,9 +1,9 @@ //! B/W Color for EPDs #[cfg(feature = "graphics")] -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; #[cfg(feature = "graphics")] -use embedded_graphics::pixelcolor::PixelColor; +use embedded_graphics_core::pixelcolor::PixelColor; #[cfg(feature = "graphics")] pub use BinaryColor::Off as White; diff --git a/src/epd1in54/graphics.rs b/src/epd1in54/graphics.rs index 8c4a9ec..ec9a59d 100644 --- a/src/epd1in54/graphics.rs +++ b/src/epd1in54/graphics.rs @@ -1,6 +1,6 @@ use crate::epd1in54::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54 EPD diff --git a/src/epd1in54b/graphics.rs b/src/epd1in54b/graphics.rs index 9fca3ef..7a64472 100644 --- a/src/epd1in54b/graphics.rs +++ b/src/epd1in54b/graphics.rs @@ -1,6 +1,6 @@ use crate::epd1in54b::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54 EPD diff --git a/src/epd1in54c/graphics.rs b/src/epd1in54c/graphics.rs index d08a7ff..028d4fe 100644 --- a/src/epd1in54c/graphics.rs +++ b/src/epd1in54c/graphics.rs @@ -1,6 +1,6 @@ use crate::epd1in54c::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 1in54c EPD diff --git a/src/epd2in13_v2/graphics.rs b/src/epd2in13_v2/graphics.rs index 0d04bf7..0bb1e78 100644 --- a/src/epd2in13_v2/graphics.rs +++ b/src/epd2in13_v2/graphics.rs @@ -1,7 +1,7 @@ use crate::buffer_len; use crate::epd2in13_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in13 v2 EPD diff --git a/src/epd2in7b/graphics.rs b/src/epd2in7b/graphics.rs index c460a9c..e344be7 100644 --- a/src/epd2in7b/graphics.rs +++ b/src/epd2in7b/graphics.rs @@ -1,6 +1,6 @@ use crate::epd2in7b::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in7B EPD diff --git a/src/epd2in9/graphics.rs b/src/epd2in9/graphics.rs index 5dba792..8678c9c 100644 --- a/src/epd2in9/graphics.rs +++ b/src/epd2in9/graphics.rs @@ -1,6 +1,6 @@ use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Display with Fullsize buffer for use with the 2in9 EPD diff --git a/src/epd2in9_v2/graphics.rs b/src/epd2in9_v2/graphics.rs index 6fc6308..e121adb 100644 --- a/src/epd2in9_v2/graphics.rs +++ b/src/epd2in9_v2/graphics.rs @@ -1,6 +1,6 @@ use crate::epd2in9::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Display with Fullsize buffer for use with the 2in9 EPD V2 diff --git a/src/epd2in9bc/graphics.rs b/src/epd2in9bc/graphics.rs index 1044aee..dd8ce9d 100644 --- a/src/epd2in9bc/graphics.rs +++ b/src/epd2in9bc/graphics.rs @@ -1,6 +1,6 @@ use crate::epd2in9bc::{DEFAULT_BACKGROUND_COLOR, HEIGHT, NUM_DISPLAY_BITS, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 2in9b/c EPD diff --git a/src/epd4in2/graphics.rs b/src/epd4in2/graphics.rs index cc98590..739efb8 100644 --- a/src/epd4in2/graphics.rs +++ b/src/epd4in2/graphics.rs @@ -1,6 +1,6 @@ use crate::epd4in2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 4in2 EPD diff --git a/src/epd7in5/graphics.rs b/src/epd7in5/graphics.rs index 4c7896e..e087cdc 100644 --- a/src/epd7in5/graphics.rs +++ b/src/epd7in5/graphics.rs @@ -1,6 +1,6 @@ use crate::epd7in5::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD diff --git a/src/epd7in5_hd/graphics.rs b/src/epd7in5_hd/graphics.rs index 1b13ec2..c731b1b 100644 --- a/src/epd7in5_hd/graphics.rs +++ b/src/epd7in5_hd/graphics.rs @@ -1,6 +1,6 @@ use crate::epd7in5_hd::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD diff --git a/src/epd7in5_v2/graphics.rs b/src/epd7in5_v2/graphics.rs index 4cc905f..6550064 100644 --- a/src/epd7in5_v2/graphics.rs +++ b/src/epd7in5_v2/graphics.rs @@ -1,6 +1,6 @@ use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Full size buffer for use with the 7in5 EPD diff --git a/src/graphics.rs b/src/graphics.rs index abdf88f..b898080 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -2,7 +2,7 @@ use crate::buffer_len; use crate::color::{Color, OctColor, TriColor}; -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; /// Displayrotation From 493cbd93942b7cc5aa73a6a867e20ad4937b4781 Mon Sep 17 00:00:00 2001 From: Chris <11088935+caemor@users.noreply.github.com> Date: Sat, 21 Aug 2021 11:23:00 +0200 Subject: [PATCH 74/80] Fix clippy warning (#86) * Fix clippy improvements warnings --- examples/epd2in13_v2.rs | 8 ++++---- examples/epd2in13bc.rs | 2 +- examples/epd4in2.rs | 4 ++-- examples/epd4in2_variable_size.rs | 4 ++-- src/epd2in13bc/mod.rs | 2 +- src/epd2in9bc/mod.rs | 2 +- src/graphics.rs | 2 +- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/examples/epd2in13_v2.rs b/examples/epd2in13_v2.rs index f245bae..be1b314 100644 --- a/examples/epd2in13_v2.rs +++ b/examples/epd2in13_v2.rs @@ -79,7 +79,7 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd2in13.update_frame(&mut spi, &display.buffer(), &mut delay)?; + epd2in13.update_frame(&mut spi, display.buffer(), &mut delay)?; epd2in13 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); @@ -133,7 +133,7 @@ fn main() -> Result<(), std::io::Error> { draw_text(&mut display, " Hello World! ", 5 + i * 12, 50); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + .update_and_display_frame(&mut spi, display.buffer(), &mut delay) .expect("display frame new graphics"); delay.delay_ms(1_000u16); } @@ -142,7 +142,7 @@ fn main() -> Result<(), std::io::Error> { // the screen can refresh for this kind of change (small single character) display.clear_buffer(Color::White); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + .update_and_display_frame(&mut spi, display.buffer(), &mut delay) .unwrap(); let spinner = ["|", "/", "-", "\\"]; @@ -150,7 +150,7 @@ fn main() -> Result<(), std::io::Error> { display.clear_buffer(Color::White); draw_text(&mut display, spinner[i % spinner.len()], 10, 100); epd2in13 - .update_and_display_frame(&mut spi, &display.buffer(), &mut delay) + .update_and_display_frame(&mut spi, display.buffer(), &mut delay) .unwrap(); } diff --git a/examples/epd2in13bc.rs b/examples/epd2in13bc.rs index 6d8d8b8..ba45aab 100644 --- a/examples/epd2in13bc.rs +++ b/examples/epd2in13bc.rs @@ -94,7 +94,7 @@ fn main() -> Result<(), std::io::Error> { // the bw-buffer of this tri-color screen epd2in13 - .update_and_display_frame(&mut spi, &display.bw_buffer(), &mut delay) + .update_and_display_frame(&mut spi, display.bw_buffer(), &mut delay) .expect("display frame new graphics"); println!("First frame done. Waiting 5s"); diff --git a/examples/epd4in2.rs b/examples/epd4in2.rs index 08464b5..729e03c 100644 --- a/examples/epd4in2.rs +++ b/examples/epd4in2.rs @@ -79,7 +79,7 @@ fn main() -> Result<(), std::io::Error> { display.set_rotation(DisplayRotation::Rotate270); draw_text(&mut display, "Rotate 270!", 5, 50); - epd4in2.update_frame(&mut spi, &display.buffer(), &mut delay)?; + epd4in2.update_frame(&mut spi, display.buffer(), &mut delay)?; epd4in2 .display_frame(&mut spi, &mut delay) .expect("display frame new graphics"); @@ -135,7 +135,7 @@ fn main() -> Result<(), std::io::Error> { draw_text(&mut display, " Hello World! ", 5 + i * 12, 50); epd4in2 - .update_frame(&mut spi, &display.buffer(), &mut delay) + .update_frame(&mut spi, display.buffer(), &mut delay) .unwrap(); epd4in2 .display_frame(&mut spi, &mut delay) diff --git a/examples/epd4in2_variable_size.rs b/examples/epd4in2_variable_size.rs index a388fcd..95a39ff 100644 --- a/examples/epd4in2_variable_size.rs +++ b/examples/epd4in2_variable_size.rs @@ -84,7 +84,7 @@ fn main() -> Result<(), std::io::Error> { draw_text(&mut display, "Rotate 270!", 5, 50); epd4in2 - .update_partial_frame(&mut spi, &display.buffer(), x, y, width, height) + .update_partial_frame(&mut spi, display.buffer(), x, y, width, height) .unwrap(); epd4in2 .display_frame(&mut spi, &mut delay) @@ -140,7 +140,7 @@ fn main() -> Result<(), std::io::Error> { draw_text(&mut display, " Hello World! ", 5 + i * 12, 50); epd4in2 - .update_partial_frame(&mut spi, &display.buffer(), x, y, width, height) + .update_partial_frame(&mut spi, display.buffer(), x, y, width, height) .unwrap(); epd4in2 .display_frame(&mut spi, &mut delay) diff --git a/src/epd2in13bc/mod.rs b/src/epd2in13bc/mod.rs index 12d6972..6c20117 100644 --- a/src/epd2in13bc/mod.rs +++ b/src/epd2in13bc/mod.rs @@ -255,7 +255,7 @@ where ) -> Result<(), SPI::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, &buffer)?; + self.interface.data(spi, buffer)?; // Clear the chromatic layer let color = self.color.get_byte_value(); diff --git a/src/epd2in9bc/mod.rs b/src/epd2in9bc/mod.rs index d76ce8e..783fab6 100644 --- a/src/epd2in9bc/mod.rs +++ b/src/epd2in9bc/mod.rs @@ -258,7 +258,7 @@ where ) -> Result<(), SPI::Error> { self.interface.cmd(spi, Command::DataStartTransmission1)?; - self.interface.data(spi, &buffer)?; + self.interface.data(spi, buffer)?; // Clear the chromatic layer let color = self.color.get_byte_value(); diff --git a/src/graphics.rs b/src/graphics.rs index abdf88f..1fbb5a4 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -300,7 +300,7 @@ impl<'a> OriginDimensions for VarDisplay<'a> { impl<'a> Display for VarDisplay<'a> { fn buffer(&self) -> &[u8] { - &self.buffer + self.buffer } fn get_mut_buffer(&mut self) -> &mut [u8] { From b8ba9fea93437c9d6a917a4d2d6bfded0ceb46f5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 21 Aug 2021 11:29:29 +0200 Subject: [PATCH 75/80] Update embedded-hal-mock requirement from 0.7 to 0.8 (#84) Updates the requirements on [embedded-hal-mock](https://github.com/dbrgn/embedded-hal-mock) to permit the latest version. - [Release notes](https://github.com/dbrgn/embedded-hal-mock/releases) - [Changelog](https://github.com/dbrgn/embedded-hal-mock/blob/master/CHANGELOG.md) - [Commits](https://github.com/dbrgn/embedded-hal-mock/compare/v0.7.0...v0.8.0) --- updated-dependencies: - dependency-name: embedded-hal-mock dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index d3c0a05..2c6352a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ bit_field = "0.10.1" [dev-dependencies] linux-embedded-hal = "0.3" -embedded-hal-mock = "0.7" +embedded-hal-mock = "0.8" [features] default = ["graphics"] From 875cc0dae3a27e90d10b57d0752c83d258d64466 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Mon, 23 Aug 2021 22:31:15 -0700 Subject: [PATCH 76/80] Update color options, format --- src/color.rs | 63 +++++++++++++++++++++++++++++++++++++++++++- src/epd5in65f/mod.rs | 12 +++++++-- 2 files changed, 72 insertions(+), 3 deletions(-) diff --git a/src/color.rs b/src/color.rs index 8867978..909bb10 100644 --- a/src/color.rs +++ b/src/color.rs @@ -72,9 +72,70 @@ impl From<()> for OctColor { } } +#[cfg(feature = "graphics")] +impl From for OctColor { + fn from(b: BinaryColor) -> OctColor { + match b { + BinaryColor::On => OctColor::Black, + BinaryColor::Off => OctColor::White, + } + } +} + +#[cfg(feature = "graphics")] +impl From for embedded_graphics::pixelcolor::Rgb888 { + fn from(b: OctColor) -> Self { + let (r, b, g) = b.rgb(); + Self::new(r, b, g) + } +} + +#[cfg(feature = "graphics")] +impl From for OctColor { + fn from(p: embedded_graphics::pixelcolor::Rgb888) -> OctColor { + use embedded_graphics::prelude::RgbColor; + let colors = [ + OctColor::Black, + OctColor::White, + OctColor::Green, + OctColor::Blue, + OctColor::Red, + OctColor::Yellow, + OctColor::Orange, + OctColor::HiZ, + ]; + // if the user has already mapped to the right color space, it will just be in the list + if let Some(found) = colors.iter().find(|c| c.rgb() == (p.r(), p.g(), p.b())) { + return *found; + } + + // This is not ideal but just pick the nearest color + *colors + .iter() + .map(|c| (c, c.rgb())) + .map(|(c, (r, g, b))| { + let dist = ((r - p.r()) as u32).pow(2) + + ((g - p.g()) as u32).pow(2) + + ((b - p.b()) as u32).pow(2); + (c, dist) + }) + .min_by_key(|(_c, dist)| *dist) + .map(|(c, _)| c) + .unwrap_or(&OctColor::White) + } +} + +#[cfg(feature = "graphics")] +impl From for OctColor { + fn from(b: embedded_graphics::pixelcolor::raw::RawU4) -> Self { + use embedded_graphics::prelude::RawData; + OctColor::from_nibble(b.into_inner()).unwrap() + } +} + #[cfg(feature = "graphics")] impl PixelColor for OctColor { - type Raw = (); + type Raw = embedded_graphics::pixelcolor::raw::RawU4; } impl OctColor { diff --git a/src/epd5in65f/mod.rs b/src/epd5in65f/mod.rs index 869fe2a..3199e38 100644 --- a/src/epd5in65f/mod.rs +++ b/src/epd5in65f/mod.rs @@ -60,7 +60,7 @@ where self.cmd_with_data(spi, Command::BoosterSoftStart, &[0xC7, 0xC7, 0x1D])?; self.cmd_with_data(spi, Command::PllControl, &[0x3C])?; self.cmd_with_data(spi, Command::TemperatureSensor, &[0x00])?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; + self.update_vcom(spi)?; self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; self.send_resolution(spi)?; @@ -68,7 +68,7 @@ where delay.delay_ms(100); - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x37])?; + self.update_vcom(spi)?; Ok(()) } } @@ -118,6 +118,7 @@ where _delay: &mut DELAY, ) -> Result<(), SPI::Error> { self.wait_busy_high(); + self.update_vcom(spi)?; self.send_resolution(spi)?; self.cmd_with_data(spi, Command::DataStartTransmission1, buffer)?; Ok(()) @@ -160,6 +161,7 @@ where fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { let bg = OctColor::colors_byte(self.color, self.color); self.wait_busy_high(); + self.update_vcom(spi)?; self.send_resolution(spi)?; self.command(spi, Command::DataStartTransmission1)?; self.interface.data_x_times(spi, bg, WIDTH * HEIGHT / 2)?; @@ -238,6 +240,12 @@ where self.send_data(spi, &[(h >> 8) as u8])?; self.send_data(spi, &[h as u8]) } + + fn update_vcom(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { + let bg_color = (self.color.get_nibble() & 0b111) << 5; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x17 | bg_color])?; + Ok(()) + } } #[cfg(test)] From e89c51cb84176a495ffe3b7e30474e675f55fc51 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Tue, 24 Aug 2021 10:37:47 -0700 Subject: [PATCH 77/80] Switch to embedded graphics core --- src/color.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/color.rs b/src/color.rs index 909bb10..ed99ff5 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,9 +1,9 @@ //! B/W Color for EPDs #[cfg(feature = "graphics")] -use embedded_graphics::pixelcolor::BinaryColor; +use embedded_graphics_core::pixelcolor::BinaryColor; #[cfg(feature = "graphics")] -use embedded_graphics::pixelcolor::PixelColor; +use embedded_graphics_core::pixelcolor::PixelColor; #[cfg(feature = "graphics")] pub use BinaryColor::Off as White; @@ -83,7 +83,7 @@ impl From for OctColor { } #[cfg(feature = "graphics")] -impl From for embedded_graphics::pixelcolor::Rgb888 { +impl From for embedded_graphics_core::pixelcolor::Rgb888 { fn from(b: OctColor) -> Self { let (r, b, g) = b.rgb(); Self::new(r, b, g) @@ -91,9 +91,9 @@ impl From for embedded_graphics::pixelcolor::Rgb888 { } #[cfg(feature = "graphics")] -impl From for OctColor { - fn from(p: embedded_graphics::pixelcolor::Rgb888) -> OctColor { - use embedded_graphics::prelude::RgbColor; +impl From for OctColor { + fn from(p: embedded_graphics_core::pixelcolor::Rgb888) -> OctColor { + use embedded_graphics_core::prelude::RgbColor; let colors = [ OctColor::Black, OctColor::White, @@ -126,16 +126,16 @@ impl From for OctColor { } #[cfg(feature = "graphics")] -impl From for OctColor { - fn from(b: embedded_graphics::pixelcolor::raw::RawU4) -> Self { - use embedded_graphics::prelude::RawData; +impl From for OctColor { + fn from(b: embedded_graphics_core::pixelcolor::raw::RawU4) -> Self { + use embedded_graphics_core::prelude::RawData; OctColor::from_nibble(b.into_inner()).unwrap() } } #[cfg(feature = "graphics")] impl PixelColor for OctColor { - type Raw = embedded_graphics::pixelcolor::raw::RawU4; + type Raw = embedded_graphics_core::pixelcolor::raw::RawU4; } impl OctColor { From 965989638a9525bf75b99567187ec24638ad5806 Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Tue, 24 Aug 2021 10:48:43 -0700 Subject: [PATCH 78/80] Convert to signed types before subtraction --- src/color.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/color.rs b/src/color.rs index ed99ff5..e5d412c 100644 --- a/src/color.rs +++ b/src/color.rs @@ -114,9 +114,9 @@ impl From for OctColor { .iter() .map(|c| (c, c.rgb())) .map(|(c, (r, g, b))| { - let dist = ((r - p.r()) as u32).pow(2) - + ((g - p.g()) as u32).pow(2) - + ((b - p.b()) as u32).pow(2); + let dist = (i32::from(r) - i32::from(p.r())).pow(2) + + (i32::from(g) - i32::from(p.g())).pow(2) + + (i32::from(b) - i32::from(p.b())).pow(2); (c, dist) }) .min_by_key(|(_c, dist)| *dist) From f6f8f3d1f5fcffa808e1b8d258cd28e2fcf4368c Mon Sep 17 00:00:00 2001 From: Mitch Souders Date: Tue, 24 Aug 2021 11:56:42 -0700 Subject: [PATCH 79/80] Transposed color channels --- src/color.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/color.rs b/src/color.rs index e5d412c..b9bd27a 100644 --- a/src/color.rs +++ b/src/color.rs @@ -85,8 +85,8 @@ impl From for OctColor { #[cfg(feature = "graphics")] impl From for embedded_graphics_core::pixelcolor::Rgb888 { fn from(b: OctColor) -> Self { - let (r, b, g) = b.rgb(); - Self::new(r, b, g) + let (r, g, b) = b.rgb(); + Self::new(r, g, b) } } From bf810dc1dc3deb10aaa37193adb05866f0bde431 Mon Sep 17 00:00:00 2001 From: Caemor <11088935+caemor@users.noreply.github.com> Date: Sun, 28 Nov 2021 23:20:43 +0100 Subject: [PATCH 80/80] Update Changelog for 0.5 --- CHANGELOG.md | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 423beb5..e9745f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,24 +8,35 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added + +### Changed + +### Fixed + +## [v0.5.0] - 2021-11-28 + +### Added + - Added QuickRefresh Trait and implemented it for EPD4in2 in #62 (thanks to @David-OConnor) - Added Epd 2in7 (B) support in #60 (thanks to @pjsier) - Added Epd 7in5 HD support (thanks to @whiite) - Added Epd 2in9 V2 support in #73 & #74 (thanks to @andber1) +- Added Epd 2in13 (BC) support in #75 (thanks to @Irbalt) +- 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) - Use specific ParseColorError instead of () - Epd4in2: Don't set the resolution (and some more) over and over again (#48) - Removed `#[allow(non_camel_case_types)]` to fix various issues around it - Added Delay to QuickRefresh Trait due to #74 (thanks to @andber1) +- 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.5.0] - -TODO! - ## [v0.4.0] - 2020-04-06 ### Added