stm32g473_hal_oppe/fdcan/
frame.rs

1use core::cmp::Ordering;
2
3use super::Id;
4use super::IdReg;
5
6use super::filter::FilterId;
7
8use super::message_ram::enums::FrameFormat as PacFrameFormat;
9use super::message_ram::{RxFifoElementHeader, TxBufferElementHeader};
10
11use super::message_ram::enums::RemoteTransmissionRequest;
12use super::message_ram::enums::{DataLength, FilterFrameMatch};
13
14/// Type of Frame
15#[derive(Clone, Copy, Debug, PartialEq)]
16#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
17pub enum FrameFormat {
18    /// Frame used by Classic CAN
19    Standard = 0,
20    /// New frame format used by FdCan
21    Fdcan = 1,
22}
23impl From<FrameFormat> for PacFrameFormat {
24    fn from(ff: FrameFormat) -> Self {
25        match ff {
26            FrameFormat::Standard => PacFrameFormat::Standard,
27            FrameFormat::Fdcan => PacFrameFormat::Fdcan,
28        }
29    }
30}
31impl From<PacFrameFormat> for FrameFormat {
32    fn from(ff: PacFrameFormat) -> Self {
33        match ff {
34            PacFrameFormat::Standard => FrameFormat::Standard,
35            PacFrameFormat::Fdcan => FrameFormat::Fdcan,
36        }
37    }
38}
39
40/// Priority of a CAN frame.
41///
42/// The priority of a frame is determined by the bits that are part of the *arbitration field*.
43/// These consist of the frame identifier bits (including the *IDE* bit, which is 0 for extended
44/// frames and 1 for standard frames), as well as the *RTR* bit, which determines whether a frame
45/// is a data or remote frame. Lower values of the *arbitration field* have higher priority.
46///
47/// This struct wraps the *arbitration field* and implements `PartialOrd` and `Ord` accordingly,
48/// ordering higher priorities greater than lower ones.
49#[derive(Debug, Copy, Clone)]
50#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
51pub struct FramePriority(pub(crate) IdReg);
52
53/// Ordering is based on the Identifier and frame type (data vs. remote) and can be used to sort
54/// frames by priority.
55impl Ord for FramePriority {
56    fn cmp(&self, other: &Self) -> Ordering {
57        self.0.cmp(&other.0)
58    }
59}
60
61impl PartialOrd for FramePriority {
62    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
63        Some(self.cmp(other))
64    }
65}
66
67impl PartialEq for FramePriority {
68    fn eq(&self, other: &Self) -> bool {
69        self.cmp(other) == Ordering::Equal
70    }
71}
72
73impl Eq for FramePriority {}
74
75/// Header of a transmit request
76#[derive(Debug, Copy, Clone)]
77#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
78pub struct TxFrameHeader {
79    /// Length of the data in bytes
80    pub len: u8,
81    /// Type of message
82    pub frame_format: FrameFormat,
83    /// Id
84    pub id: Id,
85    /// Should we use bit rate switching
86    ///
87    /// Not that this is a request and if the global frame_transmit is set to ClassicCanOnly
88    /// this is ignored.
89    pub bit_rate_switching: bool,
90    //pub error_state: Option<()>, //TODO
91    ///
92    pub marker: Option<u8>,
93}
94impl From<TxFrameHeader> for IdReg {
95    fn from(header: TxFrameHeader) -> IdReg {
96        let id: IdReg = header.id.into();
97        id.with_rtr(header.len == 0)
98    }
99}
100
101pub(crate) trait MergeTxFrameHeader {
102    fn merge(&self, header: TxFrameHeader);
103}
104impl MergeTxFrameHeader for TxBufferElementHeader {
105    fn merge(&self, header: TxFrameHeader) {
106        let id: IdReg = header.id.into();
107        self.write(|w| {
108            unsafe { w.id().bits(id.as_raw_id()) }
109                .rtr()
110                .bit(header.len == 0)
111                .xtd()
112                .set_id_type(header.id.into())
113                .set_len(DataLength::new(header.len, header.frame_format.into()))
114                .set_event(header.marker.into())
115                .fdf()
116                .set_format(header.frame_format.into())
117                .brs()
118                .bit(header.bit_rate_switching)
119            //esi.set_error_indicator(//TODO//)
120        });
121    }
122}
123
124impl From<&TxBufferElementHeader> for TxFrameHeader {
125    fn from(reg: &TxBufferElementHeader) -> Self {
126        let reader = reg.read();
127        let id = reader.id().bits();
128        let rtr = reader.rtr().rtr();
129        let xtd = reader.xtd().id_type();
130        let len = reader.to_data_length();
131        let ff: PacFrameFormat = len.into();
132        TxFrameHeader {
133            len: len.len(),
134            frame_format: ff.into(),
135            id: IdReg::from_register(id, rtr, xtd).into(),
136            bit_rate_switching: reader.brs().is_with_brs(),
137            //error_state: Option<()>, //TODO
138            marker: reader.to_event().into(),
139        }
140    }
141}
142
143/// Header of a Received Frame
144#[derive(Debug, Copy, Clone)]
145#[cfg_attr(feature = "unstable-defmt", derive(defmt::Format))]
146pub struct RxFrameInfo {
147    /// Length in bytes
148    pub len: u8,
149    /// Frame Format
150    pub frame_format: FrameFormat,
151    /// Id
152    pub id: Id,
153    /// Is this an Remote Transmit Request
154    pub rtr: bool,
155    /// Did this message match any filters
156    pub filter_match: Option<FilterId>,
157    /// was this received with bit rate switching
158    pub bit_rate_switching: bool,
159    //pub error_state: (), //TODO
160    /// Time stamp counter
161    pub time_stamp: u16,
162}
163impl RxFrameInfo {
164    /// Transforms an RxFrameInfo into an TxFrameHeader
165    pub fn to_tx_header(self, marker: Option<u8>) -> TxFrameHeader {
166        TxFrameHeader {
167            len: self.len,
168            frame_format: self.frame_format,
169            id: self.id,
170            bit_rate_switching: self.bit_rate_switching,
171            marker,
172        }
173    }
174}
175impl From<&RxFifoElementHeader> for RxFrameInfo {
176    fn from(reg: &RxFifoElementHeader) -> Self {
177        let reader = reg.read();
178        let len = reader.to_data_length();
179        let ff: PacFrameFormat = len.into();
180        let id = reader.id().bits();
181        let rtr = reader.rtr().rtr();
182        let xtd = reader.xtd().id_type();
183        let id = IdReg::from_register(id, rtr, xtd).to_id();
184        let filter = reader.to_filter_match();
185        let filter = match filter {
186            FilterFrameMatch::DidNotMatch => None,
187            FilterFrameMatch::DidMatch(filter) => Some(match id {
188                Id::Standard(_) => FilterId::Standard(filter.into()),
189                Id::Extended(_) => FilterId::Extended(filter.into()),
190            }),
191        };
192        RxFrameInfo {
193            len: len.len(),
194            frame_format: ff.into(),
195            id,
196            rtr: rtr == RemoteTransmissionRequest::TransmitRemoteFrame,
197            filter_match: filter,
198            bit_rate_switching: reader.brs().is_with_brs(),
199            time_stamp: reader.txts().bits(),
200            //error_state //TODO
201        }
202    }
203}