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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
//! # ESP-HUB75
//!
//! A `no-std` Rust driver for HUB75-style LED matrix panels on ESP32-series
//! microcontrollers. HUB75 is a standard interface for driving large, bright,
//! and colorful RGB LED displays, commonly used in digital signage and art
//! installations.
//!
//! This library provides a high-performance implementation that uses Direct
//! Memory Access (DMA) to drive the display with minimal CPU overhead. It is
//! designed to work with a variety of ESP32 models, using the most efficient
//! peripheral available on each chip:
//!
//! - **ESP32-S3**: Uses the LCD_CAM peripheral
//! - **ESP32-C6**: Uses the PARL_IO peripheral
//! - **ESP32-C5**: Uses the PARL_IO peripheral (8-bit mode only; requires a
//! latch circuit and `Hub75Pins8`)
//! - **ESP32**: Uses the I2S peripheral in parallel mode
//!
//! ## Framebuffers
//!
//! The `hub75-framebuffer` crate provides two families of framebuffer: the
//! **standard** framebuffers and the **bitplane** framebuffers. Each family
//! has a direct-drive variant (16-bit, no external latch) and a latched
//! variant (8-bit, requires an external address-latch circuit). Both families
//! can be sent directly to the peripheral without any extra formatting step.
//! The difference is how they achieve Binary Code Modulation (BCM):
//!
//! - **Standard** framebuffers (`framebuffer::plain::DmaFrameBuffer` /
//! `framebuffer::latched::DmaFrameBuffer`) pre-render a complete copy of the
//! pixel data for every BCM bit-weight. This makes DMA output straightforward
//! but multiplies memory usage by the number of frames (`frame_count`).
//! - **Bitplane** framebuffers (`framebuffer::bitplane::plain::DmaFrameBuffer`
//! / `framebuffer::bitplane::latched::DmaFrameBuffer`) store only one bit per
//! pixel per plane. The driver uses DMA descriptors to assemble the BCM
//! output on the fly, avoiding the duplicated memory. The result is
//! significantly lower RAM usage with the same visual quality.
//!
//! Bitplane framebuffers are strongly recommended for most applications.
//!
//! ## Usage
//!
//! Here is an example of how to initialize the driver for an ESP32-S3:
//!
//! ```rust,no_run
//! ```
//!
//! ## Crate Features
//!
//! - `esp32`: Enable support for the ESP32
//! - `esp32s3`: Enable support for the ESP32-S3
//! - `esp32c5`: Enable support for the ESP32-C5
//! - `esp32c6`: Enable support for the ESP32-C6
//! - `defmt`: Enable logging with `defmt`
//! - `log`: Enable logging with the `log` crate
//! - `invert-blank`: Invert the blank signal, required for some controller boards.
//! - `invert-clock`: Invert the clock signal. By default the driver outputs data
//! that changes on the falling edge of CLK so that it is stable when the panel
//! latches on the rising edge. Enable this feature if your panel requires the
//! opposite polarity.
//! - `skip-black-pixels`: Forwards to the `hub75-framebuffer` crate, enabling an
//! optimization that skips writing black pixels to the framebuffer.
//! - `iram`: Place the driver’s hot-path (render / DMA wait functions) in
//! Instruction RAM (IRAM) to avoid flash-cache stalls (for example during
//! Wi-Fi, PSRAM, or SPI-flash activity) that can cause visible flicker.
//! Enabling this feature consumes roughly 5–10 KiB of IRAM.
//!
//! ## Safety
//!
//! This crate uses `unsafe` code to interface with hardware peripherals, but it
//! exposes a safe, high-level API.
use AnyPin;
pub use hub75_framebuffer as framebuffer;
pub use Hub75;
pub use Hub75Transfer;
/// The color type used by the HUB75 driver.
pub use Color;
/// Computes the number of DMA descriptors required for a given framebuffer
/// configuration.
///
/// Users should prefer the [`hub75_dma_descriptors!`] macro which calls this
/// automatically. This function is public for advanced use cases.
///
/// # Arguments
/// * `bcm_chunk_count` - Number of BCM chunks (from
/// `FBType::bcm_chunk_count()`)
/// * `bcm_chunk_bytes` - Byte size of one BCM chunk (from
/// `FBType::bcm_chunk_bytes()`)
pub const
/// Allocates static DMA descriptors sized for the given framebuffer type.
///
/// This macro computes the required number of DMA descriptors at compile time
/// and allocates them in a static cell. It returns `&'static mut
/// [DmaDescriptor]` suitable for passing to [`Hub75::new`] or
/// [`Hub75::new_async`].
///
/// # Example
/// ```rust,ignore
/// type FBType = DmaFrameBuffer<NROWS, COLS, PLANES>;
/// let tx_descriptors = esp_hub75::hub75_dma_descriptors!(FBType);
/// ```
/// Pin configuration for a HUB75 panel without an external address latch.
///
/// This configuration requires 16 bits of data per pixel transfer, as the row
/// address lines are driven directly along with the color data.
/// Pin configuration for a HUB75 panel with an external address latch.
///
/// This configuration is more memory-efficient, requiring only 8 bits of data
/// per pixel transfer. The row address is set once per row and held by an
/// external latch on the controller board. For an example of a latch circuit,
/// see the [`hub75-framebuffer` crate documentation](https://crates.io/crates/hub75-framebuffer)
/// and its [GitHub repository](https://github.com/liebman/hub75-framebuffer).
/// A trait for applying a set of HUB75 pins onto the specific ESP32 peripheral
///
/// This allows the driver to abstract over the differences in pin
/// configurations between peripherals (I2S, LCD-CAM, PARL_IO) and between
/// direct-drive (16-bit) and latched (8-bit) HUB75 controller boards.
/// A trait for converting a set of HUB75 pins into the required format for a
/// specific ESP32 peripheral.
///
/// This allows the driver to abstract over the differences in pin
/// configurations between peripherals (I2S, LCD-CAM, PARL_IO) and between
/// direct-drive (16-bit) and latched (8-bit) HUB75 controller boards.
///
/// # Type Parameters
/// * `T` - The target pin configuration type for the specific peripheral.
/// Represents errors that can occur during HUB75 driver operations.
///
/// This enum consolidates errors from the underlying `esp-hal` DMA, peripheral,
/// and buffer management modules into a single type for easier error handling.