#![cfg_attr(docsrs, procmacros::doc_replace)]
use core::marker::PhantomData;
use super::{InputPin, OutputPin, RtcPin};
use crate::peripherals::{GPIO, LP_AON, LP_IO};
pub struct LowPowerOutput<'d, const PIN: u8> {
phantom: PhantomData<&'d mut ()>,
}
impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> {
#[instability::unstable]
pub fn new<P>(_pin: P) -> Self
where
P: OutputPin + RtcPin + 'd,
{
init_low_power_pin(PIN);
let this = Self {
phantom: PhantomData,
};
this.output_enable(true);
this
}
fn output_enable(&self, enable: bool) {
let lp_io = LP_IO::regs();
if enable {
lp_io
.out_enable_w1ts()
.write(|w| unsafe { w.enable_w1ts().bits(1 << PIN) });
} else {
lp_io
.out_enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
}
}
}
pub struct LowPowerInput<'d, const PIN: u8> {
phantom: PhantomData<&'d mut ()>,
}
impl<'d, const PIN: u8> LowPowerInput<'d, PIN> {
#[instability::unstable]
pub fn new<P>(_pin: P) -> Self
where
P: InputPin + RtcPin + 'd,
{
init_low_power_pin(PIN);
let this = Self {
phantom: PhantomData,
};
this.input_enable(true);
this.pullup_enable(false);
this.pulldown_enable(false);
this
}
fn input_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_ie().bit(enable));
}
pub fn pullup_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_wpu().bit(enable));
}
pub fn pulldown_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_wpd().bit(enable));
}
}
pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> {
phantom: PhantomData<&'d mut ()>,
}
impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> {
#[instability::unstable]
pub fn new<P>(_pin: P) -> Self
where
P: InputPin + OutputPin + RtcPin + 'd,
{
init_low_power_pin(PIN);
let this = Self {
phantom: PhantomData,
};
this.set_open_drain_output(true);
this.input_enable(true);
this.pullup_enable(true);
this.pulldown_enable(false);
this.output_enable(true);
this
}
fn output_enable(&self, enable: bool) {
let lp_io = LP_IO::regs();
if enable {
lp_io
.out_enable_w1ts()
.write(|w| unsafe { w.enable_w1ts().bits(1 << PIN) });
} else {
lp_io
.out_enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
}
}
fn input_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_ie().bit(enable));
}
pub fn pullup_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_wpu().bit(enable));
}
pub fn pulldown_enable(&self, enable: bool) {
LP_IO::regs()
.gpio(PIN as usize)
.modify(|_, w| w.fun_wpd().bit(enable));
}
fn set_open_drain_output(&self, enable: bool) {
GPIO::regs()
.pin(PIN as usize)
.modify(|_, w| w.pad_driver().bit(enable));
}
}
pub(crate) fn init_low_power_pin(pin: u8) {
LP_AON::regs()
.gpio_mux()
.modify(|r, w| unsafe { w.sel().bits(r.sel().bits() | (1 << pin)) });
LP_IO::regs()
.gpio(pin as usize)
.modify(|_, w| unsafe { w.mcu_sel().bits(0) });
}
#[doc(hidden)]
macro_rules! lp_gpio {
(
$($gpionum:literal)+
) => {
$(
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
impl $crate::gpio::RtcPin for paste::paste!($crate::peripherals::[<GPIO $gpionum>]<'_>) {
unsafe fn apply_wakeup(&self, wakeup: bool, level: u8) {
let lp_io = $crate::peripherals::LP_IO::regs();
lp_io.pin($gpionum).modify(|_, w| {
unsafe {
w.wakeup_enable().bit(wakeup).int_type().bits(level)
}
});
}
fn rtcio_pad_hold(&self, enable: bool) {
let mask = 1 << $gpionum;
unsafe {
let lp_aon = $crate::peripherals::LP_AON::regs();
lp_aon.gpio_hold0().modify(|r, w| {
if enable {
w.gpio_hold0().bits(r.gpio_hold0().bits() | mask)
} else {
w.gpio_hold0().bits(r.gpio_hold0().bits() & !mask)
}
});
}
}
fn rtc_set_config(&self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
let mask = 1 << $gpionum;
unsafe {
let lp_aon = $crate::peripherals::LP_AON::regs();
lp_aon
.gpio_mux()
.modify(|r, w| {
if mux {
w.sel().bits(r.sel().bits() | mask)
} else {
w.sel().bits(r.sel().bits() & !mask)
}
});
let lp_io = $crate::peripherals::LP_IO::regs();
lp_io.gpio($gpionum).modify(|_, w| {
w.slp_sel().bit(false);
w.fun_ie().bit(input_enable);
w.mcu_sel().bits(func as u8)
});
}
}
}
#[cfg_attr(docsrs, doc(cfg(feature = "unstable")))]
impl $crate::gpio::RtcPinWithResistors for paste::paste!($crate::peripherals::[<GPIO $gpionum>]<'_>) {
fn rtcio_pullup(&self, enable: bool) {
let lp_io = $crate::peripherals::LP_IO::regs();
lp_io.gpio($gpionum).modify(|_, w| w.fun_wpu().bit(enable));
}
fn rtcio_pulldown(&self, enable: bool) {
let lp_io = $crate::peripherals::LP_IO::regs();
lp_io.gpio($gpionum).modify(|_, w| w.fun_wpd().bit(enable));
}
}
)+
}
}
pub(crate) use lp_gpio;