diff --git a/CHANGELOG.md b/CHANGELOG.md index 7262aed74..826956338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed blanket impl of `DelayUs` not covering the `delay_ms` method. ### Changed - `spi`: traits now enforce all impls on the same struct (eg `Transfer` and `Write`) have the same `Error` type. +- `spi/blocking`: unified traits into `Read`, `Write`, `ReadWrite`. +- `spi/blocking`: renamed Transactional `exec` to `batch`. +- `spi/blocking`: Added `read_batch`, `write_batch` methods. ### Changed - `digital`: traits now enforce all impls on the same struct have the same `Error` type. diff --git a/src/spi/blocking.rs b/src/spi/blocking.rs index 756cc4f1d..d20f83562 100644 --- a/src/spi/blocking.rs +++ b/src/spi/blocking.rs @@ -2,75 +2,54 @@ use super::ErrorType; -/// Blocking transfer with separate buffers -pub trait Transfer: ErrorType { - /// Writes and reads simultaneously. `write` is written to the slave on MOSI and - /// words received on MISO are stored in `read`. - /// - /// It is allowed for `read` and `write` to have different lengths, even zero length. - /// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter, - /// incoming words after `read` has been filled will be discarded. If `write` is shorter, - /// the value of words sent in MOSI after all `write` has been sent is implementation-defined, - /// typically `0x00`, `0xFF`, or configurable. - fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error>; -} - -impl, Word: Copy> Transfer for &mut T { - fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> { - T::transfer(self, read, write) - } -} - -/// Blocking transfer with single buffer (in-place) -pub trait TransferInplace: ErrorType { - /// Writes and reads simultaneously. The contents of `words` are - /// written to the slave, and the received words are stored into the same - /// `words` buffer, overwriting it. - fn transfer_inplace(&mut self, words: &mut [Word]) -> Result<(), Self::Error>; -} - -impl, Word: Copy> TransferInplace for &mut T { - fn transfer_inplace(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { - T::transfer_inplace(self, words) - } -} - -/// Blocking read +/// Blocking read-only SPI pub trait Read: ErrorType { /// Reads `words` from the slave. /// /// The word value sent on MOSI during reading is implementation-defined, /// typically `0x00`, `0xFF`, or configurable. fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error>; + + /// Reads all slices in `words` from the slave as part of a single SPI transaction. + /// + /// The word value sent on MOSI during reading is implementation-defined, + /// typically `0x00`, `0xFF`, or configurable. + fn read_transaction(&mut self, words: &mut [&mut [Word]]) -> Result<(), Self::Error>; } impl, Word: Copy> Read for &mut T { fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { T::read(self, words) } + + fn read_transaction(&mut self, words: &mut [&mut [Word]]) -> Result<(), Self::Error> { + T::read_transaction(self, words) + } } -/// Blocking write +/// Blocking write-only SPI pub trait Write: ErrorType { /// Writes `words` to the slave, ignoring all the incoming words fn write(&mut self, words: &[Word]) -> Result<(), Self::Error>; -} -impl, Word: Copy> Write for &mut T { - fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> { - T::write(self, words) - } -} + /// Writes all slices in `words` to the slave as part of a single SPI transaction, ignoring all the incoming words + fn write_transaction(&mut self, words: &[&[Word]]) -> Result<(), Self::Error>; -/// Blocking write (iterator version) -pub trait WriteIter: ErrorType { /// Writes `words` to the slave, ignoring all the incoming words fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where WI: IntoIterator; } -impl, Word: Copy> WriteIter for &mut T { +impl, Word: Copy> Write for &mut T { + fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> { + T::write(self, words) + } + + fn write_transaction(&mut self, words: &[&[Word]]) -> Result<(), Self::Error> { + T::write_transaction(self, words) + } + fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where WI: IntoIterator, @@ -79,7 +58,7 @@ impl, Word: Copy> WriteIter for &mut T { } } -/// Operation for transactional SPI trait +/// Operation for ReadWrite::transaction /// /// This allows composition of SPI operations into a single bus transaction #[derive(Debug, PartialEq)] @@ -91,18 +70,46 @@ pub enum Operation<'a, Word: 'static + Copy = u8> { /// Write data out while reading data into the provided buffer Transfer(&'a mut [Word], &'a [Word]), /// Write data out while reading data into the provided buffer - TransferInplace(&'a mut [Word]), + TransferInPlace(&'a mut [Word]), } -/// Transactional trait allows multiple actions to be executed -/// as part of a single SPI transaction -pub trait Transactional: ErrorType { - /// Execute the provided transactions - fn exec<'a>(&mut self, operations: &mut [Operation<'a, Word>]) -> Result<(), Self::Error>; +/// Blocking read-write SPI +pub trait ReadWrite: Read + Write { + /// Writes and reads simultaneously. `write` is written to the slave on MOSI and + /// words received on MISO are stored in `read`. + /// + /// It is allowed for `read` and `write` to have different lengths, even zero length. + /// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter, + /// incoming words after `read` has been filled will be discarded. If `write` is shorter, + /// the value of words sent in MOSI after all `write` has been sent is implementation-defined, + /// typically `0x00`, `0xFF`, or configurable. + fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error>; + + /// Writes and reads simultaneously. The contents of `words` are + /// written to the slave, and the received words are stored into the same + /// `words` buffer, overwriting it. + fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error>; + + /// Execute multiple actions as part of a single SPI transaction + fn transaction<'a>( + &mut self, + operations: &mut [Operation<'a, Word>], + ) -> Result<(), Self::Error>; } -impl, Word: 'static + Copy> Transactional for &mut T { - fn exec<'a>(&mut self, operations: &mut [Operation<'a, Word>]) -> Result<(), Self::Error> { - T::exec(self, operations) +impl, Word: Copy> ReadWrite for &mut T { + fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> { + T::transfer(self, read, write) + } + + fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> { + T::transfer_in_place(self, words) + } + + fn transaction<'a>( + &mut self, + operations: &mut [Operation<'a, Word>], + ) -> Result<(), Self::Error> { + T::transaction(self, operations) } }