Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
e015806
wip: initial implementation of transmission only.
alexbohm Sep 7, 2022
b8ec8b4
Moved TWAI to its own directory and added initial reception of packets.
alexbohm Sep 8, 2022
c8a2291
Added extended id transmit and receive.
alexbohm Sep 9, 2022
0e5e04f
Added maybe better code for making packet filters.
alexbohm Sep 11, 2022
69613cc
Fixed bug with ids and improved methods of copying data to the periph…
alexbohm Sep 12, 2022
c9404bc
Added some guards against Bus Off
alexbohm Sep 13, 2022
d675ac9
Added reception of remote frames.
alexbohm Sep 18, 2022
e08ef1f
Clean up of comments, etc
alexbohm Sep 18, 2022
cd343de
Updated TWAI naming and cleaned up example a bit.
alexbohm Sep 21, 2022
336e104
Updated bitselector to include better unpacking methods.
alexbohm Sep 29, 2022
3e4a46b
Add embedded-can and limit initial TWAI implementation to esp32c3.
alexbohm Nov 10, 2022
b28bb96
Added embedded-can to esp32c3 twai example.
alexbohm Nov 10, 2022
0389fe8
Switched twai filter to using bytestrings.
alexbohm Nov 12, 2022
f26d19a
Implemented new() for twai filters.
alexbohm Nov 13, 2022
3553a0c
Clean up TWAI docs and example.
alexbohm Nov 17, 2022
fc7a428
Fix filter constructors and add examples.
alexbohm Nov 18, 2022
54b5e5d
pre driver PeripheralRef update.
alexbohm Dec 17, 2022
2b6778d
PeripheralRef/twai
alexbohm Dec 17, 2022
a8e875e
Format comments with nightly rustfmt.
alexbohm Dec 17, 2022
d18a5cc
Add gpio PeripheralRef and use volatile for direct register access.
alexbohm Dec 22, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Added maybe better code for making packet filters.
  • Loading branch information
alexbohm committed Dec 21, 2022
commit 0e5e04f9afc00b64199bc6dfbed585638749f7a7
94 changes: 94 additions & 0 deletions esp-hal-common/src/twai/bitselector.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#[derive(Debug, Clone, Copy)]
pub enum Selector {
Set,
Reset,
Any,
}

impl Selector {
pub fn into_value(&self) -> u8 {
match self {
Selector::Set => 0b1,
Selector::Reset => 0b0,
Selector::Any => 0b0,
}
}
pub fn into_mask(&self) -> u8 {
// Set bits in the mask mean we don't care about the value of that bit. The bit could be any value.
// https://www.espressif.com/sites/default/files/documentation/esp32-c3_technical_reference_manual_en.pdf#subsubsection.29.4.6
match self {
Selector::Set => 0b0,
Selector::Reset => 0b0,
Selector::Any => 0b1,
}
}
}

impl Into<Selector> for bool {
fn into(self) -> Selector {
match self {
true => Selector::Set,
false => Selector::Reset,
}
}
}

pub trait BitSelectorNewExact<T, const N: usize> {
fn new_exact(value: T) -> BitSelector<N>;
}

#[derive(Debug, Clone, Copy)]
pub struct BitSelector<const N: usize> {
pub bits: [Selector; N],
}

impl<const N: usize> BitSelector<N> {
pub fn new_any() -> Self {
Self {
bits: [Selector::Any; N],
}
}
}
// TODO: improve this.
impl BitSelectorNewExact<u16, 11> for BitSelector<11> {
fn new_exact(value: u16) -> BitSelector<11> {
Self {
bits: [
(value & 0b00000000001 != 0).into(),
(value & 0b00000000010 != 0).into(),
(value & 0b00000000100 != 0).into(),
(value & 0b00000001000 != 0).into(),
(value & 0b00000010000 != 0).into(),
(value & 0b00000100000 != 0).into(),
(value & 0b00001000000 != 0).into(),
(value & 0b00010000000 != 0).into(),
(value & 0b00100000000 != 0).into(),
(value & 0b01000000000 != 0).into(),
(value & 0b10000000000 != 0).into(),
],
}
}
}
impl BitSelectorNewExact<u8, 8> for BitSelector<8> {
fn new_exact(value: u8) -> BitSelector<8> {
Self {
bits: [
(value & 0b00000000001 != 0).into(),
(value & 0b00000000010 != 0).into(),
(value & 0b00000000100 != 0).into(),
(value & 0b00000001000 != 0).into(),
(value & 0b00000010000 != 0).into(),
(value & 0b00000100000 != 0).into(),
(value & 0b00001000000 != 0).into(),
(value & 0b00010000000 != 0).into(),
],
}
}
}
impl BitSelectorNewExact<u8, 1> for BitSelector<1> {
fn new_exact(value: u8) -> BitSelector<1> {
Self {
bits: [(value & 0b1 != 0).into()],
}
}
}
200 changes: 115 additions & 85 deletions esp-hal-common/src/twai/filter.rs
Original file line number Diff line number Diff line change
@@ -1,115 +1,145 @@
use embedded_hal::can::{ExtendedId, StandardId};
use super::bitselector::BitSelector;

