use core::marker::PhantomData;
use crate::pac::can::RegisterBlock;
use crate::{ExtendedId, Fifo, FilterOwner, Id, Instance, MasterInstance, StandardId};
const F32_RTR: u32 = 0b010; const F32_IDE: u32 = 0b100; const F16_RTR: u16 = 0b10000;
const F16_IDE: u16 = 0b01000;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub struct ListEntry16(u16);
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub struct ListEntry32(u32);
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub struct Mask16 {
id: u16,
mask: u16,
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub struct Mask32 {
id: u32,
mask: u32,
}
impl ListEntry16 {
pub fn data_frames_with_id(id: StandardId) -> Self {
Self(id.as_raw() << 5)
}
pub fn remote_frames_with_id(id: StandardId) -> Self {
Self(id.as_raw() << 5 | F16_RTR)
}
}
impl ListEntry32 {
pub fn data_frames_with_id(id: impl Into<Id>) -> Self {
match id.into() {
Id::Standard(id) => Self(u32::from(id.as_raw()) << 21),
Id::Extended(id) => Self(id.as_raw() << 3 | F32_IDE),
}
}
pub fn remote_frames_with_id(id: impl Into<Id>) -> Self {
match id.into() {
Id::Standard(id) => Self(u32::from(id.as_raw()) << 21 | F32_RTR),
Id::Extended(id) => Self(id.as_raw() << 3 | F32_IDE | F32_RTR),
}
}
}
impl Mask16 {
pub fn accept_all() -> Self {
Self { id: 0, mask: 0 }
}
pub fn frames_with_std_id(id: StandardId, mask: StandardId) -> Self {
Self {
id: id.as_raw() << 5,
mask: mask.as_raw() << 5 | F16_IDE, }
}
pub fn data_frames_only(&mut self) -> &mut Self {
self.id &= !F16_RTR; self.mask |= F16_RTR;
self
}
pub fn remote_frames_only(&mut self) -> &mut Self {
self.id |= F16_RTR; self.mask |= F16_RTR;
self
}
}
impl Mask32 {
pub fn accept_all() -> Self {
Self { id: 0, mask: 0 }
}
pub fn frames_with_ext_id(id: ExtendedId, mask: ExtendedId) -> Self {
Self {
id: id.as_raw() << 3 | F32_IDE,
mask: mask.as_raw() << 3 | F32_IDE, }
}
pub fn frames_with_std_id(id: StandardId, mask: StandardId) -> Self {
Self {
id: u32::from(id.as_raw()) << 21,
mask: u32::from(mask.as_raw()) << 21 | F32_IDE, }
}
pub fn data_frames_only(&mut self) -> &mut Self {
self.id &= !F32_RTR; self.mask |= F32_RTR;
self
}
pub fn remote_frames_only(&mut self) -> &mut Self {
self.id |= F32_RTR; self.mask |= F32_RTR;
self
}
}
#[derive(Debug, Copy, Clone)]
#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
pub enum BankConfig {
List16([ListEntry16; 4]),
List32([ListEntry32; 2]),
Mask16([Mask16; 2]),
Mask32(Mask32),
}
impl From<[ListEntry16; 4]> for BankConfig {
#[inline]
fn from(entries: [ListEntry16; 4]) -> Self {
Self::List16(entries)
}
}
impl From<[ListEntry32; 2]> for BankConfig {
#[inline]
fn from(entries: [ListEntry32; 2]) -> Self {
Self::List32(entries)
}
}
impl From<[Mask16; 2]> for BankConfig {
#[inline]
fn from(entries: [Mask16; 2]) -> Self {
Self::Mask16(entries)
}
}
impl From<Mask32> for BankConfig {
#[inline]
fn from(filter: Mask32) -> Self {
Self::Mask32(filter)
}
}
pub struct MasterFilters<'a, I: FilterOwner> {
bank_count: u8,
_can: PhantomData<&'a mut I>,
}
impl<I: FilterOwner> MasterFilters<'_, I> {
pub(crate) unsafe fn new() -> Self {
let can = &*I::REGISTERS;
can.fmr.modify(|_, w| w.finit().set_bit());
let bank_count = can.fmr.read().can2sb().bits();
Self {
bank_count,
_can: PhantomData,
}
}
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
}
fn banks_imm(&self) -> FilterBanks<'_> {
FilterBanks {
start_idx: 0,
bank_count: self.bank_count,
can: self.registers(),
}
}
pub fn num_banks(&self) -> u8 {
self.bank_count
}
pub fn clear(&mut self) -> &mut Self {
self.banks_imm().clear();
self
}
pub fn disable_bank(&mut self, index: u8) -> &mut Self {
self.banks_imm().disable(index);
self
}
pub fn enable_bank(
&mut self,
index: u8,
fifo: Fifo,
config: impl Into<BankConfig>,
) -> &mut Self {
self.banks_imm().enable(index, fifo, config.into());
self
}
}
impl<I: MasterInstance> MasterFilters<'_, I> {
pub fn set_split(&mut self, split_index: u8) -> &mut Self {
assert!(split_index <= I::NUM_FILTER_BANKS);
self.registers()
.fmr
.modify(|_, w| unsafe { w.can2sb().bits(split_index) });
self.bank_count = split_index;
self
}
pub fn slave_filters(&mut self) -> SlaveFilters<'_, I> {
SlaveFilters {
start_idx: self.bank_count,
bank_count: I::NUM_FILTER_BANKS - self.bank_count,
_can: PhantomData,
}
}
}
impl<I: FilterOwner> Drop for MasterFilters<'_, I> {
#[inline]
fn drop(&mut self) {
let can = self.registers();
can.fmr.modify(|_, w| w.finit().clear_bit());
}
}
pub struct SlaveFilters<'a, I: Instance> {
start_idx: u8,
bank_count: u8,
_can: PhantomData<&'a mut I>,
}
impl<I: Instance> SlaveFilters<'_, I> {
fn registers(&self) -> &RegisterBlock {
unsafe { &*I::REGISTERS }
}
fn banks_imm(&self) -> FilterBanks<'_> {
FilterBanks {
start_idx: self.start_idx,
bank_count: self.bank_count,
can: self.registers(),
}
}
pub fn num_banks(&self) -> u8 {
self.bank_count
}
pub fn clear(&mut self) -> &mut Self {
self.banks_imm().clear();
self
}
pub fn disable_bank(&mut self, index: u8) -> &mut Self {
self.banks_imm().disable(index);
self
}
pub fn enable_bank(
&mut self,
index: u8,
fifo: Fifo,
config: impl Into<BankConfig>,
) -> &mut Self {
self.banks_imm().enable(index, fifo, config.into());
self
}
}
struct FilterBanks<'a> {
start_idx: u8,
bank_count: u8,
can: &'a RegisterBlock,
}
impl FilterBanks<'_> {
fn clear(&mut self) {
let mask = filter_bitmask(self.start_idx, self.bank_count);
self.can.fa1r.modify(|r, w| {
let bits = r.bits();
unsafe { w.bits(bits & !mask) }
});
}
fn assert_bank_index(&self, index: u8) {
assert!((self.start_idx..self.start_idx + self.bank_count).contains(&index));
}
fn disable(&mut self, index: u8) {
self.assert_bank_index(index);
self.can
.fa1r
.modify(|r, w| unsafe { w.bits(r.bits() & !(1 << index)) })
}
fn enable(&mut self, index: u8, fifo: Fifo, config: BankConfig) {
self.assert_bank_index(index);
let mode = matches!(config, BankConfig::List16(_) | BankConfig::List32(_));
self.can.fm1r.modify(|r, w| {
let mut bits = r.bits();
if mode {
bits |= 1 << index;
} else {
bits &= !(1 << index);
}
unsafe { w.bits(bits) }
});
let scale = matches!(config, BankConfig::List32(_) | BankConfig::Mask32(_));
self.can.fs1r.modify(|r, w| {
let mut bits = r.bits();
if scale {
bits |= 1 << index;
} else {
bits &= !(1 << index);
}
unsafe { w.bits(bits) }
});
let (fxr1, fxr2);
match config {
BankConfig::List16([a, b, c, d]) => {
fxr1 = (u32::from(b.0) << 16) | u32::from(a.0);
fxr2 = (u32::from(d.0) << 16) | u32::from(c.0);
}
BankConfig::List32([a, b]) => {
fxr1 = a.0;
fxr2 = b.0;
}
BankConfig::Mask16([a, b]) => {
fxr1 = (u32::from(a.mask) << 16) | u32::from(a.id);
fxr2 = (u32::from(b.mask) << 16) | u32::from(b.id);
}
BankConfig::Mask32(a) => {
fxr1 = a.id;
fxr2 = a.mask;
}
};
let bank = &self.can.fb[usize::from(index)];
bank.fr1.write(|w| unsafe { w.bits(fxr1) });
bank.fr2.write(|w| unsafe { w.bits(fxr2) });
self.can.ffa1r.modify(|r, w| unsafe {
let mut bits = r.bits();
match fifo {
Fifo::Fifo0 => bits &= !(1 << index),
Fifo::Fifo1 => bits |= 1 << index,
}
w.bits(bits)
});
self.can
.fa1r
.modify(|r, w| unsafe { w.bits(r.bits() | (1 << index)) })
}
}
fn filter_bitmask(start_idx: u8, bank_count: u8) -> u32 {
let count_mask = (1 << bank_count) - 1; count_mask << start_idx
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_filter_bitmask() {
assert_eq!(filter_bitmask(0, 1), 0x1);
assert_eq!(filter_bitmask(1, 1), 0b10);
assert_eq!(filter_bitmask(0, 4), 0xf);
assert_eq!(filter_bitmask(1, 3), 0xe);
assert_eq!(filter_bitmask(8, 1), 0x100);
assert_eq!(filter_bitmask(8, 4), 0xf00);
}
}