use core::marker::PhantomData;
use crate::pac;
use crate::rcu::{Enable, Rcu};
pub struct B32;
pub struct B16;
pub struct B8;
pub struct B7;
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ReverseInput {
Disabled = 0b00,
Byte = 0b01,
HalfWord = 0b10,
Word = 0b11,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum ReverseOutput {
Disabled = 0,
Enabled = 1,
}
#[derive(Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[must_use]
pub struct CrcConfig {
reverse_input: ReverseInput,
reverse_output: ReverseOutput,
}
impl CrcConfig {
pub const fn new(reverse_input: ReverseInput, reverse_output: ReverseOutput) -> Self {
Self {
reverse_input,
reverse_output,
}
}
}
impl Default for CrcConfig {
fn default() -> Self {
Self {
reverse_input: ReverseInput::Disabled,
reverse_output: ReverseOutput::Disabled,
}
}
}
fn configure(crc: &pac::Crc, ps: u8, poly: u32, config: CrcConfig) {
let rev_o = matches!(config.reverse_output, ReverseOutput::Enabled);
crc.ctl().modify(|_, w| {
unsafe { w.ps().bits(ps) };
w.rev_o()
.bit(rev_o)
.rev_i()
.bits(config.reverse_input as u8)
});
crc.poly().write(|w| unsafe { w.bits(poly) });
}
fn new_seed(crc: &pac::Crc, idata: u32) {
crc.idata().write(|w| w.idata().bits(idata));
crc.ctl().modify(|_, w| w.rst().reset());
}
pub struct Crc<PS> {
crc: pac::Crc,
_poly_size: PhantomData<PS>,
}
impl Crc<B32> {
pub fn new_32bit(rcu: &mut Rcu, crc: pac::Crc, poly: u32, config: CrcConfig) -> Self {
<pac::Crc as Enable>::enable(rcu);
configure(&crc, 0b00, poly, config);
Self {
crc,
_poly_size: PhantomData,
}
}
pub fn write_32bit(&mut self, data: u32) {
let data_reg = self.crc.data().as_ptr();
unsafe { data_reg.write_volatile(data) };
}
pub fn read_32bit(&self) -> u32 {
self.read()
}
pub fn reset_with(&mut self, seed: u32) {
new_seed(&self.crc, seed);
}
}
impl Crc<B16> {
pub fn new_16bit(rcu: &mut Rcu, crc: pac::Crc, poly: u16, config: CrcConfig) -> Self {
<pac::Crc as Enable>::enable(rcu);
configure(&crc, 0b01, poly as u32, config);
Self {
crc,
_poly_size: PhantomData,
}
}
pub fn write_16bit(&mut self, data: u16) {
let data_reg = self.crc.data().as_ptr().cast::<u16>();
unsafe { data_reg.write_volatile(data) };
}
pub fn read_16bit(&self) -> u16 {
self.read() as u16
}
pub fn reset_with(&mut self, seed: u16) {
new_seed(&self.crc, seed as u32);
}
}
impl Crc<B8> {
pub fn new_8bit(rcu: &mut Rcu, crc: pac::Crc, poly: u8, config: CrcConfig) -> Self {
<pac::Crc as Enable>::enable(rcu);
configure(&crc, 0b10, poly as u32, config);
Self {
crc,
_poly_size: PhantomData,
}
}
pub fn write_8bit(&mut self, data: u8) {
let data_reg = self.crc.data().as_ptr().cast::<u8>();
unsafe { data_reg.write_volatile(data) };
}
pub fn read_8bit(&self) -> u8 {
self.read() as u8
}
pub fn reset_with(&mut self, seed: u8) {
new_seed(&self.crc, seed as u32);
}
}
impl Crc<B7> {
pub fn new_7bit(rcu: &mut Rcu, crc: pac::Crc, poly: u8, config: CrcConfig) -> Self {
<pac::Crc as Enable>::enable(rcu);
configure(&crc, 0b11, poly as u32, config);
Self {
crc,
_poly_size: PhantomData,
}
}
pub fn write_7bit(&mut self, data: u8) {
let data_reg = self.crc.data().as_ptr().cast::<u8>();
unsafe { data_reg.write_volatile(data) };
}
pub fn read_7bit(&self) -> u8 {
self.read() as u8
}
pub fn reset_with(&mut self, seed: u8) {
new_seed(&self.crc, seed as u32);
}
}
impl<PS> Crc<PS> {
pub fn read(&self) -> u32 {
self.crc.data().read().data().bits()
}
pub fn release(self, rcu: &mut Rcu) -> pac::Crc {
<pac::Crc as Enable>::disable(rcu);
self.crc
}
pub fn set_fdata(&mut self, fdata: u8) {
self.crc.fdata().write(|w| w.fdata().bits(fdata));
}
pub fn fdata(&self) -> u8 {
self.crc.fdata().read().fdata().bits()
}
}