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}