1use crate::rcc::AHB;
8use bobbin_bits::*;
9use core::intrinsics::transmute;
10use core::marker::PhantomData;
11#[allow(deprecated)]
12use hal::digital::{v2, InputPin, OutputPin, StatefulOutputPin};
13
14pub trait GPIOPin {
16 fn group(&self) -> Group;
18 fn index(&self) -> u8;
20}
21
22pub trait PinMode {
24 fn pin_mode() -> U2;
26}
27
28pub struct Input;
30impl PinMode for Input {
31 fn pin_mode() -> U2 {
33 U2::B00
34 }
35}
36
37pub struct Output<OT: OutputType, OS: OutputSpeed> {
39 _output_mode: PhantomData<OT>,
40 _output_speed: PhantomData<OS>,
41}
42impl<OT: OutputType, OS: OutputSpeed> PinMode for Output<OT, OS> {
43 fn pin_mode() -> U2 {
44 U2::B01
45 }
46}
47
48pub struct AltFn<AN: AltFnNum, OT: OutputType, OS: OutputSpeed> {
50 _afnum: PhantomData<AN>,
51 _output_mode: PhantomData<OT>,
52 _output_speed: PhantomData<OS>,
53}
54impl<AN: AltFnNum, OT: OutputType, OS: OutputSpeed> PinMode
55 for AltFn<AN, OT, OS>
56{
57 fn pin_mode() -> U2 {
58 U2::B10
59 }
60}
61
62pub struct Analog;
64impl PinMode for Analog {
65 fn pin_mode() -> U2 {
66 U2::B11
67 }
68}
69
70pub trait PullType {
72 fn pull_type(&self) -> U2;
74}
75
76pub struct PullNone;
78impl PullType for PullNone {
79 fn pull_type(&self) -> U2 {
80 U2::B00
81 }
82}
83
84pub struct PullUp;
86impl PullType for PullUp {
87 fn pull_type(&self) -> U2 {
88 U2::B01
89 }
90}
91
92pub struct PullDown;
94impl PullType for PullDown {
95 fn pull_type(&self) -> U2 {
96 U2::B10
97 }
98}
99
100pub struct PullReserved;
102impl PullType for PullReserved {
103 fn pull_type(&self) -> U2 {
104 U2::B11
105 }
106}
107
108pub trait OutputSpeed {
110 fn output_speed(&self) -> U2;
112}
113
114pub struct LowSpeed;
116impl OutputSpeed for LowSpeed {
117 fn output_speed(&self) -> U2 {
118 U2::B00
119 }
120}
121
122pub struct MediumSpeed;
124impl OutputSpeed for MediumSpeed {
125 fn output_speed(&self) -> U2 {
126 U2::B01
127 }
128}
129
130pub struct FastSpeed;
132impl OutputSpeed for FastSpeed {
133 fn output_speed(&self) -> U2 {
134 U2::B10
135 }
136}
137
138pub struct HighSpeed;
140impl OutputSpeed for HighSpeed {
141 fn output_speed(&self) -> U2 {
142 U2::B11
143 }
144}
145
146pub trait OutputType {
148 fn output_type(&self) -> U1;
150}
151
152pub struct PushPull;
154impl OutputType for PushPull {
155 fn output_type(&self) -> U1 {
156 U1::B0
157 }
158}
159
160pub struct OpenDrain;
162impl OutputType for OpenDrain {
163 fn output_type(&self) -> U1 {
164 U1::B1
165 }
166}
167
168pub trait AltFnNum {
170 fn alt_fn_num(&self) -> U4;
172}
173
174macro_rules! gen_af {
175 ([$(($af:ident, $bit:ident)) , +]) => {
176 $(
177 pub struct $af;
179 impl AltFnNum for $af {
180 fn alt_fn_num(&self) -> U4 {
181 U4::$bit
182 }
183 }
184 )+
185 }
186}
187
188gen_af!([(AF0, B0000),
189 (AF1, B0001),
190 (AF2, B0010),
191 (AF3, B0011),
192 (AF4, B0100),
193 (AF5, B0101),
194 (AF6, B0110),
195 (AF7, B0111),
196 (AF8, B1000),
197 (AF9, B1001),
198 (AF10, B1010),
199 (AF11, B1011),
200 (AF12, B1100),
201 (AF13, B1101),
202 (AF14, B1110),
203 (AF15, B1111)]);
204
205pub trait GpioExt {
207 type Ports;
209
210 fn split(self, ahb: &mut AHB) -> Self::Ports;
212}
213
214macro_rules! gpio {
215 ($GPIOX:ident, $Gpiox:ident, $gpiox:ident, $iopxenr:ident, $iopxrst:ident, $group: ident, $PXx:ident, [
216 $($PXi:ident: ($pxi:ident, $i:expr, $AFR:ident),)+
217 ]) => {
218 use crate::pac::$GPIOX;
219 pub struct $Gpiox {
221 $(
222 pub $pxi: $PXi<PullNone, Input>,
224 )+
225 }
226
227 impl GpioExt for $GPIOX {
228 type Ports = $Gpiox;
229
230 fn split(self, ahb: &mut AHB) -> Self::Ports {
231 ahb.enr().modify(|_, w| w.$iopxenr().enabled());
232 ahb.rstr().modify(|_, w| w.$iopxrst().set_bit());
233 ahb.rstr().modify(|_, w| w.$iopxrst().clear_bit());
234
235 $Gpiox {
236 $(
237 $pxi: $PXi {
238 _pullup_state: PhantomData,
239 _pin_mode: PhantomData
240 },
241 )+
242 }
243 }
244 }
245
246 impl $Gpiox {
247 fn set_pin_mode<PM: PinMode>(index: u32) {
250 let offset = 2 * index;
251 let mode_bits:u32 = PM::pin_mode().into();
252 let moder = unsafe { &(*$GPIOX::ptr()).moder };
253 moder.modify(|r, w| unsafe {
255 w.bits((r.bits()
256 & !(0b11 << offset))
257 | (mode_bits << offset))
258 });
259 }
260
261 fn set_output_speed<OS: OutputSpeed>(index: u32, os: OS) {
262 let offset = 2 * index;
263 let ospeedr = unsafe { &(*$GPIOX::ptr()).ospeedr };
264 let speed_bits:u32 = os.output_speed().into();
265 ospeedr.modify(|r, w| unsafe {
266 w.bits((r.bits()
267 & !(0b11 << offset))
268 | (speed_bits << offset))
269 });
270 }
271
272 fn set_output_type<OT: OutputType>(index: u32, ot: OT) {
273 let otyper = unsafe { &(*$GPIOX::ptr()).otyper };
274 let type_bits:u32 = ot.output_type().into();
275 otyper.modify(|r, w| unsafe {
276 w.bits(r.bits() | (type_bits << index))
277 });
278 }
279
280 }
281
282
283 pub struct $PXx<PT: PullType, PM: PinMode> {
285 i: u8,
286 _pullup_state: PhantomData<PT>,
287 _pin_mode: PhantomData<PM>
288 }
289
290 #[allow(deprecated)]
291 impl<PT: PullType, OT: OutputType, OS: OutputSpeed>
292 OutputPin for $PXx<PT, Output<OT, OS>> {
293 fn set_high(&mut self) {
294 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
296 }
297
298 fn set_low(&mut self) {
299 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) }
301 }
302 }
303
304 #[allow(deprecated)]
305 impl<PT: PullType,
306 AN: AltFnNum,
307 OT: OutputType,
308 OS: OutputSpeed> OutputPin for $PXx<PT, AltFn<AN, OT, OS>> {
309 fn set_high(&mut self) {
310 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << self.i)) }
312 }
313
314 fn set_low(&mut self) {
315 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + self.i))) }
317 }
318 }
319
320 #[allow(deprecated)]
321 impl<PT: PullType> InputPin for $PXx<PT, Input> {
322 fn is_high(&self) -> bool {
323 !self.is_low()
324 }
325
326 fn is_low(&self) -> bool {
327 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << self.i) == 0 }
329 }
330 }
331
332 $(
333 pub struct $PXi<PT: PullType, PM: PinMode> {
335 _pullup_state: PhantomData<PT>,
336 _pin_mode: PhantomData<PM>
337 }
338
339 impl <PT: PullType, PM: PinMode> GPIOPin for $PXi<PT, PM> {
340 fn group(&self) -> Group {
341 Group::$group
342 }
343
344 fn index(&self) -> u8 {
345 $i
346 }
347 }
348
349 impl<PT: PullType, PM: PinMode> $PXi<PT, PM> {
350 pub fn downgrade(self) -> $PXx<PT, PM> {
355 $PXx {
356 i: $i,
357 _pullup_state: PhantomData,
358 _pin_mode: PhantomData
359 }
360 }
361
362 pub fn pull_type<NPT: PullType>(self, pt: NPT)
364 -> $PXi<NPT, PM>
365 {
366 let shift = 0 + ($i << 1);
367 let pupdr = unsafe { &(*$GPIOX::ptr()).pupdr };
368 let pd_bits:u32 = pt.pull_type().into();
369 pupdr.modify(|r, w| unsafe {
370 w.bits((r.bits() & !(0b11 << shift))
371 | (pd_bits << shift))
372 });
373
374 unsafe { transmute(self) }
375 }
376
377 pub fn input(self) -> $PXi<PT, Input> {
382 $Gpiox::set_pin_mode::<Input>($i);
383 unsafe { transmute(self) }
384 }
385
386 pub fn analog(self) -> $PXi<PT, Analog> {
388 $Gpiox::set_pin_mode::<Analog>($i);
389 unsafe { transmute(self) }
390 }
391
392 pub fn output(self) -> $PXi<PT, Output<PushPull, LowSpeed>> {
394 let result: $PXi<PT, Output<PushPull, LowSpeed>> =
395 unsafe { transmute(self) };
396 let result2 = result
398 .output_type(PushPull)
399 .output_speed(LowSpeed);
400 $Gpiox::set_pin_mode::<Output<PushPull, LowSpeed>>($i);
401 result2
402 }
403
404 pub fn alternating<AFN: AltFnNum>(self, af: AFN) -> $PXi<PT, AltFn<AFN, PushPull, LowSpeed>> {
406 let result: $PXi<PT, AltFn<AFN, PushPull, LowSpeed>> =
407 unsafe { transmute(self) };
408 let result2 = result
410 .alt_fn(af)
411 .output_type(PushPull)
412 .output_speed(LowSpeed);
413 $Gpiox::set_pin_mode::<AltFn<AFN, PushPull, LowSpeed>>($i);
414 result2
415 }
416 }
417
418 impl<PT: PullType, OT: OutputType, OS: OutputSpeed> $PXi<PT, Output<OT, OS>> {
419 pub fn output_type<NOT: OutputType>(self, ot: NOT) -> $PXi<PT, Output<NOT, OS>> {
421 $Gpiox::set_output_type($i, ot);
422 unsafe { transmute(self) }
423 }
424
425 pub fn push_pull(self) -> $PXi<PT, Output<PushPull, OS>> {
427 self.output_type(PushPull)
428 }
429
430 pub fn open_drain(self) -> $PXi<PT, Output<OpenDrain, OS>> {
432 self.output_type(OpenDrain)
433 }
434
435 pub fn output_speed<NOS: OutputSpeed>(self, os: NOS) -> $PXi<PT, Output<OT, NOS>> {
437 $Gpiox::set_output_speed($i, os);
438 unsafe { transmute(self) }
439 }
440 }
441
442 impl<PT: PullType, AFN: AltFnNum, OT: OutputType, OS: OutputSpeed> $PXi<PT, AltFn<AFN, OT, OS>> {
443 pub fn output_type<NOT: OutputType>(self, ot: NOT) -> $PXi<PT, AltFn<AFN, NOT, OS>> {
445 $Gpiox::set_output_type($i, ot);
446 unsafe { transmute(self) }
447 }
448
449 pub fn output_speed<NOS: OutputSpeed>(self, os: NOS) -> $PXi<PT, AltFn<AFN, OT, NOS>> {
451 $Gpiox::set_output_speed($i, os);
452 unsafe { transmute(self) }
453 }
454
455 pub fn alt_fn<NAFN: AltFnNum>(self, af: NAFN) -> $PXi<PT, AltFn<NAFN, OT, OS>> {
457 let index = $i & (8 - 1);
458 let shift: usize = 0 + (index << 2);
459 let af_bits: u32 = af.alt_fn_num().into();
460 let afr = unsafe { &(*$GPIOX::ptr()).$AFR };
461 afr.modify(|r, w| unsafe {
462 w.bits((r.bits() & !(0b1111 << shift))
463 | (af_bits << shift))
464 });
465
466 unsafe { transmute(self) }
467 }
468 }
469
470 #[allow(deprecated)]
471 impl<PT: PullType, OT:OutputType, OS:OutputSpeed> OutputPin
472 for $PXi<PT, Output<OT, OS>> {
473 fn set_high(&mut self) {
474 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
476 }
477
478 fn set_low(&mut self) {
479 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) }
481 }
482 }
483
484 #[allow(deprecated)]
485 impl<PT: PullType, AN: AltFnNum, OT:OutputType, OS:OutputSpeed> OutputPin
486 for $PXi<PT, AltFn<AN, OT, OS>> {
487 fn set_high(&mut self) {
488 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << $i)) }
490 }
491
492 fn set_low(&mut self) {
493 unsafe { (*$GPIOX::ptr()).bsrr.write(|w| w.bits(1 << (16 + $i))) }
495 }
496 }
497
498 #[allow(deprecated)]
499 impl<PT: PullType, OT:OutputType, OS:OutputSpeed> StatefulOutputPin
500 for $PXi<PT, Output<OT, OS>> {
501 fn is_set_high(&self) -> bool {
502 !self.is_set_low()
503 }
504
505 fn is_set_low(&self) -> bool {
506 unsafe { (*$GPIOX::ptr()).odr.read().bits() & (1 << $i) == 0 }
508 }
509 }
510
511 impl<PT: PullType, OT:OutputType, OS:OutputSpeed> v2::toggleable::Default
512 for $PXi<PT, Output<OT, OS>> {}
513
514 #[allow(deprecated)]
515 impl<PT: PullType> InputPin for $PXi<PT, Input> {
516 fn is_high(&self) -> bool {
517 !self.is_low()
518 }
519
520 fn is_low(&self) -> bool {
521 unsafe { (*$GPIOX::ptr()).idr.read().bits() & (1 << $i) == 0 }
523 }
524 }
525
526 )+
527
528 }
529}
530
531pub enum Group {
533 A,
535 B,
537 C,
539 D,
541 E,
543 F,
545 G,
547}
548
549gpio!(GPIOA, Gpioa, gpioa, iopaen, ioparst, A, PAx, [
550 PA0: (pa0, 0, afrl),
551 PA1: (pa1, 1, afrl),
552 PA2: (pa2, 2, afrl),
553 PA3: (pa3, 3, afrl),
554 PA4: (pa4, 4, afrl),
555 PA5: (pa5, 5, afrl),
556 PA6: (pa6, 6, afrl),
557 PA7: (pa7, 7, afrl),
558 PA8: (pa8, 8, afrh),
559 PA9: (pa9, 9, afrh),
560 PA10: (pa10, 10, afrh),
561 PA11: (pa11, 11, afrh),
562 PA12: (pa12, 12, afrh),
563 PA13: (pa13, 13, afrh),
564 PA14: (pa14, 14, afrh),
565 PA15: (pa15, 15, afrh),
566]);
567
568gpio!(GPIOB, Gpiob, gpiob, iopben, iopbrst, B, PBx, [
569 PB0: (pb0, 0, afrl),
570 PB1: (pb1, 1, afrl),
571 PB2: (pb2, 2, afrl),
572 PB3: (pb3, 3, afrl),
573 PB4: (pb4, 4, afrl),
574 PB5: (pb5, 5, afrl),
575 PB6: (pb6, 6, afrl),
576 PB7: (pb7, 7, afrl),
577 PB8: (pb8, 8, afrh),
578 PB9: (pb9, 9, afrh),
579 PB10: (pb10, 10, afrh),
580 PB11: (pb11, 11, afrh),
581 PB12: (pb12, 12, afrh),
582 PB13: (pb13, 13, afrh),
583 PB14: (pb14, 14, afrh),
584 PB15: (pb15, 15, afrh),
585]);
586
587gpio!(GPIOC, Gpioc, gpioc, iopcen, iopcrst, C, PCx, [
588 PC0: (pc0, 0, afrl),
589 PC1: (pc1, 1, afrl),
590 PC2: (pc2, 2, afrl),
591 PC3: (pc3, 3, afrl),
592 PC4: (pc4, 4, afrl),
593 PC5: (pc5, 5, afrl),
594 PC6: (pc6, 6, afrl),
595 PC7: (pc7, 7, afrl),
596 PC8: (pc8, 8, afrh),
597 PC9: (pc9, 9, afrh),
598 PC10: (pc10, 10, afrh),
599 PC11: (pc11, 11, afrh),
600 PC12: (pc12, 12, afrh),
601 PC13: (pc13, 13, afrh),
602 PC14: (pc14, 14, afrh),
603 PC15: (pc15, 15, afrh),
604]);
605
606gpio!(GPIOD, Gpiod, gpiod, iopden, iopdrst, D, PDx, [
607 PD0: (pd0, 0, afrl),
608 PD1: (pd1, 1, afrl),
609 PD2: (pd2, 2, afrl),
610 PD3: (pd3, 3, afrl),
611 PD4: (pd4, 4, afrl),
612 PD5: (pd5, 5, afrl),
613 PD6: (pd6, 6, afrl),
614 PD7: (pd7, 7, afrl),
615 PD8: (pd8, 8, afrh),
616 PD9: (pd9, 9, afrh),
617 PD10: (pd10, 10, afrh),
618 PD11: (pd11, 11, afrh),
619 PD12: (pd12, 12, afrh),
620 PD13: (pd13, 13, afrh),
621 PD14: (pd14, 14, afrh),
622 PD15: (pd15, 15, afrh),
623]);
624
625gpio!(GPIOE, Gpioe, gpioe, iopeen, ioperst, E, PEx, [
626 PE0: (pe0, 0, afrl),
627 PE1: (pe1, 1, afrl),
628 PE2: (pe2, 2, afrl),
629 PE3: (pe3, 3, afrl),
630 PE4: (pe4, 4, afrl),
631 PE5: (pe5, 5, afrl),
632 PE6: (pe6, 6, afrl),
633 PE7: (pe7, 7, afrl),
634 PE8: (pe8, 8, afrh),
635 PE9: (pe9, 9, afrh),
636 PE10: (pe10, 10, afrh),
637 PE11: (pe11, 11, afrh),
638 PE12: (pe12, 12, afrh),
639 PE13: (pe13, 13, afrh),
640 PE14: (pe14, 14, afrh),
641 PE15: (pe15, 15, afrh),
642]);
643
644gpio!(GPIOF, Gpiof, gpiof, iopfen, iopfrst, F, PFx, [
645 PF0: (pf0, 0, afrl),
646 PF1: (pf1, 1, afrl),
647 PF2: (pf2, 2, afrl),
648 PF4: (pf3, 4, afrl),
649 PF6: (pf6, 6, afrl),
650 PF9: (pf9, 9, afrh),
651 PF10: (pf10, 10, afrh),
652]);