esp_lp_hal/
gpio.rs

1//! # General Purpose Input/Output
2//!
3//! ## Overview
4//!
5//! It's assumed that GPIOs are already configured correctly by the HP core.
6//!
7//! This driver supports various operations on GPIO pins, primarily manipulating
8//! the pin state (setting high/low, toggling).
9//!
10//! This module also implements a number of traits from `embedded-hal` to
11//! provide a common interface for GPIO pins.
12//!
13//! ## Examples
14//!
15//! ```rust
16//! fn main(gpio0: Input<0>, gpio1: Output<1>) -> ! {
17//!     loop {
18//!         let input_state: bool = gpio0.input_state();
19//!         gpio.set_output(input_state);
20//!
21//!         esp_lp_hal::delay::Delay.delay_millis(50);
22//!     }
23//! }
24//! ```
25
26cfg_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
36/// GPIO input driver
37pub struct Input<const PIN: u8>;
38
39impl<const PIN: u8> Input<PIN> {
40    /// Read the input state/level of the pin.
41    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
54/// GPIO output driver
55pub struct Output<const PIN: u8>;
56
57impl<const PIN: u8> Output<PIN> {
58    /// Read the output state/level of the pin.
59    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    /// Set the output state/level of the pin.
72    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// Used by the `entry` procmacro:
86#[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// Used by the `entry` procmacro:
96#[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}