atsamd_hal/sercom/spi/
reg.rs
use atsamd_hal_macros::{hal_cfg, hal_macro_helper};
use crate::ehal;
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
use crate::pac::sercom0::Spi;
#[hal_cfg("sercom0-d5x")]
use crate::pac::sercom0::Spim;
#[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;
use crate::sercom::Sercom;
use crate::time::Hertz;
use super::{BitOrder, DataWidth, Error, Flags, Phase, Polarity, Status};
pub(super) struct Registers<S: Sercom> {
pub sercom: S,
}
unsafe impl<S: Sercom> Sync for Registers<S> {}
impl<S: Sercom> Registers<S> {
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
#[inline]
pub fn spi(&self) -> &Spi {
self.sercom.spi()
}
#[hal_cfg("sercom0-d5x")]
#[inline]
pub fn spi(&self) -> &Spim {
self.sercom.spim()
}
#[inline]
pub fn reset(&mut self) {
self.spi().ctrla().write(|w| w.swrst().set_bit());
while self.spi().syncbusy().read().swrst().bit_is_set() {}
}
#[cfg(feature = "dma")]
pub fn data_ptr<Z: super::Size>(&self) -> *mut Z::Word {
self.spi().data().as_ptr() as *mut _
}
#[inline]
pub fn set_dipo_dopo(&mut self, dipo_dopo: (u8, u8)) {
let (dipo, dopo) = dipo_dopo;
self.spi().ctrla().modify(|_, w| unsafe {
w.dipo().bits(dipo);
w.dopo().bits(dopo)
});
}
#[inline]
#[hal_macro_helper]
pub fn set_op_mode(&mut self, mode: Modeselect, mssen: bool) {
self.spi().ctrla().modify(|_, w| w.mode().variant(mode));
self.spi().ctrlb().modify(|_, w| w.mssen().bit(mssen));
#[hal_cfg("sercom0-d5x")]
self.spi().ctrlc().write(|w| unsafe {
w.data32b().data_trans_32bit();
w.icspace().bits(1)
});
while self.spi().syncbusy().read().ctrlb().bit_is_set() {}
}
#[hal_cfg("sercom0-d5x")]
#[inline]
pub fn get_length(&self) -> u8 {
self.spi().length().read().len().bits()
}
#[hal_cfg("sercom0-d5x")]
#[inline]
pub fn set_length(&mut self, length: u8) {
let length = if length == 0 { 1 } else { length };
self.spi().length().write(|w| unsafe {
w.len().bits(length);
w.lenen().set_bit()
});
while self.spi().syncbusy().read().length().bit_is_set() {}
}
#[hal_cfg(any("sercom0-d11", "sercom0-d21"))]
#[inline]
pub fn set_char_size(&mut self, bits: u8) {
self.spi()
.ctrlb()
.modify(|_, w| unsafe { w.chsize().bits(bits) });
}
#[inline]
pub fn get_cpol(&self) -> Polarity {
let cpol = self.spi().ctrla().read().cpol().bit();
match cpol {
false => Polarity::IdleLow,
true => Polarity::IdleHigh,
}
}
#[inline]
pub fn set_cpol(&mut self, cpol: Polarity) {
let cpol = match cpol {
Polarity::IdleLow => false,
Polarity::IdleHigh => true,
};
self.spi().ctrla().modify(|_, w| w.cpol().bit(cpol));
}
#[inline]
pub fn get_cpha(&self) -> Phase {
let cpha = self.spi().ctrla().read().cpha().bit();
match cpha {
false => Phase::CaptureOnFirstTransition,
true => Phase::CaptureOnSecondTransition,
}
}
#[inline]
pub fn set_cpha(&mut self, cpha: Phase) {
let cpha = match cpha {
Phase::CaptureOnFirstTransition => false,
Phase::CaptureOnSecondTransition => true,
};
self.spi().ctrla().modify(|_, w| w.cpha().bit(cpha));
}
#[inline]
pub fn get_spi_mode(&self) -> ehal::spi::Mode {
let reg = self.spi().ctrla().read();
let cpol = reg.cpol().bit();
let cpha = reg.cpha().bit();
let polarity = match cpol {
false => Polarity::IdleLow,
true => Polarity::IdleHigh,
};
let phase = match cpha {
false => Phase::CaptureOnFirstTransition,
true => Phase::CaptureOnSecondTransition,
};
ehal::spi::Mode { polarity, phase }
}
#[inline]
pub fn set_spi_mode(&mut self, mode: ehal::spi::Mode) {
let cpol = match mode.polarity {
Polarity::IdleLow => false,
Polarity::IdleHigh => true,
};
let cpha = match mode.phase {
Phase::CaptureOnFirstTransition => false,
Phase::CaptureOnSecondTransition => true,
};
self.spi().ctrla().modify(|_, w| {
w.cpol().bit(cpol);
w.cpha().bit(cpha)
});
}
#[inline]
pub fn get_bit_order(&self) -> BitOrder {
let order = self.spi().ctrla().read().dord().bit();
match order {
false => BitOrder::MsbFirst,
true => BitOrder::LsbFirst,
}
}
#[inline]
pub fn set_bit_order(&mut self, order: BitOrder) {
let order = match order {
BitOrder::MsbFirst => false,
BitOrder::LsbFirst => true,
};
self.spi().ctrla().modify(|_, w| w.dord().bit(order));
}
#[inline]
pub fn get_baud(&mut self, freq: Hertz) -> Hertz {
let baud = self.spi().baud().read().baud().bits() as u32 + 1;
freq / 2 / baud
}
#[inline]
pub fn set_baud(&mut self, freq: Hertz, baud: Hertz) {
let baud = baud.to_Hz().max(1);
let bits = (freq.to_Hz() / 2 / baud).saturating_sub(1);
let bits = bits.try_into().unwrap_or(u8::MAX);
self.spi()
.baud()
.modify(|_, w| unsafe { w.baud().bits(bits) });
}
#[inline]
pub fn get_ibon(&self) -> bool {
self.spi().ctrla().read().ibon().bit()
}
#[inline]
pub fn set_ibon(&mut self, enabled: bool) {
self.spi().ctrla().modify(|_, w| w.ibon().bit(enabled));
}
#[inline]
pub fn get_run_in_standby(&self) -> bool {
self.spi().ctrla().read().runstdby().bit()
}
#[inline]
pub fn set_run_in_standby(&mut self, set: bool) {
self.spi().ctrla().modify(|_, w| w.runstdby().bit(set));
}
#[inline]
pub fn enable_interrupts(&mut self, flags: Flags) {
self.spi()
.intenset()
.write(|w| unsafe { w.bits(flags.bits()) });
}
#[inline]
pub fn disable_interrupts(&mut self, flags: Flags) {
self.spi()
.intenclr()
.write(|w| unsafe { w.bits(flags.bits()) });
}
#[inline]
pub fn rx_enable(&mut self) {
self.spi().ctrlb().modify(|_, w| w.rxen().set_bit());
while self.spi().syncbusy().read().ctrlb().bit_is_set() {}
}
#[inline]
pub fn rx_disable(&mut self) {
self.spi().ctrlb().modify(|_, w| w.rxen().clear_bit());
while self.spi().syncbusy().read().ctrlb().bit_is_set() {}
}
#[inline]
pub fn enable(&mut self) {
self.spi().ctrla().modify(|_, w| w.enable().set_bit());
while self.spi().syncbusy().read().enable().bit_is_set() {}
}
#[inline]
pub fn disable(&mut self) {
self.spi().ctrla().modify(|_, w| w.enable().clear_bit());
while self.spi().syncbusy().read().enable().bit_is_set() {}
}
#[inline]
pub fn read_data(&mut self) -> DataWidth {
self.spi().data().read().data().bits()
}
#[inline]
pub fn write_data(&mut self, data: DataWidth) {
self.spi().data().write(|w| unsafe { w.data().bits(data) })
}
#[inline]
pub fn read_flags(&self) -> Flags {
let bits = self.spi().intflag().read().bits();
Flags::from_bits_truncate(bits)
}
#[inline]
pub fn clear_flags(&mut self, flags: Flags) {
unsafe { self.spi().intflag().write(|w| w.bits(flags.bits())) };
}
#[inline]
pub fn read_status(&self) -> Status {
let bits = self.spi().status().read().bits();
Status::from_bits_truncate(bits)
}
#[inline]
pub fn clear_status(&mut self, status: Status) {
unsafe { self.spi().status().write(|w| w.bits(status.bits())) };
}
#[inline]
pub fn read_flags_errors(&self) -> Result<Flags, Error> {
self.read_status().check_bus_error()?;
Ok(self.read_flags())
}
}