#![allow(clippy::zero_prefixed_literal)]
use core::convert::Infallible;
use core::marker::PhantomData;
use core::mem::transmute;
use crate::ehal::digital::v2::OutputPin;
#[cfg(feature = "unproven")]
use crate::ehal::digital::v2::{InputPin, StatefulOutputPin, ToggleableOutputPin};
use paste::paste;
use crate::pac::PORT;
use crate::typelevel::{NoneT, Sealed};
use super::dynpin::*;
use super::reg::RegisterInterface;
pub trait DisabledConfig: Sealed {
const DYN: DynDisabled;
}
pub enum Floating {}
pub enum PullDown {}
pub enum PullUp {}
impl Sealed for Floating {}
impl Sealed for PullDown {}
impl Sealed for PullUp {}
impl DisabledConfig for Floating {
const DYN: DynDisabled = DynDisabled::Floating;
}
impl DisabledConfig for PullDown {
const DYN: DynDisabled = DynDisabled::PullDown;
}
impl DisabledConfig for PullUp {
const DYN: DynDisabled = DynDisabled::PullUp;
}
pub struct Disabled<C: DisabledConfig> {
cfg: PhantomData<C>,
}
impl<C: DisabledConfig> Sealed for Disabled<C> {}
pub type FloatingDisabled = Disabled<Floating>;
pub type PullDownDisabled = Disabled<PullDown>;
pub type PullUpDisabled = Disabled<PullUp>;
pub type Reset = FloatingDisabled;
pub trait InputConfig: Sealed {
const DYN: DynInput;
}
impl InputConfig for Floating {
const DYN: DynInput = DynInput::Floating;
}
impl InputConfig for PullDown {
const DYN: DynInput = DynInput::PullDown;
}
impl InputConfig for PullUp {
const DYN: DynInput = DynInput::PullUp;
}
pub struct Input<C: InputConfig> {
cfg: PhantomData<C>,
}
impl<C: InputConfig> Sealed for Input<C> {}
pub type FloatingInput = Input<Floating>;
pub type PullDownInput = Input<PullDown>;
pub type PullUpInput = Input<PullUp>;
pub trait InterruptConfig: Sealed {
const DYN: DynInterrupt;
}
impl InterruptConfig for Floating {
const DYN: DynInterrupt = DynInterrupt::Floating;
}
impl InterruptConfig for PullDown {
const DYN: DynInterrupt = DynInterrupt::PullDown;
}
impl InterruptConfig for PullUp {
const DYN: DynInterrupt = DynInterrupt::PullUp;
}
pub struct Interrupt<C: InterruptConfig> {
cfg: PhantomData<C>,
}
impl<C: InterruptConfig> Sealed for Interrupt<C> {}
pub type FloatingInterrupt = Interrupt<Floating>;
pub type PullDownInterrupt = Interrupt<PullDown>;
pub type PullUpInterrupt = Interrupt<PullUp>;
pub trait OutputConfig: Sealed {
const DYN: DynOutput;
}
pub enum PushPull {}
pub enum Readable {}
impl Sealed for PushPull {}
impl Sealed for Readable {}
impl OutputConfig for PushPull {
const DYN: DynOutput = DynOutput::PushPull;
}
impl OutputConfig for Readable {
const DYN: DynOutput = DynOutput::Readable;
}
pub struct Output<C: OutputConfig> {
cfg: PhantomData<C>,
}
impl<C: OutputConfig> Sealed for Output<C> {}
pub type PushPullOutput = Output<PushPull>;
pub type ReadableOutput = Output<Readable>;
pub trait AlternateConfig: Sealed {
const DYN: DynAlternate;
}
macro_rules! alternate {
(
$(
$Letter:ident
),+
) => {
paste! {
$(
#[
doc = "Type-level variant of [`AlternateConfig`] for \
alternate peripheral function " $Letter
]
pub enum $Letter {}
impl Sealed for $Letter {}
impl AlternateConfig for $Letter {
const DYN: DynAlternate = DynAlternate::$Letter;
}
#[
doc = "Type-level variant of [`PinMode`] for alternate \
peripheral function [`" $Letter "`]"
]
pub type [<Alternate $Letter>] = Alternate<$Letter>;
)+
}
};
}
alternate!(B, C, D, E, F, G);
#[cfg(any(feature = "samd21", feature = "min-samd51g"))]
alternate!(H);
#[cfg(feature = "min-samd51g")]
alternate!(I, J, K, L, M, N);
pub struct Alternate<C: AlternateConfig> {
cfg: PhantomData<C>,
}
impl<C: AlternateConfig> Sealed for Alternate<C> {}
pub trait PinMode: Sealed {
const DYN: DynPinMode;
}
impl<C: DisabledConfig> PinMode for Disabled<C> {
const DYN: DynPinMode = DynPinMode::Disabled(C::DYN);
}
impl<C: InputConfig> PinMode for Input<C> {
const DYN: DynPinMode = DynPinMode::Input(C::DYN);
}
impl<C: InterruptConfig> PinMode for Interrupt<C> {
const DYN: DynPinMode = DynPinMode::Interrupt(C::DYN);
}
impl<C: OutputConfig> PinMode for Output<C> {
const DYN: DynPinMode = DynPinMode::Output(C::DYN);
}
impl<C: AlternateConfig> PinMode for Alternate<C> {
const DYN: DynPinMode = DynPinMode::Alternate(C::DYN);
}
pub trait PinId: Sealed {
const DYN: DynPinId;
}
macro_rules! pin_id {
($Group:ident, $Id:ident, $NUM:literal) => {
paste! {
#[doc = "Pin ID representing pin " $Id]
pub enum $Id {}
impl Sealed for $Id {}
impl PinId for $Id {
const DYN: DynPinId = DynPinId {
group: DynGroup::$Group,
num: $NUM,
};
}
}
};
}
pub trait OptionalPinId {}
impl OptionalPinId for NoneT {}
impl<I: PinId> OptionalPinId for I {}
pub trait SomePinId: OptionalPinId + PinId {}
impl<I: PinId> SomePinId for I {}
pub(in crate::gpio) struct Registers<I: PinId> {
id: PhantomData<I>,
}
unsafe impl<I: PinId> RegisterInterface for Registers<I> {
#[inline]
fn id(&self) -> DynPinId {
I::DYN
}
}
impl<I: PinId> Registers<I> {
#[inline]
unsafe fn new() -> Self {
Registers { id: PhantomData }
}
#[inline]
pub(in crate::gpio) fn change_mode<M: PinMode>(&mut self) {
RegisterInterface::change_mode(self, M::DYN);
}
}
pub struct Pin<I, M>
where
I: PinId,
M: PinMode,
{
pub(in crate::gpio) regs: Registers<I>,
mode: PhantomData<M>,
}
impl<I, M> Pin<I, M>
where
I: PinId,
M: PinMode,
{
#[inline]
pub(crate) unsafe fn new() -> Pin<I, M> {
Pin {
regs: Registers::new(),
mode: PhantomData,
}
}
#[inline]
pub fn into_mode<N: PinMode>(mut self) -> Pin<I, N> {
if N::DYN != M::DYN {
self.regs.change_mode::<N>();
}
unsafe { Pin::new() }
}
#[inline]
pub fn into_floating_disabled(self) -> Pin<I, FloatingDisabled> {
self.into_mode()
}
#[inline]
pub fn into_pull_down_disabled(self) -> Pin<I, PullDownDisabled> {
self.into_mode()
}
#[inline]
pub fn into_pull_up_disabled(self) -> Pin<I, PullUpDisabled> {
self.into_mode()
}
#[inline]
pub fn into_floating_input(self) -> Pin<I, FloatingInput> {
self.into_mode()
}
#[inline]
pub fn into_pull_down_input(self) -> Pin<I, PullDownInput> {
self.into_mode()
}
#[inline]
pub fn into_pull_up_input(self) -> Pin<I, PullUpInput> {
self.into_mode()
}
#[inline]
pub fn into_floating_interrupt(self) -> Pin<I, FloatingInterrupt> {
self.into_mode()
}
#[inline]
pub fn into_pull_down_interrupt(self) -> Pin<I, PullDownInterrupt> {
self.into_mode()
}
#[inline]
pub fn into_pull_up_interrupt(self) -> Pin<I, PullUpInterrupt> {
self.into_mode()
}
#[inline]
pub fn into_push_pull_output(self) -> Pin<I, PushPullOutput> {
self.into_mode()
}
#[inline]
pub fn into_readable_output(self) -> Pin<I, ReadableOutput> {
self.into_mode()
}
#[inline]
pub fn into_alternate<C: AlternateConfig>(self) -> Pin<I, Alternate<C>> {
self.into_mode()
}
#[inline]
pub fn get_drive_strength(&self) -> bool {
self.regs.read_drive_strength()
}
#[inline]
pub fn set_drive_strength(&mut self, stronger: bool) {
self.regs.write_drive_strength(stronger);
}
#[inline]
pub(crate) fn _is_low(&self) -> bool {
self.regs.read_pin() == false
}
#[inline]
pub(crate) fn _is_high(&self) -> bool {
self.regs.read_pin() == true
}
#[inline]
pub(crate) fn _set_low(&mut self) {
self.regs.write_pin(false);
}
#[inline]
pub(crate) fn _set_high(&mut self) {
self.regs.write_pin(true);
}
#[inline]
pub(crate) fn _toggle(&mut self) {
self.regs.toggle_pin();
}
#[inline]
pub(crate) fn _is_set_low(&self) -> bool {
self.regs.read_out_pin() == false
}
#[inline]
pub(crate) fn _is_set_high(&self) -> bool {
self.regs.read_out_pin() == true
}
}
macro_rules! impl_core_convert_from {
(
$( #[$cfg1:meta] )?
$Mode1:ident,
) => {};
(
#[$cfg1:meta]
$Mode1:ident,
$(
$( #[$cfg2:meta] )?
$Mode2:ident,
)*
) => {
#[$cfg1]
impl_core_convert_from!(
$Mode1,
$(
$( #[$cfg2] )?
$Mode2,
)*
);
};
(
$Mode1:ident,
$(
$( #[$cfg2:meta] )?
$Mode2:ident,
)*
) => {
paste! {
$(
$( #[$cfg2] )?
impl<I> From<Pin<I, $Mode1>> for Pin<I, $Mode2>
where
I: PinId,
{
#[doc = "Convert from [`" $Mode1 "`] to [`" $Mode2 "`]"]
#[inline]
fn from(pin: Pin<I, $Mode1>) -> Self {
pin.into_mode()
}
}
$( #[$cfg2] )?
impl<I> From<Pin<I, $Mode2>> for Pin<I, $Mode1>
where
I: PinId,
{
#[doc = "Convert from [`" $Mode2 "`] to [`" $Mode1 "`]"]
#[inline]
fn from(pin: Pin<I, $Mode2>) -> Self {
pin.into_mode()
}
}
)*
impl_core_convert_from!(
$(
$( #[$cfg2] )?
$Mode2,
)*
);
}
};
}
impl_core_convert_from!(
FloatingDisabled,
PullDownDisabled,
PullUpDisabled,
FloatingInput,
PullDownInput,
PullUpInput,
PushPullOutput,
ReadableOutput,
FloatingInterrupt,
PullUpInterrupt,
PullDownInterrupt,
AlternateB,
AlternateC,
AlternateD,
AlternateE,
AlternateF,
AlternateG,
#[cfg(any(feature = "samd21", feature = "min-samd51g"))]
AlternateH,
#[cfg(feature = "min-samd51g")]
AlternateI,
#[cfg(feature = "min-samd51g")]
AlternateJ,
#[cfg(feature = "min-samd51g")]
AlternateK,
#[cfg(feature = "min-samd51g")]
AlternateL,
#[cfg(feature = "min-samd51g")]
AlternateM,
#[cfg(feature = "min-samd51g")]
AlternateN,
);
pub trait AnyPin
where
Self: Sealed,
Self: From<SpecificPin<Self>>,
Self: Into<SpecificPin<Self>>,
Self: AsRef<SpecificPin<Self>>,
Self: AsMut<SpecificPin<Self>>,
{
type Id: PinId;
type Mode: PinMode;
}
impl<I, M> Sealed for Pin<I, M>
where
I: PinId,
M: PinMode,
{
}
impl<I, M> AnyPin for Pin<I, M>
where
I: PinId,
M: PinMode,
{
type Id = I;
type Mode = M;
}
pub type SpecificPin<P> = Pin<<P as AnyPin>::Id, <P as AnyPin>::Mode>;
impl<P: AnyPin> AsRef<P> for SpecificPin<P> {
#[inline]
fn as_ref(&self) -> &P {
unsafe { transmute(self) }
}
}
impl<P: AnyPin> AsMut<P> for SpecificPin<P> {
#[inline]
fn as_mut(&mut self) -> &mut P {
unsafe { transmute(self) }
}
}
pub trait OptionalPin: Sealed {
type Id: OptionalPinId;
}
impl OptionalPin for NoneT {
type Id = NoneT;
}
impl<P: AnyPin> OptionalPin for P {
type Id = P::Id;
}
pub trait SomePin: AnyPin {}
impl<P: AnyPin> SomePin for P {}
impl<I, C> OutputPin for Pin<I, Output<C>>
where
I: PinId,
C: OutputConfig,
{
type Error = Infallible;
#[inline]
fn set_high(&mut self) -> Result<(), Self::Error> {
self._set_high();
Ok(())
}
#[inline]
fn set_low(&mut self) -> Result<(), Self::Error> {
self._set_low();
Ok(())
}
}
#[cfg(feature = "unproven")]
impl<I> InputPin for Pin<I, ReadableOutput>
where
I: PinId,
{
type Error = Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self._is_high())
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
#[cfg(feature = "unproven")]
impl<I, C> InputPin for Pin<I, Input<C>>
where
I: PinId,
C: InputConfig,
{
type Error = Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self._is_high())
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
#[cfg(feature = "unproven")]
impl<I, C> InputPin for Pin<I, Interrupt<C>>
where
I: PinId,
C: InterruptConfig,
{
type Error = Infallible;
#[inline]
fn is_high(&self) -> Result<bool, Self::Error> {
Ok(self._is_high())
}
#[inline]
fn is_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_low())
}
}
#[cfg(feature = "unproven")]
impl<I, C> ToggleableOutputPin for Pin<I, Output<C>>
where
I: PinId,
C: OutputConfig,
{
type Error = Infallible;
#[inline]
fn toggle(&mut self) -> Result<(), Self::Error> {
self._toggle();
Ok(())
}
}
#[cfg(feature = "unproven")]
impl<I, C> StatefulOutputPin for Pin<I, Output<C>>
where
I: PinId,
C: OutputConfig,
{
#[inline]
fn is_set_high(&self) -> Result<bool, Self::Error> {
Ok(self._is_set_high())
}
#[inline]
fn is_set_low(&self) -> Result<bool, Self::Error> {
Ok(self._is_set_low())
}
}
macro_rules! pins{
(
$(
$( #[$cfg:meta] )?
$Id:ident,
)+
) => {
paste! {
pub struct Pins {
port: Option<PORT>,
$(
#[doc = "Pin " $Id]
$( #[$cfg] )?
pub [<$Id:lower>]: Pin<$Id, Reset>,
)+
}
impl Pins {
#[inline]
pub fn new(port: PORT) -> Pins {
Pins {
port: Some(port),
$(
$( #[$cfg] )?
[<$Id:lower>]: unsafe { Pin::new() },
)+
}
}
#[inline]
pub unsafe fn port(&mut self) -> PORT {
self.port.take().unwrap()
}
}
}
};
}
macro_rules! declare_pins {
(
$(
$Group:ident {
$(
$( #[$cfg:meta] )?
($Id:ident, $NUM:literal),
)+
}
)+
) => {
$(
$(
$( #[$cfg] )?
pin_id!($Group, $Id, $NUM);
)+
)+
pins!(
$(
$(
$( #[$cfg] )?
$Id,
)+
)+
);
};
}
declare_pins!(
A {
#[cfg(not(any(feature = "samd11", feature = "samd21el", feature = "samd21gl")))]
(PA00, 00),
#[cfg(not(any(feature = "samd11", feature = "samd21el", feature = "samd21gl")))]
(PA01, 01),
(PA02, 02),
#[cfg(not(feature = "samd11c"))]
(PA03, 03),
(PA04, 04),
(PA05, 05),
#[cfg(not(feature = "samd11c"))]
(PA06, 06),
#[cfg(not(feature = "samd11c"))]
(PA07, 07),
(PA08, 08),
(PA09, 09),
#[cfg(not(feature = "samd11"))]
(PA10, 10),
#[cfg(not(feature = "samd11"))]
(PA11, 11),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PA12, 12),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PA13, 13),
(PA14, 14),
(PA15, 15),
#[cfg(not(feature = "samd11c"))]
(PA16, 16),
#[cfg(not(feature = "samd11"))]
(PA17, 17),
#[cfg(not(feature = "samd11"))]
(PA18, 18),
#[cfg(not(feature = "samd11"))]
(PA19, 19),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PA20, 20),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PA21, 21),
#[cfg(not(feature = "samd11c"))]
(PA22, 22),
#[cfg(not(feature = "samd11c"))]
(PA23, 23),
(PA24, 24),
(PA25, 25),
#[cfg(not(feature = "samd11"))]
(PA27, 27),
#[cfg(all(any(feature = "samd11", feature = "samd21"), not(feature = "samd21el")))]
(PA28, 28),
(PA30, 30),
(PA31, 31),
}
B {
#[cfg(any(feature = "min-samd21j", feature = "samd21gl", feature = "min-samd51j"))]
(PB00, 00),
#[cfg(any(feature = "min-samd21j", feature = "samd21gl", feature = "min-samd51j"))]
(PB01, 01),
#[cfg(any(feature = "min-samd21g", feature = "samd21el", feature = "min-samd51g"))]
(PB02, 02),
#[cfg(any(feature = "min-samd21g", feature = "samd21el", feature = "min-samd51g"))]
(PB03, 03),
#[cfg(any(feature = "min-samd21j", feature = "samd21el", feature = "samd21gl", feature = "min-samd51j"))]
(PB04, 04),
#[cfg(any(feature = "min-samd21j", feature = "samd21el", feature = "samd21gl", feature = "min-samd51j"))]
(PB05, 05),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB06, 06),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB07, 07),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PB08, 08),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PB09, 09),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PB10, 10),
#[cfg(any(feature = "min-samd21g", feature = "min-samd51g"))]
(PB11, 11),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB12, 12),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB13, 13),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB14, 14),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB15, 15),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB16, 16),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB17, 17),
#[cfg(feature = "min-samd51n")]
(PB18, 18),
#[cfg(feature = "min-samd51n")]
(PB19, 19),
#[cfg(feature = "min-samd51n")]
(PB20, 20),
#[cfg(feature = "min-samd51n")]
(PB21, 21),
#[cfg(all(any(feature = "min-samd21g", feature = "min-samd51g"), not(feature = "samd21gl")))]
(PB22, 22),
#[cfg(all(any(feature = "min-samd21g", feature = "min-samd51g"), not(feature = "samd21gl")))]
(PB23, 23),
#[cfg(feature = "min-samd51n")]
(PB24, 24),
#[cfg(feature = "min-samd51n")]
(PB25, 25),
#[cfg(feature = "min-samd51p")]
(PB26, 26),
#[cfg(feature = "min-samd51p")]
(PB27, 27),
#[cfg(feature = "min-samd51p")]
(PB28, 28),
#[cfg(feature = "min-samd51p")]
(PB29, 29),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB30, 30),
#[cfg(any(feature = "min-samd21j", feature = "min-samd51j"))]
(PB31, 31),
}
C {
#[cfg(feature = "min-samd51n")]
(PC00, 00),
#[cfg(feature = "min-samd51n")]
(PC01, 01),
#[cfg(feature = "min-samd51n")]
(PC02, 02),
#[cfg(feature = "min-samd51n")]
(PC03, 03),
#[cfg(feature = "min-samd51p")]
(PC04, 04),
#[cfg(feature = "min-samd51n")]
(PC05, 05),
#[cfg(feature = "min-samd51n")]
(PC06, 06),
#[cfg(feature = "min-samd51n")]
(PC07, 07),
#[cfg(feature = "min-samd51n")]
(PC10, 10),
#[cfg(feature = "min-samd51n")]
(PC11, 11),
#[cfg(feature = "min-samd51n")]
(PC12, 12),
#[cfg(feature = "min-samd51n")]
(PC13, 13),
#[cfg(feature = "min-samd51n")]
(PC14, 14),
#[cfg(feature = "min-samd51n")]
(PC15, 15),
#[cfg(feature = "min-samd51n")]
(PC16, 16),
#[cfg(feature = "min-samd51n")]
(PC17, 17),
#[cfg(feature = "min-samd51n")]
(PC18, 18),
#[cfg(feature = "min-samd51n")]
(PC19, 19),
#[cfg(feature = "min-samd51n")]
(PC20, 20),
#[cfg(feature = "min-samd51n")]
(PC21, 21),
#[cfg(feature = "min-samd51p")]
(PC22, 22),
#[cfg(feature = "min-samd51p")]
(PC23, 23),
#[cfg(feature = "min-samd51n")]
(PC24, 24),
#[cfg(feature = "min-samd51n")]
(PC25, 25),
#[cfg(feature = "min-samd51n")]
(PC26, 26),
#[cfg(feature = "min-samd51n")]
(PC27, 27),
#[cfg(feature = "min-samd51n")]
(PC28, 28),
#[cfg(feature = "min-samd51p")]
(PC30, 30),
#[cfg(feature = "min-samd51p")]
(PC31, 31),
}
D {
#[cfg(feature = "min-samd51p")]
(PD00, 00),
#[cfg(feature = "min-samd51p")]
(PD01, 01),
#[cfg(feature = "min-samd51p")]
(PD08, 08),
#[cfg(feature = "min-samd51p")]
(PD09, 09),
#[cfg(feature = "min-samd51p")]
(PD10, 10),
#[cfg(feature = "min-samd51p")]
(PD11, 11),
#[cfg(feature = "min-samd51p")]
(PD12, 12),
#[cfg(feature = "min-samd51p")]
(PD20, 20),
#[cfg(feature = "min-samd51p")]
(PD21, 21),
}
);
#[macro_export]
macro_rules! bsp_pins {
(
$(
$( #[$id_cfg:meta] )*
$Id:ident {
$( #[$name_doc:meta] )*
$( name: $name:ident $(,)? )?
$(
aliases: {
$(
$( #[$alias_cfg:meta] )*
$Mode:ident: $Alias:ident $(,)?
)+
}
)?
} $(,)?
)+
) => {
$crate::paste::paste! {
$crate::__declare_pins_type!(
$(
{
$( #[$id_cfg] )*
( $Id, [<$Id:lower>] )
$( #[$name_doc] )*
$(
#[
doc = "\nThis field can also be accessed using the [`pin_alias!`] \
macro with the following alternate names:\n "
]
$(
#[doc = $Alias:snake ", "]
)+
)?
( $( $name )? [<$Id:lower>] )
}
)+
);
$(
$( #[$id_cfg] )*
$crate::__create_pin_aliases!(
$Id
( $( $name )? [<$Id:lower>] )
$(
$(
$( #[$alias_cfg] )*
{ $Mode, $Alias }
)+
)?
);
)+
$crate::__define_pin_alias_macro!(
$(
{
( $( $name )? [<$Id:lower>] )
$(
$(
$( #[$alias_cfg] )*
[<$Alias:snake>]
)+
)?
}
)+
);
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __declare_pins_type {
(
$(
{
$( #[$id_cfg:meta] )*
( $Id:ident, $id:ident )
$( #[$name_doc:meta] )*
( $name:ident $( $others:ident )* )
}
)+
) => {
pub struct Pins {
port: Option<$crate::pac::PORT>,
$(
$( #[$id_cfg] )*
$( #[$name_doc] )*
pub $name: $crate::gpio::Pin<
$crate::gpio::$Id,
$crate::gpio::Reset
>,
)+
}
impl Pins {
#[inline]
pub fn new(port: $crate::pac::PORT) -> Self {
let mut pins = $crate::gpio::Pins::new(port);
Self {
port: Some(unsafe{ pins.port() }),
$(
$( #[$id_cfg] )*
$name: pins.$id,
)+
}
}
#[inline]
pub unsafe fn port(&mut self) -> $crate::pac::PORT {
self.port.take().unwrap()
}
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __create_pin_aliases {
(
$Id:ident
( $name:ident $( $others:ident )* )
$(
$( #[$attr:meta] )*
{ $Mode:ident, $Alias:ident }
)*
) => {
$crate::paste::paste! {
$(
$( #[$attr] )*
/// Alias for a configured [`Pin`](atsamd_hal::gpio::Pin)
pub type $Alias = $crate::gpio::Pin<
$crate::gpio::$Id,
$crate::gpio::$Mode
>;
$( #[$attr] )*
#[doc = "[`PinId`](atsamd_hal::gpio::PinId) for the [`"]
#[doc = $Alias "`] alias"]
pub type [<$Alias Id>] = $crate::gpio::$Id;
$( #[$attr] )*
#[doc = "[`PinMode`](atsamd_hal::gpio::PinMode) for the [`"]
#[doc = $Alias "`] alias"]
pub type [<$Alias Mode>] = $crate::gpio::$Mode;
$( #[$attr] )*
#[doc = "[DynPinId](atsamd_hal::gpio::DynPinId) "]
#[doc = "for the `" $Alias "` alias."]
pub const [<$Alias:snake:upper _ID>]: $crate::gpio::DynPinId =
<$crate::gpio::$Id as $crate::gpio::PinId>::DYN;
$( #[$attr] )*
#[doc = "[DynPinMode](atsamd_hal::gpio::DynPinMode) "]
#[doc = "for the `" $Alias "` alias."]
pub const [<$Alias:snake:upper _MODE>]: $crate::gpio::DynPinMode =
<$crate::gpio::$Mode as $crate::gpio::PinMode>::DYN;
)*
}
};
}
#[macro_export]
#[doc(hidden)]
macro_rules! __define_pin_alias_macro {
(
$(
{
( $name:ident $( $others:ident )* )
$(
$( #[$attr:meta] )*
$alias:ident
)*
}
)+
) => {
$crate::paste::paste! {
#[macro_export]
macro_rules! pin_alias {
$(
$(
( $pins:ident . $alias ) => {
{
$( #[$attr] )*
macro_rules! [<pin_alias_ $alias>] {
() => { $pins.$name };
}
[<pin_alias_ $alias>]!()
}
};
)*
)+
}
}
}
}