diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e4c3a9..89b7308 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - PWM complementary output capability for TIM1 with new example to demonstrate - Implement interface for reading and writing to the internal flash memory and an example for demonstration. - PWM output on complementary channels only for single channel timers (TIM16 + TIM17) +- impl embedded_hal_1::spi::SpiBus for SPI +- impl embedded_hal_1::digital traits for Pins ### Fixed diff --git a/Cargo.toml b/Cargo.toml index 393a9c7..6c1135c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,7 @@ bare-metal = { version = "1.0.0" } cast = "0.3" cortex-m = "0.7" embedded-hal = { version = "0.2", features = ["unproven"] } +embedded-hal-1 = { package = "embedded-hal", version = "1.0" } stm32f0 = "0.14" nb = "1" void = { version = "1.0", default-features = false } diff --git a/src/gpio.rs b/src/gpio.rs index dd2757e..568b904 100644 --- a/src/gpio.rs +++ b/src/gpio.rs @@ -144,6 +144,55 @@ impl InputPin for Pin> { } } +impl embedded_hal_1::digital::ErrorType for Pin { + type Error = Infallible; +} + +impl embedded_hal_1::digital::InputPin for Pin +where + Pin: InputPin, +{ + #[inline(always)] + fn is_high(&mut self) -> Result { + InputPin::is_high(self) + } + + #[inline(always)] + fn is_low(&mut self) -> Result { + InputPin::is_low(self) + } +} + +impl embedded_hal_1::digital::OutputPin for Pin +where + Pin: OutputPin, +{ + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + OutputPin::set_high(self) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + OutputPin::set_low(self) + } +} + +impl embedded_hal_1::digital::StatefulOutputPin for Pin +where + Pin: StatefulOutputPin, +{ + #[inline(always)] + fn is_set_high(&mut self) -> Result { + StatefulOutputPin::is_set_high(self) + } + + #[inline(always)] + fn is_set_low(&mut self) -> Result { + StatefulOutputPin::is_set_low(self) + } +} + macro_rules! gpio_trait { ($gpiox:ident) => { impl GpioRegExt for crate::pac::$gpiox::RegisterBlock { @@ -564,6 +613,46 @@ macro_rules! gpio { Ok(unsafe { (*$GPIOX::ptr()).is_low($i) }) } } + + impl embedded_hal_1::digital::ErrorType for $PXi{ + type Error = Infallible; + } + + impl embedded_hal_1::digital::InputPin for $PXi where $PXi: InputPin { + #[inline(always)] + fn is_high(&mut self) -> Result { + InputPin::is_high(self) + } + + #[inline(always)] + fn is_low(&mut self) -> Result { + InputPin::is_low(self) + } + } + + impl embedded_hal_1::digital::OutputPin for $PXi where $PXi: OutputPin { + #[inline(always)] + fn set_high(&mut self) -> Result<(), Self::Error> { + OutputPin::set_high(self) + } + + #[inline(always)] + fn set_low(&mut self) -> Result<(), Self::Error> { + OutputPin::set_low(self) + } + } + + impl embedded_hal_1::digital::StatefulOutputPin for $PXi where $PXi: StatefulOutputPin { + #[inline(always)] + fn is_set_high(&mut self) -> Result { + StatefulOutputPin::is_set_high(self) + } + + #[inline(always)] + fn is_set_low(&mut self) -> Result { + StatefulOutputPin::is_set_low(self) + } + } )+ } )+ diff --git a/src/spi.rs b/src/spi.rs index 17eeef7..ff990d5 100644 --- a/src/spi.rs +++ b/src/spi.rs @@ -529,3 +529,108 @@ where Ok(()) } } + +impl embedded_hal_1::spi::Error for Error { + fn kind(&self) -> embedded_hal_1::spi::ErrorKind { + match self { + Error::Overrun => embedded_hal_1::spi::ErrorKind::Overrun, + Error::ModeFault => embedded_hal_1::spi::ErrorKind::ModeFault, + Error::Crc => embedded_hal_1::spi::ErrorKind::Other, + } + } +} +impl embedded_hal_1::spi::ErrorType + for Spi +where + SPI: Deref, +{ + type Error = Error; +} + +impl embedded_hal_1::spi::SpiBus + for Spi +where + SPI: Deref, +{ + fn read(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + // We want to transfer bidirectionally, make sure we're in the correct mode + self.set_bidi(); + + for word in words.iter_mut() { + nb::block!(self.check_send())?; + self.send_u8(0); // FIXME is this necessary? + nb::block!(self.check_read())?; + *word = self.read_u8(); + } + Ok(()) + } + + fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> { + embedded_hal::blocking::spi::Write::write(self, words) + } + + fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> { + // We want to transfer bidirectionally, make sure we're in the correct mode + self.set_bidi(); + + for (w, r) in write.iter().zip(read.iter_mut()) { + nb::block!(self.check_send())?; + self.send_u8(*w); + nb::block!(self.check_read())?; + *r = self.read_u8(); + } + Ok(()) + } + + fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> { + embedded_hal::blocking::spi::Transfer::transfer(self, words).map(|_| ()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } +} + +impl embedded_hal_1::spi::SpiBus + for Spi +where + SPI: Deref, +{ + fn read(&mut self, words: &mut [u16]) -> Result<(), Self::Error> { + // We want to transfer bidirectionally, make sure we're in the correct mode + self.set_bidi(); + + for word in words.iter_mut() { + nb::block!(self.check_send())?; + self.send_u16(0); // FIXME is this necessary? + nb::block!(self.check_read())?; + *word = self.read_u16(); + } + Ok(()) + } + + fn write(&mut self, words: &[u16]) -> Result<(), Self::Error> { + embedded_hal::blocking::spi::Write::write(self, words) + } + + fn transfer(&mut self, read: &mut [u16], write: &[u16]) -> Result<(), Self::Error> { + // We want to transfer bidirectionally, make sure we're in the correct mode + self.set_bidi(); + + for (w, r) in write.iter().zip(read.iter_mut()) { + nb::block!(self.check_send())?; + self.send_u16(*w); + nb::block!(self.check_read())?; + *r = self.read_u16(); + } + Ok(()) + } + + fn transfer_in_place(&mut self, words: &mut [u16]) -> Result<(), Self::Error> { + embedded_hal::blocking::spi::Transfer::transfer(self, words).map(|_| ()) + } + + fn flush(&mut self) -> Result<(), Self::Error> { + Ok(()) + } +}