1cfg_if::cfg_if! {
27 if #[cfg(feature = "esp32c6")] {
28 type LpIo = crate::pac::LP_IO;
29 const MAX_GPIO_PIN: u8 = 7;
30 } else {
31 type LpIo = crate::pac::RTC_IO;
32 const MAX_GPIO_PIN: u8 = 21;
33 }
34}
35
36pub struct Input<const PIN: u8>;
38
39impl<const PIN: u8> Input<PIN> {
40 pub fn input_state(&self) -> bool {
42 cfg_if::cfg_if! {
43 if #[cfg(feature = "esp32c6")] {
44 (unsafe { &*LpIo::PTR }.in_().read().bits() >> PIN) & 0x1 != 0
45 } else if #[cfg(feature = "esp32s2")] {
46 (unsafe { &*LpIo::PTR }.in_().read().gpio_in_next().bits() >> PIN) & 0x1 != 0
47 } else if #[cfg(feature = "esp32s3")] {
48 (unsafe { &*LpIo::PTR }.in_().read().next().bits() >> PIN) & 0x1 != 0
49 }
50 }
51 }
52}
53
54pub struct Output<const PIN: u8>;
56
57impl<const PIN: u8> Output<PIN> {
58 pub fn output_state(&self) -> bool {
60 cfg_if::cfg_if! {
61 if #[cfg(feature = "esp32c6")] {
62 (unsafe { &*LpIo::PTR }.out().read().bits() >> PIN) & 0x1 != 0
63 } else if #[cfg(feature = "esp32s2")] {
64 (unsafe { &*LpIo::PTR }.out().read().gpio_out_data().bits() >> PIN) & 0x1 != 0
65 } else if #[cfg(feature = "esp32s3")] {
66 (unsafe { &*LpIo::PTR }.out().read().data().bits() >> PIN) & 0x1 != 0
67 }
68 }
69 }
70
71 pub fn set_output(&mut self, on: bool) {
73 if on {
74 unsafe { &*LpIo::PTR }
75 .out_w1ts()
76 .write(|w| unsafe { w.out_data_w1ts().bits(1 << PIN) });
77 } else {
78 unsafe { &*LpIo::PTR }
79 .out_w1tc()
80 .write(|w| unsafe { w.out_data_w1tc().bits(1 << PIN) });
81 }
82 }
83}
84
85#[doc(hidden)]
87pub unsafe fn conjure_output<const PIN: u8>() -> Option<Output<PIN>> {
88 if PIN > MAX_GPIO_PIN {
89 None
90 } else {
91 Some(Output)
92 }
93}
94
95#[doc(hidden)]
97pub unsafe fn conjure_input<const PIN: u8>() -> Option<Input<PIN>> {
98 if PIN > MAX_GPIO_PIN {
99 None
100 } else {
101 Some(Input)
102 }
103}
104
105#[cfg(feature = "embedded-hal")]
106impl<const PIN: u8> embedded_hal::digital::ErrorType for Input<PIN> {
107 type Error = core::convert::Infallible;
108}
109
110#[cfg(feature = "embedded-hal")]
111impl<const PIN: u8> embedded_hal::digital::ErrorType for Output<PIN> {
112 type Error = core::convert::Infallible;
113}
114
115#[cfg(feature = "embedded-hal")]
116impl<const PIN: u8> embedded_hal::digital::InputPin for Input<PIN> {
117 fn is_high(&mut self) -> Result<bool, Self::Error> {
118 Ok(self.input_state())
119 }
120
121 fn is_low(&mut self) -> Result<bool, Self::Error> {
122 Ok(!self.is_high()?)
123 }
124}
125
126#[cfg(feature = "embedded-hal")]
127impl<const PIN: u8> embedded_hal::digital::OutputPin for Output<PIN> {
128 fn set_low(&mut self) -> Result<(), Self::Error> {
129 self.set_output(false);
130 Ok(())
131 }
132
133 fn set_high(&mut self) -> Result<(), Self::Error> {
134 self.set_output(true);
135 Ok(())
136 }
137}
138
139#[cfg(feature = "embedded-hal")]
140impl<const PIN: u8> embedded_hal::digital::StatefulOutputPin for Output<PIN> {
141 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
142 Ok(self.output_state())
143 }
144
145 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
146 Ok(!self.is_set_high()?)
147 }
148}