1use embedded_hal::{
170 delay::DelayNs,
171 digital::{InputPin, OutputPin},
172 spi::SpiDevice,
173};
174
175use crate::color::TriColor;
176use crate::interface::DisplayInterface;
177use crate::traits::{
178 InternalWiAdditions, RefreshLut, WaveshareDisplay, WaveshareThreeColorDisplay,
179};
180
181pub(crate) mod command;
182use self::command::*;
183use crate::buffer_len;
184
185pub const WIDTH: u32 = 152;
187pub const HEIGHT: u32 = 296;
189
190const SINGLE_BYTE_WRITE: bool = true;
191
192pub const DEFAULT_BACKGROUND_COLOR: TriColor = TriColor::White;
194
195#[cfg(feature = "graphics")]
197pub type Display2in66b = crate::graphics::Display<
198 WIDTH,
199 HEIGHT,
200 false,
201 { buffer_len(WIDTH as usize, HEIGHT as usize) * 2 },
202 TriColor,
203>;
204
205pub struct Epd2in66b<SPI, BUSY, DC, RST, DELAY> {
207 interface: DisplayInterface<SPI, BUSY, DC, RST, DELAY, SINGLE_BYTE_WRITE>,
208 background: TriColor,
209}
210
211impl<SPI, BUSY, DC, RST, DELAY> InternalWiAdditions<SPI, BUSY, DC, RST, DELAY>
212 for Epd2in66b<SPI, BUSY, DC, RST, DELAY>
213where
214 SPI: SpiDevice,
215 BUSY: InputPin,
216 DC: OutputPin,
217 RST: OutputPin,
218 DELAY: DelayNs,
219{
220 fn init(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
221 self.hw_reset(delay)?;
223 self.sw_reset(spi, delay)?;
224 self.data_entry_mode(spi, DataEntryRow::XMinor, DataEntrySign::IncYIncX)?;
225 self.set_display_window(spi, 0, 0, WIDTH - 1, HEIGHT - 1)?;
226 self.update_control1(
227 spi,
228 WriteMode::Normal,
229 WriteMode::Normal,
230 OutputSource::S8ToS167,
231 )?;
232 self.set_cursor(spi, 0, 0)?;
233
234 Ok(())
235 }
236}
237
238impl<SPI, BUSY, DC, RST, DELAY> WaveshareThreeColorDisplay<SPI, BUSY, DC, RST, DELAY>
239 for Epd2in66b<SPI, BUSY, DC, RST, DELAY>
240where
241 SPI: SpiDevice,
242 BUSY: InputPin,
243 DC: OutputPin,
244 RST: OutputPin,
245 DELAY: DelayNs,
246{
247 fn update_color_frame(
248 &mut self,
249 spi: &mut SPI,
250 delay: &mut DELAY,
251 black: &[u8],
252 chromatic: &[u8],
253 ) -> Result<(), SPI::Error> {
254 self.update_achromatic_frame(spi, delay, black)?;
255 self.update_chromatic_frame(spi, delay, chromatic)
256 }
257
258 fn update_achromatic_frame(
259 &mut self,
260 spi: &mut SPI,
261 _delay: &mut DELAY,
262 black: &[u8],
263 ) -> Result<(), SPI::Error> {
264 self.set_cursor(spi, 0, 0)?;
265 self.interface.cmd(spi, Command::WriteBlackWhiteRAM)?;
266 self.interface.data(spi, black)
267 }
268
269 fn update_chromatic_frame(
270 &mut self,
271 spi: &mut SPI,
272 _delay: &mut DELAY,
273 chromatic: &[u8],
274 ) -> Result<(), SPI::Error> {
275 self.set_cursor(spi, 0, 0)?;
276 self.interface.cmd(spi, Command::WriteRedRAM)?;
277 self.interface.data(spi, chromatic)
278 }
279}
280
281impl<SPI, BUSY, DC, RST, DELAY> WaveshareDisplay<SPI, BUSY, DC, RST, DELAY>
282 for Epd2in66b<SPI, BUSY, DC, RST, DELAY>
283where
284 SPI: SpiDevice,
285 BUSY: InputPin,
286 DC: OutputPin,
287 RST: OutputPin,
288 DELAY: DelayNs,
289{
290 type DisplayColor = TriColor;
291
292 fn new(
293 spi: &mut SPI,
294 busy: BUSY,
295 dc: DC,
296 rst: RST,
297 delay: &mut DELAY,
298 delay_us: Option<u32>,
299 ) -> Result<Self, SPI::Error>
300 where
301 Self: Sized,
302 {
303 let mut epd = Self {
304 interface: DisplayInterface::new(busy, dc, rst, delay_us),
305 background: DEFAULT_BACKGROUND_COLOR,
306 };
307 epd.init(spi, delay)?;
308 Ok(epd)
309 }
310
311 fn sleep(&mut self, spi: &mut SPI, _delay: &mut DELAY) -> Result<(), SPI::Error> {
312 self.interface.cmd_with_data(
313 spi,
314 Command::DeepSleepMode,
315 &[DeepSleep::SleepLosingRAM as u8],
316 )
317 }
318
319 fn wake_up(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
320 self.init(spi, delay)
321 }
322
323 fn set_background_color(&mut self, color: Self::DisplayColor) {
324 self.background = color;
325 }
326
327 fn background_color(&self) -> &Self::DisplayColor {
328 &self.background
329 }
330
331 fn width(&self) -> u32 {
332 WIDTH
333 }
334
335 fn height(&self) -> u32 {
336 HEIGHT
337 }
338
339 fn update_frame(
340 &mut self,
341 spi: &mut SPI,
342 buffer: &[u8],
343 delay: &mut DELAY,
344 ) -> Result<(), SPI::Error> {
345 self.set_cursor(spi, 0, 0)?;
346 self.update_achromatic_frame(spi, delay, buffer)?;
347 self.red_pattern(spi, delay, PatW::W160, PatH::H296, StartWith::Zero) }
349
350 fn update_partial_frame(
351 &mut self,
352 spi: &mut SPI,
353 delay: &mut DELAY,
354 buffer: &[u8],
355 x: u32,
356 y: u32,
357 width: u32,
358 height: u32,
359 ) -> Result<(), SPI::Error> {
360 self.set_display_window(spi, x, y, x + width, y + height)?;
361 self.set_cursor(spi, x, y)?;
362 self.update_achromatic_frame(spi, delay, buffer)?;
363 self.set_display_window(spi, 0, 0, WIDTH, HEIGHT)
364 }
365
366 fn display_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
367 self.interface.cmd(spi, Command::MasterActivation)?;
368 self.wait_until_idle(delay)
369 }
370
371 fn update_and_display_frame(
372 &mut self,
373 spi: &mut SPI,
374 buffer: &[u8],
375 delay: &mut DELAY,
376 ) -> Result<(), SPI::Error> {
377 self.update_frame(spi, buffer, delay)?;
378 self.display_frame(spi, delay)
379 }
380
381 fn clear_frame(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
382 let (white, red) = match self.background {
383 TriColor::Black => (StartWith::Zero, StartWith::Zero),
384 TriColor::White => (StartWith::One, StartWith::Zero),
385 TriColor::Chromatic => (StartWith::Zero, StartWith::One),
386 };
387 self.black_white_pattern(spi, delay, PatW::W160, PatH::H296, white)?;
388 self.red_pattern(spi, delay, PatW::W160, PatH::H296, red)
389 }
390
391 fn set_lut(
392 &mut self,
393 _spi: &mut SPI,
394 _delay: &mut DELAY,
395 _refresh_rate: Option<RefreshLut>,
396 ) -> Result<(), SPI::Error> {
397 Ok(())
398 }
399
400 fn wait_until_idle(&mut self, _spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
401 self.wait_until_idle(delay)
402 }
403}
404
405impl<SPI, BUSY, DC, RST, DELAY> Epd2in66b<SPI, BUSY, DC, RST, DELAY>
407where
408 SPI: SpiDevice,
409 BUSY: InputPin,
410 DC: OutputPin,
411 RST: OutputPin,
412 DELAY: DelayNs,
413{
414 fn wait_until_idle(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> {
415 self.interface.wait_until_idle(delay, false);
416 Ok(())
417 }
418 fn hw_reset(&mut self, delay: &mut DELAY) -> Result<(), SPI::Error> {
419 self.interface.reset(delay, 20_000, 2_000);
421 self.wait_until_idle(delay)
422 }
423 fn sw_reset(&mut self, spi: &mut SPI, delay: &mut DELAY) -> Result<(), SPI::Error> {
424 self.interface.cmd(spi, Command::Reset)?;
425 self.wait_until_idle(delay)
426 }
427 fn data_entry_mode(
428 &mut self,
429 spi: &mut SPI,
430 row: DataEntryRow,
431 sign: DataEntrySign,
432 ) -> Result<(), SPI::Error> {
433 self.interface
434 .cmd_with_data(spi, Command::DataEntryMode, &[row as u8 | sign as u8])
435 }
436 fn set_display_window(
437 &mut self,
438 spi: &mut SPI,
439 xstart: u32,
440 ystart: u32,
441 xend: u32,
442 yend: u32,
443 ) -> Result<(), SPI::Error> {
444 self.interface.cmd_with_data(
445 spi,
446 Command::SetXAddressRange,
447 &[(((xstart >> 3) & 0x1f) as u8), (((xend >> 3) & 0x1f) as u8)],
448 )?;
449 self.interface.cmd_with_data(
450 spi,
451 Command::SetYAddressRange,
452 &[
453 ((ystart & 0xff) as u8),
454 (((ystart >> 8) & 0x01) as u8),
455 ((yend & 0xff) as u8),
456 (((yend >> 8) & 0x01) as u8),
457 ],
458 )
459 }
460 fn update_control1(
461 &mut self,
462 spi: &mut SPI,
463 red_mode: WriteMode,
464 bw_mode: WriteMode,
465 source: OutputSource,
466 ) -> Result<(), SPI::Error> {
467 self.interface.cmd_with_data(
468 spi,
469 Command::DisplayUpdateControl1,
470 &[((red_mode as u8) << 4 | bw_mode as u8), (source as u8)],
471 )
472 }
473
474 fn set_cursor(&mut self, spi: &mut SPI, x: u32, y: u32) -> Result<(), SPI::Error> {
475 self.interface.cmd_with_data(
476 spi,
477 Command::SetXAddressCounter,
478 &[((x >> 3) & 0x1f) as u8],
479 )?;
480 self.interface.cmd_with_data(
481 spi,
482 Command::SetYAddressCounter,
483 &[((y & 0xff) as u8), (((y >> 8) & 0x01) as u8)],
484 )
485 }
486
487 fn black_white_pattern(
488 &mut self,
489 spi: &mut SPI,
490 delay: &mut DELAY,
491 w: PatW,
492 h: PatH,
493 phase: StartWith,
494 ) -> Result<(), SPI::Error> {
495 self.interface.cmd_with_data(
496 spi,
497 Command::BlackWhiteRAMTestPattern,
498 &[phase as u8 | h as u8 | w as u8],
499 )?;
500 self.wait_until_idle(delay)
501 }
502 fn red_pattern(
503 &mut self,
504 spi: &mut SPI,
505 delay: &mut DELAY,
506 w: PatW,
507 h: PatH,
508 phase: StartWith,
509 ) -> Result<(), SPI::Error> {
510 self.interface.cmd_with_data(
511 spi,
512 Command::RedRAMTestPattern,
513 &[phase as u8 | h as u8 | w as u8],
514 )?;
515 self.wait_until_idle(delay)
516 }
517}