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}