atsamd_hal/gpio/pin.rs
1//! # Type-level module for GPIO pins
2//!
3//! This module provides a type-level API for GPIO pins. It uses the type system
4//! to track the state of pins at compile-time. Representing GPIO pins in this
5//! manner incurs no run-time overhead. Each [`Pin`] struct is zero-sized, so
6//! there is no data to copy around. Instead, real code is generated as a side
7//! effect of type transformations, and the resulting assembly is nearly
8//! identical to the equivalent, hand-written C.
9//!
10//! To track the state of pins at compile-time, this module uses traits to
11//! represent [type classes] and types as instances of those type classes. For
12//! example, the trait [`InputConfig`] acts as a [type-level enum] of the
13//! available input configurations, and the types [`Floating`], [`PullDown`] and
14//! [`PullUp`] are its type-level variants.
15//!
16//! Type-level [`Pin`]s are parameterized by two type-level enums, [`PinId`] and
17//! [`PinMode`].
18//!
19//! ```
20//! pub struct Pin<I, M>
21//! where
22//! I: PinId,
23//! M: PinMode,
24//! {
25//! // ...
26//! }
27//! ```
28//!
29//! A `PinId` identifies a pin by it's group (A, B, C or D) and pin number. Each
30//! `PinId` instance is named according to its datasheet identifier, e.g.
31//! [`PA02`].
32//!
33//! A `PinMode` represents the various pin modes. The available `PinMode`
34//! variants are [`Disabled`], [`Input`], [`Interrupt`], [`Output`] and
35//! [`Alternate`], each with its own corresponding configurations.
36//!
37//! It is not possible for users to create new instances of a [`Pin`]. Singleton
38//! instances of each pin are made available to users through the [`Pins`]
39//! struct.
40//!
41//! To create the [`Pins`] struct, users must supply the PAC
42//! [`Port`] peripheral. The [`Pins`] struct takes
43//! ownership of the [`Port`] and provides the corresponding pins. Each [`Pin`]
44//! within the [`Pins`] struct can be moved out and used individually.
45//!
46//!
47//! ```
48//! let mut peripherals = Peripherals::take().unwrap();
49//! let pins = Pins::new(peripherals.Port);
50//! ```
51//!
52//! Pins can be converted between modes using several different methods.
53//!
54//! ```
55//! // Use one of the literal function names
56//! let pa27 = pins.pa27.into_floating_input();
57//! // Use a generic method and one of the `PinMode` variant types
58//! let pa27 = pins.pa27.into_mode::<FloatingInput>();
59//! // Specify the target type and use `From`/`Into`
60//! let pa27: Pin<PA27, FloatingInput> = pins.pa27.into();
61//! ```
62//!
63//! # Embedded HAL traits
64//!
65//! This module implements all of the embedded HAL GPIO traits for each [`Pin`]
66//! in the corresponding [`PinMode`]s, namely: [`InputPin`], [`OutputPin`],
67//! [`ToggleableOutputPin`] and [`StatefulOutputPin`].
68//!
69//! For example, you can control the logic level of an `OutputPin` like so
70//!
71//! ```
72//! use atsamd_hal::pac::Peripherals;
73//! use atsamd_hal::gpio::Pins;
74//! use crate::ehal_02::digital::v2::OutputPin;
75//!
76//! let mut peripherals = Peripherals::take().unwrap();
77//! let mut pins = Pins::new(peripherals.Port);
78//! pins.pa27.set_high();
79//! ```
80//!
81//! # Type-level features
82//!
83//! This module also provides additional, type-level tools to work with GPIO
84//! pins.
85//!
86//! The [`OptionalPinId`] and [`OptionalPin`] traits use the [`OptionalKind`]
87//! pattern to act as type-level versions of [`Option`] for `PinId` and `Pin`
88//! respectively. And the [`AnyPin`] trait defines an [`AnyKind`] type class
89//! for all `Pin` types.
90//!
91//! [type classes]: crate::typelevel#type-classes
92//! [type-level enum]: crate::typelevel#type-level-enum
93//! [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
94//! [`ToggleableOutputPin`]: crate::ehal_02::digital::v2::ToggleableOutputPin
95//! [`AnyKind`]: crate::typelevel#anykind-trait-pattern
96
97#![allow(clippy::zero_prefixed_literal)]
98#![allow(clippy::bool_comparison)]
99
100use atsamd_hal_macros::{hal_cfg, hal_macro_helper};
101
102use core::convert::Infallible;
103use core::marker::PhantomData;
104use core::mem::transmute;
105
106use crate::ehal::digital::{ErrorType, InputPin, OutputPin, StatefulOutputPin};
107use paste::paste;
108
109use crate::pac::Port;
110
111use crate::typelevel::{NoneT, Sealed};
112
113use super::dynpin::*;
114use super::reg::RegisterInterface;
115
116//==============================================================================
117// Disabled configurations
118//==============================================================================
119
120/// Type-level enum for disabled configurations
121///
122/// The valid options are [`Floating`], [`PullDown`] and [`PullUp`]. See the
123/// [type-level enum] documentation for more details on the pattern.
124///
125/// [type-level enum]: crate::typelevel#type-level-enum
126pub trait DisabledConfig: Sealed {
127 /// Corresponding [`DynDisabled`]
128 const DYN: DynDisabled;
129}
130
131/// Type-level variant of both [`DisabledConfig`] and [`InputConfig`]
132pub enum Floating {}
133/// Type-level variant of both [`DisabledConfig`] and [`InputConfig`]
134pub enum PullDown {}
135/// Type-level variant of both [`DisabledConfig`] and [`InputConfig`]
136pub enum PullUp {}
137
138impl Sealed for Floating {}
139impl Sealed for PullDown {}
140impl Sealed for PullUp {}
141
142impl DisabledConfig for Floating {
143 const DYN: DynDisabled = DynDisabled::Floating;
144}
145impl DisabledConfig for PullDown {
146 const DYN: DynDisabled = DynDisabled::PullDown;
147}
148impl DisabledConfig for PullUp {
149 const DYN: DynDisabled = DynDisabled::PullUp;
150}
151
152/// Type-level variant of [`PinMode`] for disabled modes
153///
154/// Type `C` is one of three configurations: [`Floating`], [`PullDown`] or
155/// [`PullUp`]
156pub struct Disabled<C: DisabledConfig> {
157 cfg: PhantomData<C>,
158}
159
160impl<C: DisabledConfig> Sealed for Disabled<C> {}
161
162/// Type-level variant of [`PinMode`] for floating disabled mode
163pub type FloatingDisabled = Disabled<Floating>;
164
165/// Type-level variant of [`PinMode`] for pull-down disabled mode
166pub type PullDownDisabled = Disabled<PullDown>;
167
168/// Type-level variant of [`PinMode`] for pull-up disabled mode
169pub type PullUpDisabled = Disabled<PullUp>;
170
171/// Type alias for the [`PinMode`] at reset
172pub type Reset = FloatingDisabled;
173
174//==============================================================================
175// Input configurations
176//==============================================================================
177
178/// Type-level enum for input configurations
179///
180/// The valid options are [`Floating`], [`PullDown`] and [`PullUp`]. See the
181/// [type-level enum] documentation for more details on the pattern.
182///
183/// [type-level enum]: crate::typelevel#type-level-enum
184pub trait InputConfig: Sealed {
185 /// Corresponding [`DynInput`]
186 const DYN: DynInput;
187}
188
189impl InputConfig for Floating {
190 const DYN: DynInput = DynInput::Floating;
191}
192impl InputConfig for PullDown {
193 const DYN: DynInput = DynInput::PullDown;
194}
195impl InputConfig for PullUp {
196 const DYN: DynInput = DynInput::PullUp;
197}
198
199/// Type-level variant of [`PinMode`] for input modes
200///
201/// Type `C` is one of three input configurations: [`Floating`], [`PullDown`] or
202/// [`PullUp`]
203pub struct Input<C: InputConfig> {
204 cfg: PhantomData<C>,
205}
206
207impl<C: InputConfig> Sealed for Input<C> {}
208
209/// Type-level variant of [`PinMode`] for floating input mode
210pub type FloatingInput = Input<Floating>;
211
212/// Type-level variant of [`PinMode`] for pull-down input mode
213pub type PullDownInput = Input<PullDown>;
214
215/// Type-level variant of [`PinMode`] for pull-up input mode
216pub type PullUpInput = Input<PullUp>;
217
218//==============================================================================
219// Interrupt configurations
220//==============================================================================
221
222/// Type-level `enum` for Interrupt configurations
223pub trait InterruptConfig: Sealed {
224 /// Corresponding [`DynInterrupt`]
225 const DYN: DynInterrupt;
226}
227
228impl InterruptConfig for Floating {
229 const DYN: DynInterrupt = DynInterrupt::Floating;
230}
231impl InterruptConfig for PullDown {
232 const DYN: DynInterrupt = DynInterrupt::PullDown;
233}
234impl InterruptConfig for PullUp {
235 const DYN: DynInterrupt = DynInterrupt::PullUp;
236}
237
238/// Type-level variant of [`PinMode`] for Interrupt modes
239///
240/// Type `C` is one of three Interrupt configurations: [`Floating`],
241/// [`PullDown`] or [`PullUp`]
242pub struct Interrupt<C: InterruptConfig> {
243 cfg: PhantomData<C>,
244}
245
246impl<C: InterruptConfig> Sealed for Interrupt<C> {}
247
248/// Type-level variant of [`PinMode`] for floating Interrupt mode
249pub type FloatingInterrupt = Interrupt<Floating>;
250
251/// Type-level variant of [`PinMode`] for pull-down Interrupt mode
252pub type PullDownInterrupt = Interrupt<PullDown>;
253
254/// Type-level variant of [`PinMode`] for pull-up Interrupt mode
255pub type PullUpInterrupt = Interrupt<PullUp>;
256
257//==============================================================================
258// Output configurations
259//==============================================================================
260
261/// Type-level enum for output configurations
262///
263/// The valid options are [`PushPull`] and [`Readable`]. See the [type-level
264/// enum] documentation for more details on the pattern.
265///
266/// [type-level enum]: crate::typelevel#type-level-enum
267pub trait OutputConfig: Sealed {
268 /// Corresponding [`DynOutput`]
269 const DYN: DynOutput;
270}
271
272/// Type-level variant of [`OutputConfig`] for a push-pull configuration
273pub enum PushPull {}
274/// Type-level variant of [`OutputConfig`] for a readable push-pull
275/// configuration
276pub enum Readable {}
277
278impl Sealed for PushPull {}
279impl Sealed for Readable {}
280
281impl OutputConfig for PushPull {
282 const DYN: DynOutput = DynOutput::PushPull;
283}
284impl OutputConfig for Readable {
285 const DYN: DynOutput = DynOutput::Readable;
286}
287
288/// Type-level variant of [`PinMode`] for output modes
289///
290/// Type `C` is one of two output configurations: [`PushPull`] or [`Readable`]
291pub struct Output<C: OutputConfig> {
292 cfg: PhantomData<C>,
293}
294
295impl<C: OutputConfig> Sealed for Output<C> {}
296
297/// Type-level variant of [`PinMode`] for push-pull output mode
298pub type PushPullOutput = Output<PushPull>;
299
300/// Type-level variant of [`PinMode`] for readable push-pull output mode
301pub type ReadableOutput = Output<Readable>;
302
303//==============================================================================
304// Alternate configurations
305//==============================================================================
306
307/// Type-level enum for alternate peripheral function configurations
308///
309/// See the [type-level enum] documentation for more details on the pattern.
310///
311/// [type-level enum]: crate::typelevel#type-level-enum
312pub trait AlternateConfig: Sealed {
313 /// Corresponding [`DynAlternate`]
314 const DYN: DynAlternate;
315}
316
317macro_rules! alternate {
318 (
319 $(
320 $Letter:ident
321 ),+
322 ) => {
323 paste! {
324 $(
325 #[
326 doc = "Type-level variant of [`AlternateConfig`] for \
327 alternate peripheral function " $Letter
328 ]
329 pub enum $Letter {}
330 impl Sealed for $Letter {}
331 impl AlternateConfig for $Letter {
332 const DYN: DynAlternate = DynAlternate::$Letter;
333 }
334 #[
335 doc = "Type-level variant of [`PinMode`] for alternate \
336 peripheral function [`" $Letter "`]"
337 ]
338 pub type [<Alternate $Letter>] = Alternate<$Letter>;
339 )+
340 }
341 };
342}
343
344alternate!(B, C, D, E, F, G);
345
346#[hal_cfg(any("port-d21", "port-d5x"))]
347alternate!(H);
348
349#[hal_cfg("port-d5x")]
350alternate!(I, J, K, L, M, N);
351
352/// Type-level variant of [`PinMode`] for alternate peripheral functions
353///
354/// Type `C` is an [`AlternateConfig`]
355pub struct Alternate<C: AlternateConfig> {
356 cfg: PhantomData<C>,
357}
358
359impl<C: AlternateConfig> Sealed for Alternate<C> {}
360
361//==============================================================================
362// Pin modes
363//==============================================================================
364
365/// Type-level enum representing pin modes
366///
367/// The valid options are [`Disabled`], [`Input`], [`Output`] and [`Alternate`].
368/// See the [type-level enum] documentation for more details on the pattern.
369///
370/// [type-level enum]: crate::typelevel#type-level-enum
371pub trait PinMode: Sealed {
372 /// Corresponding [`DynPinMode`]
373 const DYN: DynPinMode;
374}
375
376impl<C: DisabledConfig> PinMode for Disabled<C> {
377 const DYN: DynPinMode = DynPinMode::Disabled(C::DYN);
378}
379
380impl<C: InputConfig> PinMode for Input<C> {
381 const DYN: DynPinMode = DynPinMode::Input(C::DYN);
382}
383
384impl<C: InterruptConfig> PinMode for Interrupt<C> {
385 const DYN: DynPinMode = DynPinMode::Interrupt(C::DYN);
386}
387
388impl<C: OutputConfig> PinMode for Output<C> {
389 const DYN: DynPinMode = DynPinMode::Output(C::DYN);
390}
391
392impl<C: AlternateConfig> PinMode for Alternate<C> {
393 const DYN: DynPinMode = DynPinMode::Alternate(C::DYN);
394}
395
396//==============================================================================
397// Pin IDs
398//==============================================================================
399
400/// Type-level enum for pin IDs
401///
402/// Valid options take the form `PXYY`, where `X` is a letter in `A`-`D` and
403/// `YY` is a number between 00-31. See the [type-level enum] documentation for
404/// more details on the pattern.
405///
406/// [type-level enum]: crate::typelevel#type-level-enum
407pub trait PinId: Sealed {
408 /// Corresponding [`DynPinId`]
409 const DYN: DynPinId;
410}
411
412macro_rules! pin_id {
413 ($Group:ident, $Id:ident, $NUM:literal) => {
414 paste! {
415 #[doc = "Pin ID representing pin " $Id]
416 pub enum $Id {}
417 impl Sealed for $Id {}
418 impl PinId for $Id {
419 const DYN: DynPinId = DynPinId {
420 group: DynGroup::$Group,
421 num: $NUM,
422 };
423 }
424 }
425 };
426}
427
428//==============================================================================
429// OptionalPinId
430//==============================================================================
431
432/// Type-level equivalent of `Option<PinId>`
433///
434/// See the [`OptionalKind`] documentation for more details on the pattern.
435///
436/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
437pub trait OptionalPinId {}
438
439impl OptionalPinId for NoneT {}
440
441impl<I: PinId> OptionalPinId for I {}
442
443/// Type-level equivalent of `Some(PinId)`
444///
445/// See the [`OptionalKind`] documentation for more details on the pattern.
446///
447/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
448pub trait SomePinId: OptionalPinId + PinId {}
449
450impl<I: PinId> SomePinId for I {}
451
452//==============================================================================
453// Registers
454//==============================================================================
455
456/// Provide a safe register interface for [`Pin`]s
457///
458/// This `struct` takes ownership of a [`PinId`] and provides an API to
459/// access the corresponding regsiters.
460pub(in crate::gpio) struct Registers<I: PinId> {
461 id: PhantomData<I>,
462}
463
464// [`Registers`] takes ownership of the [`PinId`], and [`Pin`] guarantees that
465// each pin is a singleton, so this implementation is safe.
466unsafe impl<I: PinId> RegisterInterface for Registers<I> {
467 #[inline]
468 fn id(&self) -> DynPinId {
469 I::DYN
470 }
471}
472
473impl<I: PinId> Registers<I> {
474 /// Create a new instance of [`Registers`]
475 ///
476 /// # Safety
477 ///
478 /// Users must never create two simultaneous instances of this `struct` with
479 /// the same [`PinId`]
480 #[inline]
481 unsafe fn new() -> Self {
482 Registers { id: PhantomData }
483 }
484
485 /// Provide a type-level equivalent for the
486 /// [`RegisterInterface::change_mode`] method.
487 #[inline]
488 pub(in crate::gpio) fn change_mode<M: PinMode>(&mut self) {
489 RegisterInterface::change_mode(self, M::DYN);
490 }
491}
492
493//==============================================================================
494// Pin
495//==============================================================================
496
497/// A type-level GPIO pin, parameterized by [`PinId`] and [`PinMode`] types
498pub struct Pin<I, M>
499where
500 I: PinId,
501 M: PinMode,
502{
503 pub(in crate::gpio) regs: Registers<I>,
504 mode: PhantomData<M>,
505}
506
507impl<I, M> Pin<I, M>
508where
509 I: PinId,
510 M: PinMode,
511{
512 /// Create a new [`Pin`]
513 ///
514 /// # Safety
515 ///
516 /// Each [`Pin`] must be a singleton. For a given [`PinId`], there must be
517 /// at most one corresponding [`Pin`] in existence at any given time.
518 /// Violating this requirement is `unsafe`.
519 #[inline]
520 pub(crate) unsafe fn new() -> Pin<I, M> {
521 Pin {
522 regs: Registers::new(),
523 mode: PhantomData,
524 }
525 }
526
527 /// Convert the pin to the requested [`PinMode`]
528 #[inline]
529 pub fn into_mode<N: PinMode>(mut self) -> Pin<I, N> {
530 // Only modify registers if we are actually changing pin mode
531 // This check should compile away
532 if N::DYN != M::DYN {
533 self.regs.change_mode::<N>();
534 }
535 // Safe because we drop the existing Pin
536 unsafe { Pin::new() }
537 }
538
539 /// Disable the pin and set it to float
540 #[inline]
541 pub fn into_floating_disabled(self) -> Pin<I, FloatingDisabled> {
542 self.into_mode()
543 }
544
545 /// Disable the pin and set it to pull down
546 #[inline]
547 pub fn into_pull_down_disabled(self) -> Pin<I, PullDownDisabled> {
548 self.into_mode()
549 }
550
551 /// Disable the pin and set it to pull up
552 #[inline]
553 pub fn into_pull_up_disabled(self) -> Pin<I, PullUpDisabled> {
554 self.into_mode()
555 }
556
557 /// Configure the pin to operate as a floating input
558 #[inline]
559 pub fn into_floating_input(self) -> Pin<I, FloatingInput> {
560 self.into_mode()
561 }
562
563 /// Configure the pin to operate as a pulled down input
564 #[inline]
565 pub fn into_pull_down_input(self) -> Pin<I, PullDownInput> {
566 self.into_mode()
567 }
568
569 /// Configure the pin to operate as a pulled up input
570 #[inline]
571 pub fn into_pull_up_input(self) -> Pin<I, PullUpInput> {
572 self.into_mode()
573 }
574
575 /// Configure the pin to operate as a floating interrupt
576 #[inline]
577 pub fn into_floating_interrupt(self) -> Pin<I, FloatingInterrupt> {
578 self.into_mode()
579 }
580
581 /// Configure the pin to operate as a pulled down interrupt
582 #[inline]
583 pub fn into_pull_down_interrupt(self) -> Pin<I, PullDownInterrupt> {
584 self.into_mode()
585 }
586
587 /// Configure the pin to operate as a pulled up interrupt
588 #[inline]
589 pub fn into_pull_up_interrupt(self) -> Pin<I, PullUpInterrupt> {
590 self.into_mode()
591 }
592
593 /// Configure the pin to operate as a push-pull output
594 #[inline]
595 pub fn into_push_pull_output(self) -> Pin<I, PushPullOutput> {
596 self.into_mode()
597 }
598
599 /// Configure the pin to operate as a readable push pull output
600 #[inline]
601 pub fn into_readable_output(self) -> Pin<I, ReadableOutput> {
602 self.into_mode()
603 }
604
605 /// Configure the pin to operate as the corresponding peripheral function.
606 ///
607 /// The type `C` indicates the desired peripheral function.
608 #[inline]
609 pub fn into_alternate<C: AlternateConfig>(self) -> Pin<I, Alternate<C>> {
610 self.into_mode()
611 }
612
613 /// Read the current drive strength of the pin.
614 ///
615 /// The drive strength is reset to normal on every change in pin mode.
616 #[inline]
617 pub fn get_drive_strength(&self) -> bool {
618 self.regs.read_drive_strength()
619 }
620
621 /// Set the drive strength for the pin.
622 ///
623 /// The drive strength is reset to normal on every change in pin mode.
624 #[inline]
625 pub fn set_drive_strength(&mut self, stronger: bool) {
626 self.regs.write_drive_strength(stronger);
627 }
628
629 #[inline]
630 pub(crate) fn _is_low(&self) -> bool {
631 self.regs.read_pin() == false
632 }
633
634 #[inline]
635 pub(crate) fn _is_high(&self) -> bool {
636 self.regs.read_pin() == true
637 }
638
639 #[inline]
640 pub(crate) fn _set_low(&mut self) {
641 self.regs.write_pin(false);
642 }
643
644 #[inline]
645 pub(crate) fn _set_high(&mut self) {
646 self.regs.write_pin(true);
647 }
648
649 #[inline]
650 pub(crate) fn _toggle(&mut self) {
651 self.regs.toggle_pin();
652 }
653
654 #[inline]
655 pub(crate) fn _is_set_low(&self) -> bool {
656 self.regs.read_out_pin() == false
657 }
658
659 #[inline]
660 pub(crate) fn _is_set_high(&self) -> bool {
661 self.regs.read_out_pin() == true
662 }
663}
664
665//==============================================================================
666// PinMode conversions
667//==============================================================================
668
669/// Use a recursive macro to implement [`From`](core::convert::From) for each
670/// pair of [`PinMode`]s. A macro is necessary to avoid conflicting with the
671/// reflexive implementation in [`core::convert`], i.e. `impl<T> From<T> for T`.
672macro_rules! impl_core_convert_from {
673 (
674 $( #[$cfg1:meta] )?
675 $Mode1:ident,
676 ) => {};
677 (
678 #[$cfg1:meta]
679 $Mode1:ident,
680 $(
681 $( #[$cfg2:meta] )?
682 $Mode2:ident,
683 )*
684 ) => {
685 #[$cfg1]
686 impl_core_convert_from!(
687 $Mode1,
688 $(
689 $( #[$cfg2] )?
690 $Mode2,
691 )*
692 );
693 };
694 (
695 $Mode1:ident,
696 $(
697 $( #[$cfg2:meta] )?
698 $Mode2:ident,
699 )*
700 ) => {
701 paste! {
702 $(
703 $( #[$cfg2] )?
704 impl<I> From<Pin<I, $Mode1>> for Pin<I, $Mode2>
705 where
706 I: PinId,
707 {
708 #[doc = "Convert from [`" $Mode1 "`] to [`" $Mode2 "`]"]
709 #[inline]
710 fn from(pin: Pin<I, $Mode1>) -> Self {
711 pin.into_mode()
712 }
713 }
714 $( #[$cfg2] )?
715 impl<I> From<Pin<I, $Mode2>> for Pin<I, $Mode1>
716 where
717 I: PinId,
718 {
719 #[doc = "Convert from [`" $Mode2 "`] to [`" $Mode1 "`]"]
720 #[inline]
721 fn from(pin: Pin<I, $Mode2>) -> Self {
722 pin.into_mode()
723 }
724 }
725 )*
726 impl_core_convert_from!(
727 $(
728 $( #[$cfg2] )?
729 $Mode2,
730 )*
731 );
732 }
733 };
734}
735
736#[hal_macro_helper]
737impl_core_convert_from!(
738 FloatingDisabled,
739 PullDownDisabled,
740 PullUpDisabled,
741 FloatingInput,
742 PullDownInput,
743 PullUpInput,
744 PushPullOutput,
745 ReadableOutput,
746 FloatingInterrupt,
747 PullUpInterrupt,
748 PullDownInterrupt,
749 AlternateB,
750 AlternateC,
751 AlternateD,
752 AlternateE,
753 AlternateF,
754 AlternateG,
755 #[hal_cfg(any("port-d21", "port-d5x"))]
756 AlternateH,
757 #[hal_cfg("port-d5x")]
758 AlternateI,
759 #[hal_cfg("port-d5x")]
760 AlternateJ,
761 #[hal_cfg("port-d5x")]
762 AlternateK,
763 #[hal_cfg("port-d5x")]
764 AlternateL,
765 #[hal_cfg("port-d5x")]
766 AlternateM,
767 #[hal_cfg("port-d5x")]
768 AlternateN,
769);
770
771//==============================================================================
772// AnyPin
773//==============================================================================
774
775/// Type class for [`Pin`] types
776///
777/// This trait uses the [`AnyKind`] trait pattern to create a [type class] for
778/// [`Pin`] types. See the `AnyKind` documentation for more details on the
779/// pattern.
780///
781/// ## `v1` Compatibility
782///
783/// Normally, this trait would use `Is<Type = SpecificPin<Self>>` as a super
784/// trait. But doing so would restrict implementations to only the `v2` `Pin`
785/// type in this module. To aid in backwards compatibility, we want to implement
786/// `AnyPin` for the `v1` `Pin` type as well. This is possible for a few
787/// reasons. First, both structs are zero-sized, so there is no meaningful
788/// memory layout to begin with. And even if there were, the `v1` `Pin` type is
789/// a newtype wrapper around a `v2` `Pin`, and single-field structs are
790/// guaranteed to have the same layout as the field, even for `repr(Rust)`.
791///
792/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
793/// [type class]: crate::typelevel#type-classes
794pub trait AnyPin
795where
796 Self: Sealed,
797 Self: From<SpecificPin<Self>>,
798 Self: Into<SpecificPin<Self>>,
799 Self: AsRef<SpecificPin<Self>>,
800 Self: AsMut<SpecificPin<Self>>,
801{
802 /// [`PinId`] of the corresponding [`Pin`]
803 type Id: PinId;
804 /// [`PinMode`] of the corresponding [`Pin`]
805 type Mode: PinMode;
806}
807
808impl<I, M> Sealed for Pin<I, M>
809where
810 I: PinId,
811 M: PinMode,
812{
813}
814
815impl<I, M> AnyPin for Pin<I, M>
816where
817 I: PinId,
818 M: PinMode,
819{
820 type Id = I;
821 type Mode = M;
822}
823
824/// Type alias to recover the specific [`Pin`] type from an implementation of
825/// [`AnyPin`]
826///
827/// See the [`AnyKind`] documentation for more details on the pattern.
828///
829/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
830pub type SpecificPin<P> = Pin<<P as AnyPin>::Id, <P as AnyPin>::Mode>;
831
832impl<P: AnyPin> AsRef<P> for SpecificPin<P> {
833 #[inline]
834 fn as_ref(&self) -> &P {
835 // SAFETY: This is guaranteed to be safe, because P == SpecificPin<P>
836 // Transmuting between `v1` and `v2` `Pin` types is also safe, because
837 // both are zero-sized, and single-field, newtype structs are guaranteed
838 // to have the same layout as the field anyway, even for repr(Rust).
839 unsafe { transmute(self) }
840 }
841}
842
843impl<P: AnyPin> AsMut<P> for SpecificPin<P> {
844 #[inline]
845 fn as_mut(&mut self) -> &mut P {
846 // SAFETY: This is guaranteed to be safe, because P == SpecificPin<P>
847 // Transmuting between `v1` and `v2` `Pin` types is also safe, because
848 // both are zero-sized, and single-field, newtype structs are guaranteed
849 // to have the same layout as the field anyway, even for repr(Rust).
850 unsafe { transmute(self) }
851 }
852}
853
854//==============================================================================
855// Optional pins
856//==============================================================================
857
858/// Type-level equivalent of `Option<PinId>`
859///
860/// See the [`OptionalKind`] documentation for more details on the pattern.
861///
862/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
863pub trait OptionalPin: Sealed {
864 type Id: OptionalPinId;
865}
866
867impl OptionalPin for NoneT {
868 type Id = NoneT;
869}
870
871impl<P: AnyPin> OptionalPin for P {
872 type Id = P::Id;
873}
874
875/// Type-level equivalent of `Some(PinId)`
876///
877/// See the [`OptionalKind`] documentation for more details on the pattern.
878///
879/// [`OptionalKind`]: crate::typelevel#optionalkind-trait-pattern
880pub trait SomePin: AnyPin {}
881impl<P: AnyPin> SomePin for P {}
882
883//==============================================================================
884// Embedded HAL v1 traits
885//==============================================================================
886
887impl<I, M> ErrorType for Pin<I, M>
888where
889 I: PinId,
890 M: PinMode,
891{
892 type Error = Infallible;
893}
894
895impl<I, C> OutputPin for Pin<I, Output<C>>
896where
897 I: PinId,
898 C: OutputConfig,
899{
900 #[inline]
901 fn set_low(&mut self) -> Result<(), Self::Error> {
902 self._set_low();
903 Ok(())
904 }
905
906 #[inline]
907 fn set_high(&mut self) -> Result<(), Self::Error> {
908 self._set_high();
909 Ok(())
910 }
911}
912
913impl<I> InputPin for Pin<I, ReadableOutput>
914where
915 I: PinId,
916{
917 #[inline]
918 fn is_high(&mut self) -> Result<bool, Self::Error> {
919 Ok(self._is_high())
920 }
921 #[inline]
922 fn is_low(&mut self) -> Result<bool, Self::Error> {
923 Ok(self._is_low())
924 }
925}
926
927impl<I, C> InputPin for Pin<I, Input<C>>
928where
929 I: PinId,
930 C: InputConfig,
931{
932 #[inline]
933 fn is_high(&mut self) -> Result<bool, Self::Error> {
934 Ok(self._is_high())
935 }
936 #[inline]
937 fn is_low(&mut self) -> Result<bool, Self::Error> {
938 Ok(self._is_low())
939 }
940}
941
942impl<I, C> InputPin for Pin<I, Interrupt<C>>
943where
944 I: PinId,
945 C: InterruptConfig,
946{
947 #[inline]
948 fn is_high(&mut self) -> Result<bool, Self::Error> {
949 Ok(self._is_high())
950 }
951 #[inline]
952 fn is_low(&mut self) -> Result<bool, Self::Error> {
953 Ok(self._is_low())
954 }
955}
956
957impl<I, C> StatefulOutputPin for Pin<I, Output<C>>
958where
959 I: PinId,
960 C: OutputConfig,
961{
962 #[inline]
963 fn is_set_high(&mut self) -> Result<bool, Self::Error> {
964 Ok(self._is_set_high())
965 }
966 #[inline]
967 fn is_set_low(&mut self) -> Result<bool, Self::Error> {
968 Ok(self._is_set_low())
969 }
970}
971
972//==============================================================================
973// Embedded HAL v0.2 traits
974//==============================================================================
975
976impl<I, C> crate::ehal_02::digital::v2::OutputPin for Pin<I, Output<C>>
977where
978 I: PinId,
979 C: OutputConfig,
980{
981 type Error = Infallible;
982 #[inline]
983 fn set_high(&mut self) -> Result<(), Self::Error> {
984 self._set_high();
985 Ok(())
986 }
987 #[inline]
988 fn set_low(&mut self) -> Result<(), Self::Error> {
989 self._set_low();
990 Ok(())
991 }
992}
993
994impl<I> crate::ehal_02::digital::v2::InputPin for Pin<I, ReadableOutput>
995where
996 I: PinId,
997{
998 type Error = Infallible;
999 #[inline]
1000 fn is_high(&self) -> Result<bool, Self::Error> {
1001 Ok(self._is_high())
1002 }
1003 #[inline]
1004 fn is_low(&self) -> Result<bool, Self::Error> {
1005 Ok(self._is_low())
1006 }
1007}
1008
1009impl<I, C> crate::ehal_02::digital::v2::InputPin for Pin<I, Input<C>>
1010where
1011 I: PinId,
1012 C: InputConfig,
1013{
1014 type Error = Infallible;
1015 #[inline]
1016 fn is_high(&self) -> Result<bool, Self::Error> {
1017 Ok(self._is_high())
1018 }
1019 #[inline]
1020 fn is_low(&self) -> Result<bool, Self::Error> {
1021 Ok(self._is_low())
1022 }
1023}
1024
1025impl<I, C> crate::ehal_02::digital::v2::InputPin for Pin<I, Interrupt<C>>
1026where
1027 I: PinId,
1028 C: InterruptConfig,
1029{
1030 type Error = Infallible;
1031 #[inline]
1032 fn is_high(&self) -> Result<bool, Self::Error> {
1033 Ok(self._is_high())
1034 }
1035 #[inline]
1036 fn is_low(&self) -> Result<bool, Self::Error> {
1037 Ok(self._is_low())
1038 }
1039}
1040
1041impl<I, C> crate::ehal_02::digital::v2::ToggleableOutputPin for Pin<I, Output<C>>
1042where
1043 I: PinId,
1044 C: OutputConfig,
1045{
1046 type Error = Infallible;
1047 #[inline]
1048 fn toggle(&mut self) -> Result<(), Self::Error> {
1049 self._toggle();
1050 Ok(())
1051 }
1052}
1053
1054impl<I, C> crate::ehal_02::digital::v2::StatefulOutputPin for Pin<I, Output<C>>
1055where
1056 I: PinId,
1057 C: OutputConfig,
1058{
1059 #[inline]
1060 fn is_set_high(&self) -> Result<bool, Self::Error> {
1061 Ok(self._is_set_high())
1062 }
1063 #[inline]
1064 fn is_set_low(&self) -> Result<bool, Self::Error> {
1065 Ok(self._is_set_low())
1066 }
1067}
1068
1069//==============================================================================
1070// Pin definitions
1071//==============================================================================
1072
1073macro_rules! pins{
1074 (
1075 $(
1076 #[$cfg:meta]
1077 $Id:ident,
1078 )+
1079 ) => {
1080 paste! {
1081 /// Collection of all the individual [`Pin`]s
1082 pub struct Pins {
1083 port: Option<Port>,
1084 $(
1085 #[doc = "Pin " $Id]
1086 #[$cfg]
1087 pub [<$Id:lower>]: Pin<$Id, Reset>,
1088 )+
1089 }
1090 impl Pins {
1091 /// Take ownership of the PAC
1092 /// [`Port`](crate::pac::Port) and split it into
1093 /// discrete [`Pin`]s
1094 #[inline]
1095 pub fn new(port: Port) -> Pins {
1096 Pins {
1097 port: Some(port),
1098 // Safe because we only create one `Pin` per `PinId`
1099 $(
1100 #[$cfg]
1101 [<$Id:lower>]: unsafe { Pin::new() },
1102 )+
1103 }
1104 }
1105 /// Take the PAC [`Port`]
1106 ///
1107 /// The [`Port`] can only be taken once. Subsequent calls to
1108 /// this function will panic.
1109 ///
1110 /// # Safety
1111 ///
1112 /// Direct access to the [`Port`] could allow you to invalidate
1113 /// the compiler's type-level tracking, so it is unsafe.
1114 ///
1115 /// [`Port`](crate::pac::Port)
1116 #[inline]
1117 pub unsafe fn port(&mut self) -> Port {
1118 self.port.take().unwrap()
1119 }
1120 }
1121 }
1122 };
1123}
1124
1125macro_rules! declare_pins {
1126 (
1127 $(
1128 $Group:ident {
1129 $(
1130 #[$cfg:meta]
1131 ($Id:ident, $NUM:literal),
1132 )+
1133 }
1134 )+
1135 ) => {
1136 $(
1137 $(
1138 #[$cfg]
1139 pin_id!($Group, $Id, $NUM);
1140 )+
1141 )+
1142 pins!(
1143 $(
1144 $(
1145 #[$cfg]
1146 $Id,
1147 )+
1148 )+
1149 );
1150 };
1151}
1152
1153#[hal_macro_helper]
1154declare_pins!(
1155 A {
1156 #[hal_cfg("pa00")]
1157 (PA00, 00),
1158 #[hal_cfg("pa01")]
1159 (PA01, 01),
1160 #[hal_cfg("pa02")]
1161 (PA02, 02),
1162 #[hal_cfg("pa03")]
1163 (PA03, 03),
1164 #[hal_cfg("pa04")]
1165 (PA04, 04),
1166 #[hal_cfg("pa05")]
1167 (PA05, 05),
1168 #[hal_cfg("pa06")]
1169 (PA06, 06),
1170 #[hal_cfg("pa07")]
1171 (PA07, 07),
1172 #[hal_cfg("pa08")]
1173 (PA08, 08),
1174 #[hal_cfg("pa09")]
1175 (PA09, 09),
1176 #[hal_cfg("pa10")]
1177 (PA10, 10),
1178 #[hal_cfg("pa11")]
1179 (PA11, 11),
1180 #[hal_cfg("pa12")]
1181 (PA12, 12),
1182 #[hal_cfg("pa13")]
1183 (PA13, 13),
1184 #[hal_cfg("pa14")]
1185 (PA14, 14),
1186 #[hal_cfg("pa15")]
1187 (PA15, 15),
1188 #[hal_cfg("pa16")]
1189 (PA16, 16),
1190 #[hal_cfg("pa17")]
1191 (PA17, 17),
1192 #[hal_cfg("pa18")]
1193 (PA18, 18),
1194 #[hal_cfg("pa19")]
1195 (PA19, 19),
1196 #[hal_cfg("pa20")]
1197 (PA20, 20),
1198 #[hal_cfg("pa21")]
1199 (PA21, 21),
1200 #[hal_cfg("pa22")]
1201 (PA22, 22),
1202 #[hal_cfg("pa23")]
1203 (PA23, 23),
1204 #[hal_cfg("pa24")]
1205 (PA24, 24),
1206 #[hal_cfg("pa25")]
1207 (PA25, 25),
1208 #[hal_cfg("pa27")]
1209 (PA27, 27),
1210 #[hal_cfg("pa28")]
1211 (PA28, 28),
1212 #[hal_cfg("pa30")]
1213 (PA30, 30),
1214 #[hal_cfg("pa31")]
1215 (PA31, 31),
1216 }
1217 B {
1218 #[hal_cfg("pb00")]
1219 (PB00, 00),
1220 #[hal_cfg("pb01")]
1221 (PB01, 01),
1222 #[hal_cfg("pb02")]
1223 (PB02, 02),
1224 #[hal_cfg("pb03")]
1225 (PB03, 03),
1226 #[hal_cfg("pb04")]
1227 (PB04, 04),
1228 #[hal_cfg("pb05")]
1229 (PB05, 05),
1230 #[hal_cfg("pb06")]
1231 (PB06, 06),
1232 #[hal_cfg("pb07")]
1233 (PB07, 07),
1234 #[hal_cfg("pb08")]
1235 (PB08, 08),
1236 #[hal_cfg("pb09")]
1237 (PB09, 09),
1238 #[hal_cfg("pb10")]
1239 (PB10, 10),
1240 #[hal_cfg("pb11")]
1241 (PB11, 11),
1242 #[hal_cfg("pb12")]
1243 (PB12, 12),
1244 #[hal_cfg("pb13")]
1245 (PB13, 13),
1246 #[hal_cfg("pb14")]
1247 (PB14, 14),
1248 #[hal_cfg("pb15")]
1249 (PB15, 15),
1250 #[hal_cfg("pb16")]
1251 (PB16, 16),
1252 #[hal_cfg("pb17")]
1253 (PB17, 17),
1254 #[hal_cfg("pb18")]
1255 (PB18, 18),
1256 #[hal_cfg("pb19")]
1257 (PB19, 19),
1258 #[hal_cfg("pb20")]
1259 (PB20, 20),
1260 #[hal_cfg("pb21")]
1261 (PB21, 21),
1262 #[hal_cfg("pb22")]
1263 (PB22, 22),
1264 #[hal_cfg("pb23")]
1265 (PB23, 23),
1266 #[hal_cfg("pb24")]
1267 (PB24, 24),
1268 #[hal_cfg("pb25")]
1269 (PB25, 25),
1270 #[hal_cfg("pb26")]
1271 (PB26, 26),
1272 #[hal_cfg("pb27")]
1273 (PB27, 27),
1274 #[hal_cfg("pb28")]
1275 (PB28, 28),
1276 #[hal_cfg("pb29")]
1277 (PB29, 29),
1278 #[hal_cfg("pb30")]
1279 (PB30, 30),
1280 #[hal_cfg("pb31")]
1281 (PB31, 31),
1282 }
1283 C {
1284 #[hal_cfg("pc00")]
1285 (PC00, 00),
1286 #[hal_cfg("pc01")]
1287 (PC01, 01),
1288 #[hal_cfg("pc02")]
1289 (PC02, 02),
1290 #[hal_cfg("pc03")]
1291 (PC03, 03),
1292 #[hal_cfg("pc04")]
1293 (PC04, 04),
1294 #[hal_cfg("pc05")]
1295 (PC05, 05),
1296 #[hal_cfg("pc06")]
1297 (PC06, 06),
1298 #[hal_cfg("pc07")]
1299 (PC07, 07),
1300 #[hal_cfg("pc10")]
1301 (PC10, 10),
1302 #[hal_cfg("pc11")]
1303 (PC11, 11),
1304 #[hal_cfg("pc12")]
1305 (PC12, 12),
1306 #[hal_cfg("pc13")]
1307 (PC13, 13),
1308 #[hal_cfg("pc14")]
1309 (PC14, 14),
1310 #[hal_cfg("pc15")]
1311 (PC15, 15),
1312 #[hal_cfg("pc16")]
1313 (PC16, 16),
1314 #[hal_cfg("pc17")]
1315 (PC17, 17),
1316 #[hal_cfg("pc18")]
1317 (PC18, 18),
1318 #[hal_cfg("pc19")]
1319 (PC19, 19),
1320 #[hal_cfg("pc20")]
1321 (PC20, 20),
1322 #[hal_cfg("pc21")]
1323 (PC21, 21),
1324 #[hal_cfg("pc22")]
1325 (PC22, 22),
1326 #[hal_cfg("pc23")]
1327 (PC23, 23),
1328 #[hal_cfg("pc24")]
1329 (PC24, 24),
1330 #[hal_cfg("pc25")]
1331 (PC25, 25),
1332 #[hal_cfg("pc26")]
1333 (PC26, 26),
1334 #[hal_cfg("pc27")]
1335 (PC27, 27),
1336 #[hal_cfg("pc28")]
1337 (PC28, 28),
1338 #[hal_cfg("pc30")]
1339 (PC30, 30),
1340 #[hal_cfg("pc31")]
1341 (PC31, 31),
1342 }
1343 D {
1344 #[hal_cfg("pd00")]
1345 (PD00, 00),
1346 #[hal_cfg("pd01")]
1347 (PD01, 01),
1348 #[hal_cfg("pd08")]
1349 (PD08, 08),
1350 #[hal_cfg("pd09")]
1351 (PD09, 09),
1352 #[hal_cfg("pd10")]
1353 (PD10, 10),
1354 #[hal_cfg("pd11")]
1355 (PD11, 11),
1356 #[hal_cfg("pd12")]
1357 (PD12, 12),
1358 #[hal_cfg("pd20")]
1359 (PD20, 20),
1360 #[hal_cfg("pd21")]
1361 (PD21, 21),
1362 }
1363);
1364
1365//==============================================================================
1366// bsp_pins
1367//==============================================================================
1368
1369/// # Helper macro to give meaningful names to GPIO pins
1370///
1371/// The [`atsamd_hal::gpio`](self) module generally refers to each [`Pin`] by
1372/// its [`PinId`]. However, in the context of a BSP, pins can often be given
1373/// more meaningful names. This macro gives BSP authors a convenient way to
1374/// provide custom names for each pin.
1375///
1376/// ## Calling the macro
1377///
1378/// The `bsp_pins!` macro takes a series of `PinId` blocks. Each block starts
1379/// with a `PinId` and is delimited by curly brackets. Within each block, there
1380/// are two optional fields, `name` and `aliases`. The `name` field represents
1381/// the *principal* name or function assigned to the pin and is given in
1382/// `snake_case`. If the `name` field is absent, the pin name will default to
1383/// its `PinId` (converted to `snake_case`). The `aliases` field represents any
1384/// number of alternative names for the pin, where each name corresponds to the
1385/// pin in a particular [`PinMode`]. Note that each alias is given in
1386/// `PascalCase`.
1387///
1388/// The example below defines a `name` and two `aliases` for pin `PA24`. In
1389/// `PinMode` [`AlternateC`], the pin is used as an SPI MOSI pin. In `PinMode`
1390/// [`AlternateD`], it is used as a UART TX pin. In both cases, it is a serial
1391/// output, so its `name` is `serial_out`.
1392///
1393/// ```
1394/// atsamd_hal::bsp_pins!(
1395/// PA24 {
1396/// name: serial_out,
1397/// aliases: {
1398/// AlternateC: SpiMosi,
1399/// AlternateD: UartTx,
1400/// }
1401/// }
1402/// );
1403/// ```
1404///
1405/// ## Expanding the macro
1406///
1407/// When expanded, the `bsp_pins!` macro will define a number of structs, type
1408/// aliases, constants and macros.
1409///
1410/// ### A new `Pins` struct
1411///
1412/// First, it will define a new, more-useful `Pins` struct. The [`Pins`] struct
1413/// defined in the `gpio` module is intended for general use. It contains *all*
1414/// the pins for a given chip, and each pin is named according to its `PinId`.
1415/// The `Pins` struct defined by this macro, on the other hand, contains only
1416/// the declared pins, and each pin is named appropriately.
1417///
1418/// The field name for each pin within the `Pins` struct is based on the macro
1419/// `name` field. For example, the `serial_out` pin from the example above could
1420/// be accessed like this:
1421///
1422/// ```
1423/// let mut peripherals = pac::Peripherals::take().unwrap();
1424/// let pins = bsp::Pins::new(peripherals.Port);
1425/// let out = pins.serial_out;
1426/// ```
1427///
1428/// However, that is not the only way to access each pin. While the `name` field
1429/// represents the principal name, each pin can also be accessed using its
1430/// corresponding `aliases`.
1431///
1432/// In Rust, each struct field can only have one name. To provide access to the
1433/// same struct field using several *different* names, the `bsp_pins!` macro
1434/// defines another macro, `pin_alias!`. Based on the example above, we could
1435/// use the `pin_alias!` macro to access pin `PA24` without ever referring to
1436/// the `serial_out` field.
1437///
1438/// ```
1439/// let mut peripherals = pac::Peripherals::take().unwrap();
1440/// let pins = bsp::Pins::new(peripherals.Port);
1441/// let mosi = pin_alias!(pins.spi_mosi);
1442/// ```
1443///
1444/// Note that the `SpiMosi` alias was translated to `snake_case` when accessing
1445/// the `Pins` field. The same is true for the `UartTx` alias.
1446///
1447/// ```
1448/// let mut peripherals = pac::Peripherals::take().unwrap();
1449/// let pins = bsp::Pins::new(peripherals.Port);
1450/// let tx = pin_alias!(pins.uart_tx);
1451/// ```
1452///
1453/// ### Type aliases
1454///
1455/// Next, the macro defines several useful type aliases for each pin. It
1456/// provides aliases for the corresponding `PinId`, `PinMode` and fully
1457/// specified `Pin` type of each alternate name.
1458///
1459/// The example above would exand to
1460///
1461/// ```
1462/// pub type SpiMosi = Pin<PA24, AlternateC>;
1463/// pub type SpiMosiId = PA24;
1464/// pub type SpiMosiMode = AlternateC;
1465///
1466/// pub type UartTx = Pin<PA24, AlternateD>;
1467/// pub type UartTxId = PA24;
1468/// pub type UartTxMode = AlternateD;
1469/// ```
1470///
1471/// Each `PascalCase` alias provided in the macro is used for the `Pin` type,
1472/// and the suffixes `Id` and `Mode` are appended to for the corresponding
1473/// `PinId` and `PinMode` types.
1474///
1475/// ### `DYN` constants
1476///
1477/// Although the [`pin`](self) API is more common, there are use cases for the
1478/// type-erased, [`dyn_pin`](super::dynpin) API as well. The `bsp_pins!` macro
1479/// also defines some useful constants for these cases. In particular, it
1480/// defines [`DynPinId`] and [`DynPinMode`] constants for each alias.
1481///
1482/// The example above would effectively expand to
1483///
1484/// ```
1485/// pub const SPI_MOSI_ID: DynPinId = DynPinId { group: DynGroup::A, num: 24 };
1486/// pub const SPI_MOSI_MODE: DynPinMode = DYN_ALTERNATE_C;
1487///
1488/// pub const UART_TX_ID: DynPinId = DynPinId { group: DynGroup::A, num: 24 };
1489/// pub const UART_TX_MODE: DynPinMode = DYN_ALTERNATE_D;
1490/// ```
1491///
1492/// The `PascalCase` alias provided in the macro is converted to
1493/// `SCREAMING_CASE`, and the suffixes `_ID` and `_MODE` are appended for the
1494/// corresponding `DynPinId` and `DynPinMode` constants.
1495///
1496/// ## Attributes and documentation
1497///
1498/// BSP authors can also add attributes and documentation to various parts of
1499/// the macro declaration. Attributes can be added to the entire `PinId` block.
1500/// These attributes will be propagated to every use of the corresponding
1501/// `PinId`. Attributes applied to each alias, on the other hand, will only be
1502/// propagated to items specific to that alias, like the corresponding `DYN`
1503/// constants. Finally, any documentation (or other attributes) provided for the
1504/// `name` field will be propagated to the corresponding field of the
1505/// `bsp::Pins` struct defined by this macro.
1506///
1507/// ```
1508/// atsamd_hal::bsp_pins!(
1509/// #[cfg(feature = "has_pin_PA24")]
1510/// PA24 {
1511/// /// Documentation that will appear on the corresponding field in the
1512/// /// `bsp::Pins` struct
1513/// name: serial_out,
1514/// aliases: {
1515/// #[cfg(feature = "uses_SPI")]
1516/// AlternateC: SpiMosi,
1517/// #[cfg(feature = "uses_UART")]
1518/// AlternateD: UartTx,
1519/// }
1520/// }
1521/// );
1522/// ```
1523#[macro_export]
1524macro_rules! bsp_pins {
1525 (
1526 $(
1527 $( #[$id_cfg:meta] )*
1528 $Id:ident {
1529 $( #[$name_doc:meta] )*
1530 $( name: $name:ident $(,)? )?
1531 $(
1532 aliases: {
1533 $(
1534 $( #[$alias_cfg:meta] )*
1535 $Mode:ident: $Alias:ident $(,)?
1536 )+
1537 }
1538 )?
1539 } $(,)?
1540 )+
1541 ) => {
1542 $crate::paste::paste! {
1543
1544 $crate::__declare_pins_type!(
1545 $(
1546 {
1547 $( #[$id_cfg] )*
1548 ( $Id, [<$Id:lower>] )
1549 $( #[$name_doc] )*
1550 $(
1551 #[
1552 doc = "\nThis field can also be accessed using the [`pin_alias!`] \
1553 macro with the following alternate names:\n "
1554 ]
1555 $(
1556 #[doc = $Alias:snake ", "]
1557 )+
1558 )?
1559 ( $( $name )? [<$Id:lower>] )
1560 }
1561 )+
1562 );
1563
1564 $(
1565 $( #[$id_cfg] )*
1566 $crate::__create_pin_aliases!(
1567 $Id
1568 ( $( $name )? [<$Id:lower>] )
1569 $(
1570 $(
1571 $( #[$alias_cfg] )*
1572 { $Mode, $Alias }
1573 )+
1574 )?
1575 );
1576 )+
1577
1578 $crate::__define_pin_alias_macro!(
1579 $(
1580 {
1581 ( $( $name )? [<$Id:lower>] )
1582 $(
1583 $(
1584 $( #[$alias_cfg] )*
1585 [<$Alias:snake>]
1586 )+
1587 )?
1588 }
1589 )+
1590 );
1591
1592 }
1593 };
1594}
1595
1596#[macro_export]
1597#[doc(hidden)]
1598macro_rules! __declare_pins_type {
1599 (
1600 $(
1601 {
1602 $( #[$id_cfg:meta] )*
1603 ( $Id:ident, $id:ident )
1604 $( #[$name_doc:meta] )*
1605 ( $name:ident $( $others:ident )* )
1606 }
1607 )+
1608 ) => {
1609 /// BSP replacement for the HAL
1610 /// [`Pins`](atsamd_hal::gpio::Pins) type
1611 ///
1612 /// This type is intended to provide more meaningful names for the
1613 /// given pins.
1614 pub struct Pins {
1615 port: Option<$crate::pac::Port>,
1616 $(
1617 $( #[$id_cfg] )*
1618 $( #[$name_doc] )*
1619 pub $name: $crate::gpio::Pin<
1620 $crate::gpio::$Id,
1621 $crate::gpio::Reset
1622 >,
1623 )+
1624 }
1625
1626 impl Pins {
1627
1628 /// Take ownership of the PAC [`Port`] and split it into
1629 /// discrete [`Pin`]s.
1630 ///
1631 /// This struct serves as a replacement for the HAL [`Pins`]
1632 /// struct. It is intended to provide more meaningful names for
1633 /// each [`Pin`] in a BSP. Any [`Pin`] not defined by the BSP is
1634 /// dropped.
1635 ///
1636 /// [`Port`](atsamd_hal::pac::Port)
1637 /// [`Pin`](atsamd_hal::gpio::Pin)
1638 /// [`Pins`](atsamd_hal::gpio::Pins)
1639 #[inline]
1640 pub fn new(port: $crate::pac::Port) -> Self {
1641 let mut pins = $crate::gpio::Pins::new(port);
1642 Self {
1643 port: Some(unsafe{ pins.port() }),
1644 $(
1645 $( #[$id_cfg] )*
1646 $name: pins.$id,
1647 )+
1648 }
1649 }
1650
1651 /// Take the PAC [`Port`]
1652 ///
1653 /// The [`Port`] can only be taken once. Subsequent calls to
1654 /// this function will panic.
1655 ///
1656 /// # Safety
1657 ///
1658 /// Direct access to the [`Port`] could allow you to invalidate
1659 /// the compiler's type-level tracking, so it is unsafe.
1660 ///
1661 /// [`Port`](atsamd_hal::pac::Port)
1662 #[inline]
1663 pub unsafe fn port(&mut self) -> $crate::pac::Port {
1664 self.port.take().unwrap()
1665 }
1666 }
1667 };
1668}
1669
1670#[macro_export]
1671#[doc(hidden)]
1672macro_rules! __create_pin_aliases {
1673 (
1674 $Id:ident
1675 ( $name:ident $( $others:ident )* )
1676 $(
1677 $( #[$attr:meta] )*
1678 { $Mode:ident, $Alias:ident }
1679 )*
1680 ) => {
1681 $crate::paste::paste! {
1682 $(
1683 $( #[$attr] )*
1684 /// Alias for a configured [`Pin`](atsamd_hal::gpio::Pin)
1685 pub type $Alias = $crate::gpio::Pin<
1686 $crate::gpio::$Id,
1687 $crate::gpio::$Mode
1688 >;
1689
1690 $( #[$attr] )*
1691 #[doc = "[`PinId`](atsamd_hal::gpio::PinId) for the [`"]
1692 #[doc = $Alias "`] alias"]
1693 pub type [<$Alias Id>] = $crate::gpio::$Id;
1694
1695 $( #[$attr] )*
1696 #[doc = "[`PinMode`](atsamd_hal::gpio::PinMode) for the [`"]
1697 #[doc = $Alias "`] alias"]
1698 pub type [<$Alias Mode>] = $crate::gpio::$Mode;
1699
1700 $( #[$attr] )*
1701 #[doc = "[DynPinId](atsamd_hal::gpio::DynPinId) "]
1702 #[doc = "for the `" $Alias "` alias."]
1703 pub const [<$Alias:snake:upper _ID>]: $crate::gpio::DynPinId =
1704 <$crate::gpio::$Id as $crate::gpio::PinId>::DYN;
1705
1706 $( #[$attr] )*
1707 #[doc = "[DynPinMode](atsamd_hal::gpio::DynPinMode) "]
1708 #[doc = "for the `" $Alias "` alias."]
1709 pub const [<$Alias:snake:upper _MODE>]: $crate::gpio::DynPinMode =
1710 <$crate::gpio::$Mode as $crate::gpio::PinMode>::DYN;
1711 )*
1712 }
1713 };
1714}
1715
1716#[macro_export]
1717#[doc(hidden)]
1718macro_rules! __define_pin_alias_macro {
1719 (
1720 $(
1721 {
1722 ( $name:ident $( $others:ident )* )
1723 $(
1724 $( #[$attr:meta] )*
1725 $alias:ident
1726 )*
1727 }
1728 )+
1729 ) => {
1730 $crate::paste::paste! {
1731 /// Refer to fields of the [`Pins`] struct by alternate names
1732 ///
1733 /// This macro can be used to access fields of the [`Pins`] struct
1734 /// by alternate names. See the `Pins` documentation for a list of
1735 /// the availabe pin aliases.
1736 ///
1737 /// For example. suppose `spi_mosi` were an alternate name for the
1738 /// `serial_out` pin of the `Pins` struct. You could use the
1739 /// `pin_alias!` macro to access it like this:
1740 ///
1741 /// ```
1742 /// let mut peripherals = pac::Peripherals::take().unwrap();
1743 /// let pins = bsp::Pins::new(peripherals.Port);
1744 /// // Replace this
1745 /// let mosi = pins.serial_out;
1746 /// // With this
1747 /// let mosi = pin_alias!(pins.spi_mosi);
1748 /// ```
1749 #[macro_export]
1750 macro_rules! pin_alias {
1751 $(
1752 // Always provide an identity "alias"
1753 ( $pins:ident . $name ) => { $pins.$name };
1754 )+
1755 $(
1756 $(
1757 ( $pins:ident . $alias ) => {
1758 {
1759 // Since attributes can't apply to expressions, only
1760 // items, apply any attributes to a dummy macro. This
1761 // lets us ensure the alias is only valid when the
1762 // corresponding attributes are valid.
1763 $( #[$attr] )*
1764 macro_rules! [<pin_alias_ $alias>] {
1765 () => { $pins.$name };
1766 }
1767 [<pin_alias_ $alias>]!()
1768 }
1769 };
1770 )*
1771 )+
1772 }
1773 }
1774 }
1775}