Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use associated Word types #295

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Expand Up @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
importing the `nb` crate directly in dependendent crates.
- `blocking::Serial`: renamed `bwrite_all` to `write`, `bflush` to `flush.
- Removed `prelude` to avoid method name conflicts between different flavors (blocking, nb) of the same trait. Traits must now be manually imported.
- The serial, spi, and adc traits where changed to use associated `Word` types instead of type parameters

### Removed
- Removed random number generation (`rng`) traits in favor of [rand_core](https://crates.io/crates/rand_core).
Expand Down
18 changes: 11 additions & 7 deletions src/blocking/serial.rs
@@ -1,7 +1,10 @@
//! Blocking serial API

/// Write half of a serial interface (blocking variant)
pub trait Write<Word> {
pub trait Write {
/// Word type
type Word;

/// The type of error that can occur when writing
type Error;

Expand All @@ -13,7 +16,7 @@ pub trait Write<Word> {
/// everything has been sent, call [`flush`] after this function returns.
///
/// [`flush`]: #tymethod.flush
fn write(&mut self, buffer: &[Word]) -> Result<(), Self::Error>;
fn write(&mut self, buffer: &[Self::Word]) -> Result<(), Self::Error>;

/// Block until the serial interface has sent all buffered words
fn flush(&mut self) -> Result<(), Self::Error>;
Expand All @@ -29,16 +32,17 @@ pub mod write {
///
/// [`nonblocking::serial::Write`]: ../../nonblocking/serial/trait.Write.html
/// [`blocking::serial::Write`]: ../trait.Write.html
pub trait Default<Word>: crate::nb::serial::Write<Word> {}
pub trait Default: crate::nb::serial::Write {}

impl<S, Word> crate::blocking::serial::Write<Word> for S
impl<S> crate::blocking::serial::Write for S
where
S: Default<Word>,
Word: Clone,
S: Default,
S::Word: Clone,
{
type Word = S::Word;
type Error = S::Error;

fn write(&mut self, buffer: &[Word]) -> Result<(), Self::Error> {
fn write(&mut self, buffer: &[Self::Word]) -> Result<(), Self::Error> {
for word in buffer {
nb::block!(self.write(word.clone()))?;
}
Expand Down
75 changes: 49 additions & 26 deletions src/blocking/spi.rs
@@ -1,48 +1,64 @@
//! Blocking SPI API

/// Blocking transfer
pub trait Transfer<W> {
pub trait Transfer {
/// Word type
type Word;

/// Error type
type Error;

/// Writes `words` to the slave. Returns the `words` received from the slave
fn transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], Self::Error>;
fn transfer<'w>(
&mut self,
words: &'w mut [Self::Word],
) -> Result<&'w [Self::Word], Self::Error>;
}

/// Blocking write
pub trait Write<W> {
pub trait Write {
/// Word type
type Word;

/// Error type
type 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: &[Self::Word]) -> Result<(), Self::Error>;
}

/// Blocking write (iterator version)
pub trait WriteIter<W> {
pub trait WriteIter {
/// Word type
type Word;

/// Error type
type Error;

/// Writes `words` to the slave, ignoring all the incoming words
fn write_iter<WI>(&mut self, words: WI) -> Result<(), Self::Error>
where
WI: IntoIterator<Item = W>;
WI: IntoIterator<Item = Self::Word>;
}

/// Blocking transfer
pub mod transfer {
/// Default implementation of `blocking::spi::Transfer<W>` for implementers of
/// `nonblocking::spi::FullDuplex<W>`
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
pub trait Default: crate::nb::spi::FullDuplex {}

impl<W, S> crate::blocking::spi::Transfer<W> for S
impl<S> crate::blocking::spi::Transfer for S
where
S: Default<W>,
W: Clone,
S: Default,
S::Word: Clone,
{
type Word = S::Word;
type Error = S::Error;

fn transfer<'w>(&mut self, words: &'w mut [W]) -> Result<&'w [W], S::Error> {
fn transfer<'w>(
&mut self,
words: &'w mut [Self::Word],
) -> Result<&'w [Self::Word], S::Error> {
for word in words.iter_mut() {
nb::block!(self.write(word.clone()))?;
*word = nb::block!(self.read())?;
Expand All @@ -57,16 +73,17 @@ pub mod transfer {
pub mod write {
/// Default implementation of `blocking::spi::Write<W>` for implementers
/// of `nonblocking::spi::FullDuplex<W>`
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
pub trait Default: crate::nb::spi::FullDuplex {}

impl<W, S> crate::blocking::spi::Write<W> for S
impl<S> crate::blocking::spi::Write for S
where
S: Default<W>,
W: Clone,
S: Default,
S::Word: Clone,
{
type Word = S::Word;
type Error = S::Error;

fn write(&mut self, words: &[W]) -> Result<(), S::Error> {
fn write(&mut self, words: &[Self::Word]) -> Result<(), S::Error> {
for word in words {
nb::block!(self.write(word.clone()))?;
nb::block!(self.read())?;
Expand All @@ -81,18 +98,19 @@ pub mod write {
pub mod write_iter {
/// Default implementation of `blocking::spi::WriteIter<W>` for implementers of
/// `nonblocking::spi::FullDuplex<W>`
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
pub trait Default: crate::nb::spi::FullDuplex {}

impl<W, S> crate::blocking::spi::WriteIter<W> for S
impl<S> crate::blocking::spi::WriteIter for S
where
S: Default<W>,
W: Clone,
S: Default,
S::Word: Clone,
{
type Word = S::Word;
type Error = S::Error;

fn write_iter<WI>(&mut self, words: WI) -> Result<(), S::Error>
where
WI: IntoIterator<Item = W>,
WI: IntoIterator<Item = Self::Word>,
{
for word in words.into_iter() {
nb::block!(self.write(word.clone()))?;
Expand All @@ -117,12 +135,16 @@ pub enum Operation<'a, W: 'static> {

/// Transactional trait allows multiple actions to be executed
/// as part of a single SPI transaction
pub trait Transactional<W: 'static> {
pub trait Transactional {
/// Word type
type Word: 'static;

/// Associated error type
type Error;

/// Execute the provided transactions
fn exec<'a>(&mut self, operations: &mut [Operation<'a, W>]) -> Result<(), Self::Error>;
fn exec<'a>(&mut self, operations: &mut [Operation<'a, Self::Word>])
-> Result<(), Self::Error>;
}

/// Blocking transactional impl over spi::Write and spi::Transfer
Expand All @@ -131,13 +153,14 @@ pub mod transactional {

/// Default implementation of `blocking::spi::Transactional<W>` for implementers of
/// `spi::Write<W>` and `spi::Transfer<W>`
pub trait Default<W>: Write<W> + Transfer<W> {}
pub trait Default: Write + Transfer {}

impl<W: 'static, E, S> super::Transactional<W> for S
impl<W: 'static, E, S> super::Transactional for S
where
S: self::Default<W> + Write<W, Error = E> + Transfer<W, Error = E>,
S: self::Default + Write<Word = W, Error = E> + Transfer<Word = W, Error = E>,
W: Copy + Clone,
{
type Word = W;
type Error = E;

fn exec<'a>(&mut self, operations: &mut [super::Operation<'a, W>]) -> Result<(), E> {
Expand Down
2 changes: 1 addition & 1 deletion src/fmt.rs
Expand Up @@ -3,7 +3,7 @@
//! TODO write example of usage
use core::fmt::{Result, Write};

impl<Word, Error> Write for dyn crate::nb::serial::Write<Word, Error = Error> + '_
impl<Word, Error> Write for dyn crate::nb::serial::Write<Word = Word, Error = Error> + '_
where
Word: From<u8>,
{
Expand Down
9 changes: 5 additions & 4 deletions src/lib.rs
Expand Up @@ -248,7 +248,7 @@
//!
//! fn write_all<S>(serial: &mut S, buffer: &[u8]) -> Result<(), S::Error>
//! where
//! S: hal::nb::serial::Write<u8>
//! S: hal::nb::serial::Write<Word = u8>
//! {
//! for &byte in buffer {
//! block!(serial.write(byte))?;
Expand Down Expand Up @@ -283,7 +283,7 @@
//! ) -> Result<u8, Error<S::Error, T::Error>>
//! where
//! T: hal::nb::timer::CountDown<Error = ()>,
//! S: hal::nb::serial::Read<u8>,
//! S: hal::nb::serial::Read<Word = u8>,
//! {
//! timer.start(timeout).map_err(Error::TimedOut)?;
//!
Expand Down Expand Up @@ -326,7 +326,7 @@
//!
//! fn flush<S>(serial: &mut S, cb: &mut CircularBuffer)
//! where
//! S: hal::nb::serial::Write<u8, Error = Infallible>,
//! S: hal::nb::serial::Write<Word = u8, Error = Infallible>,
//! {
//! loop {
//! if let Some(byte) = cb.peek() {
Expand Down Expand Up @@ -390,7 +390,8 @@
//! # fn deref_mut(&mut self) -> &mut T { self.0 }
//! # }
//! # struct Serial1;
//! # impl hal::nb::serial::Write<u8> for Serial1 {
//! # impl hal::nb::serial::Write for Serial1 {
//! # type Word = u8;
//! # type Error = Infallible;
//! # fn write(&mut self, _: u8) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
//! # fn flush(&mut self) -> nb::Result<(), Infallible> { Err(::nb::Error::WouldBlock) }
Expand Down
15 changes: 9 additions & 6 deletions src/nb/adc.rs
Expand Up @@ -64,29 +64,32 @@ pub trait Channel<ADC> {
/// # pub fn do_conversion(&mut self, chan: u8) -> u16 { 0xAA55_u16 }
/// # }
///
/// impl<WORD, PIN> OneShot<MyAdc, WORD, PIN> for MyAdc
/// impl<PIN> OneShot<MyAdc, PIN> for MyAdc
/// where
/// WORD: From<u16>,
/// PIN: Channel<MyAdc, ID=u8>,
/// {
/// type Word = u16;
/// type Error = ();
///
/// fn read(&mut self, pin: &mut PIN) -> nb::Result<WORD, Self::Error> {
/// fn read(&mut self, pin: &mut PIN) -> nb::Result<Self::Word, Self::Error> {
/// let chan = 1 << pin.channel();
/// self.power_up();
/// let result = self.do_conversion(chan);
/// self.power_down();
/// Ok(result.into())
/// Ok(result)
/// }
/// }
/// ```
pub trait OneShot<ADC, Word, Pin: Channel<ADC>> {
pub trait OneShot<ADC, Pin: Channel<ADC>> {
/// Word type
type Word;

/// Error type returned by ADC methods
type Error;

/// Request that the ADC begin a conversion on the specified pin
///
/// This method takes a `Pin` reference, as it is expected that the ADC will be able to sample
/// whatever channel underlies the pin.
fn read(&mut self, pin: &mut Pin) -> nb::Result<Word, Self::Error>;
fn read(&mut self, pin: &mut Pin) -> nb::Result<Self::Word, Self::Error>;
}
14 changes: 10 additions & 4 deletions src/nb/serial.rs
Expand Up @@ -4,21 +4,27 @@
///
/// Some serial interfaces support different data sizes (8 bits, 9 bits, etc.);
/// This can be encoded in this trait via the `Word` type parameter.
pub trait Read<Word> {
pub trait Read {
/// Word type
type Word;

/// Read error
type Error;

/// Reads a single word from the serial interface
fn read(&mut self) -> nb::Result<Word, Self::Error>;
fn read(&mut self) -> nb::Result<Self::Word, Self::Error>;
}

/// Write half of a serial interface
pub trait Write<Word> {
pub trait Write {
/// Word type
type Word;

/// Write error
type Error;

/// Writes a single word to the serial interface
fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>;
fn write(&mut self, word: Self::Word) -> nb::Result<(), Self::Error>;

/// Ensures that none of the previously written words are still buffered
fn flush(&mut self) -> nb::Result<(), Self::Error>;
Expand Down
12 changes: 6 additions & 6 deletions src/nb/spi.rs
Expand Up @@ -13,21 +13,21 @@
///
/// - Data is only guaranteed to be clocked out when the `read` call succeeds.
/// 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<Word> {
pub trait FullDuplex {
/// Word type
type Word;

/// An enumeration of SPI errors
type Error;

/// Reads the word stored in the shift register
///
/// **NOTE** A word must be sent to the slave before attempting to call this
/// method.
fn read(&mut self) -> nb::Result<Word, Self::Error>;
fn read(&mut self) -> nb::Result<Self::Word, Self::Error>;

/// Writes a word to the slave
fn write(&mut self, word: Word) -> nb::Result<(), Self::Error>;
fn write(&mut self, word: Self::Word) -> nb::Result<(), Self::Error>;
}

/// Clock polarity
Expand Down