use display_interface::DisplayError;
use embedded_hal::{
delay::DelayNs,
digital::{InputPin, OutputPin},
spi::SpiDevice,
};
const RESET_DELAY_MS: u8 = 10;
pub struct SpiDisplayInterface<SPI, BSY, DC, RST> {
spi: SPI,
busy: BSY,
dc: DC,
rst: RST,
}
impl<SPI, BSY, DC, RST> SpiDisplayInterface<SPI, BSY, DC, RST> {
pub fn new(spi: SPI, busy: BSY, dc: DC, rst: RST) -> Self {
SpiDisplayInterface { spi, busy, dc, rst }
}
}
impl<SPI, BSY, DC, RST> SpiDisplayInterface<SPI, BSY, DC, RST>
where
SPI: SpiDevice,
RST: OutputPin,
DC: OutputPin,
BSY: InputPin,
{
pub(crate) fn cmd(&mut self, command: u8) -> Result<(), DisplayError> {
log::trace!("cmd 0x{:02X}", command);
self.dc.set_low().map_err(|_| DisplayError::DCError)?;
self.spi
.write(&[command])
.map_err(|_| DisplayError::BusWriteError)
}
pub(crate) fn data(&mut self, data: &[u8]) -> Result<(), DisplayError> {
self.dc.set_high().map_err(|_| DisplayError::DCError)?;
self.spi
.write(data)
.map_err(|_| DisplayError::BusWriteError)
}
pub(crate) fn cmd_with_data(&mut self, command: u8, data: &[u8]) -> Result<(), DisplayError> {
log::trace!("cmd 0x{:02X}, data {:02X?}", command, data);
self.cmd(command)?;
self.data(data)
}
pub(crate) fn data_x_times(&mut self, val: u8, repetitions: u32) -> Result<(), DisplayError> {
log::trace!("writing data 0x{:02X} x {}", val, repetitions);
let _ = self.dc.set_high();
for _ in 0..repetitions {
self.spi
.write(&[val])
.map_err(|_| DisplayError::BusWriteError)?;
}
Ok(())
}
pub(crate) fn wait_until_idle(&mut self, delay: &mut impl DelayNs) {
log::trace!("Waiting until display is idle");
while self.busy.is_high().unwrap_or(true) {
delay.delay_ms(1)
}
}
pub(crate) fn wait_until_idle_active_low(&mut self, delay: &mut impl DelayNs) {
log::trace!("Waiting until display is idle (active-low busy)");
while self.busy.is_low().unwrap_or(true) {
delay.delay_ms(1)
}
}
pub(crate) fn hard_reset(&mut self, delay: &mut impl DelayNs) -> Result<(), DisplayError> {
log::trace!("Resetting display");
self.rst.set_low().map_err(|_| DisplayError::RSError)?;
delay.delay_ms(RESET_DELAY_MS.into());
self.rst.set_high().map_err(|_| DisplayError::RSError)?;
delay.delay_ms(RESET_DELAY_MS.into());
Ok(())
}
}