Skip to content

Commit df935ac

Browse files
committed
spi/blocking: group into read-only, write-only and read-write traits
1 parent 556c1be commit df935ac

File tree

2 files changed

+64
-54
lines changed

2 files changed

+64
-54
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1414
- Fixed blanket impl of `DelayUs` not covering the `delay_ms` method.
1515
### Changed
1616
- `spi`: traits now enforce all impls on the same struct (eg `Transfer` and `Write`) have the same `Error` type.
17+
- `spi/blocking`: unified traits into `Read`, `Write`, `ReadWrite`.
18+
- `spi/blocking`: renamed Transactional `exec` to `batch`.
19+
- `spi/blocking`: Added `read_batch`, `write_batch` methods.
1720

1821
### Changed
1922
- `digital`: traits now enforce all impls on the same struct have the same `Error` type.

src/spi/blocking.rs

+61-54
Original file line numberDiff line numberDiff line change
@@ -2,75 +2,54 @@
22
33
use super::ErrorType;
44

5-
/// Blocking transfer with separate buffers
6-
pub trait Transfer<Word = u8>: ErrorType {
7-
/// Writes and reads simultaneously. `write` is written to the slave on MOSI and
8-
/// words received on MISO are stored in `read`.
9-
///
10-
/// It is allowed for `read` and `write` to have different lengths, even zero length.
11-
/// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter,
12-
/// incoming words after `read` has been filled will be discarded. If `write` is shorter,
13-
/// the value of words sent in MOSI after all `write` has been sent is implementation-defined,
14-
/// typically `0x00`, `0xFF`, or configurable.
15-
fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error>;
16-
}
17-
18-
impl<T: Transfer<Word>, Word: Copy> Transfer<Word> for &mut T {
19-
fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> {
20-
T::transfer(self, read, write)
21-
}
22-
}
23-
24-
/// Blocking transfer with single buffer (in-place)
25-
pub trait TransferInplace<Word: Copy = u8>: ErrorType {
26-
/// Writes and reads simultaneously. The contents of `words` are
27-
/// written to the slave, and the received words are stored into the same
28-
/// `words` buffer, overwriting it.
29-
fn transfer_inplace(&mut self, words: &mut [Word]) -> Result<(), Self::Error>;
30-
}
31-
32-
impl<T: TransferInplace<Word>, Word: Copy> TransferInplace<Word> for &mut T {
33-
fn transfer_inplace(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
34-
T::transfer_inplace(self, words)
35-
}
36-
}
37-
38-
/// Blocking read
5+
/// Blocking read-only SPI
396
pub trait Read<Word: Copy = u8>: ErrorType {
407
/// Reads `words` from the slave.
418
///
429
/// The word value sent on MOSI during reading is implementation-defined,
4310
/// typically `0x00`, `0xFF`, or configurable.
4411
fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error>;
12+
13+
/// Reads all slices in `words` from the slave as part of a single SPI transaction.
14+
///
15+
/// The word value sent on MOSI during reading is implementation-defined,
16+
/// typically `0x00`, `0xFF`, or configurable.
17+
fn read_transaction(&mut self, words: &mut [&mut [Word]]) -> Result<(), Self::Error>;
4518
}
4619

4720
impl<T: Read<Word>, Word: Copy> Read<Word> for &mut T {
4821
fn read(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
4922
T::read(self, words)
5023
}
24+
25+
fn read_transaction(&mut self, words: &mut [&mut [Word]]) -> Result<(), Self::Error> {
26+
T::read_transaction(self, words)
27+
}
5128
}
5229

53-
/// Blocking write
30+
/// Blocking write-only SPI
5431
pub trait Write<Word: Copy = u8>: ErrorType {
5532
/// Writes `words` to the slave, ignoring all the incoming words
5633
fn write(&mut self, words: &[Word]) -> Result<(), Self::Error>;
57-
}
5834

59-
impl<T: Write<Word>, Word: Copy> Write<Word> for &mut T {
60-
fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> {
61-
T::write(self, words)
62-
}
63-
}
35+
/// Writes all slices in `words` to the slave as part of a single SPI transaction, ignoring all the incoming words
36+
fn write_transaction(&mut self, words: &[&[Word]]) -> Result<(), Self::Error>;
6437

