1#![doc = crate::before_snippet!()]
23use core::marker::PhantomData;
32
33use super::{InputPin, OutputPin, RtcPin};
34use crate::peripherals::{GPIO, LP_AON, LP_IO};
35
36pub struct LowPowerOutput<'d, const PIN: u8> {
38 phantom: PhantomData<&'d mut ()>,
39}
40
41impl<'d, const PIN: u8> LowPowerOutput<'d, PIN> {
42 #[instability::unstable]
44 pub fn new<P>(_pin: P) -> Self
45 where
46 P: OutputPin + RtcPin + 'd,
47 {
48 init_low_power_pin(PIN);
49
50 let this = Self {
51 phantom: PhantomData,
52 };
53 this.output_enable(true);
54
55 this
56 }
57
58 fn output_enable(&self, enable: bool) {
59 let lp_io = LP_IO::regs();
60 if enable {
61 lp_io
62 .out_enable_w1ts()
63 .write(|w| unsafe { w.enable_w1ts().bits(1 << PIN) });
64 } else {
65 lp_io
66 .out_enable_w1tc()
67 .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
68 }
69 }
70}
71
72pub struct LowPowerInput<'d, const PIN: u8> {
74 phantom: PhantomData<&'d mut ()>,
75}
76
77impl<'d, const PIN: u8> LowPowerInput<'d, PIN> {
78 #[instability::unstable]
80 pub fn new<P>(_pin: P) -> Self
81 where
82 P: InputPin + RtcPin + 'd,
83 {
84 init_low_power_pin(PIN);
85
86 let this = Self {
87 phantom: PhantomData,
88 };
89 this.input_enable(true);
90 this.pullup_enable(false);
91 this.pulldown_enable(false);
92
93 this
94 }
95
96 fn input_enable(&self, enable: bool) {
97 LP_IO::regs()
98 .gpio(PIN as usize)
99 .modify(|_, w| w.fun_ie().bit(enable));
100 }
101
102 pub fn pullup_enable(&self, enable: bool) {
104 LP_IO::regs()
105 .gpio(PIN as usize)
106 .modify(|_, w| w.fun_wpu().bit(enable));
107 }
108
109 pub fn pulldown_enable(&self, enable: bool) {
111 LP_IO::regs()
112 .gpio(PIN as usize)
113 .modify(|_, w| w.fun_wpd().bit(enable));
114 }
115}
116
117pub struct LowPowerOutputOpenDrain<'d, const PIN: u8> {
119 phantom: PhantomData<&'d mut ()>,
120}
121
122impl<'d, const PIN: u8> LowPowerOutputOpenDrain<'d, PIN> {
123 #[instability::unstable]
125 pub fn new<P>(_pin: P) -> Self
126 where
127 P: InputPin + OutputPin + RtcPin + 'd,
128 {
129 init_low_power_pin(PIN);
130
131 let this = Self {
132 phantom: PhantomData,
133 };
134
135 this.set_open_drain_output(true);
136 this.input_enable(true);
137 this.pullup_enable(true);
138 this.pulldown_enable(false);
139 this.output_enable(true);
140
141 this
142 }
143
144 fn output_enable(&self, enable: bool) {
145 let lp_io = LP_IO::regs();
146 if enable {
147 lp_io
148 .out_enable_w1ts()
149 .write(|w| unsafe { w.enable_w1ts().bits(1 << PIN) });
150 } else {
151 lp_io
152 .out_enable_w1tc()
153 .write(|w| unsafe { w.enable_w1tc().bits(1 << PIN) });
154 }
155 }
156
157 fn input_enable(&self, enable: bool) {
158 LP_IO::regs()
159 .gpio(PIN as usize)
160 .modify(|_, w| w.fun_ie().bit(enable));
161 }
162
163 pub fn pullup_enable(&self, enable: bool) {
165 LP_IO::regs()
166 .gpio(PIN as usize)
167 .modify(|_, w| w.fun_wpu().bit(enable));
168 }
169
170 pub fn pulldown_enable(&self, enable: bool) {
172 LP_IO::regs()
173 .gpio(PIN as usize)
174 .modify(|_, w| w.fun_wpd().bit(enable));
175 }
176
177 fn set_open_drain_output(&self, enable: bool) {
178 GPIO::regs()
179 .pin(PIN as usize)
180 .modify(|_, w| w.pad_driver().bit(enable));
181 }
182}
183
184pub(crate) fn init_low_power_pin(pin: u8) {
185 LP_AON::regs()
186 .gpio_mux()
187 .modify(|r, w| unsafe { w.sel().bits(r.sel().bits() | (1 << pin)) });
188
189 LP_IO::regs()
190 .gpio(pin as usize)
191 .modify(|_, w| unsafe { w.mcu_sel().bits(0) });
192}
193
194#[doc(hidden)]
195macro_rules! lp_gpio {
196 (
197 $($gpionum:literal)+
198 ) => {
199 $(
200 impl $crate::gpio::RtcPin for paste::paste!($crate::peripherals::[<GPIO $gpionum>]<'_>) {
201 unsafe fn apply_wakeup(&self, wakeup: bool, level: u8) {
202 let lp_io = $crate::peripherals::LP_IO::regs();
203 lp_io.pin($gpionum).modify(|_, w| {
204 unsafe {
205 w.wakeup_enable().bit(wakeup).int_type().bits(level)
206 }
207 });
208 }
209
210 fn rtcio_pad_hold(&self, enable: bool) {
211 let mask = 1 << $gpionum;
212 unsafe {
213 let lp_aon = $crate::peripherals::LP_AON::regs();
214
215 lp_aon.gpio_hold0().modify(|r, w| {
216 if enable {
217 w.gpio_hold0().bits(r.gpio_hold0().bits() | mask)
218 } else {
219 w.gpio_hold0().bits(r.gpio_hold0().bits() & !mask)
220 }
221 });
222 }
223 }
224
225 fn rtc_set_config(&self, input_enable: bool, mux: bool, func: $crate::gpio::RtcFunction) {
228 let mask = 1 << $gpionum;
229 unsafe {
230 let lp_aon = $crate::peripherals::LP_AON::regs();
231 lp_aon
233 .gpio_mux()
234 .modify(|r, w| {
235 if mux {
236 w.sel().bits(r.sel().bits() | mask)
237 } else {
238 w.sel().bits(r.sel().bits() & !mask)
239 }
240 });
241
242 let lp_io = $crate::peripherals::LP_IO::regs();
244 lp_io.gpio($gpionum).modify(|_, w| {
245 w.slp_sel().bit(false);
246 w.fun_ie().bit(input_enable);
247 w.mcu_sel().bits(func as u8)
248 });
249 }
250 }
251 }
252
253 impl $crate::gpio::RtcPinWithResistors for paste::paste!($crate::peripherals::[<GPIO $gpionum>]<'_>) {
254 fn rtcio_pullup(&self, enable: bool) {
255 let lp_io = $crate::peripherals::LP_IO::regs();
256 lp_io.gpio($gpionum).modify(|_, w| w.fun_wpu().bit(enable));
257 }
258
259 fn rtcio_pulldown(&self, enable: bool) {
260 let lp_io = $crate::peripherals::LP_IO::regs();
261 lp_io.gpio($gpionum).modify(|_, w| w.fun_wpd().bit(enable));
262 }
263 }
264 )+
265 }
266}
267
268pub(crate) use lp_gpio;