use core::fmt::Debug;
use embedded_hal::delay::DelayNs;
use embedded_hal::digital::{InputPin, OutputPin};
use embedded_hal::spi::SpiDevice;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum EpdBusError<SPIE, DCE, RSTE, BUSYE> {
Spi(SPIE),
Dc(DCE),
Reset(RSTE),
Busy(BUSYE),
}
pub type SpiBusResult<SPIE, DCE, RSTE, BUSYE, T = ()> =
Result<T, EpdBusError<SPIE, DCE, RSTE, BUSYE>>;
pub struct SpiBusWrapper<SPI, DC, RST, BUSY> {
spi: SPI,
dc: DC,
rst: RST,
busy: BUSY,
}
impl<SPI, DC, RST, BUSY> SpiBusWrapper<SPI, DC, RST, BUSY>
where
SPI: SpiDevice,
DC: OutputPin,
RST: OutputPin,
BUSY: InputPin,
{
pub fn new(spi: SPI, dc: DC, rst: RST, busy: BUSY) -> Self {
Self { spi, dc, rst, busy }
}
pub fn spi_mut(&mut self) -> &mut SPI {
&mut self.spi
}
pub fn hard_reset<DELAY: DelayNs>(
&mut self,
delay: &mut DELAY,
reset_duration_ms: u32,
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
self.rst.set_high().map_err(EpdBusError::Reset)?;
delay.delay_ms(5);
self.rst.set_low().map_err(EpdBusError::Reset)?;
delay.delay_ms(reset_duration_ms);
self.rst.set_high().map_err(EpdBusError::Reset)?;
delay.delay_ms(reset_duration_ms);
Ok(())
}
pub fn wait_busy(
&mut self,
busy_active_high: bool,
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
let mut retries = 0u64;
loop {
let is_busy = self.busy.is_high().map_err(EpdBusError::Busy)?;
if is_busy == busy_active_high {
core::hint::spin_loop();
retries += 1;
if retries > 1_000_000_000 {
break;
}
} else {
break;
}
}
Ok(())
}
pub fn wait_busy_with_delay<DELAY: DelayNs>(
&mut self,
delay: &mut DELAY,
busy_active_high: bool,
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
let mut retries = 0u32;
loop {
let is_busy = self.busy.is_high().map_err(EpdBusError::Busy)?;
if is_busy == busy_active_high {
delay.delay_ms(1);
retries += 1;
if retries > 60_000 {
break;
}
} else {
break;
}
}
Ok(())
}
pub fn send_command(
&mut self,
command: u8,
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
self.dc.set_low().map_err(EpdBusError::Dc)?;
self.spi.write(&[command]).map_err(EpdBusError::Spi)
}
pub fn send_data(
&mut self,
data: &[u8],
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
if data.is_empty() {
return Ok(());
}
self.dc.set_high().map_err(EpdBusError::Dc)?;
self.spi.write(data).map_err(EpdBusError::Spi)
}
pub fn send_command_with_data(
&mut self,
command: u8,
data: &[u8],
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
self.send_command(command)?;
self.send_data(data)
}
pub fn send_data_repeated(
&mut self,
byte: u8,
count: usize,
) -> SpiBusResult<SPI::Error, DC::Error, RST::Error, BUSY::Error> {
if count == 0 {
return Ok(());
}
self.dc.set_high().map_err(EpdBusError::Dc)?;
let chunk = [byte; 64];
let mut remaining = count;
while remaining > 0 {
let write_len = remaining.min(chunk.len());
self.spi
.write(&chunk[..write_len])
.map_err(EpdBusError::Spi)?;
remaining -= write_len;
}
Ok(())
}
}