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        (unsafe { &*LpIo::PTR }.in_().read().bits() >> PIN) & 0x1 != 0
43    }
44}
45
46/// GPIO output driver
47pub struct Output<const PIN: u8>;
48
49impl<const PIN: u8> Output<PIN> {
50    /// Read the output state/level of the pin.
51    pub fn output_state(&self) -> bool {
52        (unsafe { &*LpIo::PTR }.out().read().bits() >> PIN) & 0x1 != 0
53    }
54
55    /// Set the output state/level of the pin.
56    pub fn set_output(&mut self, on: bool) {
57        if on {
58            unsafe { &*LpIo::PTR }
59                .out_w1ts()
60                .write(|w| unsafe { w.out_data_w1ts().bits(1 << PIN) });
61        } else {
62            unsafe { &*LpIo::PTR }
63                .out_w1tc()
64                .write(|w| unsafe { w.out_data_w1tc().bits(1 << PIN) });
65        }
66    }
67}
68
69// Used by the `entry` procmacro:
70#[doc(hidden)]
71pub unsafe fn conjure_output<const PIN: u8>() -> Option<Output<PIN>> {
72    if PIN > MAX_GPIO_PIN {
73        None
74    } else {
75        Some(Output)
76    }
77}
78
79// Used by the `entry` procmacro:
80#[doc(hidden)]
81pub unsafe fn conjure_input<const PIN: u8>() -> Option<Input<PIN>> {
82    if PIN > MAX_GPIO_PIN {
83        None
84    } else {
85        Some(Input)
86    }
87}
88
89#[cfg(feature = "embedded-hal")]
90impl<const PIN: u8> embedded_hal::digital::ErrorType for Input<PIN> {
91    type Error = core::convert::Infallible;
92}
93
94#[cfg(feature = "embedded-hal")]
95impl<const PIN: u8> embedded_hal::digital::ErrorType for Output<PIN> {
96    type Error = core::convert::Infallible;
97}
98
99#[cfg(feature = "embedded-hal")]
100impl<const PIN: u8> embedded_hal::digital::InputPin for Input<PIN> {
101    fn is_high(&mut self) -> Result<bool, Self::Error> {
102        Ok(self.input_state())
103    }
104
105    fn is_low(&mut self) -> Result<bool, Self::Error> {
106        Ok(!self.is_high()?)
107    }
108}
109
110#[cfg(feature = "embedded-hal")]
111impl<const PIN: u8> embedded_hal::digital::OutputPin for Output<PIN> {
112    fn set_low(&mut self) -> Result<(), Self::Error> {
113        self.set_output(false);
114        Ok(())
115    }
116
117    fn set_high(&mut self) -> Result<(), Self::Error> {
118        self.set_output(true);
119        Ok(())
120    }
121}
122
123#[cfg(feature = "embedded-hal")]
124impl<const PIN: u8> embedded_hal::digital::StatefulOutputPin for Output<PIN> {
125    fn is_set_high(&mut self) -> Result<bool, Self::Error> {
126        Ok(self.output_state())
127    }
128
129    fn is_set_low(&mut self) -> Result<bool, Self::Error> {
130        Ok(!self.is_set_high()?)
131    }
132}