use super::{I2c, InactiveTimeout, PadSet, Registers};
use crate::{
pac::sercom0::i2cm::ctrla::Modeselect,
sercom::{ApbClkCtrl, Sercom},
time::Hertz,
typelevel::{Is, NoneT, Sealed},
};
pub struct Config<P>
where
P: PadSet,
{
pub(in super::super) registers: Registers<P::Sercom>,
pads: P,
freq: Hertz,
}
impl<P: PadSet> Config<P> {
#[inline]
fn default(sercom: P::Sercom, pads: P, freq: impl Into<Hertz>) -> Self {
let mut registers = Registers::new(sercom);
registers.swrst();
registers.set_op_mode(Modeselect::I2cMaster);
Self {
registers,
pads,
freq: freq.into(),
}
}
#[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: PadSet> Config<P> {
#[inline]
pub unsafe fn sercom(&self) -> &P::Sercom {
&self.registers.sercom
}
#[inline]
pub fn reset(self) -> Config<P> {
Config::default(self.registers.sercom, self.pads, self.freq)
}
#[inline]
pub fn free(mut self) -> (P::Sercom, P) {
self.registers.swrst();
(self.registers.free(), self.pads)
}
#[inline]
pub fn run_in_standby(mut self, set: bool) -> Self {
self.set_run_in_standby(set);
self
}
#[inline]
pub fn set_run_in_standby(&mut self, set: bool) {
self.registers.set_run_in_standby(set);
}
#[inline]
pub fn get_run_in_standby(&self) -> bool {
self.registers.get_run_in_standby()
}
#[inline]
pub fn baud(mut self, baud: impl Into<Hertz>) -> Self {
self.set_baud(baud);
self
}
#[inline]
pub fn set_baud(&mut self, baud: impl Into<Hertz>) {
self.registers.set_baud(self.freq, baud);
}
#[inline]
pub fn get_baud(&self) -> u32 {
self.registers.get_baud()
}
#[inline]
pub fn low_timeout(mut self, set: bool) -> Self {
self.set_low_timeout(set);
self
}
#[inline]
pub fn set_low_timeout(&mut self, set: bool) {
self.registers.set_low_timeout(set);
}
#[inline]
pub fn get_low_timeout(&mut self) -> bool {
self.registers.get_low_timeout()
}
#[inline]
pub fn inactive_timeout(mut self, timeout: super::InactiveTimeout) -> Self {
self.set_inactive_timeout(timeout);
self
}
#[inline]
pub fn set_inactive_timeout(&mut self, timeout: super::InactiveTimeout) {
self.registers.set_inactive_timeout(timeout);
}
#[inline]
pub fn get_inactive_timeout(&mut self) -> InactiveTimeout {
self.registers.get_inactive_timeout()
}
#[inline]
pub fn enable(mut self) -> I2c<Self>
where
Self: AnyConfig,
{
self.registers.enable();
I2c {
config: self,
_dma_channel: NoneT,
}
}
}
pub trait AnyConfig: Is<Type = SpecificConfig<Self>> {
type Sercom: Sercom;
type Pads: PadSet<Sercom = Self::Sercom>;
}
pub type SpecificConfig<C> = Config<<C as AnyConfig>::Pads>;
pub type ConfigSercom<C> = <C as AnyConfig>::Sercom;
impl<P: PadSet> Sealed for Config<P> {}
impl<P: PadSet> AnyConfig for Config<P> {
type Sercom = P::Sercom;
type Pads = P;
}
impl<P: PadSet> AsRef<Self> for Config<P> {
#[inline]
fn as_ref(&self) -> &Self {
self
}
}
impl<P: PadSet> AsMut<Self> for Config<P> {
#[inline]
fn as_mut(&mut self) -> &mut Self {
self
}
}