use core::marker::PhantomData;
use atsamd_hal_macros::{hal_cfg, hal_docs, hal_macro_helper, hal_module};
use bitflags::bitflags;
use num_traits::AsPrimitive;
use crate::ehal;
pub use crate::ehal::spi::{MODE_0, MODE_1, MODE_2, MODE_3, Phase, Polarity};
use crate::sercom::{ApbClkCtrl, Sercom, pad::SomePad};
use crate::time::Hertz;
use crate::typelevel::{Is, NoneT, Sealed};
mod reg;
use reg::Registers;
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
use crate::pac::sercom0::spi::ctrla::Modeselect;
#[hal_cfg("sercom0-d5x")]
use crate::pac::sercom0::spim::ctrla::Modeselect;
#[hal_module(
any("sercom0-d11", "sercom0-d21") => "spi/pads_thumbv6m.rs",
"sercom0-d5x" => "spi/pads_thumbv7em.rs",
)]
pub mod pads {}
pub use pads::*;
#[hal_module(
any("sercom0-d11", "sercom0-d21") => "spi/char_size.rs",
"sercom0-d5x" => "spi/length.rs",
)]
pub mod size {}
#[cfg(doc)]
#[hal_cfg(not(any("sercom0-d11", "sercom0-d21")))]
pub enum NineBit {}
#[cfg(doc)]
#[hal_cfg(not(any("sercom0-d11", "sercom0-d21")))]
pub enum EightBit {}
#[cfg(doc)]
#[hal_cfg(not(any("sercom0-d11", "sercom0-d21")))]
pub trait CharSize {
type Word;
}
#[cfg(doc)]
#[hal_cfg(not("sercom0-d5x"))]
pub trait Length {}
pub use size::*;
#[hal_cfg("sercom0-d5x")]
pub mod lengths {
seq_macro::seq!(N in 1..=255 {
pub use typenum::U~N;
});
}
pub mod impl_ehal;
#[cfg(feature = "async")]
mod async_api;
#[cfg(feature = "async")]
pub use async_api::*;
#[repr(u8)]
#[derive(Copy, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum BitOrder {
LsbFirst,
MsbFirst,
}
const DRE: u8 = 0x01;
const TXC: u8 = 0x02;
const RXC: u8 = 0x04;
const SSL: u8 = 0x08;
const ERROR: u8 = 0x80;
pub const RX_FLAG_MASK: u8 = RXC | ERROR;
pub const TX_FLAG_MASK: u8 = DRE | TXC;
bitflags! {
#[derive(Clone, Copy)]
pub struct Flags: u8 {
const DRE = DRE;
const TXC = TXC;
const RXC = RXC;
const SSL = SSL;
const ERROR = ERROR;
}
}
#[allow(dead_code)]
impl Flags {
pub(super) const RX: Self = Self::from_bits_retain(RX_FLAG_MASK);
pub(super) const TX: Self = Self::from_bits_retain(TX_FLAG_MASK);
}
bitflags! {
#[derive(Clone, Copy)]
pub struct Status: u16 {
const BUFOVF = 0x0004;
const LENERR = 0x0800;
}
}
impl Status {
pub fn check_bus_error(self) -> Result<(), Error> {
if self.contains(Status::BUFOVF) {
Err(Error::Overflow)
} else if self.contains(Status::LENERR) {
Err(Error::LengthError)
} else {
Ok(())
}
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Error {
Overflow,
LengthError,
#[cfg(feature = "dma")]
Dma(crate::dmac::Error),
}
pub trait OpMode: Sealed {
const MODE: Modeselect;
const MSSEN: bool;
}
pub enum Master {}
pub enum MasterHWSS {}
pub enum Slave {}
impl Sealed for Master {}
impl Sealed for MasterHWSS {}
impl Sealed for Slave {}
impl OpMode for Master {
const MODE: Modeselect = Modeselect::SpiMaster;
const MSSEN: bool = false;
}
impl OpMode for MasterHWSS {
const MODE: Modeselect = Modeselect::SpiMaster;
const MSSEN: bool = true;
}
impl OpMode for Slave {
const MODE: Modeselect = Modeselect::SpiSlave;
const MSSEN: bool = false;
}
pub trait MasterMode: OpMode {}
impl MasterMode for Master {}
impl MasterMode for MasterHWSS {}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
pub type DataWidth = u16;
#[hal_cfg("sercom0-d5x")]
pub type DataWidth = u32;
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
pub trait Size: CharSize {}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
impl<C: CharSize> Size for C {}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
pub type DefaultSize = EightBit;
#[hal_cfg("sercom0-d5x")]
pub trait Size: Length {}
#[hal_cfg("sercom0-d5x")]
impl<L: Length> Size for L {}
#[hal_cfg("sercom0-d5x")]
pub type DefaultSize = typenum::U1;
pub trait AtomicSize: Size {}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
impl<C: CharSize> AtomicSize for C {}
#[hal_cfg("sercom0-d5x")]
seq_macro::seq!(N in 1..=4 {
impl AtomicSize for lengths::U~N {}
});
pub trait Capability: Sealed + Default {
const RX_ENABLE: bool;
}
pub trait Receive: Capability {}
pub trait Transmit: Capability {}
#[derive(Default)]
pub struct Rx {
pub(super) in_progress: bool,
}
impl Sealed for Rx {}
impl Capability for Rx {
const RX_ENABLE: bool = true;
}
impl Receive for Rx {}
#[derive(Default)]
pub struct Tx;
impl Sealed for Tx {}
impl Capability for Tx {
const RX_ENABLE: bool = false;
}
impl Transmit for Tx {}
#[derive(Default)]
pub struct Duplex;
impl Sealed for Duplex {}
impl Capability for Duplex {
const RX_ENABLE: bool = true;
}
impl Receive for Duplex {}
impl Transmit for Duplex {}
pub struct Config<P, M = Master, Z = DefaultSize>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
regs: Registers<P::Sercom>,
pads: P,
mode: PhantomData<M>,
size: PhantomData<Z>,
freq: Hertz,
nop_word: DataWidth,
}
impl<P: ValidPads> Config<P> {
#[inline]
#[hal_macro_helper]
fn default(sercom: P::Sercom, pads: P, freq: impl Into<Hertz>) -> Self {
let mut regs = Registers { sercom };
regs.reset();
regs.set_op_mode(Master::MODE, Master::MSSEN);
regs.set_dipo_dopo(P::DIPO_DOPO);
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
regs.set_char_size(EightBit::BITS);
#[hal_cfg("sercom0-d5x")]
regs.set_length(1);
Self {
regs,
pads,
mode: PhantomData,
size: PhantomData,
freq: freq.into(),
nop_word: 0x00.as_(),
}
}
#[hal_docs(
{
/// Create a new [`Config`] in the default configuration
///
/// This function will enable the corresponding APB clock, reset the
/// [`Sercom`] peripheral, and return a [`Config`] in the default
/// configuration. The default [`OpMode`] is [`Master`], while the default
/// [`Size`] is an
}
any("sercom0-d11", "sercom0-d21") => {
/// [`EightBit`] [`CharSize`]
}
"sercom0-d5x" => {
/// `EightBit` `CharSize`
}
{
/// for SAMD11 and SAMD21 chips or a
}
any("sercom0-d11", "sercom0-d21") => {
/// `Length` of `U1`
}
"sercom0-d5x" => {
/// [`Length`] of `U1`
}
{
/// for SAMx5x chips. Note that [`Config`] takes ownership of both the
/// PAC [`Sercom`] struct as well as the [`Pads`].
///
/// Users must configure GCLK manually. The `freq` parameter represents the
/// GCLK frequency for this [`Sercom`] instance.
}
)]
#[inline]
pub fn new(
apb_clk_ctrl: &ApbClkCtrl,
mut sercom: P::Sercom,
pads: P,
freq: impl Into<Hertz>,
) -> Self {
sercom.enable_apb_clock(apb_clk_ctrl);
Self::default(sercom, pads, freq)
}
}
impl<P, M, Z> Config<P, M, Z>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
#[inline]
fn change<M2, Z2>(self) -> Config<P, M2, Z2>
where
M2: OpMode,
Z2: Size,
{
Config {
regs: self.regs,
pads: self.pads,
mode: PhantomData,
size: PhantomData,
freq: self.freq,
nop_word: self.nop_word,
}
}
#[inline]
pub unsafe fn sercom(&self) -> &P::Sercom {
&self.regs.sercom
}
#[inline]
pub fn reset(self) -> Config<P> {
Config::default(self.regs.sercom, self.pads, self.freq)
}
#[inline]
pub fn free(mut self) -> (P::Sercom, P) {
self.regs.reset();
(self.regs.sercom, self.pads)
}
#[inline]
pub fn op_mode<M2: OpMode>(mut self) -> Config<P, M2, Z> {
self.regs.set_op_mode(M2::MODE, M2::MSSEN);
self.change()
}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
#[inline]
pub fn char_size<C2: CharSize>(mut self) -> Config<P, M, C2> {
self.regs.set_char_size(C2::BITS);
self.change()
}
#[hal_cfg("sercom0-d5x")]
#[inline]
pub fn length<L2: Length>(mut self) -> Config<P, M, L2> {
self.regs.set_length(L2::U8);
self.change()
}
#[inline]
pub fn get_cpol(&self) -> Polarity {
self.regs.get_cpol()
}
#[inline]
pub fn set_cpol(&mut self, cpol: Polarity) {
self.regs.set_cpol(cpol);
}
#[inline]
pub fn cpol(mut self, cpol: Polarity) -> Self {
self.set_cpol(cpol);
self
}
#[inline]
pub fn get_cpha(&self) -> Phase {
self.regs.get_cpha()
}
#[inline]
pub fn set_cpha(&mut self, cpha: Phase) {
self.regs.set_cpha(cpha)
}
#[inline]
pub fn cpha(mut self, cpha: Phase) -> Self {
self.set_cpha(cpha);
self
}
#[inline]
pub fn get_spi_mode(&self) -> ehal::spi::Mode {
self.regs.get_spi_mode()
}
#[inline]
pub fn set_spi_mode(&mut self, mode: ehal::spi::Mode) {
self.regs.set_spi_mode(mode);
}
#[inline]
pub fn spi_mode(mut self, mode: ehal::spi::Mode) -> Self {
self.set_spi_mode(mode);
self
}
#[inline]
pub fn get_bit_order(&self) -> BitOrder {
self.regs.get_bit_order()
}
#[inline]
pub fn set_bit_order(&mut self, order: BitOrder) {
self.regs.set_bit_order(order);
}
#[inline]
pub fn bit_order(mut self, order: BitOrder) -> Self {
self.set_bit_order(order);
self
}
pub fn get_nop_word(&self) -> DataWidth {
self.nop_word
}
pub fn set_nop_word(&mut self, nop_word: DataWidth) {
self.nop_word = nop_word;
}
pub fn nop_word(mut self, nop_word: DataWidth) -> Self {
self.nop_word = nop_word;
self
}
#[inline]
pub fn get_baud(&mut self) -> Hertz {
self.regs.get_baud(self.freq)
}
#[inline]
pub fn set_baud(&mut self, baud: Hertz) {
self.regs.set_baud(self.freq, baud);
}
#[inline]
pub fn baud(mut self, baud: Hertz) -> Self {
self.set_baud(baud);
self
}
#[inline]
pub fn get_ibon(&self) -> bool {
self.regs.get_ibon()
}
#[inline]
pub fn set_ibon(&mut self, enabled: bool) {
self.regs.set_ibon(enabled);
}
#[inline]
pub fn ibon(mut self, enabled: bool) -> Self {
self.set_ibon(enabled);
self
}
#[inline]
pub fn get_run_in_standby(&self) -> bool {
self.regs.get_run_in_standby()
}
#[inline]
pub fn set_run_in_standby(&mut self, enabled: bool) {
self.regs.set_run_in_standby(enabled);
}
#[inline]
pub fn run_in_standby(mut self, enabled: bool) -> Self {
self.set_run_in_standby(enabled);
self
}
#[inline]
pub fn enable(mut self) -> Spi<Self, P::Capability>
where
Self: ValidConfig,
{
if P::Capability::RX_ENABLE {
self.regs.rx_enable();
}
self.regs.enable();
Spi {
config: self,
capability: P::Capability::default(),
_rx_channel: NoneT,
_tx_channel: NoneT,
}
}
}
#[hal_cfg("sercom0-d5x")]
impl<P, M> Config<P, M, DynLength>
where
P: ValidPads,
M: OpMode,
{
#[inline]
pub fn get_dyn_length(&self) -> u8 {
self.regs.get_length()
}
#[inline]
pub fn set_dyn_length(&mut self, length: u8) {
self.regs.set_length(length);
}
#[inline]
pub fn dyn_length(mut self, length: u8) -> Self {
self.set_dyn_length(length);
self
}
}
pub trait AnyConfig: Is<Type = SpecificConfig<Self>> {
type Sercom: Sercom;
type Pads: ValidPads<Sercom = Self::Sercom>;
type Capability: Capability;
type OpMode: OpMode;
type Size: Size;
type Word: 'static;
}
pub type SpecificConfig<C> =
Config<<C as AnyConfig>::Pads, <C as AnyConfig>::OpMode, <C as AnyConfig>::Size>;
impl<P, M, Z> Sealed for Config<P, M, Z>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
}
impl<P, M, Z> AnyConfig for Config<P, M, Z>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
type Sercom = P::Sercom;
type Pads = P;
type Capability = P::Capability;
type OpMode = M;
type Size = Z;
type Word = Z::Word;
}
impl<P, M, Z> AsRef<Self> for Config<P, M, Z>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<P, M, Z> AsMut<Self> for Config<P, M, Z>
where
P: ValidPads,
M: OpMode,
Z: Size,
{
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
pub trait ValidConfig: AnyConfig {}
impl<P, Z> ValidConfig for Config<P, Master, Z>
where
P: ValidPads<SS = NoneT>,
Z: Size,
{
}
impl<P, Z> ValidConfig for Config<P, MasterHWSS, Z>
where
P: ValidPads,
Z: Size,
P::SS: SomePad,
{
}
impl<P, Z> ValidConfig for Config<P, Slave, Z>
where
P: ValidPads,
Z: Size,
P::SS: SomePad,
{
}
pub struct Spi<C, A, RxDma = NoneT, TxDma = NoneT>
where
C: ValidConfig,
A: Capability,
{
config: C,
capability: A,
_rx_channel: RxDma,
_tx_channel: TxDma,
}
impl<C, A> AsRef<SpecificConfig<C>> for Spi<C, A>
where
C: ValidConfig,
A: Capability,
{
#[inline]
fn as_ref(&self) -> &SpecificConfig<C> {
self.config.as_ref()
}
}
impl<C, A, RxDma, TxDma> Spi<C, A, RxDma, TxDma>
where
C: ValidConfig,
A: Capability,
{
#[inline]
#[allow(clippy::type_complexity)]
#[hal_cfg("sercom0-d5x")]
pub fn length<L: Length>(self) -> Spi<Config<C::Pads, C::OpMode, L>, A, RxDma, TxDma>
where
Config<C::Pads, C::OpMode, L>: ValidConfig,
{
Spi {
config: self.config.into().length(),
capability: self.capability,
_rx_channel: self._rx_channel,
_tx_channel: self._tx_channel,
}
}
#[inline]
pub fn reconfigure(&mut self, update: impl FnOnce(&mut SpecificConfig<C>)) {
self.config.as_mut().regs.disable();
update(self.config.as_mut());
self.config.as_mut().regs.enable();
}
#[inline]
pub fn enable_interrupts(&mut self, flags: Flags) {
self.config.as_mut().regs.enable_interrupts(flags)
}
#[inline]
pub fn disable_interrupts(&mut self, flags: Flags) {
self.config.as_mut().regs.disable_interrupts(flags);
}
#[inline]
pub fn read_flags(&self) -> Flags {
self.config.as_ref().regs.read_flags()
}
#[inline]
pub fn clear_flags(&mut self, flags: Flags) {
self.config.as_mut().regs.clear_flags(flags);
}
#[inline]
pub fn read_status(&self) -> Status {
self.config.as_ref().regs.read_status()
}
#[inline]
pub fn clear_status(&mut self, status: Status) {
self.config.as_mut().regs.clear_status(status);
}
#[inline]
pub fn read_flags_errors(&self) -> Result<Flags, Error> {
self.config.as_ref().regs.read_flags_errors()
}
#[inline]
pub unsafe fn read_data(&mut self) -> DataWidth {
self.config.as_mut().regs.read_data()
}
#[inline]
pub unsafe fn write_data(&mut self, data: DataWidth) {
self.config.as_mut().regs.write_data(data);
}
#[inline]
pub fn disable(mut self) -> C {
self.config.as_mut().regs.rx_disable();
self.config.as_mut().regs.disable();
self.config
}
fn block_on_flags(&mut self, flags: Flags) -> Result<(), Error> {
while !self.read_flags().intersects(flags | Flags::ERROR) {
core::hint::spin_loop();
}
let flags = self.read_flags();
self.check_and_clear_error(flags)
}
#[inline]
fn check_and_clear_error(&mut self, flags: Flags) -> Result<(), Error> {
if flags.contains(Flags::ERROR) {
let errors = self.read_status();
self.clear_status(errors);
self.clear_flags(Flags::ERROR);
return errors.check_bus_error();
}
Ok(())
}
}
impl<C, D> Spi<C, D>
where
C: ValidConfig,
D: Receive,
C::OpMode: MasterMode,
{
#[cfg(feature = "dma")]
pub fn with_dma_channels<R, T>(self, rx: R, tx: T) -> Spi<C, D, R, T>
where
R: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
T: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
{
Spi {
capability: self.capability,
config: self.config,
_rx_channel: rx,
_tx_channel: tx,
}
}
}
impl<C> Spi<C, Duplex>
where
C: ValidConfig<OpMode = Slave>,
{
#[cfg(feature = "dma")]
pub fn with_dma_channels_slave<R, T>(self, rx: R, tx: T) -> Spi<C, Duplex, R, T>
where
R: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
T: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
{
Spi {
capability: self.capability,
config: self.config,
_rx_channel: rx,
_tx_channel: tx,
}
}
}
#[cfg(feature = "dma")]
impl<C, T> Spi<C, Rx, NoneT, T>
where
C: ValidConfig<OpMode = Slave>,
{
#[cfg(feature = "dma")]
pub fn with_rx_channel<R>(self, rx: R) -> Spi<C, Rx, R, T>
where
R: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
{
Spi {
capability: self.capability,
config: self.config,
_rx_channel: rx,
_tx_channel: self._tx_channel,
}
}
}
#[cfg(feature = "dma")]
impl<C, R> Spi<C, Tx, R, NoneT>
where
C: ValidConfig,
{
#[cfg(feature = "dma")]
pub fn with_tx_channel<T>(self, tx: T) -> Spi<C, Tx, R, T>
where
T: crate::dmac::AnyChannel<Status = crate::dmac::Ready>,
{
Spi {
capability: self.capability,
config: self.config,
_rx_channel: self._rx_channel,
_tx_channel: tx,
}
}
}
#[cfg(feature = "dma")]
impl<C, D, R, T> Spi<C, D, R, T>
where
C: ValidConfig,
D: Capability,
{
pub fn take_dma_channels(self) -> (Spi<C, D, NoneT, NoneT>, R, T)
where
R: crate::dmac::AnyChannel<Status: crate::dmac::ReadyChannel>,
T: crate::dmac::AnyChannel<Status: crate::dmac::ReadyChannel>,
{
(
Spi {
capability: self.capability,
config: self.config,
_rx_channel: NoneT,
_tx_channel: NoneT,
},
self._rx_channel,
self._tx_channel,
)
}
pub fn take_rx_channel(self) -> (Spi<C, D, NoneT, T>, R)
where
R: crate::dmac::AnyChannel<Status: crate::dmac::ReadyChannel>,
{
(
Spi {
capability: self.capability,
config: self.config,
_tx_channel: self._tx_channel,
_rx_channel: NoneT,
},
self._rx_channel,
)
}
pub fn take_tx_channel(self) -> (Spi<C, D, R, NoneT>, T)
where
T: crate::dmac::AnyChannel<Status: crate::dmac::ReadyChannel>,
{
(
Spi {
capability: self.capability,
config: self.config,
_rx_channel: self._rx_channel,
_tx_channel: NoneT,
},
self._tx_channel,
)
}
}
pub struct PanicOnWrite<T: crate::ehal::spi::ErrorType>(T);
impl<C: ValidConfig, R, T> From<PanicOnWrite<Spi<C, Rx, R, T>>> for Spi<C, Rx, R, T> {
fn from(value: PanicOnWrite<Spi<C, Rx, R, T>>) -> Self {
value.0
}
}
impl<C: ValidConfig, R, T> AsRef<Spi<C, Rx, R, T>> for PanicOnWrite<Spi<C, Rx, R, T>> {
fn as_ref(&self) -> &Spi<C, Rx, R, T> {
&self.0
}
}
impl<C: ValidConfig, R, T> AsMut<Spi<C, Rx, R, T>> for PanicOnWrite<Spi<C, Rx, R, T>> {
fn as_mut(&mut self) -> &mut Spi<C, Rx, R, T> {
&mut self.0
}
}
impl<C: ValidConfig, R, T> Spi<C, Tx, R, T> {
pub fn into_panic_on_write(self) -> PanicOnWrite<Self> {
PanicOnWrite(self)
}
}
pub struct PanicOnRead<T: crate::ehal::spi::ErrorType>(T);
impl<C: ValidConfig, R, T> From<PanicOnRead<Spi<C, Tx, R, T>>> for Spi<C, Tx, R, T> {
fn from(value: PanicOnRead<Spi<C, Tx, R, T>>) -> Self {
value.0
}
}
impl<C: ValidConfig, R, T> AsRef<Spi<C, Tx, R, T>> for PanicOnRead<Spi<C, Tx, R, T>> {
fn as_ref(&self) -> &Spi<C, Tx, R, T> {
&self.0
}
}
impl<C: ValidConfig, R, T> AsMut<Spi<C, Tx, R, T>> for PanicOnRead<Spi<C, Tx, R, T>> {
fn as_mut(&mut self) -> &mut Spi<C, Tx, R, T> {
&mut self.0
}
}
impl<C: ValidConfig, R, T> Spi<C, Tx, R, T> {
pub fn into_panic_on_read(self) -> PanicOnRead<Self> {
PanicOnRead(self)
}
}
#[hal_cfg("sercom0-d5x")]
impl<P, M, A> Spi<Config<P, M, DynLength>, A>
where
P: ValidPads,
M: OpMode,
Config<P, M, DynLength>: ValidConfig,
A: Capability,
{
#[inline]
pub fn get_dyn_length(&self) -> u8 {
self.config.get_dyn_length()
}
#[inline]
pub fn set_dyn_length(&mut self, length: u8) {
self.config.set_dyn_length(length);
}
}
#[cfg(doc)]
#[hal_cfg(not("sercom0-d5x"))]
impl<C: ValidConfig, R, T> Spi<C, Tx, R, T> {
pub fn get_dyn_length(&self) -> u8 {
unimplemented!()
}
}
pub trait AnySpi: Is<Type = SpecificSpi<Self>> {
type Sercom: Sercom;
type Pads: ValidPads;
type Capability: Capability;
type OpMode: OpMode;
type Size: Size;
type Word: 'static;
type Config: ValidConfig<Sercom = Self::Sercom>;
}
pub type SpecificSpi<S> = Spi<<S as AnySpi>::Config, <S as AnySpi>::Capability>;
impl<C, A> AsRef<Self> for Spi<C, A>
where
C: ValidConfig,
A: Capability,
{
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<C, A> AsMut<Self> for Spi<C, A>
where
C: ValidConfig,
A: Capability,
{
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<C, A> Sealed for Spi<C, A>
where
C: ValidConfig,
A: Capability,
{
}
impl<C, A> AnySpi for Spi<C, A>
where
C: ValidConfig,
A: Capability,
{
type Sercom = C::Sercom;
type Pads = C::Pads;
type Capability = A;
type OpMode = C::OpMode;
type Size = C::Size;
type Word = C::Word;
type Config = C;
}