use crate::{
gpio::{AlternateFunction, Level, LpPin, lp_io::LpFunction},
peripherals::{GPIO, IO_MUX, LPWR},
};
for_each_lp_function! {
(($_lp:ident, LP_GPIOn, $pin:literal), $gpio:ident, $_af:ident, $_lp_in:tt $_lp_out:tt) => {
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
impl LpPin for crate::peripherals::$gpio<'_> {
fn lp_number(&self) -> u8 {
$pin
}
}
};
(LP_GPIOn $( (($_lp:ident, LP_GPIOn, $pin:literal), $gpio:ident, $_af:ident, $_lp_in:tt $_lp_out:tt) ),*) => {
paste::paste! {
pub(crate) fn apply_wakeup(lp: u8, wakeup: bool, level: Level) {
let trigger = crate::gpio::lp_io::wake_trigger(level);
let gpio_wakeup = cfg_select! {
esp32c2 => LPWR::regs().cntl_gpio_wakeup(),
esp32c3 => LPWR::regs().gpio_wakeup(),
};
gpio_wakeup.modify(|_, w| unsafe {
match lp {
$(
$pin => {
w.[<gpio_pin $pin _wakeup_enable>]().bit(wakeup);
w.[<gpio_pin $pin _int_type>]().bits(trigger)
}
)*
_ => unreachable!(),
}
});
}
pub(crate) fn pad_hold(lp: u8, enable: bool) {
LPWR::regs().pad_hold().modify(|_, w| {
match lp {
$( $pin => w.[<gpio_pin $pin _hold>]().bit(enable), )*
_ => unreachable!(),
}
});
}
pub(crate) fn is_pad_held(lp: u8) -> bool {
let r = LPWR::regs().pad_hold().read();
match lp {
$( $pin => r.[<gpio_pin $pin _hold>]().bit_is_set(), )*
_ => unreachable!(),
}
}
#[cfg(sleep_driver_supported)]
pub(crate) fn wakeup_enabled_mask() -> u32 {
let gpio_wakeup = cfg_select! {
esp32c2 => LPWR::regs().cntl_gpio_wakeup().read(),
esp32c3 => LPWR::regs().gpio_wakeup().read(),
};
let mut mask = 0;
$(
if gpio_wakeup.[<gpio_pin $pin _wakeup_enable>]().bit_is_set() {
mask |= 1 << $pin;
}
)*
mask
}
}
};
}
pub(crate) fn digital_pad_hold(gpio: u8, enable: bool) {
let mask = 1 << gpio;
LPWR::regs().dig_pad_hold().modify(|r, w| unsafe {
let bits = r.dig_pad_hold().bits();
w.dig_pad_hold()
.bits(if enable { bits | mask } else { bits & !mask })
});
}
pub(crate) fn is_digital_pad_held(gpio: u8) -> bool {
LPWR::regs().dig_pad_hold().read().dig_pad_hold().bits() & (1 << gpio) != 0
}
pub(crate) fn set_config(lp: u8, input_enable: bool, _mux: bool, _func: LpFunction) {
IO_MUX::regs().gpio(lp as usize).modify(|_, w| unsafe {
w.slp_sel().bit(false);
w.mcu_sel().bits(AlternateFunction::GPIO as u8);
w.fun_ie().bit(input_enable)
});
}
#[expect(dead_code)]
pub(crate) fn init_pin(lp: u8, enable_input: bool) -> u8 {
input_enable(lp, enable_input);
lp
}
#[expect(dead_code)]
pub(crate) fn output_enable(lp: u8, enable: bool) {
if enable {
GPIO::regs()
.enable_w1ts()
.write(|w| unsafe { w.enable_w1ts().bits(1 << lp) });
} else {
GPIO::regs()
.enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << lp) });
}
}
pub(crate) fn input_enable(lp: u8, enable: bool) {
IO_MUX::regs()
.gpio(lp as usize)
.modify(|_, w| w.fun_ie().bit(enable));
}
#[expect(dead_code)]
pub(crate) fn set_open_drain_output(lp: u8, enable: bool) {
GPIO::regs()
.pin(lp as usize)
.modify(|_, w| w.pad_driver().bit(enable));
}