diff --git a/CHANGELOG.md b/CHANGELOG.md index 74a8b042a..2ce450ca7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - ESP32-C6: LP core clock is configurable (#907) - Derive `Clone` and `Copy` for `EspTwaiFrame` (#914) +- A way to configure inverted pins (#912) ### Changed diff --git a/esp-hal-common/src/gpio.rs b/esp-hal-common/src/gpio.rs index 83e50cbc5..e308f87f0 100644 --- a/esp-hal-common/src/gpio.rs +++ b/esp-hal-common/src/gpio.rs @@ -51,6 +51,28 @@ pub struct Input { _mode: PhantomData, } +pub struct InvertedInput { + _mode: PhantomData, +} + +/// Used to decide if the pin is inverted or not when the pin gets connected to +/// a peripheral +trait InputMode { + const PIN_IS_INVERTED: bool; +} + +impl InputMode for Input { + const PIN_IS_INVERTED: bool = false; +} + +impl InputMode for InvertedInput { + const PIN_IS_INVERTED: bool = true; +} + +impl InputMode for Unknown { + const PIN_IS_INVERTED: bool = false; +} + pub struct RTCInput { _mode: PhantomData, } @@ -65,6 +87,28 @@ pub struct Output { _mode: PhantomData, } +pub struct InvertedOutput { + _mode: PhantomData, +} + +/// Used to decide if the pin is inverted or not when the pin gets connected to +/// a peripheral +trait OutputMode { + const PIN_IS_INVERTED: bool; +} + +impl OutputMode for Output { + const PIN_IS_INVERTED: bool = false; +} + +impl OutputMode for InvertedOutput { + const PIN_IS_INVERTED: bool = true; +} + +impl OutputMode for Unknown { + const PIN_IS_INVERTED: bool = false; +} + pub struct RTCOutput { _mode: PhantomData, } @@ -170,9 +214,7 @@ pub trait InputPin: Pin { fn is_input_high(&self) -> bool; - fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { - self.connect_input_to_peripheral_with_options(signal, false, false) - } + fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self; fn connect_input_to_peripheral_with_options( &mut self, @@ -208,9 +250,11 @@ pub trait OutputPin: Pin { fn internal_pull_down_in_sleep_mode(&mut self, on: bool) -> &mut Self; - fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { - self.connect_peripheral_to_output_with_options(signal, false, false, false, false) - } + fn internal_pull_up(&mut self, on: bool) -> &mut Self; + + fn internal_pull_down(&mut self, on: bool) -> &mut Self; + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self; fn connect_peripheral_to_output_with_options( &mut self, @@ -227,10 +271,6 @@ pub trait OutputPin: Pin { /// pin with a previously connected [signal](`InputSignal`). Any other /// outputs connected to the signal remain intact. fn disconnect_peripheral_from_output(&mut self) -> &mut Self; - - fn internal_pull_up(&mut self, on: bool) -> &mut Self; - - fn internal_pull_down(&mut self, on: bool) -> &mut Self; } #[doc(hidden)] @@ -578,25 +618,50 @@ where }); } + /// Configures the pin to operate as a floating input pin pub fn into_floating_input(self) -> GpioPin, GPIONUM> { self.init_input(false, false); GpioPin { _mode: PhantomData } } + /// Configures the pin to operate as a pulled up input pin pub fn into_pull_up_input(self) -> GpioPin, GPIONUM> { self.init_input(false, true); GpioPin { _mode: PhantomData } } + /// Configures the pin to operate as a pulled down input pin pub fn into_pull_down_input(self) -> GpioPin, GPIONUM> { self.init_input(true, false); GpioPin { _mode: PhantomData } } + + /// Configures the pin to operate as an inverted floating input pin. + /// Only suitable to be passed into a peripheral driver. + pub fn into_inverted_floating_input(self) -> GpioPin, GPIONUM> { + self.init_input(false, false); + GpioPin { _mode: PhantomData } + } + + /// Configures the pin to operate as an inverted pulled up input pin. + /// Only suitable to be passed into a peripheral driver. + pub fn into_inverted_pull_up_input(self) -> GpioPin, GPIONUM> { + self.init_input(false, true); + GpioPin { _mode: PhantomData } + } + + /// Configures the pin to operate as an inverted pulled down input pin. + /// Only suitable to be passed into a peripheral driver. + pub fn into_inverted_pull_down_input(self) -> GpioPin, GPIONUM> { + self.init_input(true, false); + GpioPin { _mode: PhantomData } + } } impl InputPin for GpioPin where Self: GpioProperties, + MODE: InputMode, { fn set_to_input(&mut self) -> &mut Self { self.init_input(false, false); @@ -613,6 +678,15 @@ where fn is_input_high(&self) -> bool { ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 } + + fn connect_input_to_peripheral(&mut self, signal: InputSignal) -> &mut Self { + self.connect_input_to_peripheral_with_options( + signal, + MODE::PIN_IS_INVERTED, + MODE::PIN_IS_INVERTED, + ) + } + fn connect_input_to_peripheral_with_options( &mut self, signal: InputSignal, @@ -864,6 +938,18 @@ where } } +impl From> + for GpioPin, GPIONUM> +where + Self: GpioProperties, + ::PinType: IsInputPin, + GpioPin: GpioProperties, +{ + fn from(pin: GpioPin) -> Self { + pin.into_inverted_floating_input() + } +} + impl From> for GpioPin, GPIONUM> where Self: GpioProperties, @@ -875,6 +961,17 @@ where } } +impl From> for GpioPin, GPIONUM> +where + Self: GpioProperties, + ::PinType: IsOutputPin, + GpioPin: GpioProperties, +{ + fn from(pin: GpioPin) -> Self { + pin.into_inverted_pull_up_input() + } +} + impl From> for GpioPin, GPIONUM> where Self: GpioProperties, @@ -886,6 +983,18 @@ where } } +impl From> + for GpioPin, GPIONUM> +where + Self: GpioProperties, + ::PinType: IsInputPin, + GpioPin: GpioProperties, +{ + fn from(pin: GpioPin) -> Self { + pin.into_inverted_pull_down_input() + } +} + impl From> for GpioPin, GPIONUM> where Self: GpioProperties, @@ -898,6 +1007,19 @@ where } } +impl From> + for GpioPin, GPIONUM> +where + Self: GpioProperties, + ::PinType: IsOutputPin, + GpioPin: GpioProperties, + as GpioProperties>::PinType: IsOutputPin, +{ + fn from(pin: GpioPin) -> Self { + pin.into_inverted_push_pull_output() + } +} + impl From> for GpioPin where Self: GpioProperties, @@ -922,6 +1044,19 @@ where } } +impl From> + for GpioPin, GPIONUM> +where + Self: GpioProperties, + ::PinType: IsOutputPin, + GpioPin: GpioProperties, + as GpioProperties>::PinType: IsOutputPin, +{ + fn from(pin: GpioPin) -> Self { + pin.into_inverted_open_drain_output() + } +} + impl From> for GpioPin, GPIONUM> where Self: GpioProperties, @@ -993,16 +1128,32 @@ where }); } + /// Configures the pin to operate as an push pull output pin pub fn into_push_pull_output(self) -> GpioPin, GPIONUM> { self.init_output(GPIO_FUNCTION, false); GpioPin { _mode: PhantomData } } + /// Configures the pin to operate as an open drain output pin pub fn into_open_drain_output(self) -> GpioPin, GPIONUM> { self.init_output(GPIO_FUNCTION, true); GpioPin { _mode: PhantomData } } + /// Configures the pin to operate as an inverted push pull output pin. + /// Only suitable to be passed into an peripheral driver + pub fn into_inverted_push_pull_output(self) -> GpioPin, GPIONUM> { + self.init_output(GPIO_FUNCTION, false); + GpioPin { _mode: PhantomData } + } + + /// Configures the pin to operate as an open drain output pin. + /// Only suitable to be passed into an peripheral driver + pub fn into_inverted_open_drain_output(self) -> GpioPin, GPIONUM> { + self.init_output(GPIO_FUNCTION, true); + GpioPin { _mode: PhantomData } + } + pub fn into_alternate_1(self) -> GpioPin, GPIONUM> { self.init_output(AlternateFunction::Function1, false); GpioPin { _mode: PhantomData } @@ -1018,6 +1169,7 @@ impl OutputPin for GpioPin where Self: GpioProperties, ::PinType: IsOutputPin, + MODE: OutputMode, { fn set_to_open_drain_output(&mut self) -> &mut Self { self.init_output(GPIO_FUNCTION, true); @@ -1071,6 +1223,25 @@ where self } + fn internal_pull_up(&mut self, on: bool) -> &mut Self { + get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpu().bit(on)); + self + } + fn internal_pull_down(&mut self, on: bool) -> &mut Self { + get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpd().bit(on)); + self + } + + fn connect_peripheral_to_output(&mut self, signal: OutputSignal) -> &mut Self { + self.connect_peripheral_to_output_with_options( + signal, + MODE::PIN_IS_INVERTED, + false, + false, + MODE::PIN_IS_INVERTED, + ) + } + fn connect_peripheral_to_output_with_options( &mut self, signal: OutputSignal, @@ -1132,15 +1303,6 @@ where .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); self } - - fn internal_pull_up(&mut self, on: bool) -> &mut Self { - get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpu().bit(on)); - self - } - fn internal_pull_down(&mut self, on: bool) -> &mut Self { - get_io_mux_reg(GPIONUM).modify(|_, w| w.fun_wpd().bit(on)); - self - } } impl GpioPin