1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
//! This crate provides an `async`/`await` interface for controlling Waveshare E-Paper displays.
//!
//! It is built on top of `embedded-hal-async` and `embedded-graphics`, making it compatible with a
//! wide range of embedded platforms.
//!
//! ## Core traits
//!
//! ### Hardware
//!
//! The user must implement the `XHw` traits for their hardware that are needed by their display.
//! These traits abstract over common hardware functionality that displays need, like SPI
//! communication, GPIO pins (for Data/Command, Reset, and Busy) and a delay timer. You need to
//! implement these traits for your chosen peripherals. This trades off some set up code (
//! implementing these traits), for simple type signatures with fewer generic parameters.
//!
//! See the [crate::hw] module for more.
//!
//! ### Functionality
//!
//! Functionality is split into composable traits, to enable granular support per display, and
//! stateful functionality that can be checked at compilation time.
//!
//! * [Reset]: basic hardware reset support
//! * [Sleep]: displays that can be put to sleep
//! * [Wake]: displays that can be woken from sleep
//! * [DisplaySimple]: basic support for writing and displaying a single framebuffer
//! * [DisplayPartial]: support for partial refresh using a diff
//!
//! Additionally, the crate provides:
//!
//! - [`buffer`] module: Contains utilities for creating and managing efficient display buffers that
//! implement `embedded-graphics::DrawTarget`. These are designed to be fast and compact.
//! - various `<display>` modules: each display lives in its own module, such as `epd2in9` for the 2.9"
//! e-paper display.
use SpiDevice;
/// This module provides hardware abstraction traits that can be used by display drivers.
/// You should implement all the traits on a single struct, so that you can pass this one
/// hardware struct to your display driver.
///
/// Example that remains generic over the specific SPI bus:
///
/// ```
/// # use core::convert::Infallible;
/// # use core::marker::PhantomData;
/// use embassy_embedded_hal::shared_bus::asynch::spi::SpiDevice as EmbassySpiDevice;
/// use embassy_embedded_hal::shared_bus::SpiDeviceError;
/// use embassy_rp::gpio::{Input, Level, Output, Pin, Pull};
/// use embassy_rp::spi;
/// use embassy_rp::Peri;
/// use embassy_sync::blocking_mutex::raw::NoopRawMutex;
/// use embedded_hal::digital::PinState;
/// use epd_waveshare_async::hw::{BusyHw, DcHw, DelayHw, ErrorHw, ResetHw, SpiHw};
/// use thiserror::Error as ThisError;
///
/// /// Defines the hardware to use for connecting to the display.
/// pub struct DisplayHw<'a, SPI> {
/// dc: Output<'a>,
/// reset: Output<'a>,
/// busy: Input<'a>,
/// delay: embassy_time::Delay,
/// _spi_type: PhantomData<SPI>,
/// }
///
/// impl<'a, SPI: spi::Instance> DisplayHw<'a, SPI> {
/// pub fn new<DC: Pin, RESET: Pin, BUSY: Pin>(
/// dc: Peri<'a, DC>,
/// reset: Peri<'a, RESET>,
/// busy: Peri<'a, BUSY>,
/// ) -> Self {
/// let dc = Output::new(dc, Level::High);
/// let reset = Output::new(reset, Level::High);
/// let busy = Input::new(busy, Pull::Up);
///
/// Self {
/// dc,
/// reset,
/// busy,
/// delay: embassy_time::Delay,
/// _spi_type: PhantomData,
/// }
/// }
/// }
///
/// impl<'a, SPI> ErrorHw for DisplayHw<'a, SPI> {
/// type Error = Error;
/// }
///
/// impl<'a, SPI> DcHw for DisplayHw<'a, SPI> {
/// type Dc = Output<'a>;
///
/// fn dc(&mut self) -> &mut Self::Dc {
/// &mut self.dc
/// }
/// }
///
/// impl<'a, SPI> ResetHw for DisplayHw<'a, SPI> {
/// type Reset = Output<'a>;
///
/// fn reset(&mut self) -> &mut Self::Reset {
/// &mut self.reset
/// }
/// }
///
/// impl<'a, SPI> BusyHw for DisplayHw<'a, SPI> {
/// type Busy = Input<'a>;
///
/// fn busy(&mut self) -> &mut Self::Busy {
/// &mut self.busy
/// }
///
/// fn busy_when(&self) -> embedded_hal::digital::PinState {
/// epd_waveshare_async::epd2in9::DEFAULT_BUSY_WHEN
/// }
/// }
///
/// impl<'a, SPI> DelayHw for DisplayHw<'a, SPI> {
/// type Delay = embassy_time::Delay;
///
/// fn delay(&mut self) -> &mut Self::Delay {
/// &mut self.delay
/// }
/// }
///
/// impl<'a, SPI: spi::Instance + 'a> SpiHw for DisplayHw<'a, SPI> {
/// type Spi = EmbassySpiDevice<'a, NoopRawMutex, spi::Spi<'a, SPI, spi::Async>, Output<'a>>;
/// }
///
/// type RawSpiError = SpiDeviceError<spi::Error, Infallible>;
///
/// #[derive(Debug, ThisError)]
/// pub enum Error {
/// #[error("SPI error: {0:?}")]
/// SpiError(RawSpiError),
/// }
///
/// impl From<Infallible> for Error {
/// fn from(_: Infallible) -> Self {
/// unreachable!()
/// }
/// }
///
/// impl From<RawSpiError> for Error {
/// fn from(e: RawSpiError) -> Self {
/// Error::SpiError(e)
/// }
/// }
/// ```
use crateBufferView;
/// Displays that have a hardware reset.
/// Displays that can sleep to save power.
/// Displays that can be woken from a sleep state.
/// Base trait for any display where the display can be updated separate from its framebuffer data.
/// Simple displays that support writing and displaying framebuffers of a certain bit configuration.
///
/// `BITS` indicates the colour depth of each frame, and `FRAMES` indicates the total number of frames that
/// represent a complete image. For example, some 4-colour greyscale display might accept data as two
/// separate 1-bit frames instead of one frame of 2-bit pixels. This distinction is exposed so that
/// framebuffers can be written directly to displays without temp copies or transformations.
/// Displays that support a partial update, where a "diff" framebuffer is diffed against a base
/// framebuffer, and only the changed pixels from the diff are actually updated.