65-
/// Blocking write (iterator version)
66-
pub trait WriteIter<Word: Copy = u8>: ErrorType {
6738
/// Writes `words` to the slave, ignoring all the incoming words
6839
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
6940
where
7041
WI: IntoIterator<Item = Word>;
7142
}
7243

73-
impl<T: WriteIter<Word>, Word: Copy> WriteIter<Word> for &mut T {
44+
impl<T: Write<Word>, Word: Copy> Write<Word> for &mut T {
45+
fn write(&mut self, words: &[Word]) -> Result<(), Self::Error> {
46+
T::write(self, words)
47+
}
48+
49+
fn write_transaction(&mut self, words: &[&[Word]]) -> Result<(), Self::Error> {
50+
T::write_transaction(self, words)
51+
}
52+
7453
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
7554
where
7655
WI: IntoIterator<Item = Word>,
@@ -79,7 +58,7 @@ impl<T: WriteIter<Word>, Word: Copy> WriteIter<Word> for &mut T {
7958
}
8059
}
8160

82-
/// Operation for transactional SPI trait
61+
/// Operation for ReadWrite::transaction
8362
///
8463
/// This allows composition of SPI operations into a single bus transaction
8564
#[derive(Debug, PartialEq)]
@@ -91,18 +70,46 @@ pub enum Operation<'a, Word: 'static + Copy = u8> {
9170
/// Write data out while reading data into the provided buffer
9271
Transfer(&'a mut [Word], &'a [Word]),
9372
/// Write data out while reading data into the provided buffer
94-
TransferInplace(&'a mut [Word]),
73+
TransferInPlace(&'a mut [Word]),
9574
}
9675

97-
/// Transactional trait allows multiple actions to be executed
98-
/// as part of a single SPI transaction
99-
pub trait Transactional<Word: 'static + Copy = u8>: ErrorType {
100-
/// Execute the provided transactions
101-
fn exec<'a>(&mut self, operations: &mut [Operation<'a, Word>]) -> Result<(), Self::Error>;
76+
/// Blocking read-write SPI
77+
pub trait ReadWrite<Word: Copy = u8>: Read<Word> + Write<Word> {
78+
/// Writes and reads simultaneously. `write` is written to the slave on MOSI and
79+
/// words received on MISO are stored in `read`.
80+
///
81+
/// It is allowed for `read` and `write` to have different lengths, even zero length.
82+
/// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter,
83+
/// incoming words after `read` has been filled will be discarded. If `write` is shorter,
84+
/// the value of words sent in MOSI after all `write` has been sent is implementation-defined,
85+
/// typically `0x00`, `0xFF`, or configurable.
86+
fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error>;
87+
88+
/// Writes and reads simultaneously. The contents of `words` are
89+
/// written to the slave, and the received words are stored into the same
90+
/// `words` buffer, overwriting it.
91+
fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error>;
92+
93+
/// Execute multiple actions as part of a single SPI transaction
94+
fn transaction<'a>(
95+
&mut self,
96+
operations: &mut [Operation<'a, Word>],
97+
) -> Result<(), Self::Error>;
10298
}
10399

104-
impl<T: Transactional<Word>, Word: 'static + Copy> Transactional<Word> for &mut T {
105-
fn exec<'a>(&mut self, operations: &mut [Operation<'a, Word>]) -> Result<(), Self::Error> {
106-
T::exec(self, operations)
100+
impl<T: ReadWrite<Word>, Word: Copy> ReadWrite<Word> for &mut T {
101+
fn transfer(&mut self, read: &mut [Word], write: &[Word]) -> Result<(), Self::Error> {
102+
T::transfer(self, read, write)
103+
}
104+
105+
fn transfer_in_place(&mut self, words: &mut [Word]) -> Result<(), Self::Error> {
106+
T::transfer_in_place(self, words)
107+
}
108+
109+
fn transaction<'a>(
110+
&mut self,
111+
operations: &mut [Operation<'a, Word>],
112+
) -> Result<(), Self::Error> {
113+
T::transaction(self, operations)
107114
}
108115
}

0 commit comments

Comments
 (0)