sajattack / bitbang-hal

Implements embedded-hal traits by bitbanging
MIT License
40 stars 10 forks source link

SPI doesn't match the paradigm defined in embedded HAL #1

Closed austinglaser closed 5 years ago

austinglaser commented 5 years ago

The embedded hal trait (duplicated below for reference) requires that an actual SPI transaction be performed only from the send() function. send() should clock out the provided byte, as well as clocking in the byte sent by the slave. A subsequent read() call will return that cached byte (in most implementations this'll come from a register, but for bitbang it'll just be some storage in the struct).

The current implementation clocks data explicitly in both functions, meaning there's no way to simultaneously read and write data. This will render it impossible to interface with many SPI peripherals, and will break implementations expecting the HAL-defined behavior which try to use this.

/// Full duplex (master mode)
///
/// # Notes
///
/// - It's the task of the user of this interface to manage the slave select lines
///
/// - Due to how full duplex SPI works each `read` call must be preceded by a `send` call.
///
/// - 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> {
    /// 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>;

    /// Sends a word to the slave
    fn send(&mut self, word: Word) -> nb::Result<(), Self::Error>;
}
sajattack commented 5 years ago

So send() should do reading and writing, and read(), should just return the byte it got from send?

austinbes commented 5 years ago

Correct