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}