use crate::command::BufCommand;
use core::fmt::Debug;
use hal;
const RESET_DELAY_MS: u32 = 10;
pub trait DisplayInterface {
type Error;
fn send_command(&mut self, command: u8) -> Result<(), Self::Error>;
fn send_data(&mut self, data: &[u8]) -> Result<(), Self::Error>;
fn reset<D: hal::delay::DelayNs>(&mut self, delay: &mut D);
fn busy_wait(&mut self);
fn epd_update_data(&mut self, layer: u8, nbytes: u16, buf: &[u8]) -> Result<(), Self::Error>;
#[cfg(feature = "sram")]
fn sram_epd_update_data(
&mut self,
layer: u8,
nbytes: u16,
start_address: u16,
) -> Result<(), Self::Error>;
#[cfg(feature = "sram")]
fn sram_read(&mut self, address: u16, data: &mut [u8]) -> Result<(), Self::Error>;
#[cfg(feature = "sram")]
fn sram_write(&mut self, address: u16, data: &[u8]) -> Result<(), Self::Error>;
#[cfg(feature = "sram")]
fn sram_clear(&mut self, address: u16, nbytes: u16, val: u8) -> Result<(), Self::Error>;
}
pub struct Interface<SPI, CS, BUSY, DC, RESET> {
spi: SPI,
cs: CS,
busy: BUSY,
dc: DC,
reset: RESET,
}
impl<SPI, CS, BUSY, DC, RESET> Interface<SPI, CS, BUSY, DC, RESET>
where
SPI: hal::spi::SpiBus,
CS: hal::digital::OutputPin,
BUSY: hal::digital::InputPin,
DC: hal::digital::OutputPin,
RESET: hal::digital::OutputPin,
{
pub fn new(spi: SPI, pins: (CS, BUSY, DC, RESET)) -> Self {
Self {
spi,
cs: pins.0,
busy: pins.1,
dc: pins.2,
reset: pins.3,
}
}
pub fn release(self) -> (SPI, (CS, BUSY, DC, RESET)) {
(self.spi, (self.cs, self.busy, self.dc, self.reset))
}
fn write(&mut self, data: &[u8]) -> Result<(), SPI::Error> {
self.cs.set_low().ok();
if cfg!(target_os = "linux") {
for data_chunk in data.chunks(4096) {
self.spi.write(data_chunk)?;
}
} else {
self.spi.write(data)?;
}
self.cs.set_high().ok();
Ok(())
}
}
impl<SPI, CS, BUSY, DC, RESET> DisplayInterface for Interface<SPI, CS, BUSY, DC, RESET>
where
SPI: hal::spi::SpiBus,
CS: hal::digital::OutputPin,
CS::Error: Debug,
BUSY: hal::digital::InputPin,
DC: hal::digital::OutputPin,
DC::Error: Debug,
RESET: hal::digital::OutputPin,
RESET::Error: Debug,
{
type Error = SPI::Error;
fn reset<D: hal::delay::DelayNs>(&mut self, delay: &mut D) {
self.reset.set_low().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_low().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_low().unwrap();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().unwrap();
delay.delay_ms(RESET_DELAY_MS);
}
fn send_command(&mut self, command: u8) -> Result<(), Self::Error> {
self.dc.set_low().unwrap();
self.write(&[command])?;
self.dc.set_high().unwrap();
Ok(())
}
fn send_data(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.dc.set_high().unwrap();
self.write(data)
}
#[cfg(feature = "sram")]
fn sram_read(&mut self, _address: u16, _data: &mut [u8]) -> Result<(), Self::Error> {
panic!()
}
#[cfg(feature = "sram")]
fn sram_write(&mut self, _address: u16, _data: &[u8]) -> Result<(), Self::Error> {
panic!()
}
#[cfg(feature = "sram")]
fn sram_clear(&mut self, _address: u16, _nbytes: u16, _val: u8) -> Result<(), Self::Error> {
panic!()
}
#[cfg(feature = "sram")]
fn sram_epd_update_data(
&mut self,
_layer: u8,
_nbytes: u16,
_start_address: u16,
) -> Result<(), Self::Error> {
panic!()
}
fn epd_update_data(&mut self, layer: u8, nbytes: u16, buf: &[u8]) -> Result<(), Self::Error> {
let sz: usize = nbytes.into();
if layer == 0 {
BufCommand::WriteBlackData(&buf[..sz]).execute(self)
} else {
BufCommand::WriteRedData(&buf[..sz]).execute(self)
}
}
fn busy_wait(&mut self) {
while match self.busy.is_high() {
Ok(x) => x,
_ => false,
} {}
}
}
#[cfg(feature = "sram")]
const MCPSRAM_READ: u8 = 0x03;
#[cfg(feature = "sram")]
const MCPSRAM_WRITE: u8 = 0x02;
#[cfg(feature = "sram")]
const MCPSRAM_WRSR: u8 = 0x01;
#[cfg(feature = "sram")]
const K640_SEQUENTIAL_MODE: u8 = 1 << 6;
#[cfg(feature = "sram")]
pub struct SpiSramBus<SPI, EPDCS, SRAMCS> {
spi: SPI,
epd_cs: EPDCS,
sram_cs: SRAMCS,
}
#[cfg(feature = "sram")]
impl<SPI, EPDCS, SRAMCS> SpiSramBus<SPI, EPDCS, SRAMCS>
where
SPI: hal::spi::SpiBus,
EPDCS: hal::digital::OutputPin,
SRAMCS: hal::digital::OutputPin,
{
pub fn new(spi: SPI, mut pins: (EPDCS, SRAMCS)) -> SpiSramBus<SPI, EPDCS, SRAMCS> {
pins.0.set_high().ok();
pins.1.set_high().ok();
SpiSramBus {
spi,
epd_cs: pins.0,
sram_cs: pins.1,
}
}
pub fn release(self) -> (SPI, (EPDCS, SRAMCS)) {
(self.spi, (self.epd_cs, self.sram_cs))
}
pub fn sram_init(&mut self) -> Result<(), SPI::Error> {
self.sram_cs.set_low().ok();
self.spi.write(&[0xFF, 0xFF, 0xFF])?;
self.sram_cs.set_high().ok();
Ok(())
}
pub fn sram_seq(&mut self) -> Result<(), SPI::Error> {
self.sram_cs.set_low().ok();
self.spi.write(&[MCPSRAM_WRSR, K640_SEQUENTIAL_MODE])?;
self.sram_cs.set_high().ok();
Ok(())
}
pub fn sram_write(&mut self, address: u16, data: &[u8]) -> Result<(), SPI::Error> {
self.sram_cs.set_low().ok();
self.spi
.write(&[MCPSRAM_WRITE, (address >> 8) as u8, (address & 0xFF) as u8])?;
self.spi.write(data)?;
self.sram_cs.set_high().ok();
Ok(())
}
pub fn sram_read(&mut self, address: u16, data: &mut [u8]) -> Result<(), SPI::Error> {
self.sram_cs.set_low().ok();
self.spi
.write(&[MCPSRAM_READ, (address >> 8) as u8, (address & 0xFF) as u8])?;
self.spi.read(data)?;
self.sram_cs.set_high().ok();
Ok(())
}
pub fn sram_erase(&mut self, address: u16, len: u16, val: u8) -> Result<(), SPI::Error> {
if len % 4 != 0 {
panic!("sram_erase expects a len divisible by 4");
}
self.sram_cs.set_low().ok();
self.spi
.write(&[MCPSRAM_WRITE, (address >> 8) as u8, (address & 0xFF) as u8])?;
for _i in 0..len / 4 {
self.spi.write(&mut [val, val, val, val])?;
}
self.sram_cs.set_high().ok();
Ok(())
}
pub fn sram_epd_move_header(
&mut self,
address: u16,
epd_location: u8,
) -> Result<u8, SPI::Error> {
self.sram_cs.set_low().ok();
self.spi
.write(&[MCPSRAM_READ, (address >> 8) as u8, (address & 0xFF) as u8])?;
self.epd_cs.set_low().ok();
let mut loc = [epd_location];
self.spi.read(&mut loc)?;
Ok(loc[0])
}
pub fn sram_epd_move_body(&mut self, ch: u8, data_len: u16) -> Result<(), SPI::Error> {
let mut c = [ch];
for _i in 0..data_len {
let recvd = c[0];
self.spi.transfer(&mut c, &[recvd])?;
}
self.epd_cs.set_high().ok();
self.sram_cs.set_high().ok();
Ok(())
}
pub fn epd_write(&mut self, data: &[u8]) -> Result<(), SPI::Error> {
self.epd_cs.set_low().ok();
self.spi.write(data)?;
self.epd_cs.set_high().ok();
Ok(())
}
}
#[cfg(feature = "sram")]
pub struct SramDisplayInterface<SPI, EPDCS, SRAMCS, BUSY, DC, RESET> {
spi_bus: SpiSramBus<SPI, EPDCS, SRAMCS>,
busy: BUSY,
dc: DC,
reset: RESET,
}
#[cfg(feature = "sram")]
impl<SPI, EPDCS, SRAMCS, BUSY, DC, RESET> SramDisplayInterface<SPI, EPDCS, SRAMCS, BUSY, DC, RESET>
where
SPI: hal::spi::SpiBus,
EPDCS: hal::digital::OutputPin,
SRAMCS: hal::digital::OutputPin,
BUSY: hal::digital::InputPin,
DC: hal::digital::OutputPin,
RESET: hal::digital::OutputPin,
{
pub fn new(
spi_bus: SpiSramBus<SPI, EPDCS, SRAMCS>,
mut pins: (BUSY, DC, RESET),
) -> SramDisplayInterface<SPI, EPDCS, SRAMCS, BUSY, DC, RESET> {
pins.1.set_low().ok();
pins.2.set_high().ok();
SramDisplayInterface {
spi_bus,
busy: pins.0,
dc: pins.1,
reset: pins.2,
}
}
pub fn release(self) -> (SpiSramBus<SPI, EPDCS, SRAMCS>, (BUSY, DC, RESET)) {
(self.spi_bus, (self.busy, self.dc, self.reset))
}
}
#[cfg(feature = "sram")]
impl<SPI, EPDCS, SRAMCS, BUSY, DC, RESET> DisplayInterface
for SramDisplayInterface<SPI, EPDCS, SRAMCS, BUSY, DC, RESET>
where
SPI: hal::spi::SpiBus,
EPDCS: hal::digital::OutputPin,
SRAMCS: hal::digital::OutputPin,
BUSY: hal::digital::InputPin,
DC: hal::digital::OutputPin,
RESET: hal::digital::OutputPin,
{
type Error = SPI::Error;
fn send_command(&mut self, command: u8) -> Result<(), Self::Error> {
self.dc.set_low().ok();
self.spi_bus.epd_write(&mut [command])
}
fn send_data(&mut self, data: &[u8]) -> Result<(), Self::Error> {
self.dc.set_high().ok();
self.spi_bus.epd_write(data)
}
fn reset<D: hal::delay::DelayNs>(&mut self, delay: &mut D) {
self.spi_bus.sram_init().ok();
self.reset.set_low().ok();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().ok();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_low().ok();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().ok();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_low().ok();
delay.delay_ms(RESET_DELAY_MS);
self.reset.set_high().ok();
delay.delay_ms(RESET_DELAY_MS);
self.spi_bus.sram_seq().ok();
}
fn busy_wait(&mut self) {
while match self.busy.is_high() {
Ok(x) => x,
_ => false,
} {}
}
fn epd_update_data(
&mut self,
_layer: u8,
_nbytes: u16,
_buf: &[u8],
) -> Result<(), Self::Error> {
panic!()
}
fn sram_read(&mut self, address: u16, data: &mut [u8]) -> Result<(), Self::Error> {
self.spi_bus.sram_read(address, data)
}
fn sram_write(&mut self, address: u16, data: &[u8]) -> Result<(), Self::Error> {
self.spi_bus.sram_write(address, data)
}
fn sram_clear(&mut self, address: u16, nbytes: u16, val: u8) -> Result<(), Self::Error> {
self.spi_bus.sram_erase(address, nbytes, val)
}
fn sram_epd_update_data(
&mut self,
layer: u8,
nbytes: u16,
start_address: u16,
) -> Result<(), Self::Error> {
let epd_location = if layer == 0 { 0x10 } else { 0x13 };
self.dc.set_low().ok();
let ch = self
.spi_bus
.sram_epd_move_header(start_address, epd_location)?;
self.dc.set_high().ok();
self.spi_bus.sram_epd_move_body(ch, nbytes)
}
}