use core::cmp::Ordering;
use crate::Id;
use crate::IdReg;
use crate::filter::FilterId;
use crate::message_ram::enums::FrameFormat as PacFrameFormat;
use crate::message_ram::{RxFifoElementHeader, TxBufferElementHeader};
use crate::message_ram::enums::RemoteTransmissionRequest;
use crate::message_ram::enums::{DataLength, FilterFrameMatch};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum FrameFormat {
Standard = 0,
Fdcan = 1,
}
impl From<FrameFormat> for PacFrameFormat {
fn from(ff: FrameFormat) -> Self {
match ff {
FrameFormat::Standard => PacFrameFormat::Standard,
FrameFormat::Fdcan => PacFrameFormat::Fdcan,
}
}
}
impl From<PacFrameFormat> for FrameFormat {
fn from(ff: PacFrameFormat) -> Self {
match ff {
PacFrameFormat::Standard => FrameFormat::Standard,
PacFrameFormat::Fdcan => FrameFormat::Fdcan,
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct FramePriority(pub(crate) IdReg);
impl Ord for FramePriority {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0)
}
}
impl PartialOrd for FramePriority {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for FramePriority {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for FramePriority {}
#[derive(Debug, Copy, Clone)]
pub struct TxFrameHeader {
pub len: u8,
pub frame_format: FrameFormat,
pub id: Id,
pub bit_rate_switching: bool,
pub marker: Option<u8>,
}
impl From<TxFrameHeader> for IdReg {
fn from(header: TxFrameHeader) -> IdReg {
let id: IdReg = header.id.into();
id.with_rtr(header.len == 0)
}
}
pub(crate) trait MergeTxFrameHeader {
fn merge(&self, header: TxFrameHeader);
}
impl MergeTxFrameHeader for TxBufferElementHeader {
fn merge(&self, header: TxFrameHeader) {
let id: IdReg = header.id.into();
self.write(|w| {
unsafe { w.id().bits(id.as_raw_id()) }
.rtr()
.bit(header.len == 0)
.xtd()
.set_id_type(header.id.into())
.set_len(DataLength::new(header.len, header.frame_format.into()))
.set_event(header.marker.into())
.fdf()
.set_format(header.frame_format.into())
.brs()
.bit(header.bit_rate_switching)
});
}
}
impl From<&TxBufferElementHeader> for TxFrameHeader {
fn from(reg: &TxBufferElementHeader) -> Self {
let reader = reg.read();
let id = reader.id().bits();
let rtr = reader.rtr().rtr();
let xtd = reader.xtd().id_type();
let len = reader.to_data_length();
let ff: PacFrameFormat = len.into();
TxFrameHeader {
len: len.len(),
frame_format: ff.into(),
id: IdReg::from_register(id, rtr, xtd).into(),
bit_rate_switching: reader.brs().is_with_brs(),
marker: reader.to_event().into(),
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct RxFrameInfo {
pub len: u8,
pub frame_format: FrameFormat,
pub id: Id,
pub rtr: bool,
pub filter_match: Option<FilterId>,
pub bit_rate_switching: bool,
pub time_stamp: u16,
}
impl RxFrameInfo {
pub fn to_tx_header(self, marker: Option<u8>) -> TxFrameHeader {
TxFrameHeader {
len: self.len,
frame_format: self.frame_format,
id: self.id,
bit_rate_switching: self.bit_rate_switching,
marker,
}
}
}
impl From<&RxFifoElementHeader> for RxFrameInfo {
fn from(reg: &RxFifoElementHeader) -> Self {
let reader = reg.read();
let len = reader.to_data_length();
let ff: PacFrameFormat = len.into();
let id = reader.id().bits();
let rtr = reader.rtr().rtr();
let xtd = reader.xtd().id_type();
let id = IdReg::from_register(id, rtr, xtd).to_id();
let filter = reader.to_filter_match();
let filter = match filter {
FilterFrameMatch::DidNotMatch => None,
FilterFrameMatch::DidMatch(filter) => Some(match id {
Id::Standard(_) => FilterId::Standard(filter.into()),
Id::Extended(_) => FilterId::Extended(filter.into()),
}),
};
RxFrameInfo {
len: len.len(),
frame_format: ff.into(),
id,
rtr: rtr == RemoteTransmissionRequest::TransmitRemoteFrame,
filter_match: filter,
bit_rate_switching: reader.brs().is_with_brs(),
time_stamp: reader.txts().bits(),
}
}
}