pub struct ValueMask<T> {
pub value: T,
pub mask: T,
#[derive(Debug, PartialEq)]
pub enum FilterType {
Single,
Dual,
}
pub trait FilterToRegisters {
fn to_registers(self) -> [u8; 8];

pub trait Filter {
// The type of the filter.
const FILTER_TYPE: FilterType;
fn filter_type(&self) -> FilterType {
Self::FILTER_TYPE
}

fn to_registers(&self) -> [u8; 8];
}

///
///
/// Warning: This is not a perfect filter. Extended ids that match the bit layout of this filter
/// will also be accepted.
pub struct SingleStandardFilter {
pub id: ValueMask<StandardId>,
pub rtr: ValueMask<bool>,
pub data: ValueMask<[u8; 2]>,
pub id: BitSelector<11>,
pub rtr: BitSelector<1>,
pub data: [BitSelector<8>; 2],
}
impl FilterToRegisters for SingleStandardFilter {
fn to_registers(self) -> [u8; 8] {

impl Filter for SingleStandardFilter {
const FILTER_TYPE: FilterType = FilterType::Single;
fn to_registers(&self) -> [u8; 8] {
[
// Value.
(self.id.value.as_raw() >> 3) as u8,
((self.id.value.as_raw() << 5) as u8
| if self.rtr.value { 0b1 << 4 } else { 0b0 << 4 })
& 0b11110000,
self.data.value[0],
self.data.value[1],
// TODO: Implement some sort of into for slices of bits so that we can simplify some of this code.
self.id.bits[10].into_value() << 7
| self.id.bits[9].into_value() << 6
| self.id.bits[8].into_value() << 5
| self.id.bits[7].into_value() << 4
| self.id.bits[6].into_value() << 3
| self.id.bits[5].into_value() << 2
| self.id.bits[4].into_value() << 1
| self.id.bits[3].into_value(),
self.id.bits[2].into_value() << 7
| self.id.bits[1].into_value() << 6
| self.id.bits[0].into_value() << 5
| self.rtr.bits[0].into_value() << 4,
self.data[0].bits[7].into_value() << 7
| self.data[0].bits[6].into_value() << 6
| self.data[0].bits[5].into_value() << 5
| self.data[0].bits[4].into_value() << 4
| self.data[0].bits[3].into_value() << 3
| self.data[0].bits[2].into_value() << 2
| self.data[0].bits[1].into_value() << 1
| self.data[0].bits[0].into_value() << 0,
self.data[1].bits[7].into_value() << 7
| self.data[1].bits[6].into_value() << 6
| self.data[1].bits[5].into_value() << 5
| self.data[1].bits[4].into_value() << 4
| self.data[1].bits[3].into_value() << 3
| self.data[1].bits[2].into_value() << 2
| self.data[1].bits[1].into_value() << 1
| self.data[1].bits[0].into_value() << 0,
// Mask.
(self.id.mask.as_raw() >> 3) as u8,
((self.id.mask.as_raw() << 5) as u8 | if self.rtr.mask { 0b1 << 4 } else { 0b0 << 4 })
& 0b11110000,
self.data.mask[0],
self.data.mask[1],
self.id.bits[10].into_mask() << 7
| self.id.bits[9].into_mask() << 6
| self.id.bits[8].into_mask() << 5
| self.id.bits[7].into_mask() << 4
| self.id.bits[6].into_mask() << 3
| self.id.bits[5].into_mask() << 2
| self.id.bits[4].into_mask() << 1
| self.id.bits[3].into_mask(),
self.id.bits[2].into_mask() << 7
| self.id.bits[1].into_mask() << 6
| self.id.bits[0].into_mask() << 5
| self.rtr.bits[0].into_mask() << 4,
self.data[0].bits[7].into_mask() << 7
| self.data[0].bits[6].into_mask() << 6
| self.data[0].bits[5].into_mask() << 5
| self.data[0].bits[4].into_mask() << 4
| self.data[0].bits[3].into_mask() << 3
| self.data[0].bits[2].into_mask() << 2
| self.data[0].bits[1].into_mask() << 1
| self.data[0].bits[0].into_mask() << 0,
self.data[1].bits[7].into_mask() << 7
| self.data[1].bits[6].into_mask() << 6
| self.data[1].bits[5].into_mask() << 5
| self.data[1].bits[4].into_mask() << 4
| self.data[1].bits[3].into_mask() << 3
| self.data[1].bits[2].into_mask() << 2
| self.data[1].bits[1].into_mask() << 1
| self.data[1].bits[0].into_mask() << 0,
]
}
}

///
///
/// Warning: This is not a perfect filter. Standard ids that match the bit layout of this filter
/// will also be accepted.
pub struct SingleExtendedFilter {
pub id: ValueMask<ExtendedId>,
pub rtr: ValueMask<bool>,
pub id: BitSelector<29>,
pub rtr: BitSelector<1>,
}
impl FilterToRegisters for SingleExtendedFilter {
fn to_registers(self) -> [u8; 8] {
[
// Value.
(self.id.value.as_raw() >> 21) as u8,
(self.id.value.as_raw() >> 13) as u8,
(self.id.value.as_raw() >> 5) as u8,
((self.id.value.as_raw() << 3) as u8
| if self.rtr.value { 0b1 << 2 } else { 0b0 << 2 })
& 0b11111100,
// Mask.
(self.id.mask.as_raw() >> 21) as u8,
(self.id.mask.as_raw() >> 13) as u8,
(self.id.mask.as_raw() >> 5) as u8,
((self.id.mask.as_raw() << 3) as u8 | if self.rtr.mask { 0b1 << 2 } else { 0b0 << 2 })
& 0b11111100,
]
impl Filter for SingleExtendedFilter {
const FILTER_TYPE: FilterType = FilterType::Single;
fn to_registers(&self) -> [u8; 8] {
panic!("Unimplemented");
}
}

// TODO: how do we actually want to store the two filters?

///
/// TODO: is this how we actually want to store the two filters?
///
/// Warning: This is not a perfect filter. Extended ids that match the bit layout of this filter
/// will also be accepted.
pub struct DualStandardFilter {
pub id: ValueMask<StandardId>,
pub rtr: ValueMask<bool>,
// TODO: only the first filter can match on the data.
pub data: ValueMask<[u8; 1]>,
pub first_id: BitSelector<11>,
pub first_rtr: BitSelector<1>,
pub first_data: BitSelector<8>,

pub second_id: BitSelector<11>,
pub second_rtr: BitSelector<1>,
}
impl FilterToRegisters for DualStandardFilter {
fn to_registers(self) -> [u8; 8] {
impl Filter for DualStandardFilter {
const FILTER_TYPE: FilterType = FilterType::Dual;
fn to_registers(&self) -> [u8; 8] {
// TODO: this.
panic!("Unimplemented");
}
}
///
/// NOTE: The dual extended id acceptance filter can only match "the first 16 bits of the 29-bit ID".
/// NOTE: The dual extended id acceptance filters can only match "the first 16 bits of the 29-bit ID".
///
///
/// Warning: This is not a perfect filter. Standard ids that match the bit layout of this filter
/// will also be accepted.
pub struct DualExtendedFilter {
pub id: ValueMask<u16>,
pub id: [BitSelector<16>; 2],
}
impl FilterToRegisters for DualExtendedFilter {
fn to_registers(self) -> [u8; 8] {
impl Filter for DualExtendedFilter {
const FILTER_TYPE: FilterType = FilterType::Dual;
fn to_registers(&self) -> [u8; 8] {
// TODO: this.
panic!("Unimplemented");
}
}

pub enum FilterIdFormat<Std, Ext> {
Standard(Std),
Extended(Ext),
}
impl<Std, Ext> FilterToRegisters for FilterIdFormat<Std, Ext>
where
Std: FilterToRegisters,
Ext: FilterToRegisters,
{
fn to_registers(self) -> [u8; 8] {
match self {
FilterIdFormat::Standard(filter) => filter.to_registers(),
FilterIdFormat::Extended(filter) => filter.to_registers(),
}
}
}

pub enum Filter {
Single(FilterIdFormat<SingleStandardFilter, SingleExtendedFilter>),
Dual(FilterIdFormat<DualStandardFilter, DualExtendedFilter>),
}

impl FilterToRegisters for Filter {
fn to_registers(self) -> [u8; 8] {
match self {
Self::Single(single) => single.to_registers(),
Self::Dual(dual) => dual.to_registers(),
}
}
}
Loading