1use core::convert::Infallible;
22use core::marker::PhantomData;
23
24use embedded_hal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
25
26use crate::pac;
27use crate::rcu::{Enable, Rcu, Reset};
28
29enum Ctl {
34 Input = 0b00,
35 Output = 0b01,
36 Af = 0b10,
37 Analog = 0b11,
38}
39
40enum Omode {
42 PushPull = 0b0,
43 OpenDrain = 0b1,
44}
45
46pub struct Input;
48pub struct PushPull;
50pub struct OpenDrain;
52pub struct Output<OTYPE> {
54 _otype: PhantomData<OTYPE>,
55}
56pub struct Analog;
58pub struct Alternate<const AF: u8, OTYPE = PushPull> {
66 _otype: PhantomData<OTYPE>,
67}
68pub struct Debugger;
73pub struct Locked<MODE> {
79 _mode: PhantomData<MODE>,
80}
81
82pub struct Pin<const P: char, const N: u8, MODE> {
85 _mode: PhantomData<MODE>,
86}
87
88#[derive(Clone, Copy, PartialEq, Eq)]
90#[cfg_attr(feature = "defmt", derive(defmt::Format))]
91#[allow(missing_docs)]
92pub enum Port {
93 A,
94 B,
95 #[cfg(pads_ge_48)]
96 C,
97 F,
98}
99
100impl Port {
101 #[inline]
106 const fn from_char(port: char) -> Self {
107 match port {
108 'A' => Port::A,
109 'B' => Port::B,
110 #[cfg(pads_ge_48)]
111 'C' => Port::C,
112 'F' => Port::F,
113 _ => unreachable!(),
114 }
115 }
116}
117
118pub struct ErasedPin<MODE> {
125 port: Port,
126 number: u8,
127 _mode: PhantomData<MODE>,
128}
129
130#[derive(Clone, Copy, PartialEq, Eq)]
132#[cfg_attr(feature = "defmt", derive(defmt::Format))]
133pub enum Pull {
134 Floating = 0b00,
136 Up = 0b01,
138 Down = 0b10,
140}
141
142#[derive(Clone, Copy, PartialEq, Eq)]
145#[cfg_attr(feature = "defmt", derive(defmt::Format))]
146#[allow(missing_docs)]
147pub enum Speed {
148 Mhz2 = 0b00,
149 Mhz10 = 0b01,
150 Mhz50 = 0b11,
151}
152
153pub trait ValidAf<const AF: u8> {}
155
156macro_rules! pin_af {
162 () => {};
163 ( #[$cfg:meta] $p:literal $n:literal => [ $($af:literal: $fun:literal),* $(,)? ] $(, $($rest:tt)*)? ) => {
164 $(
165 #[$cfg]
166 #[doc = concat!("`AF", stringify!($af), "` — ", $fun, ".")]
167 impl<MODE> ValidAf<$af> for Pin<$p, $n, MODE> {}
168 )*
169 $( pin_af! { $($rest)* } )?
170 };
171 ( $p:literal $n:literal => [ $($af:literal: $fun:literal),* $(,)? ] $(, $($rest:tt)*)? ) => {
172 $(
173 #[doc = concat!("`AF", stringify!($af), "` — ", $fun, ".")]
174 impl<MODE> ValidAf<$af> for Pin<$p, $n, MODE> {}
175 )*
176 $( pin_af! { $($rest)* } )?
177 };
178}
179
180pin_af! {
187 'A' 0 => [1: "USART0_CTS on x4, USART1_CTS on x6/x8", 7: "CMP_OUT"],
189 'A' 1 => [0: "EVENTOUT", 1: "USART0_RTS/DE on x4, USART1_RTS/DE on x6/x8"],
190 'A' 2 => [1: "USART0_TX on x4, USART1_TX on x6/x8"],
191 'A' 3 => [1: "USART0_RX on x4, USART1_RX on x6/x8"],
192 'A' 4 => [0: "SPI0_NSS/I2S0_WS", 1: "USART0_CK on x4, USART1_CK on x6/x8", 4: "TIMER13_CH0"],
193 'A' 5 => [0: "SPI0_SCK/I2S0_CK"],
194 'A' 6 => [0: "SPI0_MISO", 1: "TIMER2_CH0", 2: "TIMER0_BRKIN", 5: "TIMER15_CH0", 6: "EVENTOUT", 7: "CMP_OUT"],
195 'A' 7 => [0: "SPI0_MOSI", 1: "TIMER2_CH1", 2: "TIMER0_CH0_ON", 4: "TIMER13_CH0", 5: "TIMER16_CH0", 6: "EVENTOUT"],
196 #[cfg(pads_ge_24)]
197 'A' 8 => [0: "CK_OUT", 1: "USART0_CK", 2: "TIMER0_CH0", 3: "EVENTOUT"],
198 'A' 9 => [1: "USART0_TX", 2: "TIMER0_CH1", 4: "I2C0_SCL", 5: "CK_OUT"],
199 'A' 10 => [0: "TIMER16_BRKIN", 1: "USART0_RX", 2: "TIMER0_CH2", 4: "I2C0_SDA"],
200 #[cfg(pads_ge_lqfp32)]
201 'A' 11 => [0: "EVENTOUT", 1: "USART0_CTS", 2: "TIMER0_CH3", 4: "I2C0_SMBA", 7: "CMP_OUT"],
202 #[cfg(pads_ge_lqfp32)]
203 'A' 12 => [0: "EVENTOUT", 1: "USART0_RTS/DE", 2: "TIMER0_ETI", 4: "I2C0_TXFRAME"],
204 'A' 13 => [0: "SWDIO", 1: "IFRP_OUT"],
205 'A' 14 => [0: "SWCLK", 1: "USART0_TX on x4, USART1_TX on x6/x8"],
206 #[cfg(pads_ge_28)]
207 'A' 15 => [0: "SPI0_NSS/I2S0_WS", 1: "USART0_RX on x4, USART1_RX on x6/x8", 3: "EVENTOUT"],
208 #[cfg(pads_ge_24)]
210 'B' 0 => [0: "EVENTOUT", 1: "TIMER2_CH2", 2: "TIMER0_CH1_ON"],
211 'B' 1 => [1: "TIMER2_CH3", 2: "TIMER13_CH0", 3: "TIMER0_CH2_ON"],
212 #[cfg(pads_ge_qfn32)]
213 'B' 2 => [1: "TIMER2_ETI"],
214 #[cfg(pads_ge_28)]
215 'B' 3 => [0: "SPI0_SCK/I2S0_CK", 1: "EVENTOUT"],
216 #[cfg(pads_ge_28)]
217 'B' 4 => [0: "SPI0_MISO", 1: "TIMER2_CH0", 2: "EVENTOUT", 4: "I2C0_TXFRAME", 6: "TIMER16_BRKIN"],
218 #[cfg(pads_ge_28)]
219 'B' 5 => [0: "SPI0_MOSI", 1: "TIMER2_CH1", 2: "I2C0_SMBA", 3: "TIMER15_BRKIN"],
220 #[cfg(pads_ge_24)]
221 'B' 6 => [0: "USART0_TX", 1: "I2C0_SCL", 2: "TIMER15_CH0_ON"],
222 #[cfg(pads_ge_24)]
223 'B' 7 => [0: "USART0_RX", 1: "I2C0_SDA", 2: "TIMER16_CH0_ON"],
224 #[cfg(pads_ge_qfn32)]
225 'B' 8 => [1: "I2C0_SCL", 2: "TIMER15_CH0"],
226 #[cfg(pads_ge_48)]
227 'B' 9 => [0: "IFRP_OUT", 1: "I2C0_SDA", 2: "TIMER16_CH0", 3: "EVENTOUT", 5: "I2S0_MCK"],
228 #[cfg(pads_ge_48)]
229 'B' 11 => [0: "EVENTOUT"],
230 #[cfg(pads_ge_48)]
231 'B' 12 => [1: "EVENTOUT", 2: "TIMER0_BRKIN"],
232 #[cfg(pads_ge_48)]
233 'B' 13 => [2: "TIMER0_CH0_ON"],
234 #[cfg(pads_ge_48)]
235 'B' 14 => [2: "TIMER0_CH1_ON"],
236 #[cfg(pads_ge_48)]
237 'B' 15 => [2: "TIMER0_CH2_ON"],
238 'F' 0 => [1: "I2C0_SDA"],
240 'F' 1 => [1: "I2C0_SCL"],
241}
242
243#[cfg(chip_x4)]
245pin_af! {
246 #[cfg(pads_ge_48)]
247 'B' 10 => [1: "I2C0_SCL"],
248 #[cfg(pads_ge_48)]
249 'B' 11 => [1: "I2C0_SDA"],
250 #[cfg(pads_ge_48)]
251 'B' 12 => [0: "SPI0_NSS"],
252 #[cfg(pads_ge_48)]
253 'B' 13 => [0: "SPI0_SCK"],
254 #[cfg(pads_ge_48)]
255 'B' 14 => [0: "SPI0_MISO"],
256 #[cfg(pads_ge_48)]
257 'B' 15 => [0: "SPI0_MOSI"],
258 #[cfg(pads_ge_48)]
259 'F' 6 => [0: "I2C0_SCL"],
260 #[cfg(pads_ge_48)]
261 'F' 7 => [0: "I2C0_SDA"],
262}
263
264#[cfg(any(chip_x6, chip_x8))]
266pin_af! {
267 #[cfg(pads_ge_24)]
268 'A' 8 => [4: "USART1_TX"],
269 #[cfg(pads_ge_24)]
270 'B' 0 => [4: "USART1_RX"],
271}
272
273#[cfg(chip_x8)]
278pin_af! {
279 'A' 0 => [4: "I2C1_SCL"],
280 'A' 1 => [4: "I2C1_SDA", 5: "TIMER14_CH0_ON"],
281 'A' 2 => [0: "TIMER14_CH0"],
282 'A' 3 => [0: "TIMER14_CH1"],
283 'A' 4 => [6: "SPI1_NSS"],
284 'A' 9 => [0: "TIMER14_BRKIN"],
285 #[cfg(pads_ge_lqfp32)]
286 'A' 11 => [5: "I2C1_SCL", 6: "SPI1_IO2"],
287 #[cfg(pads_ge_lqfp32)]
288 'A' 12 => [5: "I2C1_SDA", 6: "SPI1_IO3"],
289 'A' 13 => [6: "SPI1_MISO"],
290 'A' 14 => [6: "SPI1_MOSI"],
291 #[cfg(pads_ge_28)]
292 'A' 15 => [6: "SPI1_NSS"],
293 'B' 1 => [6: "SPI1_SCK"],
294 #[cfg(pads_ge_48)]
295 'B' 9 => [7: "SPI1_NSS"],
296 #[cfg(pads_ge_48)]
297 'B' 10 => [1: "I2C1_SCL", 6: "SPI1_IO2", 7: "SPI1_SCK"],
298 #[cfg(pads_ge_48)]
299 'B' 11 => [1: "I2C1_SDA", 6: "SPI1_IO3"],
300 #[cfg(pads_ge_48)]
301 'B' 12 => [0: "SPI1_NSS", 4: "I2C1_SMBA"],
302 #[cfg(pads_ge_48)]
303 'B' 13 => [0: "SPI1_SCK", 1: "I2C1_TXFRAME", 5: "I2C1_SCL"],
304 #[cfg(pads_ge_48)]
305 'B' 14 => [0: "SPI1_MISO", 1: "TIMER14_CH0", 5: "I2C1_SDA"],
306 #[cfg(pads_ge_48)]
307 'B' 15 => [0: "SPI1_MOSI", 1: "TIMER14_CH1", 3: "TIMER14_CH0_ON"],
308 #[cfg(pads_ge_48)]
309 'F' 6 => [0: "I2C1_SCL"],
310 #[cfg(pads_ge_48)]
311 'F' 7 => [0: "I2C1_SDA"],
312}
313
314pub trait Active {}
316
317impl Active for Input {}
318impl Active for Analog {}
319impl<const AF: u8, OTYPE> Active for Alternate<AF, OTYPE> {}
320impl<OTYPE> Active for Output<OTYPE> {}
321
322pub trait HasLock {}
326impl<const N: u8, MODE> HasLock for Pin<'A', N, MODE> {}
327impl<const N: u8, MODE> HasLock for Pin<'B', N, MODE> {}
328
329impl<const P: char, const N: u8> Pin<P, N, Debugger> {
337 pub fn activate_into_input(mut self) -> Pin<P, N, Input> {
339 self.set_mode(Ctl::Input);
340 Pin { _mode: PhantomData }
341 }
342 pub fn activate(self) -> Pin<P, N, Input> {
345 self.activate_into_input()
346 }
347 pub fn activate_into_push_pull_output(mut self) -> Pin<P, N, Output<PushPull>> {
349 self.set_mode(Ctl::Output);
350 self.set_omode(Omode::PushPull);
351 Pin { _mode: PhantomData }
352 }
353 pub fn activate_into_open_drain_output(mut self) -> Pin<P, N, Output<OpenDrain>> {
355 self.set_mode(Ctl::Output);
356 self.set_omode(Omode::OpenDrain);
357 Pin { _mode: PhantomData }
358 }
359 pub fn activate_into_output(self) -> Pin<P, N, Output<PushPull>> {
361 self.activate_into_push_pull_output()
362 }
363 pub fn activate_into_analog(mut self) -> Pin<P, N, Analog> {
365 self.set_mode(Ctl::Analog);
366 Pin { _mode: PhantomData }
367 }
368 pub fn activate_into_alternate<const AF: u8>(mut self) -> Pin<P, N, Alternate<AF>>
374 where
375 Self: ValidAf<AF>,
376 {
377 self.set_alternate(AF as u32, Omode::PushPull);
378 Pin { _mode: PhantomData }
379 }
380 pub fn activate_into_alternate_open_drain<const AF: u8>(
382 mut self,
383 ) -> Pin<P, N, Alternate<AF, OpenDrain>>
384 where
385 Self: ValidAf<AF>,
386 {
387 self.set_alternate(AF as u32, Omode::OpenDrain);
388 Pin { _mode: PhantomData }
389 }
390}
391
392#[inline]
396const fn reg(port: Port) -> &'static pac::gpioa::RegisterBlock {
397 let ptr = match port {
398 Port::A => pac::Gpioa::ptr(),
399 Port::B => pac::Gpiob::ptr().cast(),
400 #[cfg(pads_ge_48)]
404 Port::C => pac::Gpioc::ptr().cast(),
405 Port::F => pac::Gpiof::ptr().cast(),
406 };
407 unsafe { &*ptr }
410}
411
412#[inline]
413fn read_pin(port: Port, number: u8) -> bool {
414 let bits = reg(port).istat().read().bits();
415 ((bits >> number) & 0b1) == 0b1
416}
417
418#[inline]
419fn read_octl(port: Port, number: u8) -> bool {
420 let bits = reg(port).octl().read().bits();
421 ((bits >> number) & 0b1) == 0b1
422}
423
424#[inline]
425fn set_bop(port: Port, number: u8) {
426 reg(port).bop().write(|w| unsafe { w.bits(1 << number) });
428}
429
430#[inline]
431fn set_bc(port: Port, number: u8) {
432 reg(port).bc().write(|w| unsafe { w.bits(1 << number) });
434}
435
436#[inline]
437fn set_tg(port: Port, number: u8) {
438 reg(port).tg().write(|w| unsafe { w.bits(1 << number) });
440}
441
442#[allow(clippy::unused_self)]
443impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
444 fn reg(&self) -> &'static pac::gpioa::RegisterBlock {
445 reg(Port::from_char(P))
446 }
447
448 fn read_pin(&self) -> bool {
449 read_pin(Port::from_char(P), N)
450 }
451
452 fn read_octl(&self) -> bool {
453 read_octl(Port::from_char(P), N)
454 }
455 fn set_bop(&mut self) {
456 set_bop(Port::from_char(P), N);
457 }
458
459 fn set_bc(&mut self) {
460 set_bc(Port::from_char(P), N);
461 }
462
463 fn set_tg(&mut self) {
464 set_tg(Port::from_char(P), N);
465 }
466}
467
468impl<const P: char, const N: u8, MODE> Pin<P, N, MODE> {
472 fn set_mode(&mut self, mode: Ctl) {
473 let offset = N * 2;
474 self.reg().ctl().modify(|r, w| unsafe {
476 w.bits((r.bits() & !(0b11 << offset)) | ((mode as u32) << offset))
477 });
478 }
479 fn set_af(&mut self, af: u32) {
480 let is_afsel0 = N < 8;
481 let offset = (N % 8) * 4;
482 if is_afsel0 {
483 self.reg().afsel0().modify(|r, w| unsafe {
486 w.bits((r.bits() & !(0b1111 << offset)) | (af << offset))
487 });
488 } else {
489 self.reg().afsel1().modify(|r, w| unsafe {
491 w.bits((r.bits() & !(0b1111 << offset)) | (af << offset))
492 });
493 }
494 }
495 fn set_pud(&mut self, bits: u32) {
496 let offset = N * 2;
497 self.reg()
499 .pud()
500 .modify(|r, w| unsafe { w.bits((r.bits() & !(0b11 << offset)) | (bits << offset)) });
501 }
502 fn set_ospd(&mut self, bits: u32) {
503 let offset = N * 2;
504 self.reg()
506 .ospd()
507 .modify(|r, w| unsafe { w.bits((r.bits() & !(0b11 << offset)) | (bits << offset)) });
508 }
509 fn set_omode(&mut self, omode: Omode) {
510 let offset = N;
511 self.reg().omode().modify(|r, w| unsafe {
513 w.bits((r.bits() & !(0b1 << offset)) | ((omode as u32) << offset))
514 });
515 }
516 fn set_alternate(&mut self, af: u32, omode: Omode) {
520 self.set_mode(Ctl::Af);
521 self.set_af(af);
522 self.set_omode(omode);
523 }
524 fn set_lk(&mut self, lkk: bool) {
525 self.reg().lock().modify(|_, w| {
526 let w = match N {
527 0 => w.lk0().locked(),
528 1 => w.lk1().locked(),
529 2 => w.lk2().locked(),
530 3 => w.lk3().locked(),
531 4 => w.lk4().locked(),
532 5 => w.lk5().locked(),
533 6 => w.lk6().locked(),
534 7 => w.lk7().locked(),
535 8 => w.lk8().locked(),
536 9 => w.lk9().locked(),
537 10 => w.lk10().locked(),
538 11 => w.lk11().locked(),
539 12 => w.lk12().locked(),
540 13 => w.lk13().locked(),
541 14 => w.lk14().locked(),
542 15 => w.lk15().locked(),
543 _ => unreachable!(),
544 };
545 if lkk {
546 w.lkk().active()
547 } else {
548 w.lkk().not_active()
549 }
550 });
551 }
552}
553
554#[cfg(not(pads_ge_lqfp32))]
555impl<const P: char, const N: u8> Pin<P, N, Input> {
556 pub(crate) fn take_as_input() -> Self {
560 let mut pin = Pin { _mode: PhantomData };
561 pin.set_mode(Ctl::Input);
562 pin
563 }
564}
565
566impl<const P: char, const N: u8, MODE> Pin<P, N, MODE>
567where
568 MODE: Active,
569{
570 pub fn into_input(mut self) -> Pin<P, N, Input> {
572 self.set_mode(Ctl::Input);
573 Pin { _mode: PhantomData }
574 }
575 pub fn into_push_pull_output(mut self) -> Pin<P, N, Output<PushPull>> {
577 self.set_mode(Ctl::Output);
578 self.set_omode(Omode::PushPull);
579 Pin { _mode: PhantomData }
580 }
581 pub fn into_open_drain_output(mut self) -> Pin<P, N, Output<OpenDrain>> {
586 self.set_mode(Ctl::Output);
587 self.set_omode(Omode::OpenDrain);
588 Pin { _mode: PhantomData }
589 }
590 pub fn into_output(self) -> Pin<P, N, Output<PushPull>> {
592 self.into_push_pull_output()
593 }
594 pub fn into_analog(mut self) -> Pin<P, N, Analog> {
596 self.set_mode(Ctl::Analog);
597 Pin { _mode: PhantomData }
598 }
599 pub fn into_alternate<const AF: u8>(mut self) -> Pin<P, N, Alternate<AF>>
602 where
603 Self: ValidAf<AF>,
604 {
605 self.set_alternate(AF as u32, Omode::PushPull);
606 Pin { _mode: PhantomData }
607 }
608 pub fn into_alternate_open_drain<const AF: u8>(mut self) -> Pin<P, N, Alternate<AF, OpenDrain>>
611 where
612 Self: ValidAf<AF>,
613 {
614 self.set_alternate(AF as u32, Omode::OpenDrain);
615 Pin { _mode: PhantomData }
616 }
617 pub fn lock(mut self) -> Pin<P, N, Locked<MODE>>
624 where
625 Self: HasLock,
626 {
627 self.set_lk(true);
629 self.set_lk(false);
630 self.set_lk(true);
631 for _ in 0..2 {
632 self.reg().lock().read();
633 }
634 Pin { _mode: PhantomData }
635 }
636 pub fn erase(self) -> ErasedPin<MODE> {
642 ErasedPin {
643 port: Port::from_char(P),
644 number: N,
645 _mode: PhantomData,
646 }
647 }
648
649 pub fn set_pull(&mut self, p: Pull) {
651 self.set_pud(p as u32);
652 }
653 pub fn set_speed(&mut self, s: Speed) {
655 self.set_ospd(s as u32);
656 }
657}
658
659impl<const P: char, const N: u8, OTYPE> Pin<P, N, Output<OTYPE>> {
660 pub fn set_high(&mut self) {
662 self.set_bop();
663 }
664 pub fn set_low(&mut self) {
666 self.set_bc();
667 }
668 pub fn toggle(&mut self) {
670 self.set_tg();
671 }
672 pub fn is_set_high(&self) -> bool {
677 self.read_octl()
678 }
679 pub fn is_set_low(&self) -> bool {
681 !self.read_octl()
682 }
683}
684
685impl<const P: char, const N: u8> Pin<P, N, Input> {
686 pub fn is_high(&self) -> bool {
688 self.read_pin()
689 }
690 pub fn is_low(&self) -> bool {
692 !self.read_pin()
693 }
694}
695
696impl<const P: char, const N: u8> Pin<P, N, Output<OpenDrain>> {
697 pub fn is_high(&self) -> bool {
702 self.read_pin()
703 }
704 pub fn is_low(&self) -> bool {
706 !self.read_pin()
707 }
708}
709
710impl<MODE> ErasedPin<MODE> {
711 pub fn port(&self) -> Port {
713 self.port
714 }
715 pub fn number(&self) -> u8 {
717 self.number
718 }
719}
720
721impl<OTYPE> ErasedPin<Output<OTYPE>> {
722 pub fn set_high(&mut self) {
724 set_bop(self.port, self.number);
725 }
726 pub fn set_low(&mut self) {
728 set_bc(self.port, self.number);
729 }
730 pub fn toggle(&mut self) {
732 set_tg(self.port, self.number);
733 }
734 pub fn is_set_high(&self) -> bool {
739 read_octl(self.port, self.number)
740 }
741 pub fn is_set_low(&self) -> bool {
743 !read_octl(self.port, self.number)
744 }
745}
746
747impl ErasedPin<Input> {
748 pub fn is_high(&self) -> bool {
750 read_pin(self.port, self.number)
751 }
752 pub fn is_low(&self) -> bool {
754 !read_pin(self.port, self.number)
755 }
756}
757
758impl ErasedPin<Output<OpenDrain>> {
759 pub fn is_high(&self) -> bool {
764 read_pin(self.port, self.number)
765 }
766 pub fn is_low(&self) -> bool {
768 !read_pin(self.port, self.number)
769 }
770}
771
772impl<const P: char, const N: u8, OTYPE> ErrorType for Pin<P, N, Output<OTYPE>> {
773 type Error = Infallible;
774}
775impl<const P: char, const N: u8, OTYPE> OutputPin for Pin<P, N, Output<OTYPE>> {
776 fn set_high(&mut self) -> Result<(), Self::Error> {
777 self.set_bop();
778 Ok(())
779 }
780 fn set_low(&mut self) -> Result<(), Self::Error> {
781 self.set_bc();
782 Ok(())
783 }
784}
785
786impl<const P: char, const N: u8, OTYPE> StatefulOutputPin for Pin<P, N, Output<OTYPE>> {
787 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
788 Ok(self.read_octl())
789 }
790 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
791 Ok(!self.read_octl())
792 }
793 fn toggle(&mut self) -> Result<(), Self::Error> {
794 self.set_tg();
795 Ok(())
796 }
797}
798
799impl<const P: char, const N: u8> ErrorType for Pin<P, N, Input> {
800 type Error = Infallible;
801}
802impl<const P: char, const N: u8> InputPin for Pin<P, N, Input> {
803 fn is_high(&mut self) -> Result<bool, Self::Error> {
804 Ok(self.read_pin())
805 }
806 fn is_low(&mut self) -> Result<bool, Self::Error> {
807 Ok(!self.read_pin())
808 }
809}
810
811impl<const P: char, const N: u8> InputPin for Pin<P, N, Output<OpenDrain>> {
812 fn is_high(&mut self) -> Result<bool, Self::Error> {
813 Ok(self.read_pin())
814 }
815 fn is_low(&mut self) -> Result<bool, Self::Error> {
816 Ok(!self.read_pin())
817 }
818}
819
820impl<OTYPE> ErrorType for ErasedPin<Output<OTYPE>> {
821 type Error = Infallible;
822}
823impl<OTYPE> OutputPin for ErasedPin<Output<OTYPE>> {
824 fn set_high(&mut self) -> Result<(), Self::Error> {
825 set_bop(self.port, self.number);
826 Ok(())
827 }
828 fn set_low(&mut self) -> Result<(), Self::Error> {
829 set_bc(self.port, self.number);
830 Ok(())
831 }
832}
833
834impl<OTYPE> StatefulOutputPin for ErasedPin<Output<OTYPE>> {
835 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
836 Ok(read_octl(self.port, self.number))
837 }
838 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
839 Ok(!read_octl(self.port, self.number))
840 }
841 fn toggle(&mut self) -> Result<(), Self::Error> {
842 set_tg(self.port, self.number);
843 Ok(())
844 }
845}
846
847impl ErrorType for ErasedPin<Input> {
848 type Error = Infallible;
849}
850impl InputPin for ErasedPin<Input> {
851 fn is_high(&mut self) -> Result<bool, Self::Error> {
852 Ok(read_pin(self.port, self.number))
853 }
854 fn is_low(&mut self) -> Result<bool, Self::Error> {
855 Ok(!read_pin(self.port, self.number))
856 }
857}
858
859impl InputPin for ErasedPin<Output<OpenDrain>> {
860 fn is_high(&mut self) -> Result<bool, Self::Error> {
861 Ok(read_pin(self.port, self.number))
862 }
863 fn is_low(&mut self) -> Result<bool, Self::Error> {
864 Ok(!read_pin(self.port, self.number))
865 }
866}
867
868impl<const P: char, const N: u8, MODE> Pin<P, N, Locked<MODE>>
869where
870 Pin<P, N, MODE>: OutputPin,
871{
872 pub fn set_high(&mut self) {
874 self.set_bop();
875 }
876 pub fn set_low(&mut self) {
878 self.set_bc();
879 }
880}
881
882impl<const P: char, const N: u8, MODE> Pin<P, N, Locked<MODE>>
883where
884 Pin<P, N, MODE>: StatefulOutputPin,
885{
886 pub fn toggle(&mut self) {
888 self.set_tg();
889 }
890 pub fn is_set_high(&self) -> bool {
892 self.read_octl()
893 }
894 pub fn is_set_low(&self) -> bool {
896 !self.read_octl()
897 }
898}
899
900impl<const P: char, const N: u8, MODE> Pin<P, N, Locked<MODE>>
901where
902 Pin<P, N, MODE>: InputPin,
903{
904 pub fn is_high(&self) -> bool {
906 self.read_pin()
907 }
908 pub fn is_low(&self) -> bool {
910 !self.read_pin()
911 }
912}
913
914impl<const P: char, const N: u8, MODE> ErrorType for Pin<P, N, Locked<MODE>> {
915 type Error = Infallible;
916}
917
918impl<const P: char, const N: u8, MODE> OutputPin for Pin<P, N, Locked<MODE>>
919where
920 Pin<P, N, MODE>: OutputPin,
921{
922 fn set_high(&mut self) -> Result<(), Self::Error> {
923 self.set_bop();
924 Ok(())
925 }
926 fn set_low(&mut self) -> Result<(), Self::Error> {
927 self.set_bc();
928 Ok(())
929 }
930}
931
932impl<const P: char, const N: u8, MODE> StatefulOutputPin for Pin<P, N, Locked<MODE>>
933where
934 Pin<P, N, MODE>: StatefulOutputPin,
935{
936 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
937 Ok(self.read_octl())
938 }
939 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
940 Ok(!self.read_octl())
941 }
942 fn toggle(&mut self) -> Result<(), Self::Error> {
943 self.set_tg();
944 Ok(())
945 }
946}
947
948impl<const P: char, const N: u8, MODE> InputPin for Pin<P, N, Locked<MODE>>
949where
950 Pin<P, N, MODE>: InputPin,
951{
952 fn is_high(&mut self) -> Result<bool, Self::Error> {
953 Ok(self.read_pin())
954 }
955 fn is_low(&mut self) -> Result<bool, Self::Error> {
956 Ok(!self.read_pin())
957 }
958}
959
960pub trait GpioExt {
962 type Parts;
964
965 fn split(self, rcu: &mut Rcu) -> Self::Parts;
969}
970
971macro_rules! gpio {
972 ($Parts:ident, $Gpio:ty, $P:literal, [
973 $( $(#[$cfg:meta])? $name:ident : $num:literal : $mode:ty ),+ $(,)?
974 ]) => {
975 #[allow(missing_docs)]
977 pub struct $Parts {
978 $(
979 $(#[$cfg])?
980 pub $name: Pin<$P, $num, $mode>,
981 )+
982 }
983
984 impl GpioExt for $Gpio {
985 type Parts = $Parts;
986 fn split(self, rcu: &mut Rcu) -> Self::Parts {
987 <$Gpio as Enable>::enable(rcu);
988 <$Gpio as Reset>::reset(rcu);
989 $Parts {
990 $(
991 $(#[$cfg])?
992 $name: Pin::<$P, $num, $mode> { _mode: PhantomData },
993 )+
994 }
995 }
996 }
997 };
998}
999
1000gpio!(PartsA, pac::Gpioa, 'A', [
1004 pa0:0:Input,
1005 pa1:1:Input,
1006 pa2:2:Input,
1007 pa3:3:Input,
1008 pa4:4:Input,
1009 pa5:5:Input,
1010 pa6:6:Input,
1011 pa7:7:Input,
1012 #[cfg(pads_ge_24)] pa8:8:Input,
1013 pa9:9:Input,
1016 pa10:10:Input,
1017 #[cfg(pads_ge_lqfp32)] pa11:11:Input,
1018 #[cfg(pads_ge_lqfp32)] pa12:12:Input,
1019 pa13:13:Debugger,
1020 pa14:14:Debugger,
1021 #[cfg(pads_ge_28)] pa15:15:Input,
1022]);
1023
1024gpio!(PartsB, pac::Gpiob, 'B', [
1025 #[cfg(pads_ge_24)] pb0:0:Input,
1026 pb1:1:Input,
1027 #[cfg(pads_ge_qfn32)] pb2:2:Input,
1030 #[cfg(pads_ge_28)] pb3:3:Input,
1031 #[cfg(pads_ge_28)] pb4:4:Input,
1032 #[cfg(pads_ge_28)] pb5:5:Input,
1033 #[cfg(pads_ge_24)] pb6:6:Input,
1034 #[cfg(pads_ge_24)] pb7:7:Input,
1035 #[cfg(pads_ge_qfn32)] pb8:8:Input,
1036 #[cfg(pads_ge_48)] pb9:9:Input,
1037 #[cfg(pads_ge_48)] pb10:10:Input,
1038 #[cfg(pads_ge_48)] pb11:11:Input,
1039 #[cfg(pads_ge_48)] pb12:12:Input,
1040 #[cfg(pads_ge_48)] pb13:13:Input,
1041 #[cfg(pads_ge_48)] pb14:14:Input,
1042 #[cfg(pads_ge_48)] pb15:15:Input,
1043]);
1044
1045#[cfg(pads_ge_48)]
1048gpio!(PartsC, pac::Gpioc, 'C', [
1049 pc13:13:Input,
1050 pc14:14:Input,
1051 pc15:15:Input,
1052]);
1053
1054gpio!(PartsF, pac::Gpiof, 'F', [
1055 pf0:0:Input,
1056 pf1:1:Input,
1057 #[cfg(pads_ge_48)] pf6:6:Input,
1058 #[cfg(pads_ge_48)] pf7:7:Input,
1059]);