1use embedded_hal::{delay::*, digital::*, spi::SpiDevice};
58
59use crate::interface::DisplayInterface;
60use crate::traits::{
61 InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay,
62};
63
64pub const WIDTH: u32 = 128;
66pub const HEIGHT: u32 = 296;
68pub const DEFAULT_BACKGROUND_COLOR: Color = Color::White;
70
71const NUM_DISPLAY_BITS: u32 = WIDTH / 8 * HEIGHT;
72
73const IS_BUSY_LOW: bool = true;
74const VCOM_DATA_INTERVAL: u8 = 0x07;
75const WHITE_BORDER: u8 = 0x70;
76const BLACK_BORDER: u8 = 0x30;
77const CHROMATIC_BORDER: u8 = 0xb0;
78const FLOATING_BORDER: u8 = 0xF0;
79const SINGLE_BYTE_WRITE: bool = true;
80
81use crate::color::{Color, TriColor};
82
83pub(crate) mod command;
84use self::command::Command;
85use crate::buffer_len;
86
87#[cfg(feature = "graphics")]
90pub type Display2in9bc = crate::graphics::Display<
91 WIDTH,
92 HEIGHT,
93 false,
94 { buffer_len(WIDTH as usize, HEIGHT as usize) },
95 Color,
96>;
97
98pub struct Epd2in9bc<SPI, BUSY, DC, RST, DELAY> {
100 interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
101 color: Color,
102}
103
104impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
105 for Epd2in9bc<SPI, BUSY, DC, RST, DELAY>
106where
107 SPI: SpiDevice,
108 BUSY: InputPin,
109 DC: OutputPin,
110 RST: OutputPin,
111 DELAY: DelayNs,
112{
113 fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
114 self.interface.reset(delay, 10_000, 10_000);
117
118 self.interface
120 .cmd_with_data(spi, Command::BoosterSoftStart, &[0x17, 0x17, 0x17])?;
121
122 self.command(spi, Command::PowerOn)?;
124 delay.delay_us(5000);
125 self.wait_until_idle(spi, delay)?;
126
127 self.cmd_with_data(spi, Command::PanelSetting, &[0x8F])?;
129
130 self.cmd_with_data(
131 spi,
132 Command::VcomAndDataIntervalSetting,
133 &[WHITE_BORDER | VCOM_DATA_INTERVAL],
134 )?;
135
136 self.send_resolution(spi)?;
138
139 self.cmd_with_data(spi, Command::VcmDcSetting, &[0x0A])?;
140
141 self.wait_until_idle(spi, delay)?;
142
143 Ok(())
144 }
145}
146
147impl<SPI, BUSY, DC, RST, DELAY> WaveshareThreeColorDisplay<SPI, BUSY, DC, RST, DELAY>
148 for Epd2in9bc<SPI, BUSY, DC, RST, DELAY>
149where
150 SPI: SpiDevice,
151 BUSY: InputPin,
152 DC: OutputPin,
153 RST: OutputPin,
154 DELAY: DelayNs,
155{
156 fn update_color_frame(
157 &mut self,
158 spi: &mut SPI,
159 delay: &mut DELAY,
160 black: &[u8],
161 chromatic: &[u8],
162 ) -> Result<(), SPI::Error> {
163 self.update_achromatic_frame(spi, delay, black)?;
164 self.update_chromatic_frame(spi, delay, chromatic)
165 }
166
167 fn update_achromatic_frame(
171 &mut self,
172 spi: &mut SPI,
173 _delay: &mut DELAY,
174 black: &[u8],
175 ) -> Result<(), SPI::Error> {
176 self.interface.cmd(spi, Command::DataStartTransmission1)?;
177 self.interface.data(spi, black)?;
178 Ok(())
179 }
180
181 fn update_chromatic_frame(
185 &mut self,
186 spi: &mut SPI,
187 delay: &mut DELAY,
188 chromatic: &[u8],
189 ) -> Result<(), SPI::Error> {
190 self.interface.cmd(spi, Command::DataStartTransmission2)?;
191 self.interface.data(spi, chromatic)?;
192
193 self.wait_until_idle(spi, delay)?;
194 Ok(())
195 }
196}
197
198impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
199 for Epd2in9bc<SPI, BUSY, DC, RST, DELAY>
200where
201 SPI: SpiDevice,
202 BUSY: InputPin,
203 DC: OutputPin,
204 RST: OutputPin,
205 DELAY: DelayNs,
206{
207 type DisplayColor = Color;
208 fn new(
209 spi: &mut SPI,
210 busy: BUSY,
211 dc: DC,
212 rst: RST,
213 delay: &mut DELAY,
214 delay_us: Option<u32>,
215 ) -> Result<Self, SPI::Error> {
216 let interface = DisplayInterface::new(busy, dc, rst, delay_us);
217 let color = DEFAULT_BACKGROUND_COLOR;
218
219 let mut epd = Epd2in9bc { interface, color };
220
221 epd.init(spi, delay)?;
222
223 Ok(epd)
224 }
225
226 fn sleep(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
227 self.interface.cmd_with_data(
229 spi,
230 Command::VcomAndDataIntervalSetting,
231 &[FLOATING_BORDER | VCOM_DATA_INTERVAL],
232 )?;
233
234 self.command(spi, Command::PowerOff)?;
235 self.wait_until_idle(spi, delay)?;
237
238 self.cmd_with_data(spi, Command::DeepSleep, &[0xA5])?;
239
240 Ok(())
241 }
242
243 fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
244 self.init(spi, delay)
245 }
246
247 fn set_background_color(&mut self, color: Color) {
248 self.color = color;
249 }
250
251 fn background_color(&self) -> &Color {
252 &self.color
253 }
254
255 fn width(&self) -> u32 {
256 WIDTH
257 }
258
259 fn height(&self) -> u32 {
260 HEIGHT
261 }
262
263 fn update_frame(
264 &mut self,
265 spi: &mut SPI,
266 buffer: &[u8],
267 delay: &mut DELAY,
268 ) -> Result<(), SPI::Error> {
269 self.interface.cmd(spi, Command::DataStartTransmission1)?;
270
271 self.interface.data(spi, buffer)?;
272
273 let color = self.color.get_byte_value();
275
276 self.interface.cmd(spi, Command::DataStartTransmission2)?;
277 self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
278
279 self.wait_until_idle(spi, delay)?;
280 Ok(())
281 }
282
283 #[allow(unused)]
284 fn update_partial_frame(
285 &mut self,
286 spi: &mut SPI,
287 delay: &mut DELAY,
288 buffer: &[u8],
289 x: u32,
290 y: u32,
291 width: u32,
292 height: u32,
293 ) -> Result<(), SPI::Error> {
294 Ok(())
295 }
296
297 fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
298 self.command(spi, Command::DisplayRefresh)?;
299
300 self.wait_until_idle(spi, delay)?;
301 Ok(())
302 }
303
304 fn update_and_display_frame(
305 &mut self,
306 spi: &mut SPI,
307 buffer: &[u8],
308 delay: &mut DELAY,
309 ) -> Result<(), SPI::Error> {
310 self.update_frame(spi, buffer, delay)?;
311 self.display_frame(spi, delay)?;
312 Ok(())
313 }
314
315 fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
316 self.send_resolution(spi)?;
317
318 let color = DEFAULT_BACKGROUND_COLOR.get_byte_value();
319
320 self.interface.cmd(spi, Command::DataStartTransmission1)?;
322
323 self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
324
325 self.interface.cmd(spi, Command::DataStartTransmission2)?;
327 self.interface.data_x_times(spi, color, NUM_DISPLAY_BITS)?;
328
329 self.wait_until_idle(spi, delay)?;
330 Ok(())
331 }
332
333 fn set_lut(
334 &mut self,
335 _spi: &mut SPI,
336 _delay: &mut DELAY,
337 _refresh_rate: Option<RefreshLut>,
338 ) -> Result<(), SPI::Error> {
339 Ok(())
340 }
341
342 fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
343 self.interface.wait_until_idle(delay, IS_BUSY_LOW);
344 Ok(())
345 }
346}
347
348impl<SPI, BUSY, DC, RST, DELAY> Epd2in9bc<SPI, BUSY, DC, RST, DELAY>
349where
350 SPI: SpiDevice,
351 BUSY: InputPin,
352 DC: OutputPin,
353 RST: OutputPin,
354 DELAY: DelayNs,
355{
356 fn command(&mut self, spi: &mut SPI, command: Command) -> Result<(), SPI::Error> {
357 self.interface.cmd(spi, command)
358 }
359
360 fn send_data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> {
361 self.interface.data(spi, data)
362 }
363
364 fn cmd_with_data(
365 &mut self,
366 spi: &mut SPI,
367 command: Command,
368 data: &[u8],
369 ) -> Result<(), SPI::Error> {
370 self.interface.cmd_with_data(spi, command, data)
371 }
372
373 fn send_resolution(&mut self, spi: &mut SPI) -> Result<(), SPI::Error> {
374 let w = self.width();
375 let h = self.height();
376
377 self.command(spi, Command::ResolutionSetting)?;
378
379 self.send_data(spi, &[w as u8])?;
380 self.send_data(spi, &[(h >> 8) as u8])?;
381 self.send_data(spi, &[h as u8])
382 }
383
384 pub fn set_border_color(&mut self, spi: &mut SPI, color: TriColor) -> Result<(), SPI::Error> {
386 let border = match color {
387 TriColor::Black => BLACK_BORDER,
388 TriColor::White => WHITE_BORDER,
389 TriColor::Chromatic => CHROMATIC_BORDER,
390 };
391 self.cmd_with_data(
392 spi,
393 Command::VcomAndDataIntervalSetting,
394 &[border | VCOM_DATA_INTERVAL],
395 )
396 }
397}