From bfedcbf0deb8d5327d1b68c2e93b210040fe8273 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 00:14:05 +0100 Subject: [PATCH 1/8] Initial commit - fully functional --- src/epd2in66b/command.rs | 117 +++++++++ src/epd2in66b/mod.rs | 511 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 629 insertions(+) create mode 100644 src/epd2in66b/command.rs create mode 100644 src/epd2in66b/mod.rs diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs new file mode 100644 index 00000000..a7528507 --- /dev/null +++ b/src/epd2in66b/command.rs @@ -0,0 +1,117 @@ +#![allow(dead_code)] +///! SPI Commands for the SSD1675B driver chip +use crate::traits; + +#[allow(dead_code)] +#[derive(Copy, Clone)] +pub(crate) enum Command { + DriverOutputControl = 0x01, + GateDrivingVoltageControl = 0x02, + SourceDrivingVoltageControl = 0x04, + ProgramOTPInitialCodeSetting = 0x08, + WriteRegisterForInitialCodeSetting = 0x09, + ReadRegisterForInitiaslCodeSetting = 0x0a, + BoosterSoftstartControl = 0x0c, + GateScanStartPosition = 0x0f, + DeepSleepMode = 0x10, + DataEntryMode = 0x11, + Reset = 0x12, + HVReadyDetection = 0x14, + VCIDetection = 0x15, + TemperatureSensorSelection = 0x18, + WriteTemperatureRegister = 0x1a, + ReadTemperatureRegister = 0x1b, + ExternalTemperatureSensorWriteCommand = 0x1c, + MasterActivation = 0x20, + DisplayUpdateControl1 = 0x21, + DisplayUpdateControl2 = 0x22, + WriteBlackWhiteRAM = 0x24, + WriteRedRAM = 0x26, + ReadRAM = 0x27, + SenseVCOM = 0x28, + VCOMSenseDuration = 0x29, + ProgramOTPVCOM = 0x2a, + WriteRegisterForVCOMControl = 0x2b, + WriteVCOMRegister = 0x2c, + ReadOTPDisplayOptions = 0x2d, + ReadOTPUserId = 0x2e, + ReadStatusBits = 0x2f, + ProgramOTPWaveformSetting = 0x30, + LoadOTPWaveformSetting = 0x31, + WriteLUTRegister = 0x32, + CalculateCRC = 0x34, + ReadCRC = 0x35, + ProgramOTPSelection = 0x36, + WriteRegisterForDisplayOption = 0x37, + WriteRegisterForUserID = 0x38, + OTPProgramMode = 0x39, + SetDummyLinePeriod = 0x3a, + SetGateLineWidth = 0x3b, + BorderWaveformControl = 0x3c, + RAMReadOption = 0x41, + SetXAddressRange = 0x44, + SetYAddressRange = 0x45, + RedRAMTestPattern = 0x46, + BlackWhiteRAMTestPattern = 0x47, + SetXAddressCounter = 0x4e, + SetYAddressCounter = 0x4f, + SetAnalogBlockControl = 0x74, + SetDigitalBlockControl = 0x7e, + NOP = 0x7f, +} + +impl traits::Command for Command { + /// Returns the address of the command + fn address(self) -> u8 { + self as u8 + } +} + +pub(crate) enum DataEntrySign { + DecYDecX = 0b00, + DecYIncX = 0b01, + IncYDecX = 0b10, + IncYIncX = 0b11, +} +pub(crate) enum DataEntryRow { + XMinor = 0b000, + YMinor = 0b100, +} + +pub(crate) enum WriteMode { + Normal = 0b0000, + ForceZero = 0b0100, + Invert = 01000, +} +pub(crate) enum OutputSource { + S0ToS175 = 0x00, + S8ToS167 = 0x80, +} + +pub(crate) enum DeepSleep { + Awake = 0b00, + SleepKeepingRAM = 0b01, + SleepLosingRAM = 0b11, +} + +pub(crate) enum PatH { + H8 = 0b000_0000, + H16 = 0b001_0000, + H32 = 0b010_0000, + H64 = 0b011_0000, + H128 = 0b100_0000, + H256 = 0b101_0000, + H296 = 0b110_0000, +} +pub(crate) enum PatW { + W8 = 0b000, + W16 = 0b001, + W32 = 0b010, + W64 = 0b011, + W128 = 0b100, + W160 = 0b101, +} +pub(crate) enum StartWith { + Zero = 0x00, + One = 0x80, +} diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs new file mode 100644 index 00000000..5dbfdd3f --- /dev/null +++ b/src/epd2in66b/mod.rs @@ -0,0 +1,511 @@ +//! A simple Driver for the Waveshare 2.66"-B E-Ink Display via SPI +//! +//! More information on this display can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) +//! This driver was built and tested for 296x152, 2.66inch E-Ink display HAT for Raspberry Pi Pico, three-color, SPI interface. +//! +//! # Example for the 2.66"B Pi Pico Hat E-Ink Display +//! +//!```rust, no_run +//!#![no_std] +//!#![no_main] +//! +//!use embedded_graphics::{ +//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, +//! prelude::*, +//! primitives::PrimitiveStyle, +//! text::{Alignment, Text}, +//!}; +//! +//!use cortex_m_rt::entry; +//!//use defmt::*; +//!use defmt_rtt as _; +//! +//!use panic_probe as _; +//!use rp_pico::hal::{ +//! self, +//! clocks::{init_clocks_and_plls, Clock}, +//! gpio::{FunctionSpi, PinState, Pins}, +//! pac, +//! sio::Sio, +//! watchdog::Watchdog, +//!}; +//! +//!use fugit::RateExtU32; +//! +//!use epd_waveshare::{epd2in66b::*, prelude::*}; +//! +//!// Use embedded-graphics to create a bitmap to show +//!fn drawing() -> Display2in66b { +//! // Create a Display buffer to draw on, specific for this ePaper +//! let mut display = Display2in66b::default(); +//! +//! // Landscape mode, USB plug to the right +//! display.set_rotation(DisplayRotation::Rotate270); +//! +//! // Change the background from the default black to white +//! let _ = display +//! .bounding_box() +//! .into_styled(PrimitiveStyle::with_fill(TriColor::White)) +//! .draw(&mut display); +//! +//! // Draw some text on the buffer +//! let text = "Pico-ePaper-2.66 B/W/R"; +//! Text::with_alignment( +//! text, +//! display.bounding_box().center() + Point::new(1, 0), +//! MonoTextStyle::new(&FONT_10X20, TriColor::Black), +//! Alignment::Center, +//! ) +//! .draw(&mut display) +//! .unwrap(); +//! Text::with_alignment( +//! text, +//! display.bounding_box().center() + Point::new(0, 1), +//! MonoTextStyle::new(&FONT_10X20, TriColor::Chromatic), +//! Alignment::Center, +//! ) +//! .draw(&mut display) +//! .unwrap(); +//! +//! display +//!} +//! +//!#[entry] +//!fn main() -> ! { +//! let mut pac = pac::Peripherals::take().unwrap(); +//! let core = pac::CorePeripherals::take().unwrap(); +//! let mut watchdog = Watchdog::new(pac.WATCHDOG); +//! let external_xtal_freq_hz = 12_000_000u32; +//! let clocks = init_clocks_and_plls( +//! external_xtal_freq_hz, +//! pac.XOSC, +//! pac.CLOCKS, +//! pac.PLL_SYS, +//! pac.PLL_USB, +//! &mut pac.RESETS, +//! &mut watchdog, +//! ) +//! .ok() +//! .unwrap(); +//! +//! let sio = Sio::new(pac.SIO); +//! let pins = Pins::new( +//! pac.IO_BANK0, +//! pac.PADS_BANK0, +//! sio.gpio_bank0, +//! &mut pac.RESETS, +//! ); +//! // pin assignemnts +//! let _ = pins.gpio10.into_mode::(); +//! let _ = pins.gpio11.into_mode::(); +//! let chip_select_pin = pins.gpio9.into_push_pull_output_in_state(PinState::High); +//! let is_busy_pin = pins.gpio13.into_floating_input(); +//! let data_or_command_pin = pins.gpio8.into_push_pull_output_in_state(PinState::High); +//! let reset_pin = pins.gpio12.into_push_pull_output_in_state(PinState::High); +//! +//! // spi +//! let spi = hal::Spi::<_, _, 8>::new(pac.SPI1); +//! let mut spi = spi.init( +//! &mut pac.RESETS, +//! clocks.peripheral_clock.freq(), +//! 20_000_000u32.Hz(), +//! &SPI_MODE, +//! ); +//! +//! //delay +//! let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); +//! +//! // Setup EPD +//! let mut e_paper = Epd2in66b::new( +//! &mut spi, +//! chip_select_pin, +//! is_busy_pin, +//! data_or_command_pin, +//! reset_pin, +//! &mut delay, +//! None, +//! ) +//! .unwrap(); +//! +//! // Create and fill a Display buffer +//! let display = drawing(); +//! +//! // Send the Display buffer to the ePaper RAM +//! e_paper +//! .update_color_frame( +//! &mut spi, +//! &mut delay, +//! &display.bw_buffer(), +//! &display.chromatic_buffer(), +//! ) +//! .unwrap(); +//! +//! // Render the ePaper RAM - takes time. +//! e_paper.display_frame(&mut spi, &mut delay).unwrap(); +//! +//! // Always sleep your EPD as much as possible - ePaper wears out while powered on. +//! e_paper.sleep(&mut spi, &mut delay).unwrap(); +//! +//! delay.delay_ms(60 * 1000); +//! +//! // Set the display all-white before storing your ePaper long-term. +//! e_paper.wake_up(&mut spi, &mut delay).unwrap(); +//! e_paper.clear_frame(&mut spi, &mut delay).unwrap(); +//! e_paper.display_frame(&mut spi, &mut delay).unwrap(); +//! e_paper.sleep(&mut spi, &mut delay).unwrap(); +//! +//! loop {} +//!} +//!``` + +use embedded_hal::{ + blocking::{delay::*, spi::Write}, + digital::v2::*, +}; + +use crate::color::TriColor; +use crate::interface::DisplayInterface; +use crate::traits::{ + InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay, +}; + +pub(crate) mod command; +use self::command::*; +use crate::buffer_len; + +/// Display height in pixels. +pub const WIDTH: u32 = 152; +/// Display width in pixels +pub const HEIGHT: u32 = 296; + +/// White, display this during long-term storage +pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White; + +/// A Display buffer configured with our extent and color depth. +#[cfg(feature = "graphics")] +pub type Display2in66b = crate::graphics::Display< + WIDTH, + HEIGHT, + false, + { buffer_len(WIDTH as usize, HEIGHT as usize) * 2 }, + TriColor, +>; + +/// The EPD 2in66-B driver. +pub struct Epd2in66b { + interface: DisplayInterface, + background: TriColor, +} + +impl InternalWiAdditions + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + // We follow the sequence of the Pi-Pico hat example code. + self.hw_reset(delay)?; + self.sw_reset(spi, delay)?; + self.data_entry_mode(spi, DataEntryRow::XMinor, DataEntrySign::IncYIncX)?; + self.set_display_window(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?; + self.update_control1( + spi, + WriteMode::Normal, + WriteMode::Normal, + OutputSource::S8ToS167, + )?; + self.set_cursor(spi, 0, 0)?; + + Ok(()) + } +} + +impl WaveshareThreeColorDisplay + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn update_color_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + black: &[u8], + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.update_achromatic_frame(spi, delay, black)?; + self.update_chromatic_frame(spi, delay, chromatic) + } + + fn update_achromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + black: &[u8], + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.interface.cmd(spi, Command::WriteBlackWhiteRAM)?; + self.interface.data(spi, black) + } + + fn update_chromatic_frame( + &mut self, + spi: &mut SPI, + _delay: &mut DELAY, + chromatic: &[u8], + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.interface.cmd(spi, Command::WriteRedRAM)?; + self.interface.data(spi, chromatic) + } +} + +impl WaveshareDisplay + for Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + type DisplayColor = TriColor; + + fn new( + spi: &mut SPI, + cs: CS, + busy: BUSY, + dc: DC, + rst: RST, + delay: &mut DELAY, + delay_us: Option, + ) -> Result + where + Self: Sized, + { + let mut epd = Self { + interface: DisplayInterface::new(cs, busy, dc, rst, delay_us), + background: DEFAULT_BACKGROUND_COLOR, + }; + epd.init(spi, delay)?; + Ok(epd) + } + + fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::DeepSleepMode, + &[DeepSleep::SleepLosingRAM as u8], + ) + } + + fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.init(spi, delay) + } + + fn set_background_color(&mut self, color: Self::DisplayColor) { + self.background = color; + } + + fn background_color(&self) -> &Self::DisplayColor { + &self.background + } + + fn width(&self) -> u32 { + WIDTH + } + + fn height(&self) -> u32 { + HEIGHT + } + + fn update_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.set_cursor(spi, 0, 0)?; + self.update_achromatic_frame(spi, delay, buffer)?; + self.red_pattern(spi, delay, PatW::W160, PatH::H296, StartWith::Zero) // do NOT consider background here since red overrides other colors + } + + fn update_partial_frame( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + buffer: &[u8], + x: u32, + y: u32, + width: u32, + height: u32, + ) -> Result<(), SPI::Error> { + self.set_display_window(spi, x, y, x + width, y + height)?; + self.set_cursor(spi, x, y)?; + self.update_achromatic_frame(spi, delay, buffer)?; + self.set_display_window(spi, 0, 0, WIDTH, HEIGHT) + } + + fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::MasterActivation)?; + self.wait_until_idle(delay) + } + + fn update_and_display_frame( + &mut self, + spi: &mut SPI, + buffer: &[u8], + delay: &mut DELAY, + ) -> Result<(), SPI::Error> { + self.update_frame(spi, buffer, delay)?; + self.display_frame(spi, delay) + } + + fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + let (white, red) = match self.background { + TriColor::Black => (StartWith::Zero, StartWith::Zero), + TriColor::White => (StartWith::One, StartWith::Zero), + TriColor::Chromatic => (StartWith::Zero, StartWith::One), + }; + self.black_white_pattern(spi, delay, PatW::W160, PatH::H296, white)?; + self.red_pattern(spi, delay, PatW::W160, PatH::H296, red) + } + + fn set_lut( + &mut self, + _spi: &mut SPI, + _delay: &mut DELAY, + _refresh_rate: Option, + ) -> Result<(), SPI::Error> { + Ok(()) + } + + fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.wait_until_idle(delay) + } +} + +// Helper functions that enforce some type and value constraints. Meant to help with code readability. They caught some of my silly errors -> yay rust!. +impl Epd2in66b +where + SPI: Write, + CS: OutputPin, + BUSY: InputPin, + DC: OutputPin, + RST: OutputPin, + DELAY: DelayUs, +{ + fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.wait_until_idle(delay, false); + Ok(()) + } + fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> { + // The initial delay is taken from other code here, the 2 ms comes from the SSD1675B datasheet. + self.interface.reset(delay, 20_000, 2_000); + self.wait_until_idle(delay) + } + fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> { + self.interface.cmd(spi, Command::Reset)?; + self.wait_until_idle(delay) + } + fn data_entry_mode( + &mut self, + spi: &mut SPI, + row: DataEntryRow, + sign: DataEntrySign, + ) -> Result<(), SPI::Error> { + self.interface + .cmd_with_data(spi, Command::DataEntryMode, &[row as u8 | sign as u8]) + } + fn set_display_window( + &mut self, + spi: &mut SPI, + xstart: u32, + ystart: u32, + xend: u32, + yend: u32, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::SetXAddressRange, + &[(((xstart >> 3) & 0x1f) as u8), (((xend >> 3) & 0x1f) as u8)], + )?; + self.interface.cmd_with_data( + spi, + Command::SetYAddressRange, + &[ + ((ystart & 0xff) as u8), + (((ystart >> 8) & 0x01) as u8), + ((yend & 0xff) as u8), + (((yend >> 8) & 0x01) as u8), + ], + ) + } + fn update_control1( + &mut self, + spi: &mut SPI, + red_mode: WriteMode, + bw_mode: WriteMode, + source: OutputSource, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::DisplayUpdateControl1, + &[((red_mode as u8) << 4 | bw_mode as u8), (source as u8)], + ) + } + + fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::SetXAddressCounter, + &[((x >> 3) & 0x1f) as u8], + )?; + self.interface.cmd_with_data( + spi, + Command::SetYAddressCounter, + &[((y & 0xff) as u8), (((y >> 8) & 0x01) as u8)], + ) + } + + fn black_white_pattern( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + w: PatW, + h: PatH, + phase: StartWith, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::BlackWhiteRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + )?; + self.wait_until_idle(delay) + } + fn red_pattern( + &mut self, + spi: &mut SPI, + delay: &mut DELAY, + w: PatW, + h: PatH, + phase: StartWith, + ) -> Result<(), SPI::Error> { + self.interface.cmd_with_data( + spi, + Command::RedRAMTestPattern, + &[phase as u8 | h as u8 | w as u8], + )?; + self.wait_until_idle(delay) + } +} diff --git a/src/lib.rs b/src/lib.rs index 677f16b9..0d94ec76 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -79,6 +79,7 @@ pub mod epd1in54b; pub mod epd1in54c; pub mod epd2in13_v2; pub mod epd2in13bc; +pub mod epd2in66b; pub mod epd2in7b; pub mod epd2in9; pub mod epd2in9_v2; From a5a1f319960e35042fdf126b1c52ba0175fbdf2e Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:40:03 +0100 Subject: [PATCH 2/8] documentation --- src/epd2in66b/mod.rs | 70 ++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 31 deletions(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 5dbfdd3f..7ce8fba0 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -1,41 +1,38 @@ -//! A simple Driver for the Waveshare 2.66"-B E-Ink Display via SPI +//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B'. //! -//! More information on this display can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) -//! This driver was built and tested for 296x152, 2.66inch E-Ink display HAT for Raspberry Pi Pico, three-color, SPI interface. //! -//! # Example for the 2.66"B Pi Pico Hat E-Ink Display +//! This driver was built and tested for this 296x152, 2.66inch E-Ink display hat for the Pi Pico, it is expected to work for +//! other boards too, but that might depend on how the OTP memory in the display is programmed by the factory. //! +//! The driver embedded in the display of this board is the SSD1675B, [documented by cursedhardware](https://cursedhardware.github.io/epd-driver-ic/SSD1675B.pdf). +//! +//! The pin assigments are shown on the Waveshare wiki [schematic](https://www.waveshare.com/w/upload/8/8d/Pico-ePaper-2.66.pdf). +//! +//! Information on this display/hat can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B). +//! Do read this documentation, in particular to understand how often this display both must and cannot be updated. +//! +//! # Example for the 'Pico-ePaper-2.66-B' Pi Pico Hat E-Ink Display +//! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will +//! need to adjust for your preferred setup. //!```rust, no_run //!#![no_std] //!#![no_main] -//! -//!use embedded_graphics::{ -//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, -//! prelude::*, -//! primitives::PrimitiveStyle, -//! text::{Alignment, Text}, -//!}; +//!use epd_waveshare::{epd2in66b::*, prelude::*}; //! //!use cortex_m_rt::entry; //!//use defmt::*; //!use defmt_rtt as _; -//! //!use panic_probe as _; -//!use rp_pico::hal::{ -//! self, -//! clocks::{init_clocks_and_plls, Clock}, -//! gpio::{FunctionSpi, PinState, Pins}, -//! pac, -//! sio::Sio, -//! watchdog::Watchdog, -//!}; -//! -//!use fugit::RateExtU32; -//! -//!use epd_waveshare::{epd2in66b::*, prelude::*}; //! //!// Use embedded-graphics to create a bitmap to show //!fn drawing() -> Display2in66b { +//! use embedded_graphics::{ +//! mono_font::{ascii::FONT_10X20, MonoTextStyle}, +//! prelude::*, +//! primitives::PrimitiveStyle, +//! text::{Alignment, Text}, +//! }; +//! //! // Create a Display buffer to draw on, specific for this ePaper //! let mut display = Display2in66b::default(); //! @@ -72,6 +69,17 @@ //! //!#[entry] //!fn main() -> ! { +//! use fugit::RateExtU32; +//! use rp_pico::hal::{ +//! self, +//! clocks::{init_clocks_and_plls, Clock}, +//! gpio::{FunctionSpi, PinState, Pins}, +//! pac, +//! sio::Sio, +//! watchdog::Watchdog, +//! }; +//! +//! // Boilerplate to access the peripherals //! let mut pac = pac::Peripherals::take().unwrap(); //! let core = pac::CorePeripherals::take().unwrap(); //! let mut watchdog = Watchdog::new(pac.WATCHDOG); @@ -87,7 +95,6 @@ //! ) //! .ok() //! .unwrap(); -//! //! let sio = Sio::new(pac.SIO); //! let pins = Pins::new( //! pac.IO_BANK0, @@ -95,7 +102,8 @@ //! sio.gpio_bank0, //! &mut pac.RESETS, //! ); -//! // pin assignemnts +//! +//! // Pin assignments of the Pi Pico-ePaper-2.66 Hat //! let _ = pins.gpio10.into_mode::(); //! let _ = pins.gpio11.into_mode::(); //! let chip_select_pin = pins.gpio9.into_push_pull_output_in_state(PinState::High); @@ -103,19 +111,19 @@ //! let data_or_command_pin = pins.gpio8.into_push_pull_output_in_state(PinState::High); //! let reset_pin = pins.gpio12.into_push_pull_output_in_state(PinState::High); //! -//! // spi +//! // SPI //! let spi = hal::Spi::<_, _, 8>::new(pac.SPI1); //! let mut spi = spi.init( //! &mut pac.RESETS, //! clocks.peripheral_clock.freq(), -//! 20_000_000u32.Hz(), +//! 20_000_000u32.Hz(), // The SSD1675B docs say 20MHz max //! &SPI_MODE, //! ); //! -//! //delay +//! // Delay //! let mut delay = cortex_m::delay::Delay::new(core.SYST, clocks.system_clock.freq().to_Hz()); //! -//! // Setup EPD +//! // Setup the EPD driver //! let mut e_paper = Epd2in66b::new( //! &mut spi, //! chip_select_pin, @@ -143,7 +151,7 @@ //! // Render the ePaper RAM - takes time. //! e_paper.display_frame(&mut spi, &mut delay).unwrap(); //! -//! // Always sleep your EPD as much as possible - ePaper wears out while powered on. +//! // Always turn off your EPD as much as possible - ePaper wears out while powered on. //! e_paper.sleep(&mut spi, &mut delay).unwrap(); //! //! delay.delay_ms(60 * 1000); From ba6b8ef2a3e33660105b7cd7cdd90b569eabc582 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:40:57 +0100 Subject: [PATCH 3/8] fix number base bug & clippy remarks --- src/epd2in66b/command.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs index a7528507..bd6c28f1 100644 --- a/src/epd2in66b/command.rs +++ b/src/epd2in66b/command.rs @@ -57,7 +57,7 @@ pub(crate) enum Command { SetYAddressCounter = 0x4f, SetAnalogBlockControl = 0x74, SetDigitalBlockControl = 0x7e, - NOP = 0x7f, + Nop = 0x7f, } impl traits::Command for Command { @@ -81,7 +81,7 @@ pub(crate) enum DataEntryRow { pub(crate) enum WriteMode { Normal = 0b0000, ForceZero = 0b0100, - Invert = 01000, + Invert = 0b1000, } pub(crate) enum OutputSource { S0ToS175 = 0x00, From 7fe3069a829d68486113c160976a9deef30e2477 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 11:42:01 +0100 Subject: [PATCH 4/8] remove a redundant attribute --- src/epd2in66b/command.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/epd2in66b/command.rs b/src/epd2in66b/command.rs index bd6c28f1..d0d22059 100644 --- a/src/epd2in66b/command.rs +++ b/src/epd2in66b/command.rs @@ -2,7 +2,6 @@ ///! SPI Commands for the SSD1675B driver chip use crate::traits; -#[allow(dead_code)] #[derive(Copy, Clone)] pub(crate) enum Command { DriverOutputControl = 0x01, From b176194a7639e51a328e65073fd381927a4c46f3 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 12:29:10 +0100 Subject: [PATCH 5/8] add 2in66 entry to the README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index bb088199..97b399bb 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ epd.update_and_display_frame( & mut spi, & display.buffer()) ?; | [2.9 Inch B/W/R (B/C)](https://www.waveshare.com/product/displays/e-paper/epaper-2/2.9inch-e-paper-module-b.htm) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | | [5.65 Inch 7 Color (F)](https://www.waveshare.com/5.65inch-e-paper-module-f.htm) | Black, White, Red, Green, Blue, Yellow, Orange | ✕ | ✕ | ✔ | ✔ | | [2.7 Inch 3 Color (B)](https://www.waveshare.com/2.7inch-e-paper-b.htm) | Black, White, Red | ✕ | ✔ | ✔ | ✔ | +| [2.66 Inch 3 Color (B)](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B) | Black, White, Red | ✕ | ✕ | ✔ | ✔ | ### [1]: 7.5 Inch B/W V2 (A) From 1c717ebe595e949be755d67d7b44342452b8c2c4 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 12:35:02 +0100 Subject: [PATCH 6/8] documentation tweaks --- src/epd2in66b/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 7ce8fba0..17a4abcd 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -1,7 +1,7 @@ -//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B'. +//! A driver for the Waveshare three-color E-ink Pi Pico hat 'Pico-ePaper-2.66-B' B/W/R. //! //! -//! This driver was built and tested for this 296x152, 2.66inch E-Ink display hat for the Pi Pico, it is expected to work for +//! This driver was built and tested for this 296x152, 2.66inch three-color E-Ink display hat for the Pi Pico, it is expected to work for //! other boards too, but that might depend on how the OTP memory in the display is programmed by the factory. //! //! The driver embedded in the display of this board is the SSD1675B, [documented by cursedhardware](https://cursedhardware.github.io/epd-driver-ic/SSD1675B.pdf). @@ -9,9 +9,9 @@ //! The pin assigments are shown on the Waveshare wiki [schematic](https://www.waveshare.com/w/upload/8/8d/Pico-ePaper-2.66.pdf). //! //! Information on this display/hat can be found at the [Waveshare Wiki](https://www.waveshare.com/wiki/Pico-ePaper-2.66-B). -//! Do read this documentation, in particular to understand how often this display both must and cannot be updated. +//! Do read this documentation, in particular to understand how often this display both should and should not be updated. //! -//! # Example for the 'Pico-ePaper-2.66-B' Pi Pico Hat E-Ink Display +//! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. //!```rust, no_run From 058483c2780d49667941d3c8d4a674c734b45aaf Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 13:06:59 +0100 Subject: [PATCH 7/8] tweak documentation to pass (skip) doc test --- src/epd2in66b/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index 17a4abcd..ed67d850 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -14,7 +14,7 @@ //! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. -//!```rust, no_run +//!```no_run //!#![no_std] //!#![no_main] //!use epd_waveshare::{epd2in66b::*, prelude::*}; From b94f12b3ebdd3513b99d48fa7103b3b7aeb02bf9 Mon Sep 17 00:00:00 2001 From: Reinout Heeck Date: Mon, 27 Feb 2023 13:32:12 +0100 Subject: [PATCH 8/8] tweak documentation to pass (skip) doc test, try2 --- src/epd2in66b/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/epd2in66b/mod.rs b/src/epd2in66b/mod.rs index ed67d850..42666312 100644 --- a/src/epd2in66b/mod.rs +++ b/src/epd2in66b/mod.rs @@ -14,7 +14,7 @@ //! # Example for the 'Pico-ePaper-2.66-B' B/W/R Pi Pico Hat E-Ink Display //! This example was created in an environment using the [Knurling](https://github.com/knurling-rs) ```flip-link```, ```defmt``` and ```probe-run``` tools - you will //! need to adjust for your preferred setup. -//!```no_run +//!```ignore //!#![no_std] //!#![no_main] //!use epd_waveshare::{epd2in66b::*, prelude::*};