epd_waveshare_async/
hw.rs1use embedded_hal::{
2 digital::{ErrorType as PinErrorType, InputPin, OutputPin, PinState},
3 spi::ErrorType as SpiErrorType,
4};
5use embedded_hal_async::{delay::DelayNs, digital::Wait, spi::SpiDevice};
6
7use crate::log::trace;
8
9pub trait ErrorHw {
14 type Error;
15}
16
17pub trait SpiHw {
19 type Spi: SpiDevice;
20}
21
22pub trait DcHw {
24 type Dc: OutputPin;
25
26 fn dc(&mut self) -> &mut Self::Dc;
27}
28
29pub trait ResetHw {
31 type Reset: OutputPin;
32
33 fn reset(&mut self) -> &mut Self::Reset;
34}
35
36pub trait BusyHw {
38 type Busy: InputPin + Wait;
39
40 fn busy(&mut self) -> &mut Self::Busy;
41
42 fn busy_when(&self) -> embedded_hal::digital::PinState;
47}
48
49pub trait DelayHw {
51 type Delay: DelayNs;
52
53 fn delay(&mut self) -> &mut Self::Delay;
54}
55
56pub(crate) trait BusyWait: ErrorHw {
58 async fn wait_if_busy(&mut self) -> Result<(), Self::Error>;
62}
63
64pub(crate) trait CommandDataSend: SpiHw + ErrorHw {
66 async fn send(
68 &mut self,
69 spi: &mut Self::Spi,
70 command: u8,
71 data: &[u8],
72 ) -> Result<(), Self::Error>;
73}
74
75impl<HW> BusyWait for HW
76where
77 HW: BusyHw + ErrorHw,
78 <HW as ErrorHw>::Error: From<<HW::Busy as PinErrorType>::Error>,
79{
80 async fn wait_if_busy(&mut self) -> Result<(), HW::Error> {
81 let busy_when = self.busy_when();
82 let busy = self.busy();
83 match busy_when {
84 PinState::High => {
85 if busy.is_high()? {
86 trace!("Waiting for busy EPD");
87 busy.wait_for_low().await?;
88 }
89 }
90 PinState::Low => {
91 if busy.is_low()? {
92 trace!("Waiting for busy EPD");
93 busy.wait_for_high().await?;
94 }
95 }
96 };
97 Ok(())
98 }
99}
100
101impl<HW> CommandDataSend for HW
102where
103 HW: DcHw + BusyHw + BusyWait + SpiHw + ErrorHw,
104 HW::Error: From<<HW::Spi as SpiErrorType>::Error>
105 + From<<HW::Dc as PinErrorType>::Error>
106 + From<<HW::Busy as PinErrorType>::Error>,
107{
108 async fn send(
109 &mut self,
110 spi: &mut Self::Spi,
111 command: u8,
112 data: &[u8],
113 ) -> Result<(), Self::Error> {
114 trace!("Sending EPD command: {:?}", command);
115 self.wait_if_busy().await?;
116
117 self.dc().set_low()?;
118 spi.write(&[command]).await?;
119
120 if !data.is_empty() {
121 self.dc().set_high()?;
122 spi.write(data).await?;
123 }
124
125 Ok(())
126 }
127}