From 891368fb3511113ecb3a5123e97603115e2008a1 Mon Sep 17 00:00:00 2001 From: Volkalex28 Date: Tue, 9 Jan 2024 00:09:37 +0200 Subject: [PATCH] Add type for gpio::AnyPin This makes it possible to safely implement the InputPin and OutputPin traits for AnyPin. Now you can convert any pin to AnyPin with the appropriate type and use it in other library modules Added: - Peripheral implementation for AnyPin - Implementation of Pin for AnyPin - Implementation of OutputPin for AnyPin with type IsOutputPin - Implementation of InputPin for AnyPin with type IsInputPin - Upgrade types for AnyPin (for example InputOutputAnalogPinType -> InputOutputPinType) - Implementation of From for AnyPin with the appropriate type Changed: - The Gpio::degrage method returns AnyPin with the appropriate type undefined --- esp-hal-common/src/gpio.rs | 410 ++++++++++++++++++++++++++++++++++--- 1 file changed, 387 insertions(+), 23 deletions(-) diff --git a/esp-hal-common/src/gpio.rs b/esp-hal-common/src/gpio.rs index dcaf8dc086a..130fa035b8c 100644 --- a/esp-hal-common/src/gpio.rs +++ b/esp-hal-common/src/gpio.rs @@ -38,11 +38,11 @@ pub const NO_PIN: Option = None; #[derive(Copy, Clone)] pub enum Event { - RisingEdge = 1, + RisingEdge = 1, FallingEdge = 2, - AnyEdge = 3, - LowLevel = 4, - HighLevel = 5, + AnyEdge = 3, + LowLevel = 4, + HighLevel = 5, } pub struct Unknown {} @@ -133,7 +133,7 @@ pub struct AF1; pub struct AF2; pub enum DriveStrength { - I5mA = 0, + I5mA = 0, I10mA = 1, I20mA = 2, I40mA = 3, @@ -151,7 +151,7 @@ pub enum AlternateFunction { #[derive(PartialEq)] pub enum RtcFunction { - Rtc = 0, + Rtc = 0, Digital = 1, } @@ -1355,7 +1355,359 @@ where } } -impl embedded_hal::digital::v2::InputPin for AnyPin> { +impl From> for AnyPin +where + TYPE: PinType, +{ + fn from(pin: AnyPin) -> Self { + Self { + inner: pin.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl crate::peripheral::Peripheral for AnyPin +where + TYPE: PinType, +{ + type P = Self; + + unsafe fn clone_unchecked(&mut self) -> Self::P { + let inner = &mut self.inner; + let this: AnyPin = handle_gpio_input!(inner, target, { + crate::peripheral::Peripheral::clone_unchecked(target).into() + }); + Self { + inner: this.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl crate::peripheral::sealed::Sealed for AnyPin where TYPE: PinType {} + +impl AnyPin +where + TYPE: PinType, +{ + pub fn degrade(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl AnyPin { + pub fn into_input_type(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl AnyPin { + pub fn into_input_type(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } + + pub fn into_input_output_type(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } + + pub fn into_input_only_analog_type(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl AnyPin { + pub fn into_input_type(self) -> AnyPin { + AnyPin { + inner: self.inner, + _type: core::marker::PhantomData::default(), + } + } +} + +impl Pin for AnyPin +where + TYPE: PinType, +{ + fn number(&self) -> u8 { + let inner = &self.inner; + handle_gpio_input!(inner, target, { Pin::number(target) }) + } + + fn sleep_mode(&mut self, on: bool) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { Pin::sleep_mode(target, on) }) + } + + fn set_alternate_function(&mut self, alternate: AlternateFunction) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + Pin::set_alternate_function(target, alternate) + }) + } + + fn is_listening(&self) -> bool { + let inner = &self.inner; + handle_gpio_input!(inner, target, { Pin::is_listening(target) }) + } + + fn listen_with_options( + &mut self, + event: Event, + int_enable: bool, + nmi_enable: bool, + wake_up_from_light_sleep: bool, + ) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + Pin::listen_with_options( + target, + event, + int_enable, + nmi_enable, + wake_up_from_light_sleep, + ) + }) + } + + fn listen(&mut self, event: Event) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { Pin::listen(target, event) }) + } + + fn unlisten(&mut self) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { Pin::unlisten(target) }) + } + + fn is_interrupt_set(&self) -> bool { + let inner = &self.inner; + handle_gpio_input!(inner, target, { Pin::is_interrupt_set(target) }) + } + + fn clear_interrupt(&mut self) { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { Pin::clear_interrupt(target) }) + } +} + +impl InputPin for AnyPin +where + MODE: InputMode, + TYPE: IsInputPin, +{ + fn set_to_input(&mut self) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::set_to_input(target); + }); + self + } + + fn enable_input(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::enable_input(target, on); + }); + self + } + + fn enable_input_in_sleep_mode(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::enable_input_in_sleep_mode(target, on); + }); + self + } + + fn is_input_high(&self) -> bool { + let inner = &self.inner; + handle_gpio_input!(inner, target, { InputPin::is_input_high(target) }) + } + + fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::connect_input_to_peripheral(target, signal); + }); + self + } + + fn connect_input_to_peripheral_with_options( + &mut self, + signal: InputSignal, + invert: bool, + force_via_gpio_mux: bool, + ) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::connect_input_to_peripheral_with_options( + target, + signal, + invert, + force_via_gpio_mux, + ); + }); + self + } + + fn disconnect_input_from_peripheral(&mut self, signal: InputSignal) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_input!(inner, target, { + InputPin::disconnect_input_from_peripheral(target, signal); + }); + self + } +} + +impl OutputPin for AnyPin +where + MODE: OutputMode, + TYPE: IsOutputPin, +{ + fn set_to_open_drain_output(&mut self) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::set_to_open_drain_output(target); + }); + self + } + + fn set_to_push_pull_output(&mut self) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::set_to_push_pull_output(target); + }); + self + } + + fn enable_output(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::enable_output(target, on); + }); + self + } + + fn set_output_high(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::set_output_high(target, on); + }); + self + } + + fn set_drive_strength(&mut self, strength: DriveStrength) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::set_drive_strength(target, strength); + }); + self + } + + fn enable_open_drain(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::enable_open_drain(target, on); + }); + self + } + + fn enable_output_in_sleep_mode(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::enable_output_in_sleep_mode(target, on); + }); + self + } + + fn internal_pull_up_in_sleep_mode(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::internal_pull_up_in_sleep_mode(target, on); + }); + self + } + + fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::internal_pull_down_in_sleep_mode(target, on); + }); + self + } + + fn internal_pull_up(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::internal_pull_up(target, on); + }); + self + } + + fn internal_pull_down(&mut self, on: bool) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::internal_pull_down(target, on); + }); + self + } + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::connect_peripheral_to_output(target, signal); + }); + self + } + + fn connect_peripheral_to_output_with_options( + &mut self, + signal: OutputSignal, + invert: bool, + invert_enable: bool, + enable_from_gpio: bool, + force_via_gpio_mux: bool, + ) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::connect_peripheral_to_output_with_options( + target, + signal, + invert, + invert_enable, + enable_from_gpio, + force_via_gpio_mux, + ); + }); + self + } + + fn disconnect_peripheral_from_output(&mut self) -> &mut Self { + let inner = &mut self.inner; + handle_gpio_output!(inner, target, { + OutputPin::disconnect_peripheral_from_output(target); + }); + self + } +} + +impl embedded_hal::digital::v2::InputPin for AnyPin, TYPE> { type Error = core::convert::Infallible; fn is_high(&self) -> Result { @@ -1370,12 +1722,12 @@ impl embedded_hal::digital::v2::InputPin for AnyPin> { } #[cfg(feature = "eh1")] -impl embedded_hal_1::digital::ErrorType for AnyPin> { +impl embedded_hal_1::digital::ErrorType for AnyPin, TYPE> { type Error = Infallible; } #[cfg(feature = "eh1")] -impl embedded_hal_1::digital::InputPin for AnyPin> { +impl embedded_hal_1::digital::InputPin for AnyPin, TYPE> { fn is_high(&self) -> Result { let inner = &self.inner; handle_gpio_input!(inner, target, { target.is_high() }) @@ -1387,7 +1739,7 @@ impl embedded_hal_1::digital::InputPin for AnyPin> { } } -impl embedded_hal::digital::v2::OutputPin for AnyPin> { +impl embedded_hal::digital::v2::OutputPin for AnyPin, TYPE> { type Error = Infallible; fn set_low(&mut self) -> Result<(), Self::Error> { @@ -1401,7 +1753,7 @@ impl embedded_hal::digital::v2::OutputPin for AnyPin> { } } -impl embedded_hal::digital::v2::StatefulOutputPin for AnyPin> { +impl embedded_hal::digital::v2::StatefulOutputPin for AnyPin, TYPE> { fn is_set_high(&self) -> Result { let inner = &self.inner; handle_gpio_output!(inner, target, { target.is_set_high() }) @@ -1413,7 +1765,7 @@ impl embedded_hal::digital::v2::StatefulOutputPin for AnyPin> } } -impl embedded_hal::digital::v2::ToggleableOutputPin for AnyPin> { +impl embedded_hal::digital::v2::ToggleableOutputPin for AnyPin, TYPE> { type Error = Infallible; fn toggle(&mut self) -> Result<(), Self::Error> { @@ -1423,12 +1775,12 @@ impl embedded_hal::digital::v2::ToggleableOutputPin for AnyPin embedded_hal_1::digital::ErrorType for AnyPin> { +impl embedded_hal_1::digital::ErrorType for AnyPin, TYPE> { type Error = Infallible; } #[cfg(feature = "eh1")] -impl embedded_hal_1::digital::OutputPin for AnyPin> { +impl embedded_hal_1::digital::OutputPin for AnyPin, TYPE> { fn set_low(&mut self) -> Result<(), Self::Error> { let inner = &mut self.inner; handle_gpio_output!(inner, target, { target.set_low() }) @@ -1441,7 +1793,7 @@ impl embedded_hal_1::digital::OutputPin for AnyPin> { } #[cfg(feature = "eh1")] -impl embedded_hal_1::digital::StatefulOutputPin for AnyPin> { +impl embedded_hal_1::digital::StatefulOutputPin for AnyPin, TYPE> { fn is_set_high(&self) -> Result { let inner = &self.inner; handle_gpio_output!(inner, target, { target.is_set_high() }) @@ -1454,7 +1806,7 @@ impl embedded_hal_1::digital::StatefulOutputPin for AnyPin> { } #[cfg(feature = "eh1")] -impl embedded_hal_1::digital::ToggleableOutputPin for AnyPin> { +impl embedded_hal_1::digital::ToggleableOutputPin for AnyPin, TYPE> { fn toggle(&mut self) -> Result<(), Self::Error> { let inner = &mut self.inner; handle_gpio_output!(inner, target, { target.toggle() }) @@ -1462,7 +1814,7 @@ impl embedded_hal_1::digital::ToggleableOutputPin for AnyPin> } #[cfg(feature = "async")] -impl embedded_hal_async::digital::Wait for AnyPin> { +impl embedded_hal_async::digital::Wait for AnyPin, TYPE> { async fn wait_for_high(&mut self) -> Result<(), Self::Error> { let inner = &mut self.inner; handle_gpio_input!(inner, target, { target.wait_for_high().await }) @@ -1600,28 +1952,40 @@ macro_rules! gpio { )+ } - pub struct AnyPin { - pub(crate) inner: ErasedPin + pub struct AnyPin { + pub(crate) inner: ErasedPin, + pub(crate) _type: core::marker::PhantomData, } $( + impl From< [] > for AnyPin]> { + fn from(value: []) -> Self { + AnyPin { + inner: ErasedPin::[](value), + _type: core::marker::PhantomData::default(), + } + } + } + impl From< [] > for AnyPin { fn from(value: []) -> Self { AnyPin { - inner: ErasedPin::[](value) + inner: ErasedPin::[](value), + _type: core::marker::PhantomData::default(), } } } impl [] { - pub fn degrade(self) -> AnyPin { + pub fn degrade(self) -> AnyPin]> { AnyPin { - inner: ErasedPin::[](self) + inner: ErasedPin::[](self), + _type: core::marker::PhantomData::default(), } } } - impl TryInto<[]> for AnyPin { + impl TryInto<[]> for AnyPin { type Error = (); fn try_into(self) -> Result<[], Self::Error> {