1use super::*;
2
3struct Assert<const L: u8, const R: u8>;
5
6impl<const L: u8, const R: u8> Assert<L, R> {
7 pub const LESS: u8 = R - L - 1;
8}
9
10impl<MODE, HL, const P: char, const N: u8> Pin<MODE, HL, P, N> {
11 fn set_alternate<const A: u8>(&mut self) {
12 #[allow(path_statements, clippy::no_effect)]
13 {
14 Assert::<A, 16>::LESS;
15 }
16 let offset = 2 * { N };
17 unsafe {
18 if N < 8 {
19 let offset2 = 4 * { N };
20 (*Gpio::<P>::ptr()).afrl.modify(|r, w| {
21 w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
22 });
23 } else {
24 let offset2 = 4 * { N - 8 };
25 (*Gpio::<P>::ptr()).afrh.modify(|r, w| {
26 w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
27 });
28 }
29 (*Gpio::<P>::ptr())
30 .moder
31 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)));
32 }
33 }
34 pub fn into_alternate<const A: u8>(
36 mut self,
37 _moder: &mut MODER<P>,
38 _otyper: &mut OTYPER<P>,
39 _afr: &mut Afr<HL, P>,
40 ) -> Pin<Alternate<PushPull, A>, HL, P, N> {
41 self.set_alternate::<A>();
42 Pin::new()
43 }
44
45 pub fn into_alternate_push_pull<const A: u8>(
47 self,
48 moder: &mut MODER<P>,
49 otyper: &mut OTYPER<P>,
50 afr: &mut Afr<HL, P>,
51 ) -> Pin<Alternate<PushPull, A>, HL, P, N> {
52 self.into_alternate::<A>(moder, otyper, afr)
53 }
54
55 #[allow(path_statements)]
57 pub fn into_alternate_open_drain<const A: u8>(
58 self,
59 moder: &mut MODER<P>,
60 otyper: &mut OTYPER<P>,
61 afr: &mut Afr<HL, P>,
62 ) -> Pin<Alternate<OpenDrain, A>, HL, P, N> {
63 self.into_alternate::<A>(moder, otyper, afr)
64 .set_open_drain()
65 }
66
67 pub fn into_floating_input(
69 mut self,
70 _moder: &mut MODER<P>,
71 _pupdr: &mut PUPDR<P>,
72 ) -> Pin<Input<Floating>, HL, P, N> {
73 self.mode::<Input<Floating>>();
74 Pin::new()
75 }
76
77 pub fn into_pull_down_input(
79 mut self,
80 _moder: &mut MODER<P>,
81 _pupdr: &mut PUPDR<P>,
82 ) -> Pin<Input<PullDown>, HL, P, N> {
83 self.mode::<Input<PullDown>>();
84 Pin::new()
85 }
86
87 pub fn into_pull_up_input(
89 mut self,
90 _moder: &mut MODER<P>,
91 _pupdr: &mut PUPDR<P>,
92 ) -> Pin<Input<PullUp>, HL, P, N> {
93 self.mode::<Input<PullUp>>();
94 Pin::new()
95 }
96
97 pub fn into_open_drain_output(
100 mut self,
101 _moder: &mut MODER<P>,
102 _otyper: &mut OTYPER<P>,
103 ) -> Pin<Output<OpenDrain>, HL, P, N> {
104 self.mode::<Output<OpenDrain>>();
105 Pin::new()
106 }
107
108 pub fn into_open_drain_output_in_state(
111 mut self,
112 _moder: &mut MODER<P>,
113 _otyper: &mut OTYPER<P>,
114 initial_state: PinState,
115 ) -> Pin<Output<OpenDrain>, HL, P, N> {
116 self._set_state(initial_state);
117 self.mode::<Output<OpenDrain>>();
118 Pin::new()
119 }
120
121 pub fn into_push_pull_output(
124 mut self,
125 _moder: &mut MODER<P>,
126 _otyper: &mut OTYPER<P>,
127 ) -> Pin<Output<PushPull>, HL, P, N> {
128 self._set_low();
129 self.mode::<Output<PushPull>>();
130 Pin::new()
131 }
132
133 pub fn into_push_pull_output_in_state(
136 mut self,
137 _moder: &mut MODER<P>,
138 _otyper: &mut OTYPER<P>,
139 initial_state: PinState,
140 ) -> Pin<Output<PushPull>, HL, P, N> {
141 self._set_state(initial_state);
142 self.mode::<Output<PushPull>>();
143 Pin::new()
144 }
145
146 pub fn into_analog(
148 mut self,
149 _moder: &mut MODER<P>,
150 _pupdr: &mut PUPDR<P>,
151 ) -> Pin<Analog, HL, P, N> {
152 self.mode::<Analog>();
153 Pin::new()
154 }
155
156 #[inline(always)]
161 fn mode<M: PinMode>(&mut self) {
162 let offset = 2 * N;
163 unsafe {
164 (*Gpio::<P>::ptr())
165 .pupdr
166 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::PUPDR << offset)));
167
168 if let Some(otyper) = M::OTYPER {
169 (*Gpio::<P>::ptr())
170 .otyper
171 .modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
172 }
173
174 (*Gpio::<P>::ptr())
175 .moder
176 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
177 }
178 }
179}
180
181impl<MODE, HL, const P: char, const N: u8> Pin<MODE, HL, P, N>
182where
183 MODE: PinMode,
184{
185 fn with_mode<M, F, R>(&mut self, f: F) -> R
186 where
187 M: PinMode,
188 F: FnOnce(&mut Pin<M, HL, P, N>) -> R,
189 {
190 self.mode::<M>();
191
192 let _resetti = ResetMode { pin: self };
195
196 let mut witness = Pin::new();
197
198 f(&mut witness)
199 }
200
201 pub fn with_floating_input<R>(
206 &mut self,
207 f: impl FnOnce(&mut Pin<Input<Floating>, HL, P, N>) -> R,
208 ) -> R {
209 self.with_mode(f)
210 }
211
212 pub fn with_pull_down_input<R>(
217 &mut self,
218 f: impl FnOnce(&mut Pin<Input<PullDown>, HL, P, N>) -> R,
219 ) -> R {
220 self.with_mode(f)
221 }
222
223 pub fn with_pull_up_input<R>(
228 &mut self,
229 f: impl FnOnce(&mut Pin<Input<PullUp>, HL, P, N>) -> R,
230 ) -> R {
231 self.with_mode(f)
232 }
233
234 pub fn with_analog<R>(&mut self, f: impl FnOnce(&mut Pin<Analog, HL, P, N>) -> R) -> R {
239 self.with_mode(f)
240 }
241
242 pub fn with_open_drain_output<R>(
249 &mut self,
250 f: impl FnOnce(&mut Pin<Output<OpenDrain>, HL, P, N>) -> R,
251 ) -> R {
252 self.with_mode(f)
253 }
254
255 pub fn with_open_drain_output_in_state<R>(
263 &mut self,
264 state: PinState,
265 f: impl FnOnce(&mut Pin<Output<OpenDrain>, HL, P, N>) -> R,
266 ) -> R {
267 self._set_state(state);
268 self.with_mode(f)
269 }
270
271 pub fn with_push_pull_output<R>(
278 &mut self,
279 f: impl FnOnce(&mut Pin<Output<PushPull>, HL, P, N>) -> R,
280 ) -> R {
281 self.with_mode(f)
282 }
283
284 pub fn with_push_pull_output_in_state<R>(
292 &mut self,
293 state: PinState,
294 f: impl FnOnce(&mut Pin<Output<PushPull>, HL, P, N>) -> R,
295 ) -> R {
296 self._set_state(state);
297 self.with_mode(f)
298 }
299}
300
301struct ResetMode<'a, ORIG: PinMode, HL, const P: char, const N: u8> {
302 pin: &'a mut Pin<ORIG, HL, P, N>,
303}
304
305impl<'a, ORIG: PinMode, HL, const P: char, const N: u8> Drop for ResetMode<'a, ORIG, HL, P, N> {
306 fn drop(&mut self) {
307 self.pin.mode::<ORIG>();
308 }
309}
310
311pub trait PinMode: crate::Sealed {
315 #[doc(hidden)]
319 const PUPDR: u32;
320 #[doc(hidden)]
321 const MODER: u32;
322 #[doc(hidden)]
323 const OTYPER: Option<u32> = None;
324}
325
326impl crate::Sealed for Input<Floating> {}
327impl PinMode for Input<Floating> {
328 const PUPDR: u32 = 0b00;
329 const MODER: u32 = 0b00;
330}
331
332impl crate::Sealed for Input<PullDown> {}
333impl PinMode for Input<PullDown> {
334 const PUPDR: u32 = 0b10;
335 const MODER: u32 = 0b00;
336}
337
338impl crate::Sealed for Input<PullUp> {}
339impl PinMode for Input<PullUp> {
340 const PUPDR: u32 = 0b01;
341 const MODER: u32 = 0b00;
342}
343
344impl crate::Sealed for Analog {}
345impl PinMode for Analog {
346 const PUPDR: u32 = 0b00;
347 const MODER: u32 = 0b11;
348}
349
350impl crate::Sealed for Output<OpenDrain> {}
351impl PinMode for Output<OpenDrain> {
352 const PUPDR: u32 = 0b00;
353 const MODER: u32 = 0b01;
354 const OTYPER: Option<u32> = Some(0b1);
355}
356
357impl crate::Sealed for Output<PushPull> {}
358impl PinMode for Output<PushPull> {
359 const PUPDR: u32 = 0b00;
360 const MODER: u32 = 0b01;
361 const OTYPER: Option<u32> = Some(0b0);
362}