atsamd_hal/sercom/i2c/
pads_thumbv7em.rs

1//! Define a container for a set of SERCOM pads
2//!
3//! See the [i2c module](super) documentation for more details on declaring and
4//! instantiating a [`Pads`] type.
5
6use crate::{gpio::AnyPin, sercom::*, typelevel::Sealed};
7use core::marker::PhantomData;
8
9/// Container for a set of SERCOM [`Pad`]s
10///
11/// See the [module-level](crate::sercom::i2c) documentation for more
12/// details on specifying a `Pads` type and creating instances.
13pub struct Pads<S, SDA, SCL>
14where
15    S: Sercom,
16    SDA: IsI2cPad<PadNum = Pad0, Sercom = S>,
17    SCL: IsI2cPad<PadNum = Pad1, Sercom = S>,
18    (SDA, SCL): ShareIoSet,
19{
20    sercom: PhantomData<S>,
21    sda: SDA,
22    scl: SCL,
23}
24
25impl<S, DI, CI> PadsFromIds<S, DI, CI>
26where
27    S: Sercom,
28    DI: GetPad<S>,
29    CI: GetPad<S>,
30    Pad<S, DI>: IsI2cPad<Sercom = S, PadNum = Pad0>,
31    Pad<S, CI>: IsI2cPad<Sercom = S, PadNum = Pad1>,
32    (Pad<S, DI>, Pad<S, CI>): ShareIoSet,
33{
34    pub fn new(sda: impl AnyPin<Id = DI>, scl: impl AnyPin<Id = CI>) -> Self {
35        Self {
36            sercom: PhantomData,
37            sda: sda.into().into_mode(),
38            scl: scl.into().into_mode(),
39        }
40    }
41}
42
43impl<S, SDA, SCL> Pads<S, SDA, SCL>
44where
45    S: Sercom,
46    SDA: IsI2cPad<PadNum = Pad0, Sercom = S>,
47    SCL: IsI2cPad<PadNum = Pad1, Sercom = S>,
48    (SDA, SCL): ShareIoSet,
49{
50    /// Consume the [`Pads`] and return each individual
51    /// [`Pin`](crate::gpio::Pin)
52    #[inline]
53    pub fn free(self) -> (SDA, SCL) {
54        (self.sda, self.scl)
55    }
56}
57
58//=============================================================================
59// PadsFromIds
60//=============================================================================
61
62/// Define a set of [`Pads`] using [`PinId`]s instead of [`Pin`]s
63///
64/// In some cases, it is more convenient to specify a set of `Pads` using
65/// `PinId`s rather than `Pin`s. This alias makes it easier to do so.
66///
67/// The first parameter is the [`Sercom`], while the
68/// remaining two are [`PinId`]s representing the corresponding type
69/// parameters of [`Pads`], i.e. `SDA` & `SCL`.
70///
71/// ```
72/// use atsamd_hal::pac::Peripherals;
73/// use atsamd_hal::gpio::{PA08, PA09, Pins};
74/// use atsamd_hal::sercom::{Sercom0, i2c};
75/// use atsamd_hal::typelevel::NoneT;
76///
77/// pub type Pads = i2c::PadsFromIds<Sercom0, PA08, PA09>;
78///
79/// pub fn create_pads() -> Pads {
80///     let peripherals = Peripherals::take().unwrap();
81///     let pins = Pins::new(peripherals.PORT);
82///     i2c::Pads::default().sda(pins.pa08).scl(pins.pa09)
83/// }
84/// ```
85///
86/// [`Pin`]: crate::gpio::Pin
87/// [`PinId`]: crate::gpio::PinId
88pub type PadsFromIds<S, SDA, SCL> = Pads<S, Pad<S, SDA>, Pad<S, SCL>>;
89
90//=============================================================================
91// PadSet
92//=============================================================================
93
94/// Type-level function to recover the [`Pad`] types from a generic set
95/// of [`Pads`]
96///
97/// This trait is used as an interface between the [`Pads`] type and other
98/// types in this module. It acts as a [type-level function], returning the
99/// corresponding [`Sercom`] and [`OptionalPad`] types. It serves to cut down on
100/// the total number of type parameters needed in the [`Config`] struct. The
101/// `Config` struct doesn't need access to the [`Pin`]s directly.  Rather, it
102/// only needs to apply the [`SomePad`] trait bound when a `Pin` is required.
103/// The `PadSet` trait allows each `Config` struct to store an instance of
104/// `Pads` without itself being generic over all six type parameters of the
105/// `Pads` type.
106///
107/// This trait is a simplified version of the [`AnyKind`] trait pattern.
108///
109/// [`Pin`]: crate::gpio::Pin
110/// [`Config`]: super::Config
111/// [type-level function]: crate::typelevel#type-level-functions
112/// [`AnyKind`]: crate::typelevel#anykind-trait-pattern
113pub trait PadSet: Sealed {
114    type Sercom: Sercom;
115    type Sda: IsI2cPad<PadNum = Pad0, Sercom = Self::Sercom>;
116    type Scl: IsI2cPad<PadNum = Pad1, Sercom = Self::Sercom>;
117}
118
119impl<S, SDA, SCL> Sealed for Pads<S, SDA, SCL>
120where
121    S: Sercom,
122    SDA: IsI2cPad<PadNum = Pad0, Sercom = S>,
123    SCL: IsI2cPad<PadNum = Pad1, Sercom = S>,
124    (SDA, SCL): ShareIoSet,
125{
126}
127
128impl<S, SDA, SCL> PadSet for Pads<S, SDA, SCL>
129where
130    S: Sercom,
131    SDA: IsI2cPad<PadNum = Pad0, Sercom = S>,
132    SCL: IsI2cPad<PadNum = Pad1, Sercom = S>,
133    (SDA, SCL): ShareIoSet,
134{
135    type Sercom = S;
136    type Sda = SDA;
137    type Scl = SCL;
138}