use super::{ExtendedId, StandardId};
#[derive(Debug, PartialEq, Eq)]
pub enum FilterType {
Single,
Dual,
}
pub trait Filter {
const FILTER_TYPE: FilterType;
fn filter_type(&self) -> FilterType {
Self::FILTER_TYPE
}
fn to_registers(&self) -> [u8; 8];
}
pub type BitFilter<const N: usize> = [u8; N];
macro_rules! set_bit_from_byte {
($code:expr, $mask:expr, $byte:expr, $shift:expr) => {
match $byte {
b'0' => {
$mask |= 1 << $shift;
}
b'1' => {
$code |= 1 << $shift;
$mask |= 1 << $shift;
}
b'x' => {}
_ => ::core::panic!("BitFilter bits must be either '1', '0' or 'x'."),
}
};
}
const fn code_mask_to_register_array(code: u32, mask: u32) -> [u8; 8] {
let [code_3, code_2, code_1, code_0] = code.to_be_bytes();
let [mask_3, mask_2, mask_1, mask_0] = (!mask).to_be_bytes();
[
code_3, code_2, code_1, code_0, mask_3, mask_2, mask_1, mask_0,
]
}
pub struct SingleStandardFilter {
raw: [u8; 8],
}
impl SingleStandardFilter {
#[procmacros::doc_replace]
pub const fn new(id: &BitFilter<11>, rtr: &BitFilter<1>, payload: [&BitFilter<8>; 2]) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
{
let mut idx = 0;
while idx < 11 {
let shift = 31 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, id[idx], shift);
idx += 1;
}
}
{
let shift = 20;
set_bit_from_byte!(acceptance_code, acceptance_mask, rtr[0], shift);
}
{
let mut payload_index = 0;
while payload_index < 2 {
let mut idx = 0;
while idx < 8 {
let shift = 15 - (8 * payload_index) - idx;
set_bit_from_byte!(
acceptance_code,
acceptance_mask,
payload[payload_index][idx],
shift
);
idx += 1;
}
payload_index += 1;
}
}
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
pub fn new_from_code_mask(
id_code: StandardId,
id_mask: StandardId,
rtr_code: bool,
rtr_mask: bool,
payload_code: [u8; 2],
payload_mask: [u8; 2],
) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
acceptance_code |= (id_code.as_raw() as u32) << 21;
acceptance_mask |= (id_mask.as_raw() as u32) << 21;
acceptance_code |= (rtr_code as u32) << 20;
acceptance_mask |= (rtr_mask as u32) << 20;
acceptance_code |= ((payload_code[0] as u32) << 8) | (payload_code[1] as u32);
acceptance_mask |= ((payload_mask[0] as u32) << 8) | (payload_mask[1] as u32);
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
}
impl Filter for SingleStandardFilter {
const FILTER_TYPE: FilterType = FilterType::Single;
fn to_registers(&self) -> [u8; 8] {
self.raw
}
}
pub struct SingleExtendedFilter {
raw: [u8; 8],
}
impl SingleExtendedFilter {
pub const fn new(id: &BitFilter<29>, rtr: &BitFilter<1>) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
{
let mut idx = 0;
while idx < 29 {
let shift = 31 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, id[idx], shift);
idx += 1;
}
}
{
let shift = 2;
set_bit_from_byte!(acceptance_code, acceptance_mask, rtr[0], shift);
}
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
pub fn new_from_code_mask(
id_code: ExtendedId,
id_mask: ExtendedId,
rtr_code: bool,
rtr_mask: bool,
) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
acceptance_code |= id_code.as_raw() << 3;
acceptance_mask |= id_mask.as_raw() << 3;
acceptance_code |= (rtr_code as u32) << 2;
acceptance_mask |= (rtr_mask as u32) << 2;
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
}
impl Filter for SingleExtendedFilter {
const FILTER_TYPE: FilterType = FilterType::Single;
fn to_registers(&self) -> [u8; 8] {
self.raw
}
}
pub struct DualStandardFilter {
raw: [u8; 8],
}
impl DualStandardFilter {
pub const fn new(
first_id: &BitFilter<11>,
first_rtr: &BitFilter<1>,
first_payload: &BitFilter<8>,
second_id: &BitFilter<11>,
second_rtr: &BitFilter<1>,
) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
{
let mut idx = 0;
while idx < 11 {
let shift = 31 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, first_id[idx], shift);
idx += 1;
}
}
{
let shift = 20;
set_bit_from_byte!(acceptance_code, acceptance_mask, first_rtr[0], shift);
}
{
let mut idx = 0;
while idx < 4 {
let shift = 19 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, first_payload[idx], shift);
idx += 1;
}
while idx < 8 {
let shift = 3 + 4 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, first_payload[idx], shift);
idx += 1;
}
}
{
let mut idx = 0;
while idx < 11 {
let shift = 15 - idx;
set_bit_from_byte!(acceptance_code, acceptance_mask, second_id[idx], shift);
idx += 1;
}
}
{
let shift = 4;
set_bit_from_byte!(acceptance_code, acceptance_mask, second_rtr[0], shift);
}
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
#[expect(clippy::too_many_arguments)]
pub fn new_from_code_mask(
first_id_code: StandardId,
first_id_mask: StandardId,
first_rtr_code: bool,
first_rtr_mask: bool,
first_payload_code: u8,
first_payload_mask: u8,
second_id_code: StandardId,
second_id_mask: StandardId,
second_rtr_code: bool,
second_rtr_mask: bool,
) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
acceptance_code |= (first_id_code.as_raw() as u32) << 21;
acceptance_mask |= (first_id_mask.as_raw() as u32) << 21;
acceptance_code |= (first_rtr_code as u32) << 20;
acceptance_mask |= (first_rtr_mask as u32) << 20;
acceptance_code |= ((first_payload_code & 0xF0) as u32) << 12;
acceptance_mask |= ((first_payload_mask & 0xF0) as u32) << 12;
acceptance_code |= (first_payload_code & 0x0F) as u32;
acceptance_mask |= (first_payload_mask & 0x0F) as u32;
acceptance_code |= (second_id_code.as_raw() as u32) << 5;
acceptance_mask |= (second_id_mask.as_raw() as u32) << 5;
acceptance_code |= (second_rtr_code as u32) << 4;
acceptance_mask |= (second_rtr_mask as u32) << 4;
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
}
impl Filter for DualStandardFilter {
const FILTER_TYPE: FilterType = FilterType::Dual;
fn to_registers(&self) -> [u8; 8] {
self.raw
}
}
pub struct DualExtendedFilter {
raw: [u8; 8],
}
impl DualExtendedFilter {
pub const fn new(ids: [&BitFilter<16>; 2]) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
{
let mut filter_idx = 0;
while filter_idx < 2 {
let mut idx = 0;
while idx < 16 {
let shift = 31 - (filter_idx * 16) - idx;
set_bit_from_byte!(
acceptance_code,
acceptance_mask,
ids[filter_idx][idx],
shift
);
idx += 1;
}
filter_idx += 1;
}
}
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
pub fn new_from_code_mask(ids_code: [u16; 2], ids_mask: [u16; 2]) -> Self {
let mut acceptance_code: u32 = 0;
let mut acceptance_mask: u32 = 0;
acceptance_code |= (ids_code[0] as u32) << 16;
acceptance_mask |= (ids_mask[0] as u32) << 16;
acceptance_code |= ids_code[1] as u32;
acceptance_mask |= ids_mask[1] as u32;
Self {
raw: code_mask_to_register_array(acceptance_code, acceptance_mask),
}
}
}
impl Filter for DualExtendedFilter {
const FILTER_TYPE: FilterType = FilterType::Dual;
fn to_registers(&self) -> [u8; 8] {
self.raw
}
}