diff --git a/src/bus/four_wire_ref.rs b/src/bus/four_wire_ref.rs new file mode 100644 index 0000000..4bb6fa0 --- /dev/null +++ b/src/bus/four_wire_ref.rs @@ -0,0 +1,83 @@ +#![allow(clippy::inconsistent_digit_grouping, clippy::unusual_byte_groupings)] + +use core::fmt; +use embedded_hal::blocking::spi::{Transfer, Write}; +use embedded_hal::digital::v2::OutputPin; + +use crate::bus::{Bus, FourWire, FourWireError}; + +const WRITE_MODE_MASK: u8 = 0b00000_1_00; + +// TODO This name is not ideal, should be renamed to VDM +/// This is just like [crate::bus::FourWire] but takes references instead of ownership +/// for the SPI bus and the ChipSelect pin +pub struct FourWireRef<'a, Spi: Transfer + Write, ChipSelect: OutputPin>( + FourWire, OutputPinRef<'a, ChipSelect>>, +); + +impl<'a, Spi: Transfer + Write, ChipSelect: OutputPin> FourWireRef<'a, Spi, ChipSelect> { + pub fn new(spi: &'a mut Spi, cs: &'a mut ChipSelect) -> Self { + Self(FourWire::new(SpiRef(spi), OutputPinRef(cs))) + } + + // this is actually a bit silly, but maybe someday someone finds this useful + pub fn release(self) -> (&'a mut Spi, &'a mut ChipSelect) { + let (spi_ref, cs_ref) = self.0.release(); + (spi_ref.0, cs_ref.0) + } +} + +impl + Write, ChipSelect: OutputPin> Bus + for FourWireRef<'_, Spi, ChipSelect> +{ + type Error = + FourWireError<>::Error, >::Error, ChipSelect::Error>; + + #[inline] + fn read_frame(&mut self, block: u8, address: u16, data: &mut [u8]) -> Result<(), Self::Error> { + self.0.read_frame(block, address, data) + } + + #[inline] + fn write_frame(&mut self, block: u8, address: u16, data: &[u8]) -> Result<(), Self::Error> { + self.0.write_frame(block, address, data) + } +} + +#[derive(Debug)] +pub struct SpiRef<'a, Spi: Transfer + Write>(&'a mut Spi); + +impl<'a, Spi: Transfer + Write> Transfer for SpiRef<'a, Spi> { + type Error = >::Error; + + #[inline] + fn transfer<'w>(&mut self, words: &'w mut [u8]) -> Result<&'w [u8], Self::Error> { + self.0.transfer(words) + } +} + +impl<'a, Spi: Transfer + Write> Write for SpiRef<'a, Spi> { + type Error = >::Error; + + #[inline] + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + self.0.write(words) + } +} + +#[derive(Debug)] +pub struct OutputPinRef<'a, P: OutputPin>(&'a mut P); + +impl<'a, P: OutputPin> OutputPin for OutputPinRef<'a, P> { + type Error = P::Error; + + #[inline] + fn set_low(&mut self) -> Result<(), Self::Error> { + self.0.set_low() + } + + #[inline] + fn set_high(&mut self) -> Result<(), Self::Error> { + self.0.set_high() + } +} diff --git a/src/bus/mod.rs b/src/bus/mod.rs index 8b09625..a51c0c5 100644 --- a/src/bus/mod.rs +++ b/src/bus/mod.rs @@ -1,10 +1,14 @@ use core::fmt::Debug; mod four_wire; +mod four_wire_ref; mod three_wire; pub use self::four_wire::FourWire; pub use self::four_wire::FourWireError; +pub use self::four_wire_ref::FourWireRef; +pub use self::four_wire_ref::OutputPinRef; +pub use self::four_wire_ref::SpiRef; pub use self::three_wire::ThreeWire; pub use self::three_wire::ThreeWireError;