#![cfg_attr(docsrs, procmacros::doc_replace)]
use core::marker::PhantomData;
use super::{InputPin, OutputPin, RtcPin};
use crate::{
gpio::RtcFunction,
peripherals::{GPIO, RTC_IO},
};
pub struct LowPowerOutput<'d, const PIN: u8> {
phantom: PhantomData<&'d ()>,
}
impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> {
pub fn new<P>(pin: P) -> Self
where
P: OutputPin + RtcPin + 'd,
{
pin.rtc_set_config(false, true, RtcFunction::Rtc);
let this = Self {
phantom: PhantomData,
};
this.output_enable(true);
this
}
fn output_enable(&self, enable: bool) {
let rtc_io = RTC_IO::regs();
if enable {
rtc_io
.rtc_gpio_enable_w1ts()
.write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << PIN) });
} else {
rtc_io
.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> {
pub fn new<P>(pin: P) -> Self
where
P: InputPin + RtcPin + 'd,
{
pin.rtc_set_config(true, true, RtcFunction::Rtc);
let this = Self {
phantom: PhantomData,
};
this.input_enable(true);
this.pullup_enable(false);
this.pulldown_enable(false);
this
}
fn input_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.fun_ie().bit(enable));
}
pub fn pullup_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.rue().bit(enable));
}
pub fn pulldown_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.rde().bit(enable));
}
}
pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> {
phantom: PhantomData<&'d ()>,
}
impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> {
pub fn new<P>(pin: P) -> Self
where
P: InputPin + OutputPin + RtcPin + 'd,
{
pin.rtc_set_config(true, true, RtcFunction::Rtc);
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 rtc_io = RTC_IO::regs();
if enable {
rtc_io
.rtc_gpio_enable_w1ts()
.write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << PIN) });
} else {
rtc_io
.enable_w1tc()
.write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
}
}
fn input_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.fun_ie().bit(enable));
}
pub fn pullup_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.rue().bit(enable));
}
pub fn pulldown_enable(&self, enable: bool) {
RTC_IO::regs()
.touch_pad(PIN as usize)
.modify(|_, w| w.rde().bit(enable));
}
fn set_open_drain_output(&self, enable: bool) {
GPIO::regs()
.pin(PIN as usize)
.modify(|_, w| w.pad_driver().bit(enable));
}
}