diff --git a/src/lib.rs b/src/lib.rs index 1682658..b1ef66f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,21 +1,14 @@ #![no_std] -//! This library is an embedded-hal based driver implementation for the GDEQ031T10 e-paper display. -//! -//! **Note**: 9-bit SPI mode (where the data/command is designated with an extra bit for each byte) -//! is not supported by this driver. Only the mode with a dedicated data/command line is supported. - use embedded_hal::{ delay::DelayNs, - digital::{InputPin, OutputPin}, - spi::{Operation, SpiDevice}, + digital::{InputPin, OutputPin}, spi::{Operation, SpiDevice}, }; -const EPD_WIDTH: usize = 240; -const EPD_HEIGHT: usize = 320; -const EPD_ARRAY: usize = EPD_WIDTH * EPD_HEIGHT / 8; +const EPD_WIDTH: u32 = 240; +const EPD_HEIGHT: u32 = 320; +const EPD_ARRAY: u32 = EPD_WIDTH * EPD_HEIGHT / 8; -/// The display driver for the GDEQ031T10 e-paper display. pub struct EPaperDisplay { busy: BusyPin, reset: ResetPin, @@ -24,176 +17,23 @@ pub struct EPaperDisplay { delay: Delay, } -/// An error that may occur during display initialisation. pub enum InitError { - /// This variant is for any error with setting the level of the reset pin. - /// - /// This variant may be uninhabited if the `ResetPin` type parameter for [EPaperDisplay] is one that - /// doesn't produce errors. ResetError(ResetError), - /// This variant is for errors when attempting to communicate with the display controller after reset. WriteError(WriteError), } -/// An error when trying to communicate with the display controller. pub enum WriteError { - /// This variant is for any error with setting the level of the DC (Data/Command) pin. - /// - /// This variant may be uninhabited if the `DcPin` type parameter for [EPaperDisplay] is one that - /// doesn't produce errors. DcError(DcError), - /// This variant is for errors produced by the SPI driver. SpiError(SpiError), } -pub struct Frame([u8; EPD_ARRAY]); - -impl Frame { - pub const fn new_white() -> Self { - Self([0xff; EPD_ARRAY]) - } - - pub const fn new_black() -> Self { - Self([0x00; EPD_ARRAY]) - } -} - -pub struct DoubleFrame { - old: Frame, - new: Frame, - partial_window: PartialWindow, -} - -pub enum PixelColour { - Black = 0, - White = 1, -} - -pub trait ApplyParitalWindow: private::Sealed { - fn apply< - BusyPin: InputPin, - ResetPin: OutputPin, - DcPin: OutputPin, - Spi: SpiDevice, - Delay: DelayNs, - >( - &self, - display: &mut EPaperDisplay, - ); - - fn update_partial_window(&mut self, min_x: u16, max_x: u16, min_y: u16, max_y: u16); - - fn reset_partial_window(&mut self); -} - -mod private { - pub(super) trait Sealed {} - - impl Sealed for super::NoPartialWindow {} - - impl Sealed for super::AutomaticPartialWindow {} -} - -pub struct NoPartialWindow; - -impl ApplyParitalWindow for NoPartialWindow { - fn apply< - BusyPin: InputPin, - ResetPin: OutputPin, - DcPin: OutputPin, - Spi: SpiDevice, - Delay: DelayNs, - >( - &self, - _display: &mut EPaperDisplay, - ) { - } - - fn update_partial_window(&mut self, _min_x: u16, _max_x: u16, _min_y: u16, _max_y: u16) {} - - fn reset_partial_window(&mut self) {} -} - -pub struct AutomaticPartialWindow { - min_x: u16, - max_x: u16, - min_y: u16, - max_y: u16, -} - -impl ApplyParitalWindow for AutomaticPartialWindow { - fn apply< - BusyPin: InputPin, - ResetPin: OutputPin, - DcPin: OutputPin, - Spi: SpiDevice, - Delay: DelayNs, - >( - &self, - display: &mut EPaperDisplay, - ) { - let hrst = self.min_x as u8 & 0b11111000; - let hred = self.max_x as u8 | 0b111; - let vrst = self.min_y & 0x1FF; - let vred = self.max_y & 0x1FF; - display.write_command(0x90); - display.write_data(hrst); - display.write_data(hred); - display.write_data((vrst >> 8) as u8); - display.write_data((vrst & 0xFF) as u8); - display.write_data((vred >> 8) as u8); - display.write_data((vred & 0xFF) as u8); - display.write_data(0x00); - } - - fn update_partial_window(&mut self, min_x: u16, max_x: u16, min_y: u16, max_y: u16) { - self.min_x = core::cmp::min(self.min_x, min_x); - self.max_x = core::cmp::max(self.max_x, max_x); - self.min_y = core::cmp::min(self.min_y, min_y); - self.max_y = core::cmp::max(self.max_y, max_y); - } - - fn reset_partial_window(&mut self) { - *self = AutomaticPartialWindow { - min_x: EPD_WIDTH as u16, - max_x: 0, - min_y: EPD_HEIGHT as u16, - max_y: 0, - } - } -} - -impl DoubleFrame { - pub fn new(old: Frame, new: Frame) -> Self { - Self { - old, - new, - partial_window: NoPartialWindow, - } - } - - pub fn draw_pixel(&mut self, x: usize, y: usize, colour: PixelColour) { - todo!() - } -} - -impl DoubleFrame { - pub fn new_with_automatic_partial_window(old: Frame, new: Frame) -> Self { - Self { - old, - new, - partial_window: AutomaticPartialWindow { - min_x: EPD_WIDTH as u16, - max_x: 0, - min_y: EPD_HEIGHT as u16, - max_y: 0, - }, - } - } -} - -impl - EPaperDisplay +impl< + BusyPin: InputPin, + ResetPin: OutputPin, + DcPin: OutputPin, + Spi: SpiDevice, + Delay: DelayNs, +> EPaperDisplay { pub fn new( busy: BusyPin, @@ -214,26 +54,22 @@ impl Result<(), WriteError> { self.dc.set_low().map_err(WriteError::DcError)?; - self.spi - .transaction(&mut [ - Operation::DelayNs(60), - Operation::Write(&[byte]), - Operation::DelayNs(20), - ]) - .map_err(WriteError::SpiError)?; + self.spi.transaction(&mut [ + Operation::DelayNs(60), + Operation::Write(&[byte]), + Operation::DelayNs(20), + ]).map_err(WriteError::SpiError)?; self.delay.delay_ns(40); Ok(()) } fn write_data(&mut self, byte: u8) -> Result<(), WriteError> { self.dc.set_high().map_err(WriteError::DcError)?; - self.spi - .transaction(&mut [ - Operation::DelayNs(60), - Operation::Write(&[byte]), - Operation::DelayNs(20), - ]) - .map_err(WriteError::SpiError)?; + self.spi.transaction(&mut [ + Operation::DelayNs(60), + Operation::Write(&[byte]), + Operation::DelayNs(20), + ]).map_err(WriteError::SpiError)?; self.delay.delay_ns(40); Ok(()) } @@ -271,39 +107,4 @@ impl(&mut self, double_frame: &mut DoubleFrame) { - double_frame.partial_window.apply(self); - self.write_command(0x10); - for byte in double_frame.old.0 { - self.write_data(byte); - } - self.write_command(0x13); - for byte in double_frame.new.0 { - self.write_data(byte); - } - self.write_command(0x12); - double_frame.old.0 = double_frame.new.0; - - self.delay.delay_ms(1); - self.wait_for_display(); - } - - /// Puts the display into deep sleep mode which effectively deinitialises the display controller. - /// - /// Reinitialising the display with [EPaperDisplay::new] is sufficient to wake the display back up. - /// - /// All display controller registers will be reset by this process. - pub fn deep_sleep(mut self) { - self.write_command(0x07); - self.write_data(0xA5); - } - - pub fn enable_partial_mode(&mut self) { - self.write_command(0x91); - } - - pub fn disable_partial_mode(&mut self) { - self.write_command(0x92); - } }