diff --git a/spi/Cargo.toml b/spi/Cargo.toml index b6013af..b55ca54 100644 --- a/spi/Cargo.toml +++ b/spi/Cargo.toml @@ -19,5 +19,5 @@ all-features = true [dependencies] embedded-hal = "0.2.3" -display-interface = "0.4" +display-interface = { git = "https://github.com/chrismoos/display-interface", branch = "rw-interface"} byte-slice-cast = { version = "0.3.5", default-features = false } diff --git a/spi/src/lib.rs b/spi/src/lib.rs index 632ad25..2a35ae6 100644 --- a/spi/src/lib.rs +++ b/spi/src/lib.rs @@ -5,6 +5,7 @@ use embedded_hal as hal; use hal::digital::v2::OutputPin; +use display_interface::v2::{ReadInterface, WriteInterface, WriteMode}; use display_interface::{DataFormat, DisplayError, WriteOnlyDataCommand}; fn send_u8>( @@ -133,6 +134,95 @@ where } } +impl ReadInterface for SPIInterface +where + SPI: hal::spi::FullDuplex, + DC: OutputPin, + CS: OutputPin, +{ + fn read_stream(&mut self, f: &mut dyn FnMut(u8) -> bool) -> Result<(), DisplayError> { + // Assert chip select pin + self.cs.set_low().map_err(|_| DisplayError::CSError)?; + + // 1 = data for reads + self.dc.set_high().map_err(|_| DisplayError::DCError)?; + + loop { + let b = self.spi.read().map_err(|_| DisplayError::BusReadError)?; + if !f(b) { + break; + } + } + + // Deassert chip select pin + self.cs.set_high().map_err(|_| DisplayError::CSError) + } +} + +impl WriteInterface for SPIInterface +where + SPI: hal::blocking::spi::Write, + DC: OutputPin, + CS: OutputPin, +{ + fn write(&mut self, mode: WriteMode, buf: &[u8]) -> Result<(), DisplayError> { + // Assert chip select pin + self.cs.set_low().map_err(|_| DisplayError::CSError)?; + + // 1 = data, 0 = command + match mode { + WriteMode::Command => { + self.dc.set_low().map_err(|_| DisplayError::DCError)?; + } + WriteMode::Data => { + self.dc.set_high().map_err(|_| DisplayError::DCError)?; + } + } + + self.spi + .write(buf) + .map_err(|_| DisplayError::BusWriteError)?; + + // Deassert chip select pin + self.cs.set_high().map_err(|_| DisplayError::CSError) + } + + fn write_stream<'a>( + &mut self, + mode: WriteMode, + func: &mut dyn FnMut() -> Option<&'a u8>, + ) -> Result<(), DisplayError> { + // Assert chip select pin + self.cs.set_low().map_err(|_| DisplayError::CSError)?; + + // 1 = data, 0 = command + match mode { + WriteMode::Command => { + self.dc.set_low().map_err(|_| DisplayError::DCError)?; + } + WriteMode::Data => { + self.dc.set_high().map_err(|_| DisplayError::DCError)?; + } + } + + loop { + match func() { + Some(b) => { + self.spi + .write(&[*b]) + .map_err(|_| DisplayError::BusWriteError)?; + } + None => { + break; + } + } + } + + // Deassert chip select pin + self.cs.set_high().map_err(|_| DisplayError::CSError) + } +} + impl WriteOnlyDataCommand for SPIInterface where SPI: hal::blocking::spi::Write, diff --git a/src/lib.rs b/src/lib.rs index 2f53a37..616f0c6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,6 +18,8 @@ pub enum DisplayError { InvalidFormatError, /// Unable to write to bus BusWriteError, + // Unable to read from bus + BusReadError, /// Unable to assert or de-assert data/command switching signal DCError, /// Unable to assert chip select signal @@ -57,3 +59,5 @@ pub trait WriteOnlyDataCommand { /// Send pixel data to display fn send_data(&mut self, buf: DataFormat<'_>) -> Result<(), DisplayError>; } + +pub mod v2; diff --git a/src/v2.rs b/src/v2.rs new file mode 100644 index 0000000..1a6eef8 --- /dev/null +++ b/src/v2.rs @@ -0,0 +1,88 @@ +use crate::DisplayError; + +#[derive(Clone, Debug)] +pub enum WriteMode { + Data, + Command, +} + +pub trait WriteInterface { + fn write(&mut self, mode: WriteMode, buf: &[DataFormat]) -> Result<(), DisplayError> { + self.write_iter(mode, &mut buf.into_iter()) + } + + fn write_iter( + &mut self, + mode: WriteMode, + iter: &mut dyn Iterator, + ) -> Result<(), DisplayError> { + self.write_stream(mode, &mut || iter.next()) + } + + fn write_stream<'a>( + &mut self, + mode: WriteMode, + func: &mut dyn FnMut() -> Option<&'a DataFormat>, + ) -> Result<(), DisplayError>; +} + +pub trait ReadInterface { + fn read(&mut self, buf: &mut [DataFormat]) -> Result<(), DisplayError> { + let mut n = 0; + self.read_stream(&mut |b| { + if n == buf.len() { + return false; + } + buf[n] = b; + n += 1; + true + }) + } + + fn read_stream(&mut self, f: &mut dyn FnMut(DataFormat) -> bool) -> Result<(), DisplayError>; +} + +pub trait ReadWriteInterface: ReadInterface + WriteInterface {} +impl ReadWriteInterface for T where + T: ReadInterface + WriteInterface +{ +} + +pub struct ReadIterator<'a, DataFormat> { + reader: &'a mut dyn ReadInterface, +} + +impl<'a, DataFormat> ReadIterator<'a, DataFormat> { + fn new(reader: &'a mut dyn ReadInterface) -> ReadIterator<'a, DataFormat> { + ReadIterator { reader: reader } + } +} + +impl<'a, DataFormat> Iterator for ReadIterator<'a, DataFormat> +where + DataFormat: Default, +{ + type Item = Result; + fn next(&mut self) -> Option { + let mut next: DataFormat = Default::default(); + match self.reader.read_stream(&mut |b| { + next = b; + false + }) { + Ok(_) => Some(Ok(next)), + Err(e) => Some(Err(e)), + } + } +} + +impl<'a, DataFormat> IntoIterator for &'a mut dyn ReadInterface +where + DataFormat: Default, +{ + type Item = Result; + type IntoIter = ReadIterator<'a, DataFormat>; + + fn into_iter(self) -> Self::IntoIter { + ReadIterator::new(self) + } +}