epd_waveshare_async/
lib.rs

1#![no_std]
2
3use core::error::Error as CoreError;
4
5use embedded_graphics::{prelude::Point, primitives::Rectangle};
6use embedded_hal::digital::{ErrorType as PinErrorType, InputPin, OutputPin};
7use embedded_hal_async::{
8    delay::DelayNs,
9    digital::Wait,
10    spi::{ErrorType as SpiErrorType, SpiDevice},
11};
12
13use crate::epd2in9::RefreshMode;
14
15pub mod buffer;
16pub mod epd2in9;
17
18mod log;
19
20#[derive(Debug, Copy, Clone, PartialEq)]
21pub enum Error {
22    InvalidArgument,
23}
24
25#[allow(async_fn_in_trait)]
26pub trait Epd<HW>
27where
28    HW: EpdHw,
29{
30    type RefreshMode;
31    type Command;
32    type Buffer;
33
34    /// Creates a buffer for use with this display.
35    fn new_buffer(&self) -> Self::Buffer;
36
37    fn width(&self) -> u32;
38
39    fn height(&self) -> u32;
40
41    /// Initialise the display. This must be called before any other operations.
42    async fn init(&mut self, spi: &mut HW::Spi, mode: RefreshMode) -> Result<(), HW::Error>;
43
44    /// Sets the refresh mode for the display.
45    async fn set_refresh_mode(
46        &mut self,
47        spi: &mut HW::Spi,
48        mode: Self::RefreshMode,
49    ) -> Result<(), HW::Error>;
50
51    /// Hardware reset the display. The display must be reinitialised after calling this.
52    async fn reset(&mut self) -> Result<(), HW::Error>;
53
54    /// Puts the display to sleep.
55    async fn sleep(&mut self, spi: &mut HW::Spi) -> Result<(), HW::Error>;
56
57    /// Wakes and re-initialises the display if it's asleep.
58    async fn wake(&mut self, spi: &mut HW::Spi) -> Result<(), HW::Error>;
59
60    /// Writes the buffers data to the display and displays it.
61    async fn display_buffer(
62        &mut self,
63        spi: &mut HW::Spi,
64        buffer: &Self::Buffer,
65    ) -> Result<(), HW::Error>;
66
67    /// Sets the window to write to during a call to [write_image]. This can enable partial writes
68    /// to a subsection of the display.
69    async fn set_window(&mut self, spi: &mut HW::Spi, shape: Rectangle) -> Result<(), HW::Error>;
70
71    /// Sets the cursor position for where the next byte of image data will be written.
72    async fn set_cursor(
73        &mut self,
74        spi: &mut HW::Spi,
75        position: Point,
76    ) -> Result<(), <HW as EpdHw>::Error>;
77
78    /// Writes raw image data, starting at the current cursor position and auto-incrementing x then y within the current window.
79    async fn write_image(&mut self, spi: &mut HW::Spi, image: &[u8]) -> Result<(), HW::Error>;
80
81    /// Updates (refreshes) the display based on the RAM. Note that this can be stateful. For
82    /// example, on the Epd2in9 display, there are two RAM buffers. Calling this function swaps
83    /// the active buffer. Consider this scenario:
84    ///
85    /// 1. [write_image] is used to turn the RAM all white.
86    /// 2. [update_display] is called, which refreshes the display to be all white.
87    /// 3. [write_image] is used to turn the RAM all black.
88    /// 4. [update_display] is called, which refreshes the display to be all black.
89    /// 5. [update_display] is called again, which refreshes the display to be all white again.
90    async fn update_display(&mut self, spi: &mut HW::Spi) -> Result<(), HW::Error>;
91
92    /// Send the following command and data to the display. Waits until the display is no longer busy before sending.
93    async fn send(
94        &mut self,
95        spi: &mut HW::Spi,
96        command: Self::Command,
97        data: &[u8],
98    ) -> Result<(), HW::Error>;
99
100    /// Waits for the current operation to complete if the display is busy.
101    /// Note that this will wait forever if the display is asleep.
102    async fn wait_if_busy(&mut self) -> Result<(), HW::Error>;
103}
104
105/// Provides access to the hardware needed to control an EPD.
106pub trait EpdHw {
107    type Spi: SpiDevice;
108    type Dc: OutputPin;
109    type Reset: OutputPin;
110    type Busy: InputPin + Wait;
111    type Delay: DelayNs;
112    type Error: CoreError
113        + From<<Self::Spi as SpiErrorType>::Error>
114        + From<<Self::Dc as PinErrorType>::Error>
115        + From<<Self::Reset as PinErrorType>::Error>
116        + From<<Self::Busy as PinErrorType>::Error>
117        + From<Error>;
118
119    fn dc(&mut self) -> &mut Self::Dc;
120    fn reset(&mut self) -> &mut Self::Reset;
121    fn busy(&mut self) -> &mut Self::Busy;
122    fn delay(&mut self) -> &mut Self::Delay;
123}