From a234f051327869bc07c3edd0b6019e9e7e4a3bcd Mon Sep 17 00:00:00 2001 From: Andrew Thomas Date: Thu, 19 May 2022 17:53:32 -0500 Subject: [PATCH] Update 7in5 V3 implementation --- src/epd7in5_v2/graphics.rs | 42 ++--------- src/epd7in5_v2/mod.rs | 95 ++++-------------------- src/epd7in5_v3/command.rs | 59 +++++++++------ src/epd7in5_v3/graphics.rs | 57 ++++++++++---- src/epd7in5_v3/mod.rs | 148 ++++++++++++++----------------------- 5 files changed, 152 insertions(+), 249 deletions(-) diff --git a/src/epd7in5_v2/graphics.rs b/src/epd7in5_v2/graphics.rs index a2ed76a7..65500647 100644 --- a/src/epd7in5_v2/graphics.rs +++ b/src/epd7in5_v2/graphics.rs @@ -1,6 +1,5 @@ -use crate::color::TriColor; -use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH, NUM_DISPLAY_BITS}; -use crate::graphics::{TriDisplay, DisplayRotation}; +use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; +use crate::graphics::{Display, DisplayRotation}; use embedded_graphics_core::pixelcolor::BinaryColor; use embedded_graphics_core::prelude::*; @@ -9,7 +8,7 @@ use embedded_graphics_core::prelude::*; /// Can also be manually constructed: /// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); WIDTH / 8 * HEIGHT]` pub struct Display7in5 { - buffer: [u8; 2 * NUM_DISPLAY_BITS as usize], + buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], rotation: DisplayRotation, } @@ -17,14 +16,14 @@ impl Default for Display7in5 { fn default() -> Self { Display7in5 { buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); - 2 * NUM_DISPLAY_BITS as usize], + WIDTH as usize * HEIGHT as usize / 8], rotation: DisplayRotation::default(), } } } impl DrawTarget for Display7in5 { - type Color = TriColor; + type Color = BinaryColor; type Error = core::convert::Infallible; fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> @@ -32,7 +31,7 @@ impl DrawTarget for Display7in5 { I: IntoIterator>, { for pixel in pixels { - self.draw_helper_tri(WIDTH, HEIGHT, pixel)?; + self.draw_helper(WIDTH, HEIGHT, pixel)?; } Ok(()) } @@ -44,7 +43,7 @@ impl OriginDimensions for Display7in5 { } } -impl TriDisplay for Display7in5 { +impl Display for Display7in5 { fn buffer(&self) -> &[u8] { &self.buffer } @@ -60,33 +59,6 @@ impl TriDisplay for Display7in5 { 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()..] - } - /*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)] diff --git a/src/epd7in5_v2/mod.rs b/src/epd7in5_v2/mod.rs index 8ae5acdb..3ee95af3 100644 --- a/src/epd7in5_v2/mod.rs +++ b/src/epd7in5_v2/mod.rs @@ -15,9 +15,9 @@ use embedded_hal::{ digital::v2::{InputPin, OutputPin}, }; -use crate::color::TriColor; +use crate::color::Color; use crate::interface::DisplayInterface; -use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay}; +use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay}; pub(crate) mod command; use self::command::Command; @@ -32,12 +32,7 @@ pub const WIDTH: u32 = 800; /// Height of the display pub const HEIGHT: u32 = 480; /// Default Background Color -//pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; - -pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; - -/// Number of bits for b/w buffer and same for chromatic buffer -const NUM_DISPLAY_BITS: u32 = WIDTH * HEIGHT / 8; +pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; const IS_BUSY_LOW: bool = true; /// Epd7in5 (V2) driver @@ -46,7 +41,7 @@ pub struct Epd7in5 { /// Connection Interface interface: DisplayInterface, /// Background Color - color: TriColor, + color: Color, } impl InternalWiAdditions @@ -61,74 +56,28 @@ where { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 4); + self.interface.reset(delay, 2); // V2 procedure as described here: // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py // and as per specs: // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf - //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; + self.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(spi, delay)?; - self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; - //self.cmd_with_data(spi, Command::PllControl, &[0x06])?; + 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::VcomAndDataIntervalSetting, &[0x11, 0x07])?; self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?; self.wait_until_idle(spi, delay)?; Ok(()) } } -impl WaveshareThreeColorDisplay - for Epd7in5 -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_no_delay(spi); - Ok(()) - } -} - impl WaveshareDisplay for Epd7in5 where @@ -139,7 +88,7 @@ where RST: OutputPin, DELAY: DelayMs, { - type DisplayColor = TriColor; + type DisplayColor = Color; fn new( spi: &mut SPI, cs: CS, @@ -178,17 +127,6 @@ where ) -> Result<(), SPI::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; - - self.interface.data(spi, buffer)?; - - // Clear the chromatic layer - let color = self.color.get_byte_value(); - - self.interface.cmd(spi, Command::DataStartTransmission2)?; - self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; - - self.wait_until_idle(spi, delay)?; - Ok(()) } @@ -235,11 +173,11 @@ where Ok(()) } - fn set_background_color(&mut self, color: TriColor) { + fn set_background_color(&mut self, color: Color) { self.color = color; } - fn background_color(&self) -> &TriColor { + fn background_color(&self) -> &Color { &self.color } @@ -298,11 +236,6 @@ where Ok(()) } - fn wait_until_idle_no_delay(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { - let _ = self.interface.wait_until_idle(IS_BUSY_LOW); - Ok(()) - } - fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { let w = self.width(); let h = self.height(); @@ -323,6 +256,6 @@ mod tests { fn epd_size() { assert_eq!(WIDTH, 800); assert_eq!(HEIGHT, 480); - assert_eq!(DEFAULT_BACKGROUND_COLOR, TriColor::White); + assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); } } diff --git a/src/epd7in5_v3/command.rs b/src/epd7in5_v3/command.rs index 3ab1ebaf..cc7dcdc7 100644 --- a/src/epd7in5_v3/command.rs +++ b/src/epd7in5_v3/command.rs @@ -1,4 +1,4 @@ -//! SPI Commands for the Waveshare 7.5" E-Ink Display +//! SPI Commands for the Waveshare 7.5" V3 E-Ink Display use crate::traits; @@ -71,52 +71,63 @@ pub(crate) enum Command { /// This command builds the VCOM Look-Up Table (LUTC). LutForVcom = 0x20, - /// This command builds the White to White Look-Up Table (LUTWW). - LutWhiteToWhite = 0x21, - /// This command builds the Black to White Look-Up Table (LUTKW). - LutBlackToWhite = 0x22, - /// This command builds the White to Black Look-Up Table (LUTWK). - LutWhiteToBlack = 0x23, - /// This command builds the Black to Black Look-Up Table (LUTKK). - LutBlackToBlack = 0x24, - /// This command builds the Border? Look-Up Table (LUTR0). - LutBorder = 0x25, - + /// This command builds the Black Look-Up Table (LUTB). + LutBlack = 0x21, + /// This command builds the White Look-Up Table (LUTW). + LutWhite = 0x22, + /// This command builds the Gray1 Look-Up Table (LUTG1). + LutGray1 = 0x23, + /// This command builds the Gray2 Look-Up Table (LUTG2). + LutGray2 = 0x24, + /// This command builds the Red0 Look-Up Table (LUTR0). + LutRed0 = 0x25, + /// This command builds the Red1 Look-Up Table (LUTR1). + LutRed1 = 0x26, + /// This command builds the Red2 Look-Up Table (LUTR2). + LutRed2 = 0x27, + /// This command builds the Red3 Look-Up Table (LUTR3). + LutRed3 = 0x28, /// This command builds the XON Look-Up Table (LUTXON). - LutXon = 0x2A, + LutXon = 0x29, /// The command controls the PLL clock frequency. PllControl = 0x30, /// This command reads the temperature sensed by the temperature sensor. TemperatureSensor = 0x40, + /// This command selects the Internal or External temperature sensor. + TemperatureCalibration = 0x41, + /// This command could write data to the external temperature sensor. + TemperatureSensorWrite = 0x42, + /// This command could read data from the external temperature sensor. + TemperatureSensorRead = 0x43, /// This command indicates the interval of Vcom and data output. When setting the /// vertical back porch, the total blanking will be kept (20 Hsync). VcomAndDataIntervalSetting = 0x50, + /// This command indicates the input power condition. Host can read this flag to learn + /// the battery condition. + LowPowerDetection = 0x51, /// This command defines non-overlap period of Gate and Source. TconSetting = 0x60, /// This command defines alternative resolution and this setting is of higher priority /// than the RES\[1:0\] in R00H (PSR). TconResolution = 0x61, - //TODO /// This command defines MCU host direct access external memory mode. - GateSourceStart = 0x65, + /// This command defines MCU host direct access external memory mode. + SpiFlashControl = 0x65, /// The LUT_REV / Chip Revision is read from OTP address = 25001 and 25000. Revision = 0x70, + /// This command reads the IC status. + GetStatus = 0x71, + /// This command implements related VCOM sensing setting. + AutoMeasurementVcom = 0x80, + /// This command gets the VCOM value. + ReadVcomValue = 0x81, /// This command sets `VCOM_DC` value. VcmDcSetting = 0x82, - - // TODO - ProgramMode = 0xA0, - // - // TODO - ActiveProgram = 0xA1, - - // TODO - ReadOtpData = 0xA2, // /// 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_v3/graphics.rs b/src/epd7in5_v3/graphics.rs index 65500647..1b34119d 100644 --- a/src/epd7in5_v3/graphics.rs +++ b/src/epd7in5_v3/graphics.rs @@ -1,14 +1,14 @@ -use crate::epd7in5_v2::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH}; -use crate::graphics::{Display, DisplayRotation}; -use embedded_graphics_core::pixelcolor::BinaryColor; +use crate::color::TriColor; +use crate::epd7in5_v3::{DEFAULT_BACKGROUND_COLOR, HEIGHT, WIDTH, NUM_DISPLAY_BITS}; +use crate::graphics::{TriDisplay, DisplayRotation}; use embedded_graphics_core::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]` +/// `buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 2 * NUM_DISPLAY_BITS as usize]` pub struct Display7in5 { - buffer: [u8; WIDTH as usize * HEIGHT as usize / 8], + buffer: [u8; 2 * NUM_DISPLAY_BITS as usize], rotation: DisplayRotation, } @@ -16,14 +16,14 @@ impl Default for Display7in5 { fn default() -> Self { Display7in5 { buffer: [DEFAULT_BACKGROUND_COLOR.get_byte_value(); - WIDTH as usize * HEIGHT as usize / 8], + 2 * NUM_DISPLAY_BITS as usize], rotation: DisplayRotation::default(), } } } impl DrawTarget for Display7in5 { - type Color = BinaryColor; + type Color = TriColor; type Error = core::convert::Infallible; fn draw_iter(&mut self, pixels: I) -> Result<(), Self::Error> @@ -31,7 +31,7 @@ impl DrawTarget for Display7in5 { I: IntoIterator>, { for pixel in pixels { - self.draw_helper(WIDTH, HEIGHT, pixel)?; + self.draw_helper_tri(WIDTH, HEIGHT, pixel, crate::graphics::DisplayColorRendering::Positive)?; } Ok(()) } @@ -43,7 +43,7 @@ impl OriginDimensions for Display7in5 { } } -impl Display for Display7in5 { +impl TriDisplay for Display7in5 { fn buffer(&self) -> &[u8] { &self.buffer } @@ -59,13 +59,40 @@ impl Display for Display7in5 { 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()..] + } + /*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_v2; + use crate::epd7in5_v3; use crate::graphics::{Display, DisplayRotation}; use embedded_graphics::{ prelude::*, @@ -84,7 +111,7 @@ mod tests { fn graphics_default() { let display = Display7in5::default(); for &byte in display.buffer() { - assert_eq!(byte, epd7in5_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + assert_eq!(byte, epd7in5_v3::DEFAULT_BACKGROUND_COLOR.get_byte_value()); } } @@ -101,7 +128,7 @@ mod tests { assert_eq!(buffer[0], Color::Black.get_byte_value()); for &byte in buffer.iter().skip(1) { - assert_eq!(byte, epd7in5_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + assert_eq!(byte, epd7in5_v3::DEFAULT_BACKGROUND_COLOR.get_byte_value()); } } @@ -119,7 +146,7 @@ mod tests { assert_eq!(buffer[0], Color::Black.get_byte_value()); for &byte in buffer.iter().skip(1) { - assert_eq!(byte, epd7in5_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + assert_eq!(byte, epd7in5_v3::DEFAULT_BACKGROUND_COLOR.get_byte_value()); } } @@ -137,7 +164,7 @@ mod tests { assert_eq!(buffer[0], Color::Black.get_byte_value()); for &byte in buffer.iter().skip(1) { - assert_eq!(byte, epd7in5_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + assert_eq!(byte, epd7in5_v3::DEFAULT_BACKGROUND_COLOR.get_byte_value()); } } @@ -155,7 +182,7 @@ mod tests { assert_eq!(buffer[0], Color::Black.get_byte_value()); for &byte in buffer.iter().skip(1) { - assert_eq!(byte, epd7in5_v2::DEFAULT_BACKGROUND_COLOR.get_byte_value()); + assert_eq!(byte, epd7in5_v3::DEFAULT_BACKGROUND_COLOR.get_byte_value()); } } } diff --git a/src/epd7in5_v3/mod.rs b/src/epd7in5_v3/mod.rs index 1b0e6971..f3b80773 100644 --- a/src/epd7in5_v3/mod.rs +++ b/src/epd7in5_v3/mod.rs @@ -1,4 +1,4 @@ -//! A simple Driver for the Waveshare 7.5" E-Ink Display (V2) via SPI +//! A simple Driver for the Waveshare 7.5" E-Ink Display (V3) via SPI //! //! # References //! @@ -6,16 +6,13 @@ //! - [Waveshare C driver](https://github.com/waveshare/e-Paper/blob/702def0/RaspberryPi%26JetsonNano/c/lib/e-Paper/EPD_7in5_V2.c) //! - [Waveshare Python driver](https://github.com/waveshare/e-Paper/blob/702def0/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5_V2.py) //! -//! Important note for V2: -//! Revision V2 has been released on 2019.11, the resolution is upgraded to 800×480, from 640×384 of V1. -//! The hardware and interface of V2 are compatible with V1, however, the related software should be updated. use embedded_hal::{ blocking::{delay::*, spi::Write}, digital::v2::{InputPin, OutputPin}, }; -use crate::color::Color; +use crate::color::TriColor; use crate::interface::DisplayInterface; use crate::traits::{InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay}; @@ -32,20 +29,25 @@ pub const WIDTH: u32 = 800; /// Height of the display pub const HEIGHT: u32 = 480; /// Default Background Color -pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White; +//pub const DEFAULT_BACKGROUND_COLOR: 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; /// Epd7in5 (V3) driver /// -pub struct Epd7in5_v3 { +pub struct Epd7in5 { /// Connection Interface interface: DisplayInterface, /// Background Color - color: Color, + color: TriColor, } impl InternalWiAdditions - for Epd7in5_v3 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -56,32 +58,31 @@ where { fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { // Reset the device - self.interface.reset(delay, 2); + self.interface.reset(delay, 4); - // V2 procedure as described per specs: - // https://www.waveshare.com/w/upload/8/8c/7.5inch-e-paper-b-v3-specification.pdf - - self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; - self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x17, 0x3F, 0x3F])?; + // V2 procedure as described here: + // https://github.com/waveshare/e-Paper/blob/master/RaspberryPi%26JetsonNano/python/lib/waveshare_epd/epd7in5bc_V2.py + // and as per specs: + // https://www.waveshare.com/w/upload/6/60/7.5inch_e-Paper_V2_Specification.pdf + //self.cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x27, 0x17])?; + self.cmd_with_data(spi, Command::PowerSetting, &[0x07, 0x07, 0x3F, 0x3F])?; self.command(spi, Command::PowerOn)?; - - self.cmd_with_data(spi, Command::PanelSetting, &[0x1F])?; - self.cmd_with_data(spi, Command::PllControl, &[0x06])?; + self.wait_until_idle(spi, delay)?; + self.cmd_with_data(spi, Command::PanelSetting, &[0x0F])?; + //self.cmd_with_data(spi, Command::PllControl, &[0x06])?; self.cmd_with_data(spi, Command::TconResolution, &[0x03, 0x20, 0x01, 0xE0])?; self.cmd_with_data(spi, Command::DualSpi, &[0x00])?; + self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x11, 0x07])?; self.cmd_with_data(spi, Command::TconSetting, &[0x22])?; - self.cmd_with_data(spi, Command::VcomAndDataIntervalSetting, &[0x10, 0x07])?; - - self.wait_until_idle(spi, delay)?; - self.command(spi, Command::DisplayRefresh)?; + self.cmd_with_data(spi, Command::SpiFlashControl, &[0x00, 0x00, 0x00, 0x00])?; self.wait_until_idle(spi, delay)?; Ok(()) } } impl WaveshareThreeColorDisplay - for Epd7in5_v3 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -96,60 +97,16 @@ where black: &[u8], chromatic: &[u8], ) -> Result<(), SPI::Error> { - assert_eq!(black.len(), chromatic.len()); - - self.wait_until_idle_simple(); - - self.command(spi, Command::DataStartTransmission1)?; - - for (data_black, data_chromatic) in black.iter().zip(chromatic.iter()) { - let mut temp_black = *data_black; - let mut temp_chromatic = *data_chromatic; - - for _ in 0..4 { - let mut data = if temp_chromatic & 0x80 == 0 { - 0x04 - } else if temp_black & 0x80 == 0 { - 0x00 - } else { - 0x03 - }; - data <<= 4; - temp_black <<= 1; - temp_chromatic <<= 1; - data |= if temp_chromatic & 0x80 == 0 { - 0x04 - } else if temp_black & 0x80 == 0 { - 0x00 - } else { - 0x03 - }; - temp_black <<= 1; - temp_chromatic <<= 1; - self.send_data(spi, &[data])?; - } - } - - Ok(()) + 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.wait_until_idle_simple(); - self.command(spi, Command::DataStartTransmission1)?; - for byte in black { - let mut temp = *byte; - for _ in 0..4 { - let mut data = if temp & 0x80 == 0 { 0x00 } else { 0x03 }; - data <<= 4; - temp <<= 1; - data |= if temp & 0x80 == 0 { 0x00 } else { 0x03 }; - temp <<= 1; - self.send_data(spi, &[data])?; - } - } + self.interface.cmd(spi, Command::DataStartTransmission1)?; + self.interface.data(spi, black)?; Ok(()) } @@ -161,25 +118,16 @@ where spi: &mut SPI, chromatic: &[u8], ) -> Result<(), SPI::Error> { - self.wait_until_idle_simple(); - self.command(spi, Command::DataStartTransmission1)?; - for byte in chromatic { - let mut temp = *byte; - for _ in 0..4 { - let mut data = if temp & 0x80 == 0 { 0x04 } else { 0x03 }; - data <<= 4; - temp <<= 1; - data |= if temp & 0x80 == 0 { 0x04 } else { 0x03 }; - temp <<= 1; - self.send_data(spi, &[data])?; - } - } + self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.data(spi, chromatic)?; + + self.wait_until_idle_raw()?; Ok(()) } } impl WaveshareDisplay - for Epd7in5_v3 + for Epd7in5 where SPI: Write, CS: OutputPin, @@ -188,7 +136,7 @@ where RST: OutputPin, DELAY: DelayMs, { - type DisplayColor = Color; + type DisplayColor = TriColor; fn new( spi: &mut SPI, cs: CS, @@ -200,7 +148,7 @@ where let interface = DisplayInterface::new(cs, busy, dc, rst); let color = DEFAULT_BACKGROUND_COLOR; - let mut epd = Epd7in5_v3 { interface, color }; + let mut epd = Epd7in5 { interface, color }; epd.init(spi, delay)?; @@ -227,6 +175,17 @@ where ) -> Result<(), SPI::Error> { self.wait_until_idle(spi, delay)?; self.cmd_with_data(spi, Command::DataStartTransmission2, buffer)?; + + self.interface.data(spi, buffer)?; + + // Clear the chromatic layer + let color = self.color.get_byte_value(); + + self.interface.cmd(spi, Command::DataStartTransmission2)?; + self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?; + + self.wait_until_idle(spi, delay)?; + Ok(()) } @@ -273,11 +232,11 @@ where Ok(()) } - 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 } @@ -302,7 +261,7 @@ where } } -impl Epd7in5_v3 +impl Epd7in5 where SPI: Write, CS: OutputPin, @@ -330,14 +289,15 @@ where fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { while self.interface.is_busy(IS_BUSY_LOW) { - self.interface.cmd(spi, Command::Revision)?; + self.interface.cmd(spi, Command::GetStatus)?; delay.delay_ms(20); } Ok(()) } - fn wait_until_idle_simple(&mut self) { + fn wait_until_idle_raw(&mut self) -> Result<(), SPI::Error> { let _ = self.interface.wait_until_idle(IS_BUSY_LOW); + Ok(()) } fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> { @@ -360,6 +320,6 @@ mod tests { fn epd_size() { assert_eq!(WIDTH, 800); assert_eq!(HEIGHT, 480); - assert_eq!(DEFAULT_BACKGROUND_COLOR, Color::White); + assert_eq!(DEFAULT_BACKGROUND_COLOR, TriColor::White); } -} \ No newline at end of file +}