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
//! # `epdsi` — E-Paper Display Serial Interface Framework
//!
//! A `no_std`, [`embedded-hal`] 1.0 compatible driver framework for Electronic Paper
//! Displays (EPDs), covering seven driver ICs and ten panels behind one API.
//!
//! Most EPD crates bind one driver IC to one panel. `epdsi` separates the two, so adding
//! a panel to an existing controller is a single new file, and adding a controller does
//! not disturb the panels already supported.
//!
//! # Architecture
//!
//! Four pieces compose into a driver:
//!
//! - [`EpdPanel`] — a zero-sized type holding static physical facts about one panel:
//! [`WIDTH`](EpdPanel::WIDTH), [`HEIGHT`](EpdPanel::HEIGHT),
//! [`COLOR_MODE`](EpdPanel::COLOR_MODE), plus optional
//! [`vcom`](EpdPanel::vcom), [`custom_lut`](EpdPanel::custom_lut) and
//! [`gate_voltage`](EpdPanel::gate_voltage) overrides. See [`panels`].
//! - [`EpdController`] — the driver IC's command and register logic: init sequence,
//! window and cursor addressing, frame writes, refresh, sleep. See [`controllers`].
//! - [`SpiBusWrapper`] — the physical transport, wrapping an `embedded-hal` `SpiDevice`
//! plus DC, RST and BUSY pins. See [`bus`]. Panels needing OTP register reads over a
//! bit-banged 3-wire link use [`Spi3Bus`] instead (see [`bus3`]).
//! - [`EpdDriver`] — the orchestrator, built with [`EpdBuilder`], exposing the public
//! API: `init`, `set_window`, `write_frame`, `clear_frame`, `refresh`, `sleep`.
//!
//! Colour is unified across all panels by [`ColorMode`] and [`ColorChannel`], so
//! multi-buffer COGs (Pervasive's separate black/white and red RAM, for instance) are
//! always addressed explicitly rather than implicitly. Panels using the 4 bpp ACeP /
//! Spectra palette pack two pixels per byte through [`SevenColor::pack`].
//!
//! # Supported controllers and panels
//!
//! | Controller | Panels | Resolution | Colour mode |
//! | :--- | :--- | :--- | :--- |
//! | [`Ssd1681Controller`] | [`GDEM0154Z90`] | 200 × 200 | Tri-Color |
//! | [`Ssd1680Controller`] | [`GDEM0213B74`] | 122 × 250 | Monochrome |
//! | [`Jd79661Controller`] | [`ZJY122250_0213AJH_E5`] / [`GDEY0213F51`] | 122 × 250 | Quad-Color |
//! | [`Uc8253Controller`] | [`GDEY037T03`] | 240 × 416 | Monochrome |
//! | [`Ssd1677Controller`] | [`GDEQ0426T82`] | 800 × 480 | Monochrome |
//! | [`Ed2208Controller`] | [`GDEP073E01`] | 800 × 480 | Spectra 6 (4 bpp) |
//! | [`PervasiveBwController`] | [`E2266KS0C1`], [`E2290KS0F1`] | 152 × 296, 168 × 384 | Monochrome |
//! | [`PervasiveBwryController`] | [`E2154QS0F1`], [`E2417QS0A3`] | 152 × 152, 400 × 300 | Quad-Color (Spectra-4) |
//!
//! [`Ssd1680Controller`] and [`Ssd1681Controller`] are thin wrappers over the shared
//! [`Ssd168xController`]. Many panels also carry vendor-parity aliases, such as
//! `EPD_266_KS_0C` for [`E2266KS0C1`] or `GxEPD2_370_GDEY037T03` for [`GDEY037T03`].
//!
//! # Quick start
//!
//! ```rust,no_run
//! # use embedded_hal_mock::eh1::{
//! # spi::Mock as SpiMock, digital::Mock as PinMock, delay::NoopDelay,
//! # };
//! # let spi_device = SpiMock::<u8>::new(&[]);
//! # let (dc_pin, rst_pin, busy_pin) =
//! # (PinMock::new(&[]), PinMock::new(&[]), PinMock::new(&[]));
//! # let mut delay = NoopDelay;
//! # #[cfg(feature = "graphics")] {
//! use epdsi::prelude::*;
//! use embedded_graphics::{
//! prelude::*, primitives::{Rectangle, PrimitiveStyle},
//! pixelcolor::BinaryColor, geometry::{Point, Size},
//! };
//!
//! // Wrap the SPI device and its control pins.
//! let epd_bus = SpiBusWrapper::new(spi_device, dc_pin, rst_pin, busy_pin);
//! let controller = Ssd1681Controller::new(GDEM0154Z90::WIDTH, GDEM0154Z90::HEIGHT);
//!
//! // Bind controller and panel into a driver.
//! let mut epd = EpdBuilder::<_, GDEM0154Z90>::new(controller).build(epd_bus);
//! epd.init(&mut delay).unwrap();
//!
//! // Both RAM channels must be primed on a tri-colour panel.
//! epd.clear_frame(ColorChannel::BlackWhite, 0xFF).unwrap();
//! epd.clear_frame(ColorChannel::RedYellow, 0x00).unwrap();
//!
//! // Draw through embedded-graphics into a PageBuffer.
//! let mut bw_buf = [0xFFu8; 200 * 200 / 8];
//! let mut display = PageBuffer::new(&mut bw_buf, 200, 200, 0);
//! Rectangle::new(Point::new(10, 10), Size::new(50, 50))
//! .into_styled(PrimitiveStyle::with_fill(BinaryColor::On))
//! .draw(&mut display)
//! .unwrap();
//!
//! epd.write_frame(ColorChannel::BlackWhite, display.as_slice()).unwrap();
//! epd.refresh(&mut delay).unwrap();
//! # }
//! ```
//!
//! [`prelude`] re-exports everything above and is the intended single import.
//!
//! # Low-RAM paged rendering
//!
//! A full 800 × 480 monochrome frame is 48 KB — more than many targets have. Rather than
//! buffering a whole frame, [`render_paged`](graphics::render_paged) sweeps the panel one
//! horizontal band at a time, handing a small stack-allocated [`PageBuffer`] to a closure
//! for each band, writing it, and refreshing once at the end. This is the GxEPD2 paged
//! pattern; RAM use is set by the page height you choose, not by panel size.
//!
//! # Colour panels refresh slowly, and that is physics
//!
//! Tri-Color and Quad-Color panels have no fast differential waveform. The coloured
//! pigment is a heavier particle needing the full OTP waveform to migrate, so *every*
//! update takes seconds — roughly 14 s on [`GDEM0154Z90`]. Partial refresh modes select a
//! controller LUT that only exists for monochrome panels; on a colour panel it produces
//! wrong output rather than a fast update. Partial *window* updates still work, at full
//! refresh speed.
//!
//! # Cargo features
//!
//! - `graphics` *(default)* — implements `embedded-graphics-core`'s `DrawTarget` and
//! `Dimensions` for [`PageBuffer`]. Disable to drop the dependency; the buffer and
//! paged rendering still work, you just fill pixels yourself.
//! - `defmt` — derives `defmt::Format` on the public error and mode enums for logging on
//! embedded targets.
//!
//! # Hardware note
//!
//! On EXT3-1 extension boards, the **J3 jumper must be OPEN** (10 µH path) for panels
//! 3.7" and smaller. Closed (47 µH) the DC-DC booster sags during current bursts, which
//! shows up as BUSY-pin hangs that look like driver bugs but are not.
//!
//! # Complete examples
//!
//! Runnable, flashable programs for every supported controller live in
//! [`rust-rpico2-discovery`] (RP2350 Pico 2, `rp-hal`) and
//! [`rust-reterminal-e1002-examples`] (XIAO ESP32-S3, Embassy + `esp-hal`).
//!
//! The minimum supported Rust version is 1.75.
//!
//! [`Ssd168xController`]: controllers::Ssd168xController
//! [`Ssd1680Controller`]: controllers::Ssd1680Controller
//! [`Ssd1681Controller`]: controllers::Ssd1681Controller
//! [`Ssd1677Controller`]: controllers::Ssd1677Controller
//! [`Uc8253Controller`]: controllers::Uc8253Controller
//! [`Jd79661Controller`]: controllers::Jd79661Controller
//! [`Ed2208Controller`]: controllers::Ed2208Controller
//! [`PervasiveBwController`]: controllers::PervasiveBwController
//! [`PervasiveBwryController`]: controllers::PervasiveBwryController
//! [`GDEM0154Z90`]: panels::GDEM0154Z90
//! [`GDEM0213B74`]: panels::GDEM0213B74
//! [`ZJY122250_0213AJH_E5`]: panels::ZJY122250_0213AJH_E5
//! [`GDEY0213F51`]: panels::GDEY0213F51
//! [`GDEY037T03`]: panels::GDEY037T03
//! [`GDEQ0426T82`]: panels::GDEQ0426T82
//! [`GDEP073E01`]: panels::GDEP073E01
//! [`E2266KS0C1`]: panels::E2266KS0C1
//! [`E2290KS0F1`]: panels::E2290KS0F1
//! [`E2154QS0F1`]: panels::E2154QS0F1
//! [`E2417QS0A3`]: panels::E2417QS0A3
//! [`PageBuffer`]: graphics::PageBuffer
//! [`embedded-hal`]: https://docs.rs/embedded-hal/1.0.0/embedded_hal/
//! [`rust-rpico2-discovery`]: https://github.com/melastmohican/rust-rpico2-discovery
//! [`rust-reterminal-e1002-examples`]: https://github.com/melastmohican/rust-reterminal-e1002-examples
pub use SpiBusWrapper;
pub use Spi3Bus;
pub use ;
pub use ;