1#![doc = crate::before_snippet!()]
25use core::marker::PhantomData;
33
34use super::{InputPin, OutputPin, RtcPin};
35use crate::{
36 gpio::RtcFunction,
37 peripherals::{GPIO, RTC_IO},
38};
39
40pub struct LowPowerOutput<'d, const PIN: u8> {
42 phantom: PhantomData<&'d ()>,
43}
44
45impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> {
46 pub fn new<P>(pin: P) -> Self
48 where
49 P: OutputPin + RtcPin + 'd,
50 {
51 pin.rtc_set_config(false, true, RtcFunction::Rtc);
52
53 let this = Self {
54 phantom: PhantomData,
55 };
56 this.output_enable(true);
57
58 this
59 }
60
61 fn output_enable(&self, enable: bool) {
62 let rtc_io = RTC_IO::regs();
63
64 if enable {
65 rtc_io
66 .rtc_gpio_enable_w1ts()
67 .write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << PIN) });
68 } else {
69 rtc_io
70 .enable_w1tc()
71 .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
72 }
73 }
74}
75
76pub struct LowPowerInput<'d, const PIN: u8> {
78 phantom: PhantomData<&'d mut ()>,
79}
80
81impl<'d, const PIN: u8> LowPowerInput<'d, PIN> {
82 pub fn new<P>(pin: P) -> Self
84 where
85 P: InputPin + RtcPin + 'd,
86 {
87 pin.rtc_set_config(true, true, RtcFunction::Rtc);
88
89 let this = Self {
90 phantom: PhantomData,
91 };
92 this.input_enable(true);
93 this.pullup_enable(false);
94 this.pulldown_enable(false);
95
96 this
97 }
98
99 fn input_enable(&self, enable: bool) {
100 RTC_IO::regs()
101 .touch_pad(PIN as usize)
102 .modify(|_, w| w.fun_ie().bit(enable));
103 }
104
105 pub fn pullup_enable(&self, enable: bool) {
107 RTC_IO::regs()
108 .touch_pad(PIN as usize)
109 .modify(|_, w| w.rue().bit(enable));
110 }
111
112 pub fn pulldown_enable(&self, enable: bool) {
114 RTC_IO::regs()
115 .touch_pad(PIN as usize)
116 .modify(|_, w| w.rde().bit(enable));
117 }
118}
119
120pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> {
122 phantom: PhantomData<&'d ()>,
123}
124
125impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> {
126 pub fn new<P>(pin: P) -> Self
128 where
129 P: InputPin + OutputPin + RtcPin + 'd,
130 {
131 pin.rtc_set_config(true, true, RtcFunction::Rtc);
132
133 let this = Self {
134 phantom: PhantomData,
135 };
136
137 this.set_open_drain_output(true);
138 this.input_enable(true);
139 this.pullup_enable(true);
140 this.pulldown_enable(false);
141 this.output_enable(true);
142
143 this
144 }
145
146 fn output_enable(&self, enable: bool) {
147 let rtc_io = RTC_IO::regs();
148
149 if enable {
150 rtc_io
151 .rtc_gpio_enable_w1ts()
152 .write(|w| unsafe { w.rtc_gpio_enable_w1ts().bits(1 << PIN) });
153 } else {
154 rtc_io
155 .enable_w1tc()
156 .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
157 }
158 }
159
160 fn input_enable(&self, enable: bool) {
161 RTC_IO::regs()
162 .touch_pad(PIN as usize)
163 .modify(|_, w| w.fun_ie().bit(enable));
164 }
165
166 pub fn pullup_enable(&self, enable: bool) {
168 RTC_IO::regs()
169 .touch_pad(PIN as usize)
170 .modify(|_, w| w.rue().bit(enable));
171 }
172
173 pub fn pulldown_enable(&self, enable: bool) {
175 RTC_IO::regs()
176 .touch_pad(PIN as usize)
177 .modify(|_, w| w.rde().bit(enable));
178 }
179
180 fn set_open_drain_output(&self, enable: bool) {
181 GPIO::regs()
182 .pin(PIN as usize)
183 .modify(|_, w| w.pad_driver().bit(enable));
184 }
185}