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