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<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
11 for Pin<P, N, Alternate<A, PushPull>>
12{
13 #[inline(always)]
14 fn from(f: Pin<P, N, Input<MODE>>) -> Self {
15 f.into_alternate::<A>()
16 }
17}
18
19impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
20 for Pin<P, N, Alternate<A, PushPull>>
21{
22 #[inline(always)]
23 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
24 f.into_alternate::<A>()
25 }
26}
27
28impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
29 for Pin<P, N, Alternate<A, PushPull>>
30{
31 #[inline(always)]
32 fn from(f: Pin<P, N, Analog>) -> Self {
33 f.into_alternate::<A>()
34 }
35}
36
37impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, OpenDrain>>>
38 for Pin<P, N, Alternate<A, PushPull>>
39{
40 #[inline(always)]
41 fn from(f: Pin<P, N, Alternate<B, OpenDrain>>) -> Self {
42 f.into_alternate::<A>()
43 }
44}
45
46impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Input<MODE>>>
47 for Pin<P, N, Alternate<A, OpenDrain>>
48{
49 #[inline(always)]
50 fn from(f: Pin<P, N, Input<MODE>>) -> Self {
51 f.into_alternate_open_drain::<A>()
52 }
53}
54
55impl<const P: char, const N: u8, const A: u8, MODE> From<Pin<P, N, Output<MODE>>>
56 for Pin<P, N, Alternate<A, OpenDrain>>
57{
58 #[inline(always)]
59 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
60 f.into_alternate_open_drain::<A>()
61 }
62}
63
64impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Analog>>
65 for Pin<P, N, Alternate<A, OpenDrain>>
66{
67 #[inline(always)]
68 fn from(f: Pin<P, N, Analog>) -> Self {
69 f.into_alternate_open_drain::<A>()
70 }
71}
72
73impl<const P: char, const N: u8, const A: u8, const B: u8> From<Pin<P, N, Alternate<B, PushPull>>>
74 for Pin<P, N, Alternate<A, OpenDrain>>
75{
76 #[inline(always)]
77 fn from(f: Pin<P, N, Alternate<B, PushPull>>) -> Self {
78 f.into_alternate_open_drain::<A>()
79 }
80}
81
82impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullDown>> {
83 #[inline(always)]
84 fn from(f: Pin<P, N, Input<Floating>>) -> Self {
85 f.into_pull_down_input()
86 }
87}
88
89impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<PullDown>> {
90 #[inline(always)]
91 fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
92 f.into_pull_down_input()
93 }
94}
95
96impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
97 for Pin<P, N, Input<PullDown>>
98{
99 #[inline(always)]
100 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
101 f.into_pull_down_input()
102 }
103}
104
105impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullDown>> {
106 #[inline(always)]
107 fn from(f: Pin<P, N, Analog>) -> Self {
108 f.into_pull_down_input()
109 }
110}
111
112impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
113 for Pin<P, N, Input<PullDown>>
114{
115 #[inline(always)]
116 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
117 f.into_pull_down_input()
118 }
119}
120
121impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
122 for Pin<P, N, Input<PullDown>>
123{
124 #[inline(always)]
125 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
126 f.into_pull_down_input()
127 }
128}
129
130impl<const P: char, const N: u8> From<Pin<P, N, Input<Floating>>> for Pin<P, N, Input<PullUp>> {
131 #[inline(always)]
132 fn from(f: Pin<P, N, Input<Floating>>) -> Self {
133 f.into_pull_up_input()
134 }
135}
136
137impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<PullUp>> {
138 #[inline(always)]
139 fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
140 f.into_pull_up_input()
141 }
142}
143
144impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Input<PullUp>> {
145 #[inline(always)]
146 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
147 f.into_pull_up_input()
148 }
149}
150
151impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<PullUp>> {
152 #[inline(always)]
153 fn from(f: Pin<P, N, Analog>) -> Self {
154 f.into_pull_up_input()
155 }
156}
157
158impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
159 for Pin<P, N, Input<PullUp>>
160{
161 #[inline(always)]
162 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
163 f.into_pull_up_input()
164 }
165}
166
167impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
168 for Pin<P, N, Input<PullUp>>
169{
170 #[inline(always)]
171 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
172 f.into_pull_up_input()
173 }
174}
175
176impl<const P: char, const N: u8> From<Pin<P, N, Input<PullDown>>> for Pin<P, N, Input<Floating>> {
177 #[inline(always)]
178 fn from(f: Pin<P, N, Input<PullDown>>) -> Self {
179 f.into_floating_input()
180 }
181}
182
183impl<const P: char, const N: u8> From<Pin<P, N, Input<PullUp>>> for Pin<P, N, Input<Floating>> {
184 #[inline(always)]
185 fn from(f: Pin<P, N, Input<PullUp>>) -> Self {
186 f.into_floating_input()
187 }
188}
189
190impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>>
191 for Pin<P, N, Input<Floating>>
192{
193 #[inline(always)]
194 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
195 f.into_floating_input()
196 }
197}
198
199impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Input<Floating>> {
200 #[inline(always)]
201 fn from(f: Pin<P, N, Analog>) -> Self {
202 f.into_floating_input()
203 }
204}
205
206impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
207 for Pin<P, N, Input<Floating>>
208{
209 #[inline(always)]
210 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
211 f.into_floating_input()
212 }
213}
214
215impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
216 for Pin<P, N, Input<Floating>>
217{
218 #[inline(always)]
219 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
220 f.into_floating_input()
221 }
222}
223
224impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
225 for Pin<P, N, Output<OpenDrain>>
226{
227 #[inline(always)]
228 fn from(f: Pin<P, N, Input<MODE>>) -> Self {
229 f.into_open_drain_output()
230 }
231}
232
233impl<const P: char, const N: u8> From<Pin<P, N, Output<PushPull>>>
234 for Pin<P, N, Output<OpenDrain>>
235{
236 #[inline(always)]
237 fn from(f: Pin<P, N, Output<PushPull>>) -> Self {
238 f.into_open_drain_output()
239 }
240}
241
242impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<OpenDrain>> {
243 #[inline(always)]
244 fn from(f: Pin<P, N, Analog>) -> Self {
245 f.into_open_drain_output()
246 }
247}
248
249impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
250 for Pin<P, N, Output<OpenDrain>>
251{
252 #[inline(always)]
253 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
254 f.into_open_drain_output()
255 }
256}
257
258impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
259 for Pin<P, N, Output<OpenDrain>>
260{
261 #[inline(always)]
262 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
263 f.into_open_drain_output()
264 }
265}
266
267impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>>
268 for Pin<P, N, Output<PushPull>>
269{
270 #[inline(always)]
271 fn from(f: Pin<P, N, Input<MODE>>) -> Self {
272 f.into_push_pull_output()
273 }
274}
275
276impl<const P: char, const N: u8> From<Pin<P, N, Output<OpenDrain>>>
277 for Pin<P, N, Output<PushPull>>
278{
279 #[inline(always)]
280 fn from(f: Pin<P, N, Output<OpenDrain>>) -> Self {
281 f.into_push_pull_output()
282 }
283}
284
285impl<const P: char, const N: u8> From<Pin<P, N, Analog>> for Pin<P, N, Output<PushPull>> {
286 #[inline(always)]
287 fn from(f: Pin<P, N, Analog>) -> Self {
288 f.into_push_pull_output()
289 }
290}
291
292impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
293 for Pin<P, N, Output<PushPull>>
294{
295 #[inline(always)]
296 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
297 f.into_push_pull_output()
298 }
299}
300
301impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
302 for Pin<P, N, Output<PushPull>>
303{
304 #[inline(always)]
305 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
306 f.into_push_pull_output()
307 }
308}
309
310impl<const P: char, const N: u8, MODE> From<Pin<P, N, Input<MODE>>> for Pin<P, N, Analog> {
311 #[inline(always)]
312 fn from(f: Pin<P, N, Input<MODE>>) -> Self {
313 f.into_analog()
314 }
315}
316
317impl<const P: char, const N: u8, MODE> From<Pin<P, N, Output<MODE>>> for Pin<P, N, Analog> {
318 #[inline(always)]
319 fn from(f: Pin<P, N, Output<MODE>>) -> Self {
320 f.into_analog()
321 }
322}
323
324impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, PushPull>>>
325 for Pin<P, N, Analog>
326{
327 #[inline(always)]
328 fn from(f: Pin<P, N, Alternate<A, PushPull>>) -> Self {
329 f.into_analog()
330 }
331}
332
333impl<const P: char, const N: u8, const A: u8> From<Pin<P, N, Alternate<A, OpenDrain>>>
334 for Pin<P, N, Analog>
335{
336 #[inline(always)]
337 fn from(f: Pin<P, N, Alternate<A, OpenDrain>>) -> Self {
338 f.into_analog()
339 }
340}
341
342impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
343 pub(super) fn set_alternate<const A: u8>(&mut self) {
344 #[allow(path_statements, clippy::no_effect)]
345 {
346 Assert::<A, 16>::LESS;
347 }
348 let offset = 2 * { N };
349 unsafe {
350 if N < 8 {
351 let offset2 = 4 * { N };
352 (*Gpio::<P>::ptr()).afrl.modify(|r, w| {
353 w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
354 });
355 } else {
356 let offset2 = 4 * { N - 8 };
357 (*Gpio::<P>::ptr()).afrh.modify(|r, w| {
358 w.bits((r.bits() & !(0b1111 << offset2)) | ((A as u32) << offset2))
359 });
360 }
361 (*Gpio::<P>::ptr())
362 .moder
363 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (0b10 << offset)));
364 }
365 }
366 pub fn into_alternate<const A: u8>(mut self) -> Pin<P, N, Alternate<A, PushPull>> {
368 self.set_alternate::<A>();
369 Pin::new()
370 }
371
372 #[allow(path_statements)]
374 pub fn into_alternate_open_drain<const A: u8>(self) -> Pin<P, N, Alternate<A, OpenDrain>> {
375 self.into_alternate::<A>().set_open_drain()
376 }
377
378 pub fn into_floating_input(mut self) -> Pin<P, N, Input<Floating>> {
380 self.mode::<Input<Floating>>();
381 Pin::new()
382 }
383
384 pub fn into_pull_down_input(mut self) -> Pin<P, N, Input<PullDown>> {
386 self.mode::<Input<PullDown>>();
387 Pin::new()
388 }
389
390 pub fn into_pull_up_input(mut self) -> Pin<P, N, Input<PullUp>> {
392 self.mode::<Input<PullUp>>();
393 Pin::new()
394 }
395
396 pub fn into_open_drain_output(mut self) -> Pin<P, N, Output<OpenDrain>> {
399 self.mode::<Output<OpenDrain>>();
400 Pin::new()
401 }
402
403 pub fn into_open_drain_output_in_state(
406 mut self,
407 initial_state: PinState,
408 ) -> Pin<P, N, Output<OpenDrain>> {
409 self._set_state(initial_state);
410 self.mode::<Output<OpenDrain>>();
411 Pin::new()
412 }
413
414 pub fn into_push_pull_output(mut self) -> Pin<P, N, Output<PushPull>> {
417 self._set_low();
418 self.mode::<Output<PushPull>>();
419 Pin::new()
420 }
421
422 pub fn into_push_pull_output_in_state(
425 mut self,
426 initial_state: PinState,
427 ) -> Pin<P, N, Output<PushPull>> {
428 self._set_state(initial_state);
429 self.mode::<Output<PushPull>>();
430 Pin::new()
431 }
432
433 pub fn into_analog(mut self) -> Pin<P, N, Analog> {
435 self.mode::<Analog>();
436 Pin::new()
437 }
438
439 pub fn into_dynamic(self) -> DynamicPin<P, N> {
443 self.into_floating_input();
444 DynamicPin::new(Dynamic::InputFloating)
445 }
446
447 #[inline(always)]
452 pub(super) fn mode<M: PinMode>(&mut self) {
453 let offset = 2 * N;
454 unsafe {
455 (*Gpio::<P>::ptr())
456 .pupdr
457 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::PUPDR << offset)));
458
459 if let Some(otyper) = M::OTYPER {
460 (*Gpio::<P>::ptr())
461 .otyper
462 .modify(|r, w| w.bits(r.bits() & !(0b1 << N) | (otyper << N)));
463 }
464
465 (*Gpio::<P>::ptr())
466 .moder
467 .modify(|r, w| w.bits((r.bits() & !(0b11 << offset)) | (M::MODER << offset)));
468 }
469 }
470}
471
472impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
473where
474 MODE: PinMode,
475{
476 fn with_mode<M, F, R>(&mut self, f: F) -> R
477 where
478 M: PinMode,
479 F: FnOnce(&mut Pin<P, N, M>) -> R,
480 {
481 self.mode::<M>();
482
483 let _resetti = ResetMode { pin: self };
486
487 let mut witness = Pin::new();
488
489 f(&mut witness)
490 }
491
492 pub fn with_floating_input<R>(
497 &mut self,
498 f: impl FnOnce(&mut Pin<P, N, Input<Floating>>) -> R,
499 ) -> R {
500 self.with_mode(f)
501 }
502
503 pub fn with_pull_down_input<R>(
508 &mut self,
509 f: impl FnOnce(&mut Pin<P, N, Input<PullDown>>) -> R,
510 ) -> R {
511 self.with_mode(f)
512 }
513
514 pub fn with_pull_up_input<R>(
519 &mut self,
520 f: impl FnOnce(&mut Pin<P, N, Input<PullUp>>) -> R,
521 ) -> R {
522 self.with_mode(f)
523 }
524
525 pub fn with_analog<R>(&mut self, f: impl FnOnce(&mut Pin<P, N, Analog>) -> R) -> R {
530 self.with_mode(f)
531 }
532
533 pub fn with_open_drain_output<R>(
540 &mut self,
541 f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
542 ) -> R {
543 self.with_mode(f)
544 }
545
546 pub fn with_open_drain_output_in_state<R>(
554 &mut self,
555 state: PinState,
556 f: impl FnOnce(&mut Pin<P, N, Output<OpenDrain>>) -> R,
557 ) -> R {
558 self._set_state(state);
559 self.with_mode(f)
560 }
561
562 pub fn with_push_pull_output<R>(
569 &mut self,
570 f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
571 ) -> R {
572 self.with_mode(f)
573 }
574
575 pub fn with_push_pull_output_in_state<R>(
583 &mut self,
584 state: PinState,
585 f: impl FnOnce(&mut Pin<P, N, Output<PushPull>>) -> R,
586 ) -> R {
587 self._set_state(state);
588 self.with_mode(f)
589 }
590}
591
592struct ResetMode<'a, const P: char, const N: u8, ORIG: PinMode> {
593 pin: &'a mut Pin<P, N, ORIG>,
594}
595
596impl<'a, const P: char, const N: u8, ORIG: PinMode> Drop for ResetMode<'a, P, N, ORIG> {
597 fn drop(&mut self) {
598 self.pin.mode::<ORIG>();
599 }
600}
601
602pub trait PinMode: crate::Sealed {
606 #[doc(hidden)]
610 const PUPDR: u32;
611 #[doc(hidden)]
612 const MODER: u32;
613 #[doc(hidden)]
614 const OTYPER: Option<u32> = None;
615}
616
617impl crate::Sealed for Input<Floating> {}
618impl PinMode for Input<Floating> {
619 const PUPDR: u32 = 0b00;
620 const MODER: u32 = 0b00;
621}
622
623impl crate::Sealed for Input<PullDown> {}
624impl PinMode for Input<PullDown> {
625 const PUPDR: u32 = 0b10;
626 const MODER: u32 = 0b00;
627}
628
629impl crate::Sealed for Input<PullUp> {}
630impl PinMode for Input<PullUp> {
631 const PUPDR: u32 = 0b01;
632 const MODER: u32 = 0b00;
633}
634
635impl crate::Sealed for Analog {}
636impl PinMode for Analog {
637 const PUPDR: u32 = 0b00;
638 const MODER: u32 = 0b11;
639}
640
641impl crate::Sealed for Output<OpenDrain> {}
642impl PinMode for Output<OpenDrain> {
643 const PUPDR: u32 = 0b00;
644 const MODER: u32 = 0b01;
645 const OTYPER: Option<u32> = Some(0b1);
646}
647
648impl crate::Sealed for Output<PushPull> {}
649impl PinMode for Output<PushPull> {
650 const PUPDR: u32 = 0b00;
651 const MODER: u32 = 0b01;
652 const OTYPER: Option<u32> = Some(0b0);
653}