use core::fmt::Debug;
use core::marker::PhantomData;
use embedded_hal::{
blocking::{delay::DelayMs, spi::Write},
digital::v2::{InputPin, OutputPin},
};
const RESET_DELAY_MS: u8 = 10;
pub(crate) struct DisplayInterface<SPI, CS, BUSY, DC, RST> {
_spi: PhantomData<SPI>,
cs: CS,
busy: BUSY,
dc: DC,
rst: RST,
}
impl<SPI, CS, BUSY, DC, RST> DisplayInterface<SPI, CS, BUSY, DC, RST>
where
SPI: Write<u8>,
CS: OutputPin,
CS::Error: Debug,
BUSY: InputPin,
DC: OutputPin,
DC::Error: Debug,
RST: OutputPin,
RST::Error: Debug,
{
pub fn new(cs: CS, busy: BUSY, dc: DC, rst: RST) -> Self {
DisplayInterface {
_spi: PhantomData::default(),
cs,
busy,
dc,
rst,
}
}
pub(crate) fn cmd(&mut self, spi: &mut SPI, command: u8) -> Result<(), SPI::Error> {
self.dc.set_low().unwrap();
self.write(spi, &[command])
}
pub(crate) fn data(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> {
self.dc.set_high().unwrap();
self.write(spi, data)
}
pub(crate) fn cmd_with_data(
&mut self,
spi: &mut SPI,
command: u8,
data: &[u8],
) -> Result<(), SPI::Error> {
self.cmd(spi, command)?;
self.data(spi, data)
}
pub(crate) fn data_x_times(
&mut self,
spi: &mut SPI,
val: u8,
repetitions: u32,
) -> Result<(), SPI::Error> {
let _ = self.dc.set_high();
for _ in 0..repetitions {
self.write(spi, &[val])?;
}
Ok(())
}
pub(crate) fn wait_until_idle(&mut self) {
while self.busy.is_high().unwrap_or(true) {}
}
pub(crate) fn reset<DELAY: DelayMs<u8>>(&mut self, delay: &mut DELAY) {
self.rst.set_low().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.rst.set_high().unwrap();
delay.delay_ms(RESET_DELAY_MS);
}
fn write(&mut self, spi: &mut SPI, data: &[u8]) -> Result<(), SPI::Error> {
self.cs.set_low().unwrap();
if cfg!(target_os = "linux") {
for data_chunk in data.chunks(4096) {
spi.write(data_chunk)?;
}
} else {
spi.write(data)?;
}
self.cs.set_high().unwrap();
Ok(())
}
}