use atsamd_hal_macros::hal_cfg;
use core::ops::Deref;
use crate::pac;
use pac::Peripherals;
use pac::sercom0;
#[hal_cfg("sercom0-d5x")]
use pac::Mclk as ApbClkCtrl;
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
use pac::Pm as ApbClkCtrl;
#[cfg(feature = "dma")]
use crate::dmac::TriggerSource;
use crate::typelevel::Sealed;
pub mod pad;
pub use pad::*;
pub mod i2c;
pub mod spi;
pub mod uart;
#[cfg(feature = "dma")]
pub mod dma;
pub trait Sercom: Sealed + Deref<Target = sercom0::RegisterBlock> {
const NUM: usize;
#[cfg(feature = "dma")]
const DMA_RX_TRIGGER: TriggerSource;
#[cfg(feature = "dma")]
const DMA_TX_TRIGGER: TriggerSource;
#[cfg(feature = "async")]
type Interrupt: crate::async_hal::interrupts::InterruptSource;
fn enable_apb_clock(&mut self, ctrl: &ApbClkCtrl);
fn reg_block(peripherals: &mut Peripherals) -> &crate::pac::sercom0::RegisterBlock;
#[cfg(feature = "async")]
#[inline]
fn rx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
&crate::sercom::async_api::RX_WAKERS[Self::NUM]
}
#[cfg(feature = "async")]
#[inline]
fn tx_waker() -> &'static embassy_sync::waitqueue::AtomicWaker {
&crate::sercom::async_api::TX_WAKERS[Self::NUM]
}
}
macro_rules! sercom {
( $apbmask:ident, $N:expr) => {
paste::paste! {
pub type [< Sercom $N >] = $crate::pac::[< Sercom $N >];
impl Sealed for [< Sercom $N >] {}
impl Sercom for [< Sercom $N >] {
const NUM: usize = $N;
#[cfg(feature = "dma")]
const DMA_RX_TRIGGER: TriggerSource = TriggerSource::[< Sercom $N Rx >];
#[cfg(feature = "dma")]
const DMA_TX_TRIGGER: TriggerSource = TriggerSource::[< Sercom $N Tx >];
#[cfg(feature = "async")]
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
type Interrupt = $crate::async_hal::interrupts::[< SERCOM $N >];
#[cfg(feature = "async")]
#[hal_cfg("sercom0-d5x")]
type Interrupt = $crate::async_hal::interrupts::[< SERCOM $N >];
#[inline]
fn enable_apb_clock(&mut self, ctrl: &ApbClkCtrl) {
ctrl.$apbmask().modify(|_, w| w.[< sercom $N _>]().set_bit());
}
#[inline]
fn reg_block(peripherals: &mut Peripherals) -> &crate::pac::sercom0::RegisterBlock {
&*peripherals.[< sercom $N >]
}
}
}
};
}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
sercom!(apbcmask, 0);
#[hal_cfg(any("sercom1-d11", "sercom1-d21"))]
sercom!(apbcmask, 1);
#[hal_cfg(any("sercom2-d11", "sercom2-d21"))]
sercom!(apbcmask, 2);
#[hal_cfg("sercom3-d21")]
sercom!(apbcmask, 3);
#[hal_cfg("sercom4-d21")]
sercom!(apbcmask, 4);
#[hal_cfg("sercom5-d21")]
sercom!(apbcmask, 5);
#[hal_cfg("sercom0-d5x")]
sercom!(apbamask, 0);
#[hal_cfg("sercom1-d5x")]
sercom!(apbamask, 1);
#[hal_cfg("sercom2-d5x")]
sercom!(apbbmask, 2);
#[hal_cfg("sercom3-d5x")]
sercom!(apbbmask, 3);
#[hal_cfg("sercom4-d5x")]
sercom!(apbdmask, 4);
#[hal_cfg("sercom5-d5x")]
sercom!(apbdmask, 5);
#[hal_cfg("sercom6-d5x")]
sercom!(apbdmask, 6);
#[hal_cfg("sercom7-d5x")]
sercom!(apbdmask, 7);
#[hal_cfg("sercom0-d11")]
#[cfg(feature = "async")]
const NUM_SERCOM: usize = 3;
#[hal_cfg("sercom0-d21")]
#[cfg(feature = "async")]
const NUM_SERCOM: usize = 6;
#[hal_cfg("sercom0-d5x")]
#[cfg(feature = "async")]
const NUM_SERCOM: usize = 8;
#[cfg(feature = "async")]
pub(super) mod async_api {
use embassy_sync::waitqueue::AtomicWaker;
#[allow(clippy::declare_interior_mutable_const)]
const NEW_WAKER: AtomicWaker = AtomicWaker::new();
pub(super) static RX_WAKERS: [AtomicWaker; super::NUM_SERCOM] = [NEW_WAKER; super::NUM_SERCOM];
pub(super) static TX_WAKERS: [AtomicWaker; super::NUM_SERCOM] = [NEW_WAKER; super::NUM_SERCOM];
}