pub use super::interrupt::{Interrupt, InterruptLine, Interrupts};
use core::num::{NonZeroU16, NonZeroU8};
#[derive(Clone, Copy, Debug)]
pub struct NominalBitTiming {
pub prescaler: NonZeroU16,
pub seg1: NonZeroU8,
pub seg2: NonZeroU8,
pub sync_jump_width: NonZeroU8,
}
impl NominalBitTiming {
#[inline]
pub(crate) fn nbrp(&self) -> u16 {
u16::from(self.prescaler) & 0x1FF
}
#[inline]
pub(crate) fn ntseg1(&self) -> u8 {
u8::from(self.seg1)
}
#[inline]
pub(crate) fn ntseg2(&self) -> u8 {
u8::from(self.seg2) & 0x7F
}
#[inline]
pub(crate) fn nsjw(&self) -> u8 {
u8::from(self.sync_jump_width) & 0x7F
}
}
impl Default for NominalBitTiming {
#[inline]
fn default() -> Self {
Self {
prescaler: NonZeroU16::new(1).unwrap(),
seg1: NonZeroU8::new(11).unwrap(),
seg2: NonZeroU8::new(4).unwrap(),
sync_jump_width: NonZeroU8::new(4).unwrap(),
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct DataBitTiming {
pub transceiver_delay_compensation: bool,
pub prescaler: NonZeroU8,
pub seg1: NonZeroU8,
pub seg2: NonZeroU8,
pub sync_jump_width: NonZeroU8,
}
impl DataBitTiming {
#[inline]
pub(crate) fn dbrp(&self) -> u8 {
u8::from(self.prescaler) & 0x1F
}
#[inline]
pub(crate) fn dtseg1(&self) -> u8 {
u8::from(self.seg1) & 0x1F
}
#[inline]
pub(crate) fn dtseg2(&self) -> u8 {
u8::from(self.seg2) & 0x0F
}
#[inline]
pub(crate) fn dsjw(&self) -> u8 {
u8::from(self.sync_jump_width) & 0x0F
}
}
impl Default for DataBitTiming {
#[inline]
fn default() -> Self {
Self {
transceiver_delay_compensation: false,
prescaler: NonZeroU8::new(1).unwrap(),
seg1: NonZeroU8::new(11).unwrap(),
seg2: NonZeroU8::new(4).unwrap(),
sync_jump_width: NonZeroU8::new(4).unwrap(),
}
}
}
#[derive(Clone, Copy, Debug)]
pub enum FrameTransmissionConfig {
ClassicCanOnly,
AllowFdCan,
AllowFdCanAndBRS,
}
#[derive(Clone, Copy, Debug)]
pub enum ClockDivider {
_1 = 0b0000,
_2 = 0b0001,
_4 = 0b0010,
_6 = 0b0011,
_8 = 0b0100,
_10 = 0b0101,
_12 = 0b0110,
_14 = 0b0111,
_16 = 0b1000,
_18 = 0b1001,
_20 = 0b1010,
_22 = 0b1011,
_24 = 0b1100,
_26 = 0b1101,
_28 = 0b1110,
_30 = 0b1111,
}
#[derive(Clone, Copy, Debug)]
pub enum TimestampPrescaler {
_1 = 1,
_2 = 2,
_3 = 3,
_4 = 4,
_5 = 5,
_6 = 6,
_7 = 7,
_8 = 8,
_9 = 9,
_10 = 10,
_11 = 11,
_12 = 12,
_13 = 13,
_14 = 14,
_15 = 15,
_16 = 16,
}
#[derive(Clone, Copy, Debug)]
pub enum TimestampSource {
None,
Prescaler(TimestampPrescaler),
FromTIM3,
}
#[derive(Clone, Copy, Debug)]
pub enum NonMatchingFilter {
IntoRxFifo0 = 0b00,
IntoRxFifo1 = 0b01,
Reject = 0b11,
}
#[derive(Clone, Copy, Debug)]
pub struct GlobalFilter {
pub handle_standard_frames: NonMatchingFilter,
pub handle_extended_frames: NonMatchingFilter,
pub reject_remote_standard_frames: bool,
pub reject_remote_extended_frames: bool,
}
impl GlobalFilter {
pub const fn reject_all() -> Self {
Self {
handle_standard_frames: NonMatchingFilter::Reject,
handle_extended_frames: NonMatchingFilter::Reject,
reject_remote_standard_frames: true,
reject_remote_extended_frames: true,
}
}
pub const fn set_handle_standard_frames(
mut self,
filter: NonMatchingFilter,
) -> Self {
self.handle_standard_frames = filter;
self
}
pub const fn set_handle_extended_frames(
mut self,
filter: NonMatchingFilter,
) -> Self {
self.handle_extended_frames = filter;
self
}
pub const fn set_reject_remote_standard_frames(mut self, filter: bool) -> Self {
self.reject_remote_standard_frames = filter;
self
}
pub const fn set_reject_remote_extended_frames(mut self, filter: bool) -> Self {
self.reject_remote_extended_frames = filter;
self
}
}
impl Default for GlobalFilter {
#[inline]
fn default() -> Self {
Self {
handle_standard_frames: NonMatchingFilter::IntoRxFifo0,
handle_extended_frames: NonMatchingFilter::IntoRxFifo0,
reject_remote_standard_frames: false,
reject_remote_extended_frames: false,
}
}
}
#[derive(Clone, Copy, Debug)]
pub struct FdCanConfig {
pub nbtr: NominalBitTiming,
pub dbtr: DataBitTiming,
pub automatic_retransmit: bool,
pub transmit_pause: bool,
pub frame_transmit: FrameTransmissionConfig,
pub non_iso_mode: bool,
pub edge_filtering: bool,
pub protocol_exception_handling: bool,
pub clock_divider: ClockDivider,
pub interrupt_line_config: Interrupts,
pub timestamp_source: TimestampSource,
pub global_filter: GlobalFilter,
}
impl FdCanConfig {
#[inline]
pub const fn set_nominal_bit_timing(mut self, btr: NominalBitTiming) -> Self {
self.nbtr = btr;
self
}
#[inline]
pub const fn set_data_bit_timing(mut self, btr: DataBitTiming) -> Self {
self.dbtr = btr;
self
}
#[inline]
pub const fn set_automatic_retransmit(mut self, enabled: bool) -> Self {
self.automatic_retransmit = enabled;
self
}
#[inline]
pub const fn set_transmit_pause(mut self, enabled: bool) -> Self {
self.transmit_pause = enabled;
self
}
#[inline]
pub const fn set_non_iso_mode(mut self, enabled: bool) -> Self {
self.non_iso_mode = enabled;
self
}
#[inline]
pub const fn set_edge_filtering(mut self, enabled: bool) -> Self {
self.edge_filtering = enabled;
self
}
#[inline]
pub const fn set_frame_transmit(mut self, fts: FrameTransmissionConfig) -> Self {
self.frame_transmit = fts;
self
}
#[inline]
pub const fn set_protocol_exception_handling(mut self, peh: bool) -> Self {
self.protocol_exception_handling = peh;
self
}
#[inline]
#[deprecated(
since = "0.1.3",
note = "Deprecated in favour of .select_interrupt_line_1(..)"
)]
pub const fn set_interrupt_line_config(mut self, l0int: Interrupts) -> Self {
self.interrupt_line_config = l0int;
self
}
#[inline]
pub const fn select_interrupt_line_1(mut self, l1int: Interrupts) -> Self {
self.interrupt_line_config = l1int;
self
}
#[inline]
pub const fn set_clock_divider(mut self, div: ClockDivider) -> Self {
self.clock_divider = div;
self
}
#[inline]
pub const fn set_timestamp_source(mut self, tss: TimestampSource) -> Self {
self.timestamp_source = tss;
self
}
#[inline]
pub const fn set_global_filter(mut self, filter: GlobalFilter) -> Self {
self.global_filter = filter;
self
}
}
impl Default for FdCanConfig {
#[inline]
fn default() -> Self {
Self {
nbtr: NominalBitTiming::default(),
dbtr: DataBitTiming::default(),
automatic_retransmit: true,
transmit_pause: false,
frame_transmit: FrameTransmissionConfig::ClassicCanOnly,
non_iso_mode: false,
edge_filtering: false,
interrupt_line_config: Interrupts::none(),
protocol_exception_handling: true,
clock_divider: ClockDivider::_1,
timestamp_source: TimestampSource::None,
global_filter: GlobalFilter::default(),
}
}
}