From 9057a37333d11e0a17ba8b8b771fa76921c410af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 15:52:22 +0200 Subject: [PATCH 1/6] Keep a single PinType trait --- esp-hal/src/gpio/mod.rs | 110 ++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 48 deletions(-) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index fef1fe145f6..f5ea7d2fb07 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -644,20 +644,33 @@ pub fn connect_high_to_peripheral(signal: InputSignal) { }); } -#[doc(hidden)] -pub trait PinType {} + #[doc(hidden)] -pub trait IsOutputPin: PinType {} +pub trait BooleanType { + const VALUE: bool; +} #[doc(hidden)] -pub trait IsInputPin: PinType {} +pub struct True {} + +impl BooleanType for True { + const VALUE: bool = true; +} #[doc(hidden)] -pub trait IsAnalogPin: PinType {} +pub struct False {} + +impl BooleanType for False { + const VALUE: bool = false; +} #[doc(hidden)] -pub trait IsTouchPin: PinType {} +pub trait PinType { + type IsOutput: BooleanType; + type IsAnalog: BooleanType; + type IsTouch: BooleanType; +} #[doc(hidden)] pub struct InputOutputPinType; @@ -674,27 +687,35 @@ pub struct InputOnlyAnalogPinType; #[doc(hidden)] pub struct InputOutputAnalogTouchPinType; -impl PinType for InputOutputPinType {} -impl IsOutputPin for InputOutputPinType {} -impl IsInputPin for InputOutputPinType {} +impl PinType for InputOutputPinType { + type IsOutput = True; + type IsAnalog = False; + type IsTouch = False; +} -impl PinType for InputOnlyPinType {} -impl IsInputPin for InputOnlyPinType {} +impl PinType for InputOnlyPinType { + type IsOutput = False; + type IsAnalog = False; + type IsTouch = False; +} -impl PinType for InputOutputAnalogPinType {} -impl IsOutputPin for InputOutputAnalogPinType {} -impl IsInputPin for InputOutputAnalogPinType {} -impl IsAnalogPin for InputOutputAnalogPinType {} +impl PinType for InputOutputAnalogPinType { + type IsOutput = True; + type IsAnalog = True; + type IsTouch = False; +} -impl PinType for InputOnlyAnalogPinType {} -impl IsInputPin for InputOnlyAnalogPinType {} -impl IsAnalogPin for InputOnlyAnalogPinType {} +impl PinType for InputOnlyAnalogPinType { + type IsOutput = False; + type IsAnalog = True; + type IsTouch = False; +} -impl PinType for InputOutputAnalogTouchPinType {} -impl IsOutputPin for InputOutputAnalogTouchPinType {} -impl IsInputPin for InputOutputAnalogTouchPinType {} -impl IsAnalogPin for InputOutputAnalogTouchPinType {} -impl IsTouchPin for InputOutputAnalogTouchPinType {} +impl PinType for InputOutputAnalogTouchPinType { + type IsOutput = True; + type IsAnalog = True; + type IsTouch = True; +} /// GPIO pin pub struct GpioPin; @@ -702,7 +723,7 @@ pub struct GpioPin; impl GpioPin where Self: GpioProperties, - ::PinType: IsOutputPin, + ::PinType: PinType, { /// Is the input pin high? #[inline] @@ -720,17 +741,24 @@ where impl GpioPin where Self: GpioProperties, - ::PinType: IsInputPin, { pub(crate) fn new() -> Self { Self } + + /// Create a pin out of thin air. + /// + /// # Safety + /// + /// Ensure that only one instance of a pin exists at one time. + pub unsafe fn steal() -> Self { + Self::new() + } } impl InputPin for GpioPin where Self: GpioProperties, - ::PinType: IsInputPin, { fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { let gpio = unsafe { &*GPIO::PTR }; @@ -874,20 +902,6 @@ where } } -impl GpioPin -where - Self: GpioProperties, -{ - /// Create a pin out of thin air. - /// - /// # Safety - /// - /// Ensure that only one instance of a pin exists at one time. - pub unsafe fn steal() -> Self { - Self - } -} - impl Pin for GpioPin where Self: GpioProperties, @@ -966,7 +980,7 @@ where impl GpioPin where Self: GpioProperties, - ::PinType: IsOutputPin, + ::PinType: PinType, { /// Drives the pin high. #[inline] @@ -1028,9 +1042,9 @@ impl private::Sealed for GpioPin where Self: GpioPro impl GpioPin where Self: GpioProperties, - ::PinType: IsOutputPin, + ::PinType: PinType, { - fn init_output(&self, alternate: AlternateFunction, open_drain: bool, _: private::Internal) { + fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { let gpio = unsafe { &*GPIO::PTR }; #[cfg(esp32)] @@ -1080,14 +1094,14 @@ where impl OutputPin for GpioPin where Self: GpioProperties, - ::PinType: IsOutputPin, + ::PinType: PinType, { fn set_to_open_drain_output(&mut self, _: private::Internal) { - self.init_output(GPIO_FUNCTION, true, private::Internal); + self.init_output(GPIO_FUNCTION, true); } fn set_to_push_pull_output(&mut self, _: private::Internal) { - self.init_output(GPIO_FUNCTION, false, private::Internal); + self.init_output(GPIO_FUNCTION, false); } fn enable_output(&mut self, on: bool, _: private::Internal) { @@ -1223,7 +1237,7 @@ where impl AnalogPin for GpioPin where Self: GpioProperties, - ::PinType: IsAnalogPin, + ::PinType: PinType, { /// Configures the pin for analog mode. fn set_analog(&self, _: private::Internal) { @@ -1235,7 +1249,7 @@ where impl TouchPin for GpioPin where Self: GpioProperties, - ::PinType: IsTouchPin, + ::PinType: PinType, { fn set_touch(&self, _: private::Internal) { crate::soc::gpio::internal_into_touch(GPIONUM); From 06dc14c0552d3d48276a6c636629d4bf8d6e9d3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 15:54:49 +0200 Subject: [PATCH 2/6] Merge impl blocks --- esp-hal/src/gpio/mod.rs | 122 ++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 67 deletions(-) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index f5ea7d2fb07..752120a824b 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -720,24 +720,6 @@ impl PinType for InputOutputAnalogTouchPinType { /// GPIO pin pub struct GpioPin; -impl GpioPin -where - Self: GpioProperties, - ::PinType: PinType, -{ - /// Is the input pin high? - #[inline] - pub fn is_high(&self) -> bool { - ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 - } - - /// Is the input pin low? - #[inline] - pub fn is_low(&self) -> bool { - !self.is_high() - } -} - impl GpioPin where Self: GpioProperties, @@ -754,6 +736,18 @@ where pub unsafe fn steal() -> Self { Self::new() } + + /// Is the input pin high? + #[inline] + pub fn is_high(&self) -> bool { + ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 + } + + /// Is the input pin low? + #[inline] + pub fn is_low(&self) -> bool { + !self.is_high() + } } impl InputPin for GpioPin @@ -977,55 +971,6 @@ where } } -impl GpioPin -where - Self: GpioProperties, - ::PinType: PinType, -{ - /// Drives the pin high. - #[inline] - pub fn set_high(&mut self) { - ::Bank::write_output_set(1 << (GPIONUM % 32)); - } - - /// Drives the pin low. - #[inline] - pub fn set_low(&mut self) { - ::Bank::write_output_clear(1 << (GPIONUM % 32)); - } - - /// Drives the pin high or low depending on the provided value. - #[inline] - pub fn set_state(&mut self, state: bool) { - match state { - true => self.set_high(), - false => self.set_low(), - } - } - - /// Is the pin in drive high mode? - #[inline] - pub fn is_set_high(&self) -> bool { - ::Bank::read_output() & (1 << (GPIONUM % 32)) != 0 - } - - /// Is the pin in drive low mode? - #[inline] - pub fn is_set_low(&self) -> bool { - !self.is_set_high() - } - - /// Toggle pin output. - #[inline] - pub fn toggle(&mut self) { - if self.is_set_high() { - self.set_low(); - } else { - self.set_high(); - } - } -} - impl crate::peripheral::Peripheral for GpioPin where Self: GpioProperties, @@ -1089,6 +1034,49 @@ where .clear_bit() }); } + + /// Drives the pin high. + #[inline] + pub fn set_high(&mut self) { + ::Bank::write_output_set(1 << (GPIONUM % 32)); + } + + /// Drives the pin low. + #[inline] + pub fn set_low(&mut self) { + ::Bank::write_output_clear(1 << (GPIONUM % 32)); + } + + /// Drives the pin high or low depending on the provided value. + #[inline] + pub fn set_state(&mut self, state: bool) { + match state { + true => self.set_high(), + false => self.set_low(), + } + } + + /// Is the pin in drive high mode? + #[inline] + pub fn is_set_high(&self) -> bool { + ::Bank::read_output() & (1 << (GPIONUM % 32)) != 0 + } + + /// Is the pin in drive low mode? + #[inline] + pub fn is_set_low(&self) -> bool { + !self.is_set_high() + } + + /// Toggle pin output. + #[inline] + pub fn toggle(&mut self) { + if self.is_set_high() { + self.set_low(); + } else { + self.set_high(); + } + } } impl OutputPin for GpioPin From fe2feb6406c97a396e3f52d689e03c843c31bd2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 16:00:30 +0200 Subject: [PATCH 3/6] Deduplicate usb pad workaround --- esp-hal/src/gpio/mod.rs | 88 ++++++++++++++++------------------------- 1 file changed, 34 insertions(+), 54 deletions(-) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 752120a824b..a9fb3ac43a7 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -750,6 +750,36 @@ where } } +/// Workaround to make D+ and D- work on the ESP32-C3 and ESP32-S3, which by +/// default are assigned to the `USB_SERIAL_JTAG` peripheral. +#[cfg(any(esp32c3, esp32s3))] +fn disable_usb_pads(gpionum: u8) { + cfg_if::cfg_if! { + if #[cfg(esp32c3)] { + let pins = [18, 19]; + } else if #[cfg(esp32s3)] { + let pins = [19, 20]; + } + } + + if pins.contains(&gpionum) { + unsafe { &*crate::peripherals::USB_DEVICE::PTR } + .conf0() + .modify(|_, w| { + w.usb_pad_enable() + .clear_bit() + .dm_pullup() + .clear_bit() + .dm_pulldown() + .clear_bit() + .dp_pullup() + .clear_bit() + .dp_pulldown() + .clear_bit() + }); + } +} + impl InputPin for GpioPin where Self: GpioProperties, @@ -764,44 +794,8 @@ where #[cfg(esp32)] crate::soc::gpio::errata36(GPIONUM, Some(pull_up), Some(pull_down)); - // NOTE: Workaround to make GPIO18 and GPIO19 work on the ESP32-C3, which by - // default are assigned to the `USB_SERIAL_JTAG` peripheral. - #[cfg(esp32c3)] - if GPIONUM == 18 || GPIONUM == 19 { - unsafe { &*crate::peripherals::USB_DEVICE::PTR } - .conf0() - .modify(|_, w| { - w.usb_pad_enable() - .clear_bit() - .dm_pullup() - .clear_bit() - .dm_pulldown() - .clear_bit() - .dp_pullup() - .clear_bit() - .dp_pulldown() - .clear_bit() - }); - } - - // Same workaround as above for ESP32-S3 - #[cfg(esp32s3)] - if GPIONUM == 19 || GPIONUM == 20 { - unsafe { &*crate::peripherals::USB_DEVICE::PTR } - .conf0() - .modify(|_, w| { - w.usb_pad_enable() - .clear_bit() - .dm_pullup() - .clear_bit() - .dm_pulldown() - .clear_bit() - .dp_pullup() - .clear_bit() - .dp_pulldown() - .clear_bit() - }); - } + #[cfg(any(esp32c3, esp32s3))] + disable_usb_pads(GPIONUM); get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.mcu_sel() @@ -1002,22 +996,8 @@ where gpio.func_out_sel_cfg(GPIONUM as usize) .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); - // NOTE: Workaround to make GPIO18 and GPIO19 work on the ESP32-C3, which by - // default are assigned to the `USB_SERIAL_JTAG` peripheral. - #[cfg(esp32c3)] - if GPIONUM == 18 || GPIONUM == 19 { - unsafe { &*crate::peripherals::USB_DEVICE::PTR } - .conf0() - .modify(|_, w| w.usb_pad_enable().clear_bit()); - } - - // Same workaround as above for ESP32-S3 - #[cfg(esp32s3)] - if GPIONUM == 19 || GPIONUM == 20 { - unsafe { &*crate::peripherals::USB_DEVICE::PTR } - .conf0() - .modify(|_, w| w.usb_pad_enable().clear_bit()); - } + #[cfg(any(esp32c3, esp32s3))] + disable_usb_pads(GPIONUM); get_io_mux_reg(GPIONUM).modify(|_, w| unsafe { w.mcu_sel() From 59e1fa4f58dafcdd0541c8eb344fe28ba5efdd6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 16:34:27 +0200 Subject: [PATCH 4/6] Deduplicate some bit manipulation --- esp-hal/src/gpio/mod.rs | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index a9fb3ac43a7..78b96697180 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -748,6 +748,14 @@ where pub fn is_low(&self) -> bool { !self.is_high() } + + fn write_out_en(&self, enable: bool) { + if enable { + ::Bank::write_out_en_set(1 << (GPIONUM % 32)); + } else { + ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); + } + } } /// Workaround to make D+ and D- work on the ESP32-C3 and ESP32-S3, which by @@ -787,7 +795,8 @@ where fn init_input(&self, pull_down: bool, pull_up: bool, _: private::Internal) { let gpio = unsafe { &*GPIO::PTR }; - ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); + self.write_out_en(false); + gpio.func_out_sel_cfg(GPIONUM as usize) .modify(|_, w| unsafe { w.out_sel().bits(OutputSignal::GPIO as OutputSignalType) }); @@ -824,7 +833,7 @@ where } fn is_input_high(&self, _: private::Internal) -> bool { - ::Bank::read_input() & (1 << (GPIONUM % 32)) != 0 + self.is_high() } fn connect_input_to_peripheral(&mut self, signal: InputSignal, _: private::Internal) { @@ -989,7 +998,8 @@ where #[cfg(esp32)] crate::soc::gpio::errata36(GPIONUM, Some(false), Some(false)); - ::Bank::write_out_en_set(1 << (GPIONUM % 32)); + self.write_out_en(true); + gpio.pin(GPIONUM as usize) .modify(|_, w| w.pad_driver().bit(open_drain)); @@ -1073,18 +1083,14 @@ where } fn enable_output(&mut self, on: bool, _: private::Internal) { - if on { - ::Bank::write_out_en_set(1 << (GPIONUM % 32)); - } else { - ::Bank::write_out_en_clear(1 << (GPIONUM % 32)); - } + self.write_out_en(on); } fn set_output_high(&mut self, high: bool, _: private::Internal) { if high { - ::Bank::write_output_set(1 << (GPIONUM % 32)); + self.set_high() } else { - ::Bank::write_output_clear(1 << (GPIONUM % 32)); + self.set_low() } } From abfcd4b9a0d6ea2cd082365ea2e964a5e4f94cdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 17:00:35 +0200 Subject: [PATCH 5/6] Remove gpio dispatch proc macro --- esp-hal-procmacros/src/enum_dispatch.rs | 77 ------------------------- esp-hal-procmacros/src/lib.rs | 33 ----------- esp-hal/src/gpio/mod.rs | 64 ++++++++++++++------ 3 files changed, 45 insertions(+), 129 deletions(-) delete mode 100644 esp-hal-procmacros/src/enum_dispatch.rs diff --git a/esp-hal-procmacros/src/enum_dispatch.rs b/esp-hal-procmacros/src/enum_dispatch.rs deleted file mode 100644 index 3a010bd9849..00000000000 --- a/esp-hal-procmacros/src/enum_dispatch.rs +++ /dev/null @@ -1,77 +0,0 @@ -use proc_macro2::{Group, TokenStream, TokenTree}; -use quote::{format_ident, quote}; -use syn::{ - parse::{Parse, ParseStream, Result}, - Ident, -}; - -#[derive(Debug)] -pub(crate) struct MakeGpioEnumDispatchMacro { - pub name: String, - pub filter: Vec, - pub elements: Vec<(String, usize)>, -} - -impl Parse for MakeGpioEnumDispatchMacro { - fn parse(input: ParseStream) -> Result { - let name = input.parse::()?.to_string(); - let filter = input - .parse::()? - .stream() - .into_iter() - .map(|v| match v { - TokenTree::Group(_) => String::new(), - TokenTree::Ident(ident) => ident.to_string(), - TokenTree::Punct(_) => String::new(), - TokenTree::Literal(_) => String::new(), - }) - .filter(|p| !p.is_empty()) - .collect(); - - let mut elements = vec![]; - - let stream = input.parse::()?.stream().into_iter(); - let mut element_name = String::new(); - for v in stream { - match v { - TokenTree::Ident(ident) => { - element_name = ident.to_string(); - } - TokenTree::Literal(lit) => { - let index = lit.to_string().parse().unwrap(); - elements.push((element_name.clone(), index)); - } - _ => (), - } - } - - Ok(MakeGpioEnumDispatchMacro { - name, - filter, - elements, - }) - } -} - -pub(crate) fn build_match_arms(input: MakeGpioEnumDispatchMacro) -> Vec { - let mut arms = Vec::new(); - for (gpio_type, num) in input.elements { - let enum_name = format_ident!("ErasedPin"); - let variant_name = format_ident!("Gpio{}", num); - - if input.filter.contains(&gpio_type) { - arms.push({ - quote! { #enum_name::#variant_name($target) => $body } - }); - } else { - arms.push({ - quote! { - #[allow(unused)] - #enum_name::#variant_name($target) => { panic!("Unsupported") } - } - }); - } - } - - arms -} diff --git a/esp-hal-procmacros/src/lib.rs b/esp-hal-procmacros/src/lib.rs index 0a1106e4b87..5f423b6ce5e 100644 --- a/esp-hal-procmacros/src/lib.rs +++ b/esp-hal-procmacros/src/lib.rs @@ -52,8 +52,6 @@ use proc_macro::TokenStream; #[cfg(feature = "embassy")] mod embassy; -#[cfg(feature = "enum-dispatch")] -mod enum_dispatch; #[cfg(feature = "interrupt")] mod interrupt; #[cfg(any( @@ -339,37 +337,6 @@ pub fn handler(args: TokenStream, input: TokenStream) -> TokenStream { .into() } -/// Create an enum for erased GPIO pins, using the enum-dispatch pattern -/// -/// Only used internally -#[cfg(feature = "enum-dispatch")] -#[proc_macro] -pub fn make_gpio_enum_dispatch_macro(input: TokenStream) -> TokenStream { - use quote::{format_ident, quote}; - - use self::enum_dispatch::{build_match_arms, MakeGpioEnumDispatchMacro}; - - let input = syn::parse_macro_input!(input as MakeGpioEnumDispatchMacro); - - let macro_name = format_ident!("{}", input.name); - let arms = build_match_arms(input); - - quote! { - #[doc(hidden)] - #[macro_export] - macro_rules! #macro_name { - ($m:ident, $target:ident, $body:block) => { - match $m { - #(#arms)* - } - } - } - - pub(crate) use #macro_name; - } - .into() -} - /// Load code to be run on the LP/ULP core. /// /// ## Example diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index 78b96697180..b01e6a19e6a 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -644,8 +644,6 @@ pub fn connect_high_to_peripheral(signal: InputSignal) { }); } - - #[doc(hidden)] pub trait BooleanType { const VALUE: bool; @@ -670,6 +668,10 @@ pub trait PinType { type IsOutput: BooleanType; type IsAnalog: BooleanType; type IsTouch: BooleanType; + + fn is_output() -> bool { + ::VALUE + } } #[doc(hidden)] @@ -1327,6 +1329,16 @@ pub trait GpioProperties { type PinType: PinType; } +#[doc(hidden)] +#[macro_export] +macro_rules! if_output_pin { + (InputOnlyAnalog, { $($then:tt)* } else { $($else:tt)* } ) => { $($else)* }; + (InputOutputAnalog, { $($then:tt)* } else { $($else:tt)* } ) => { $($then)* }; + (InputOutputAnalogTouch, { $($then:tt)* } else { $($else:tt)* } ) => { $($then)* }; + (InputOutput, { $($then:tt)* } else { $($else:tt)* } ) => { $($then)* }; +} +pub use if_output_pin; + #[doc(hidden)] #[macro_export] macro_rules! gpio { @@ -1430,25 +1442,39 @@ macro_rules! gpio { } } - procmacros::make_gpio_enum_dispatch_macro!( - handle_gpio_output - { InputOutputAnalogTouch, InputOutputAnalog, InputOutput, } - { - $( - $type,$gpionum - )+ + // These macros call the code block on the actually contained GPIO pin. + + #[doc(hidden)] + #[macro_export] + macro_rules! handle_gpio_output { + ($this:ident, $inner:ident, $code:tt) => { + match $this { + $( + ErasedPin::[]($inner) => if_output_pin!($type, { + $code + } else {{ + let _ = $inner; + panic!("Unsupported") + }}), + )+ + } } - ); - - procmacros::make_gpio_enum_dispatch_macro!( - handle_gpio_input - { InputOutputAnalogTouch, InputOutputAnalog, InputOutput, InputOnlyAnalog } - { - $( - $type,$gpionum - )+ + } + + #[doc(hidden)] + #[macro_export] + macro_rules! handle_gpio_input { + ($this:ident, $inner:ident, $code:tt) => { + match $this { + $( + ErasedPin::[]($inner) => $code + )+ + } } - ); + } + + pub(crate) use handle_gpio_output; + pub(crate) use handle_gpio_input; } }; } From 479c91a61cb069422cc01e9df80b27fdfe601a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1niel=20Buga?= Date: Tue, 3 Sep 2024 19:28:53 +0200 Subject: [PATCH 6/6] Inline PinType into GpioProperties --- esp-hal/src/gpio/mod.rs | 121 ++++++++++++++-------------------------- 1 file changed, 43 insertions(+), 78 deletions(-) diff --git a/esp-hal/src/gpio/mod.rs b/esp-hal/src/gpio/mod.rs index b01e6a19e6a..2424372a1d6 100644 --- a/esp-hal/src/gpio/mod.rs +++ b/esp-hal/src/gpio/mod.rs @@ -645,79 +645,15 @@ pub fn connect_high_to_peripheral(signal: InputSignal) { } #[doc(hidden)] -pub trait BooleanType { - const VALUE: bool; -} +pub trait BooleanType {} #[doc(hidden)] pub struct True {} - -impl BooleanType for True { - const VALUE: bool = true; -} +impl BooleanType for True {} #[doc(hidden)] pub struct False {} - -impl BooleanType for False { - const VALUE: bool = false; -} - -#[doc(hidden)] -pub trait PinType { - type IsOutput: BooleanType; - type IsAnalog: BooleanType; - type IsTouch: BooleanType; - - fn is_output() -> bool { - ::VALUE - } -} - -#[doc(hidden)] -pub struct InputOutputPinType; - -#[doc(hidden)] -pub struct InputOnlyPinType; - -#[doc(hidden)] -pub struct InputOutputAnalogPinType; - -#[doc(hidden)] -pub struct InputOnlyAnalogPinType; - -#[doc(hidden)] -pub struct InputOutputAnalogTouchPinType; - -impl PinType for InputOutputPinType { - type IsOutput = True; - type IsAnalog = False; - type IsTouch = False; -} - -impl PinType for InputOnlyPinType { - type IsOutput = False; - type IsAnalog = False; - type IsTouch = False; -} - -impl PinType for InputOutputAnalogPinType { - type IsOutput = True; - type IsAnalog = True; - type IsTouch = False; -} - -impl PinType for InputOnlyAnalogPinType { - type IsOutput = False; - type IsAnalog = True; - type IsTouch = False; -} - -impl PinType for InputOutputAnalogTouchPinType { - type IsOutput = True; - type IsAnalog = True; - type IsTouch = True; -} +impl BooleanType for False {} /// GPIO pin pub struct GpioPin; @@ -991,8 +927,7 @@ impl private::Sealed for GpioPin where Self: GpioPro impl GpioPin where - Self: GpioProperties, - ::PinType: PinType, + Self: GpioProperties, { fn init_output(&self, alternate: AlternateFunction, open_drain: bool) { let gpio = unsafe { &*GPIO::PTR }; @@ -1073,8 +1008,7 @@ where impl OutputPin for GpioPin where - Self: GpioProperties, - ::PinType: PinType, + Self: GpioProperties, { fn set_to_open_drain_output(&mut self, _: private::Internal) { self.init_output(GPIO_FUNCTION, true); @@ -1212,8 +1146,7 @@ where #[cfg(any(adc, dac))] impl AnalogPin for GpioPin where - Self: GpioProperties, - ::PinType: PinType, + Self: GpioProperties, { /// Configures the pin for analog mode. fn set_analog(&self, _: private::Internal) { @@ -1224,8 +1157,7 @@ where #[cfg(touch)] impl TouchPin for GpioPin where - Self: GpioProperties, - ::PinType: PinType, + Self: GpioProperties, { fn set_touch(&self, _: private::Internal) { crate::soc::gpio::internal_into_touch(GPIONUM); @@ -1326,7 +1258,10 @@ pub trait GpioProperties { type Bank: BankGpioRegisterAccess; type InterruptStatus: InterruptStatusRegisterAccess; type Signals: GpioSignal; - type PinType: PinType; + + type IsOutput: BooleanType; + type IsAnalog: BooleanType; + type IsTouch: BooleanType; } #[doc(hidden)] @@ -1337,7 +1272,37 @@ macro_rules! if_output_pin { (InputOutputAnalogTouch, { $($then:tt)* } else { $($else:tt)* } ) => { $($then)* }; (InputOutput, { $($then:tt)* } else { $($else:tt)* } ) => { $($then)* }; } -pub use if_output_pin; +pub(crate) use if_output_pin; + +#[doc(hidden)] +#[macro_export] +macro_rules! pin_types { + (InputOnly) => { + type IsOutput = $crate::gpio::False; + type IsAnalog = $crate::gpio::False; + type IsTouch = $crate::gpio::False; + }; + (InputOnlyAnalog) => { + type IsOutput = $crate::gpio::False; + type IsAnalog = $crate::gpio::True; + type IsTouch = $crate::gpio::False; + }; + (InputOutput) => { + type IsOutput = $crate::gpio::True; + type IsAnalog = $crate::gpio::False; + type IsTouch = $crate::gpio::False; + }; + (InputOutputAnalog) => { + type IsOutput = $crate::gpio::True; + type IsAnalog = $crate::gpio::True; + type IsTouch = $crate::gpio::False; + }; + (InputOutputAnalogTouch) => { + type IsOutput = $crate::gpio::True; + type IsAnalog = $crate::gpio::True; + type IsTouch = $crate::gpio::True; + }; +} #[doc(hidden)] #[macro_export] @@ -1370,7 +1335,7 @@ macro_rules! gpio { type Bank = $crate::gpio::[< Bank $bank GpioRegisterAccess >]; type InterruptStatus = $crate::gpio::[< InterruptStatusRegisterAccessBank $bank >]; type Signals = [< Gpio $gpionum Signals >]; - type PinType = $crate::gpio::[<$type PinType>]; + $crate::pin_types!($type); } #[doc(hidden)]