diff --git a/src/blocking/spi.rs b/src/blocking/spi.rs index b1e81bb8a..93fad65c1 100644 --- a/src/blocking/spi.rs +++ b/src/blocking/spi.rs @@ -102,3 +102,52 @@ pub mod write_iter { } } } + +/// Operation for transactional SPI trait +/// +/// This allows composition of SPI operations into a single bus transaction +#[derive(Debug, PartialEq)] +pub enum Operation<'a, W: 'static> { + /// Write data from the provided buffer, discarding read data + Write(&'a [W]), + /// Write data out while reading data into the provided buffer + Transfer(&'a mut [W]), +} + +/// Transactional trait allows multiple actions to be executed +/// as part of a single SPI transaction +pub trait Transactional { + /// Associated error type + type Error; + + /// Execute the provided transactions + fn try_exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Self::Error>; +} + +/// Blocking transactional impl over spi::Write and spi::Transfer +pub mod transactional { + use super::{Operation, Transfer, Write}; + + /// Default implementation of `blocking::spi::Transactional` for implementers of + /// `spi::Write` and `spi::Transfer` + pub trait Default: Write + Transfer {} + + impl super::Transactional for S + where + S: self::Default + Write + Transfer, + W: Copy + Clone, + { + type Error = E; + + fn try_exec<'a>(&mut self, operations: &mut [super::Operation<'a, W>]) -> Result<(), E> { + for op in operations { + match op { + Operation::Write(w) => self.try_write(w)?, + Operation::Transfer(t) => self.try_transfer(t).map(|_| ())?, + } + } + + Ok(()) + } + } +}