From 49f3b8e97d9b9b3c6a457b939f9d227c6eeed369 Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 3 Nov 2021 09:11:29 +0300 Subject: [PATCH 1/2] add default SPI word types --- CHANGELOG.md | 1 + src/spi/blocking.rs | 12 +++++++----- src/spi/mod.rs | 9 +++++++++ src/spi/nb.rs | 4 +++- 4 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d22d3d92..856e11c55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] ### Added +- Default SPI word types - Added `Can` Controller Area Network traits. - `Error` traits for SPI, I2C and Serial traits. The error types used in those must implement these `Error` traits, which implies providing a conversion to a common diff --git a/src/spi/blocking.rs b/src/spi/blocking.rs index b98207277..d1d4b3db2 100644 --- a/src/spi/blocking.rs +++ b/src/spi/blocking.rs @@ -4,8 +4,10 @@ //! traits. To save boilerplate when that's the case a `Default` marker trait may be provided. //! Implementing that marker trait will opt in your type into a blanket implementation. +use super::U8; + /// Blocking transfer -pub trait Transfer { +pub trait Transfer { /// Error type type Error: crate::spi::Error; @@ -24,7 +26,7 @@ impl, W> Transfer for &mut T { } /// Blocking write -pub trait Write { +pub trait Write { /// Error type type Error: crate::spi::Error; @@ -41,7 +43,7 @@ impl, W> Write for &mut T { } /// Blocking write (iterator version) -pub trait WriteIter { +pub trait WriteIter { /// Error type type Error: crate::spi::Error; @@ -66,7 +68,7 @@ impl, W> WriteIter for &mut T { /// /// This allows composition of SPI operations into a single bus transaction #[derive(Debug, PartialEq)] -pub enum Operation<'a, W: 'static> { +pub enum Operation<'a, W: 'static = U8> { /// Write data from the provided buffer, discarding read data Write(&'a [W]), /// Write data out while reading data into the provided buffer @@ -75,7 +77,7 @@ pub enum Operation<'a, W: 'static> { /// Transactional trait allows multiple actions to be executed /// as part of a single SPI transaction -pub trait Transactional { +pub trait Transactional { /// Associated error type type Error: crate::spi::Error; diff --git a/src/spi/mod.rs b/src/spi/mod.rs index c367e70d8..e95b4ed14 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -3,6 +3,15 @@ pub mod blocking; pub mod nb; +/// 8-bit SPI Word (default) +pub type U8 = u8; +/// 9-bit SPI Word +pub struct U9; +/// 16-bit SPI Word +pub struct U16; +/// 18-bit SPI Word +pub struct U18; + /// Clock polarity #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Polarity { diff --git a/src/spi/nb.rs b/src/spi/nb.rs index c7d377ef9..041bea1e0 100644 --- a/src/spi/nb.rs +++ b/src/spi/nb.rs @@ -1,5 +1,7 @@ //! Serial Peripheral Interface +use super::U8; + /// Full duplex (master mode) /// /// # Notes @@ -16,7 +18,7 @@ /// /// - Some SPIs can work with 8-bit *and* 16-bit words. You can overload this trait with different /// `Word` types to allow operation in both modes. -pub trait FullDuplex { +pub trait FullDuplex { /// An enumeration of SPI errors type Error: crate::spi::Error; From a2a5f2bd2ce7181a932ebafc35ba40e0b528d0ca Mon Sep 17 00:00:00 2001 From: Andrey Zgarbul Date: Wed, 3 Nov 2021 12:00:42 +0300 Subject: [PATCH 2/2] add SpiWord trait --- src/spi/blocking.rs | 57 +++++++++++++++++++++++++++++++-------------- src/spi/mod.rs | 25 ++++++++++++++++++++ src/spi/nb.rs | 19 ++++++++------- 3 files changed, 75 insertions(+), 26 deletions(-) diff --git a/src/spi/blocking.rs b/src/spi/blocking.rs index d1d4b3db2..00f779f38 100644 --- a/src/spi/blocking.rs +++ b/src/spi/blocking.rs @@ -4,61 +4,70 @@ //! traits. To save boilerplate when that's the case a `Default` marker trait may be provided. //! Implementing that marker trait will opt in your type into a blanket implementation. -use super::U8; +use super::{SpiWord, U8}; /// Blocking transfer -pub trait Transfer { +pub trait Transfer { /// Error type type Error: crate::spi::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(&mut self, words: &mut [W]) -> Result<(), Self::Error>; + fn transfer(&mut self, words: &mut [W::Data]) -> Result<(), Self::Error>; } -impl, W> Transfer for &mut T { +impl, W> Transfer for &mut T +where + W: SpiWord, +{ type Error = T::Error; - fn transfer(&mut self, words: &mut [W]) -> Result<(), Self::Error> { + fn transfer(&mut self, words: &mut [W::Data]) -> Result<(), Self::Error> { T::transfer(self, words) } } /// Blocking write -pub trait Write { +pub trait Write { /// Error type type Error: crate::spi::Error; /// Writes `words` to the slave, ignoring all the incoming words - fn write(&mut self, words: &[W]) -> Result<(), Self::Error>; + fn write(&mut self, words: &[W::Data]) -> Result<(), Self::Error>; } -impl, W> Write for &mut T { +impl, W> Write for &mut T +where + W: SpiWord, +{ type Error = T::Error; - fn write(&mut self, words: &[W]) -> Result<(), Self::Error> { + fn write(&mut self, words: &[W::Data]) -> Result<(), Self::Error> { T::write(self, words) } } /// Blocking write (iterator version) -pub trait WriteIter { +pub trait WriteIter { /// Error type type Error: crate::spi::Error; /// Writes `words` to the slave, ignoring all the incoming words fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where - WI: IntoIterator; + WI: IntoIterator; } -impl, W> WriteIter for &mut T { +impl, W> WriteIter for &mut T +where + W: SpiWord, +{ type Error = T::Error; fn write_iter(&mut self, words: WI) -> Result<(), Self::Error> where - WI: IntoIterator, + WI: IntoIterator, { T::write_iter(self, words) } @@ -68,16 +77,24 @@ impl, W> WriteIter for &mut T { /// /// This allows composition of SPI operations into a single bus transaction #[derive(Debug, PartialEq)] -pub enum Operation<'a, W: 'static = U8> { +pub enum Operation<'a, W = U8> +where + W: SpiWord, + W::Data: 'static, +{ /// Write data from the provided buffer, discarding read data - Write(&'a [W]), + Write(&'a [W::Data]), /// Write data out while reading data into the provided buffer - Transfer(&'a mut [W]), + Transfer(&'a mut [W::Data]), } /// Transactional trait allows multiple actions to be executed /// as part of a single SPI transaction -pub trait Transactional { +pub trait Transactional +where + W: SpiWord, + W::Data: 'static, +{ /// Associated error type type Error: crate::spi::Error; @@ -85,7 +102,11 @@ pub trait Transactional { fn exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Self::Error>; } -impl, W: 'static> Transactional for &mut T { +impl, W> Transactional for &mut T +where + W: SpiWord, + W::Data: 'static, +{ type Error = T::Error; fn exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Self::Error> { diff --git a/src/spi/mod.rs b/src/spi/mod.rs index e95b4ed14..7bb9da473 100644 --- a/src/spi/mod.rs +++ b/src/spi/mod.rs @@ -1,8 +1,16 @@ //! SPI traits +use crate::private::Sealed; + pub mod blocking; pub mod nb; +/// Marker trait for SPI Word +pub trait SpiWord: Sealed { + /// Specified data size type + type Data: Sized; +} + /// 8-bit SPI Word (default) pub type U8 = u8; /// 9-bit SPI Word @@ -12,6 +20,23 @@ pub struct U16; /// 18-bit SPI Word pub struct U18; +impl Sealed for U9 {} +impl Sealed for U16 {} +impl Sealed for U18 {} + +impl SpiWord for U8 { + type Data = u8; +} +impl SpiWord for U9 { + type Data = u16; +} +impl SpiWord for U16 { + type Data = u16; +} +impl SpiWord for U18 { + type Data = u32; +} + /// Clock polarity #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum Polarity { diff --git a/src/spi/nb.rs b/src/spi/nb.rs index 041bea1e0..342bac0ee 100644 --- a/src/spi/nb.rs +++ b/src/spi/nb.rs @@ -1,6 +1,6 @@ //! Serial Peripheral Interface -use super::U8; +use super::{SpiWord, U8}; /// Full duplex (master mode) /// @@ -17,8 +17,8 @@ use super::U8; /// The slave select line shouldn't be released before that. /// /// - Some SPIs can work with 8-bit *and* 16-bit words. You can overload this trait with different -/// `Word` types to allow operation in both modes. -pub trait FullDuplex { +/// `W` types to allow operation in both modes. +pub trait FullDuplex { /// An enumeration of SPI errors type Error: crate::spi::Error; @@ -26,20 +26,23 @@ pub trait FullDuplex { /// /// **NOTE** A word must be sent to the slave before attempting to call this /// method. - fn read(&mut self) -> nb::Result; + fn read(&mut self) -> nb::Result; /// Writes a word to the slave - fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>; + fn write(&mut self, word: W::Data) -> nb::Result<(), Self::Error>; } -impl, Word> FullDuplex for &mut T { +impl, W> FullDuplex for &mut T +where + W: SpiWord, +{ type Error = T::Error; - fn read(&mut self) -> nb::Result { + fn read(&mut self) -> nb::Result { T::read(self) } - fn write(&mut self, word: Word) -> nb::Result<(), Self::Error> { + fn write(&mut self, word: W::Data) -> nb::Result<(), Self::Error> { T::write(self, word) } }