use core::marker::PhantomData;
use embedded_can::{ExtendedId, StandardId};
use vcell::VolatileCell;
pub type FiltersStandard<'a, P> = Filters<'a, P, FilterStandardId>;
pub type FiltersExtended<'a, P> = Filters<'a, P, FilterExtendedId>;
pub struct Filters<'a, P, T> {
memory: &'a mut [VolatileCell<T>],
len: usize,
_markers: PhantomData<P>,
}
impl<'a, P, T: Copy> Filters<'a, P, T> {
pub(crate) unsafe fn new(memory: &'a mut [VolatileCell<T>]) -> Self {
Self {
memory,
len: 0,
_markers: PhantomData,
}
}
fn set<F: Copy + Into<T>>(&mut self, index: usize, filter: F) -> Result<(), F> {
self.memory
.get_mut(index)
.map(|f| f.set(filter.into()))
.ok_or(filter)
}
pub fn push<F: Copy + Into<T>>(&mut self, filter: F) -> Result<usize, F> {
let index = self.len;
self.set(index, filter)?;
self.len += 1;
Ok(index)
}
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct FilterStandardId(pub(super) u32);
#[repr(C)]
#[derive(Copy, Clone)]
pub struct FilterExtendedId(pub(super) [u32; 2]);
#[derive(Copy, Clone)]
pub enum Filter {
Disabled,
Range {
action: Action,
low: StandardId,
high: StandardId,
},
Dual {
action: Action,
id1: StandardId,
id2: StandardId,
},
Classic {
action: Action,
filter: StandardId,
mask: StandardId,
},
StoreBuffer {
id: StandardId,
msg_type: SbMsgType,
offset: u8,
},
}
#[derive(Default, Copy, Clone)]
pub enum SbMsgType {
#[default]
RxBuffer = 0,
DebugA,
DebugB,
DebugC,
}
#[derive(Copy, Clone)]
pub enum ExtFilter {
Disabled,
MaskedRange {
action: Action,
low: ExtendedId,
high: ExtendedId,
},
Dual {
action: Action,
id1: ExtendedId,
id2: ExtendedId,
},
Classic {
action: Action,
filter: ExtendedId,
mask: ExtendedId,
},
Range {
action: Action,
low: ExtendedId,
high: ExtendedId,
},
StoreBuffer {
id: ExtendedId,
msg_type: SbMsgType,
offset: u8,
},
}
#[derive(Copy, Clone)]
pub enum Action {
StoreFifo0,
StoreFifo1,
Reject,
Priority,
PriorityFifo0,
PriorityFifo1,
}
impl From<Action> for u32 {
fn from(val: Action) -> Self {
match val {
Action::StoreFifo0 => 0x1,
Action::StoreFifo1 => 0x2,
Action::Reject => 0x3,
Action::Priority => 0x4,
Action::PriorityFifo0 => 0x5,
Action::PriorityFifo1 => 0x6,
}
}
}
impl From<Filter> for FilterStandardId {
fn from(val: Filter) -> Self {
let v = match val {
Filter::Disabled => 0,
Filter::Range { action, high, low } => {
let action: u32 = action.into();
(high.as_raw() as u32) | ((low.as_raw() as u32) << 16) | (action << 27)
}
Filter::Dual { action, id1, id2 } => {
let action: u32 = action.into();
(id2.as_raw() as u32) | ((id1.as_raw() as u32) << 16) | (action << 27) | (1 << 30)
}
Filter::Classic {
action,
filter,
mask,
} => {
let action: u32 = action.into();
(mask.as_raw() as u32)
| ((filter.as_raw() as u32) << 16)
| (action << 27)
| (2 << 30)
}
Filter::StoreBuffer {
id,
msg_type,
offset,
} => (id.as_raw() as u32) << 16 | (msg_type as u32) << 9 | offset as u32 | (0x7 << 27),
};
FilterStandardId(v)
}
}
impl From<ExtFilter> for FilterExtendedId {
fn from(val: ExtFilter) -> Self {
let (v1, v2) = match val {
ExtFilter::Disabled => (0, 0),
ExtFilter::MaskedRange { action, high, low } => {
let action: u32 = action.into();
((action << 29 | low.as_raw()), high.as_raw())
}
ExtFilter::Dual { action, id1, id2 } => {
let action: u32 = action.into();
((action << 29 | id1.as_raw()), (1 << 30 | id2.as_raw()))
}
ExtFilter::Classic {
action,
filter,
mask,
} => {
let action: u32 = action.into();
((action << 29 | filter.as_raw()), (2 << 30 | mask.as_raw()))
}
ExtFilter::Range { action, high, low } => {
let action: u32 = action.into();
((action << 29 | low.as_raw()), (3 << 30 | high.as_raw()))
}
ExtFilter::StoreBuffer {
id,
msg_type,
offset,
} => (
(0x7 << 29 | id.as_raw()),
(msg_type as u32) << 9 | offset as u32,
),
};
FilterExtendedId([v1, v2])
}
}