epd_waveshare/traits.rs
1use core::marker::Sized;
2use embedded_hal::{delay::*, digital::*, spi::SpiDevice};
3
4/// All commands need to have this trait which gives the address of the command
5/// which needs to be send via SPI with activated CommandsPin (Data/Command Pin in CommandMode)
6pub(crate) trait Command: Copy {
7 fn address(self) -> u8;
8}
9
10/// Seperates the different LUT for the Display Refresh process
11#[derive(Debug, Clone, PartialEq, Eq, Copy, Default)]
12pub enum RefreshLut {
13 /// The "normal" full Lookuptable for the Refresh-Sequence
14 #[default]
15 Full,
16 /// The quick LUT where not the full refresh sequence is followed.
17 /// This might lead to some
18 Quick,
19}
20
21pub(crate) trait InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
22where
23 SPI: SpiDevice,
24 BUSY: InputPin,
25 DC: OutputPin,
26 RST: OutputPin,
27 DELAY: DelayNs,
28{
29 /// This initialises the EPD and powers it up
30 ///
31 /// This function is already called from
32 /// - [new()](WaveshareDisplay::new())
33 /// - [`wake_up`]
34 ///
35 ///
36 /// This function calls [reset](WaveshareDisplay::reset),
37 /// so you don't need to call reset your self when trying to wake your device up
38 /// after setting it to sleep.
39 fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
40}
41
42/// Functions to interact with three color panels
43pub trait WaveshareThreeColorDisplay<SPI, BUSY, DC, RST, DELAY>:
44 WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
45where
46 SPI: SpiDevice,
47 BUSY: InputPin,
48 DC: OutputPin,
49 RST: OutputPin,
50 DELAY: DelayNs,
51{
52 /// Transmit data to the SRAM of the EPD
53 ///
54 /// Updates both the black and the secondary color layers
55 fn update_color_frame(
56 &mut self,
57 spi: &mut SPI,
58 delay: &mut DELAY,
59 black: &[u8],
60 chromatic: &[u8],
61 ) -> Result<(), SPI::Error>;
62
63 /// Update only the black/white data of the display.
64 ///
65 /// This must be finished by calling `update_chromatic_frame`.
66 fn update_achromatic_frame(
67 &mut self,
68 spi: &mut SPI,
69 delay: &mut DELAY,
70 black: &[u8],
71 ) -> Result<(), SPI::Error>;
72
73 /// Update only the chromatic data of the display.
74 ///
75 /// This should be preceded by a call to `update_achromatic_frame`.
76 /// This data takes precedence over the black/white data.
77 fn update_chromatic_frame(
78 &mut self,
79 spi: &mut SPI,
80 delay: &mut DELAY,
81 chromatic: &[u8],
82 ) -> Result<(), SPI::Error>;
83}
84
85/// All the functions to interact with the EPDs
86///
87/// This trait includes all public functions to use the EPDs
88///
89/// # Example
90///
91///```rust, no_run
92///# use embedded_hal_mock::eh1::*;
93///# fn main() -> Result<(), embedded_hal::spi::ErrorKind> {
94///use embedded_graphics::{
95/// pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle},
96///};
97///use epd_waveshare::{epd4in2::*, prelude::*};
98///#
99///# let expectations = [];
100///# let mut spi = spi::Mock::new(&expectations);
101///# let expectations = [];
102///# let cs_pin = digital::Mock::new(&expectations);
103///# let busy_in = digital::Mock::new(&expectations);
104///# let dc = digital::Mock::new(&expectations);
105///# let rst = digital::Mock::new(&expectations);
106///# let mut delay = delay::NoopDelay::new();
107///
108///// Setup EPD
109///let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?;
110///
111///// Use display graphics from embedded-graphics
112///let mut display = Display4in2::default();
113///
114///// Use embedded graphics for drawing a line
115///
116///let _ = Line::new(Point::new(0, 120), Point::new(0, 295))
117/// .into_styled(PrimitiveStyle::with_stroke(Color::Black, 1))
118/// .draw(&mut display);
119///
120/// // Display updated frame
121///epd.update_frame(&mut spi, &display.buffer(), &mut delay)?;
122///epd.display_frame(&mut spi, &mut delay)?;
123///
124///// Set the EPD to sleep
125///epd.sleep(&mut spi, &mut delay)?;
126///# Ok(())
127///# }
128///```
129pub trait WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
130where
131 SPI: SpiDevice,
132 BUSY: InputPin,
133 DC: OutputPin,
134 RST: OutputPin,
135 DELAY: DelayNs,
136{
137 /// The Color Type used by the Display
138 type DisplayColor;
139 /// Creates a new driver from a SPI peripheral, CS Pin, Busy InputPin, DC
140 ///
141 /// `delay_us` is the number of us the idle loop should sleep on.
142 /// Setting it to 0 implies busy waiting.
143 /// Setting it to None means a default value is used.
144 ///
145 /// This already initialises the device.
146 fn new(
147 spi: &mut SPI,
148 busy: BUSY,
149 dc: DC,
150 rst: RST,
151 delay: &mut DELAY,
152 delay_us: Option<u32>,
153 ) -> Result<Self, SPI::Error>
154 where
155 Self: Sized;
156
157 /// Let the device enter deep-sleep mode to save power.
158 ///
159 /// The deep sleep mode returns to standby with a hardware reset.
160 fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
161
162 /// Wakes the device up from sleep
163 ///
164 /// Also reintialises the device if necessary.
165 fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
166
167 /// Sets the backgroundcolor for various commands like [clear_frame](WaveshareDisplay::clear_frame)
168 fn set_background_color(&mut self, color: Self::DisplayColor);
169
170 /// Get current background color
171 fn background_color(&self) -> &Self::DisplayColor;
172
173 /// Get the width of the display
174 fn width(&self) -> u32;
175
176 /// Get the height of the display
177 fn height(&self) -> u32;
178
179 /// Transmit a full frame to the SRAM of the EPD
180 fn update_frame(
181 &mut self,
182 spi: &mut SPI,
183 buffer: &[u8],
184 delay: &mut DELAY,
185 ) -> Result<(), SPI::Error>;
186
187 /// Transmits partial data to the SRAM of the EPD
188 ///
189 /// (x,y) is the top left corner
190 ///
191 /// BUFFER needs to be of size: width / 8 * height !
192 #[allow(clippy::too_many_arguments)]
193 fn update_partial_frame(
194 &mut self,
195 spi: &mut SPI,
196 delay: &mut DELAY,
197 buffer: &[u8],
198 x: u32,
199 y: u32,
200 width: u32,
201 height: u32,
202 ) -> Result<(), SPI::Error>;
203
204 /// Displays the frame data from SRAM
205 ///
206 /// This function waits until the device isn`t busy anymore
207 fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
208
209 /// Provide a combined update&display and save some time (skipping a busy check in between)
210 fn update_and_display_frame(
211 &mut self,
212 spi: &mut SPI,
213 buffer: &[u8],
214 delay: &mut DELAY,
215 ) -> Result<(), SPI::Error>;
216
217 /// Clears the frame buffer on the EPD with the declared background color
218 ///
219 /// The background color can be changed with [`WaveshareDisplay::set_background_color`]
220 fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
221
222 /// Trait for using various Waveforms from different LUTs
223 /// E.g. for partial refreshes
224 ///
225 /// A full refresh is needed after a certain amount of quick refreshes!
226 ///
227 /// WARNING: Quick Refresh might lead to ghosting-effects/problems with your display. Especially for the 4.2in Display!
228 ///
229 /// If None is used the old value will be loaded on the LUTs once more
230 fn set_lut(
231 &mut self,
232 spi: &mut SPI,
233 delay: &mut DELAY,
234 refresh_rate: Option<RefreshLut>,
235 ) -> Result<(), SPI::Error>;
236
237 /// Wait until the display has stopped processing data
238 ///
239 /// You can call this to make sure a frame is displayed before goin further
240 fn wait_until_idle(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error>;
241}
242
243/// Allows quick refresh support for displays that support it; lets you send both
244/// old and new frame data to support this.
245///
246/// When using the quick refresh look-up table, the display must receive separate display
247/// buffer data marked as old, and new. This is used to determine which pixels need to change,
248/// and how they will change. This isn't required when using full refreshes.
249///
250/// (todo: Example ommitted due to CI failures.)
251/// Example:
252///```rust, no_run
253///# use embedded_hal_mock::eh1::*;
254///# fn main() -> Result<(), embedded_hal::spi::ErrorKind> {
255///# use embedded_graphics::{
256///# pixelcolor::BinaryColor::On as Black, prelude::*, primitives::{Line, PrimitiveStyle},
257///# };
258///# use epd_waveshare::{epd4in2::*, prelude::*};
259///# use epd_waveshare::graphics::VarDisplay;
260///#
261///# let expectations = [];
262///# let mut spi = spi::Mock::new(&expectations);
263///# let expectations = [];
264///# let cs_pin = digital::Mock::new(&expectations);
265///# let busy_in = digital::Mock::new(&expectations);
266///# let dc = digital::Mock::new(&expectations);
267///# let rst = digital::Mock::new(&expectations);
268///# let mut delay = delay::NoopDelay::new();
269///#
270///# // Setup EPD
271///# let mut epd = Epd4in2::new(&mut spi, busy_in, dc, rst, &mut delay, None)?;
272///let (x, y, frame_width, frame_height) = (20, 40, 80,80);
273///
274///let mut buffer = [DEFAULT_BACKGROUND_COLOR.get_byte_value(); 80 / 8 * 80];
275///let mut display = VarDisplay::new(frame_width, frame_height, &mut buffer,false).unwrap();
276///
277///epd.update_partial_old_frame(&mut spi, &mut delay, display.buffer(), x, y, frame_width, frame_height)
278/// .ok();
279///
280///display.clear(Color::White).ok();
281///// Execute drawing commands here.
282///
283///epd.update_partial_new_frame(&mut spi, &mut delay, display.buffer(), x, y, frame_width, frame_height)
284/// .ok();
285///# Ok(())
286///# }
287///```
288pub trait QuickRefresh<SPI, BUSY, DC, RST, DELAY>
289where
290 SPI: SpiDevice,
291 BUSY: InputPin,
292 DC: OutputPin,
293 RST: OutputPin,
294 DELAY: DelayNs,
295{
296 /// Updates the old frame.
297 fn update_old_frame(
298 &mut self,
299 spi: &mut SPI,
300 buffer: &[u8],
301 delay: &mut DELAY,
302 ) -> Result<(), SPI::Error>;
303
304 /// Updates the new frame.
305 fn update_new_frame(
306 &mut self,
307 spi: &mut SPI,
308 buffer: &[u8],
309 delay: &mut DELAY,
310 ) -> Result<(), SPI::Error>;
311
312 /// Displays the new frame
313 fn display_new_frame(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error>;
314
315 /// Updates and displays the new frame.
316 fn update_and_display_new_frame(
317 &mut self,
318 spi: &mut SPI,
319 buffer: &[u8],
320 delay: &mut DELAY,
321 ) -> Result<(), SPI::Error>;
322
323 /// Updates the old frame for a portion of the display.
324 #[allow(clippy::too_many_arguments)]
325 fn update_partial_old_frame(
326 &mut self,
327 spi: &mut SPI,
328 delay: &mut DELAY,
329 buffer: &[u8],
330 x: u32,
331 y: u32,
332 width: u32,
333 height: u32,
334 ) -> Result<(), SPI::Error>;
335
336 /// Updates the new frame for a portion of the display.
337 #[allow(clippy::too_many_arguments)]
338 fn update_partial_new_frame(
339 &mut self,
340 spi: &mut SPI,
341 delay: &mut DELAY,
342 buffer: &[u8],
343 x: u32,
344 y: u32,
345 width: u32,
346 height: u32,
347 ) -> Result<(), SPI::Error>;
348
349 /// Clears the partial frame buffer on the EPD with the declared background color
350 /// The background color can be changed with [`WaveshareDisplay::set_background_color`]
351 fn clear_partial_frame(
352 &mut self,
353 spi: &mut SPI,
354 delay: &mut DELAY,
355 x: u32,
356 y: u32,
357 width: u32,
358 height: u32,
359 ) -> Result<(), SPI::Error>;
360}