1use bytes::Bytes;
42use embedded_can::{ExtendedId, Id, StandardId};
43use log::debug;
44use modular_bitfield_msb::prelude::*;
45
46pub const STANDARD_IDENTIFIER_MASK: u16 = 0x7FF;
47
48pub const EXTENDED_IDENTIFIER_MASK: u32 = 0x3FFFF;
49
50pub const MAX_PAYLOAD_CAN_2_0: usize = 8;
51
52pub const MAX_PAYLOAD_CAN_FD: usize = 64;
53
54#[derive(BitfieldSpecifier, Debug, Eq, PartialEq, Ord, PartialOrd, Copy, Clone)]
56#[allow(clippy::upper_case_acronyms)]
57#[bits = 4]
58pub enum DLC {
59 Zero,
60 One,
61 Two,
62 Three,
63 Four,
64 Five,
65 Six,
66 Seven,
67 Eight,
68 Twelve,
69 Sixteen,
70 Twenty,
71 TwentyFour,
72 ThirtyTwo,
73 FortyEight,
74 SixtyFour,
75}
76
77#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
79pub enum MessageError {
80 InvalidLength(usize),
82 InvalidTypeSize(usize),
84}
85
86impl DLC {
87 fn from_length(value: usize) -> Result<Self, MessageError> {
88 match value {
89 0 => Ok(Self::Zero),
90 1 => Ok(Self::One),
91 2 => Ok(Self::Two),
92 3 => Ok(Self::Three),
93 4 => Ok(Self::Four),
94 5 => Ok(Self::Five),
95 6 => Ok(Self::Six),
96 7 => Ok(Self::Seven),
97 8 => Ok(Self::Eight),
98 12 => Ok(Self::Twelve),
99 16 => Ok(Self::Sixteen),
100 20 => Ok(Self::Twenty),
101 24 => Ok(Self::TwentyFour),
102 32 => Ok(Self::ThirtyTwo),
103 48 => Ok(Self::FortyEight),
104 64 => Ok(Self::SixtyFour),
105 val => Err(MessageError::InvalidLength(val)),
106 }
107 }
108}
109
110#[bitfield(bits = 64)]
112#[derive(BitfieldSpecifier, Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Default)]
113pub struct TxHeader {
114 #[skip]
116 __: B2,
117 pub sid11: bool,
119 pub extended_identifier: B18,
121 pub standard_identifier: B11,
123 #[skip]
125 __: B16,
126 pub sequence: B7,
128 pub error_status_indicator: bool,
130 pub fd_frame: bool,
132 pub bit_rate_switch: bool,
134 pub remote_transmission_request: bool,
136 pub identifier_extension_flag: bool,
138 pub data_length_code: DLC,
140}
141
142pub trait MessageType<const L: usize> {
143 fn setup_header(&self, header: &mut TxHeader, payload_length: usize) -> Result<(), MessageError>;
145}
146
147#[derive(Debug, Copy, Clone)]
150pub struct Can20<const L: usize> {}
151
152impl<const L: usize> MessageType<L> for Can20<L> {
153 fn setup_header(&self, _header: &mut TxHeader, payload_length: usize) -> Result<(), MessageError> {
154 if L > 8 || payload_length > 8 {
155 let max = payload_length.max(L);
156 debug!("Maximum of 64 bytes allowed. Current size: {max} bytes");
157 return Err(MessageError::InvalidLength(max));
158 }
159
160 if payload_length > L {
161 debug!("Payload length {payload_length} must be less than or equal {L}");
162 return Err(MessageError::InvalidLength(payload_length));
163 }
164
165 if L % 4 != 0 {
166 debug!("CAN2.0 generic argument must be 4 or 8");
167 return Err(MessageError::InvalidTypeSize(L));
168 }
169
170 Ok(())
171 }
172}
173#[derive(Debug, Copy, Clone)]
176pub struct CanFd<const L: usize> {
177 pub bitrate_switch: bool,
178}
179
180impl<const L: usize> MessageType<L> for CanFd<L> {
181 fn setup_header(&self, header: &mut TxHeader, payload_length: usize) -> Result<(), MessageError> {
182 if L > 64 || payload_length > 64 {
183 let max = payload_length.max(L);
184 debug!("Maximum of 64 bytes allowed. Current size: {max} bytes");
185 return Err(MessageError::InvalidLength(max));
186 }
187
188 if payload_length > L {
189 debug!("Payload length {payload_length} must be less than or equal {L}");
190 return Err(MessageError::InvalidLength(payload_length));
191 }
192
193 if L % 4 != 0 {
194 debug!("CANFD generic argument must be a multiple of 4");
195 return Err(MessageError::InvalidTypeSize(L));
196 }
197
198 header.set_bit_rate_switch(self.bitrate_switch);
199 header.set_fd_frame(true);
200 Ok(())
201 }
202}
203
204#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
206pub struct TxMessage<T: MessageType<L>, const L: usize> {
207 pub(crate) header: TxHeader,
209 pub(crate) buff: Bytes,
211 pub(crate) message_type: T,
213}
214
215impl<T: MessageType<L>, const L: usize> TxMessage<T, L> {
216 pub fn new(message_type: T, data: Bytes, identifier: Id) -> Result<Self, MessageError> {
218 let mut header = TxHeader::new();
219
220 let mut payload_length = data.len();
221
222 message_type.setup_header(&mut header, payload_length)?;
223
224 while let Err(MessageError::InvalidLength(_)) = DLC::from_length(payload_length) {
226 payload_length += 1;
227 }
228
229 header.set_data_length_code(DLC::from_length(payload_length)?);
230
231 match identifier {
232 Id::Standard(sid) => header.set_standard_identifier(sid.as_raw()),
233 Id::Extended(eid) => {
234 header.set_extended_identifier(eid.as_raw() & EXTENDED_IDENTIFIER_MASK);
235 header.set_standard_identifier((eid.as_raw() >> 18) as u16 & STANDARD_IDENTIFIER_MASK);
236 header.set_identifier_extension_flag(true);
237 }
238 }
239
240 Ok(TxMessage {
241 header,
242 buff: data,
243 message_type,
244 })
245 }
246
247 pub fn get_payload(&self) -> &[u8] {
249 self.buff.as_ref()
250 }
251
252 pub fn get_header(&self) -> &TxHeader {
254 &self.header
255 }
256}
257
258#[bitfield(bits = 64)]
260#[derive(Default, PartialEq, Eq, Debug)]
261#[repr(u64)]
262pub struct RxHeader {
263 #[skip]
265 __: B2,
266 sid11: bool,
268 extended_identifier: B18,
270 standard_identifier: B11,
272 #[skip]
273 __: B16,
274 filter_hit: B5,
276 #[skip]
277 __: B2,
278 error_status_indicator: bool,
280 fd_frame: bool,
282 bit_rate_switch: bool,
284 remote_transmission_request: bool,
286 identifier_extension_flag: bool,
288 data_length_code: DLC,
290}
291
292impl RxHeader {
293 fn get_id(&self) -> Id {
294 if self.identifier_extension_flag() {
295 let id = ((self.standard_identifier() as u32) << 18) | (self.extended_identifier());
296 let extended_id = ExtendedId::new(id);
297 Id::Extended(extended_id.unwrap())
298 } else {
299 let id = StandardId::new(self.standard_identifier());
300 Id::Standard(id.unwrap())
301 }
302 }
303
304 #[cfg(test)]
305 pub fn new_test_cfg(identifier: Id) -> Self {
306 match identifier {
307 Id::Extended(eid) => Self::new()
308 .with_data_length_code(DLC::Eight)
309 .with_standard_identifier((eid.as_raw() >> 18) as u16 & STANDARD_IDENTIFIER_MASK)
310 .with_extended_identifier(eid.as_raw() & EXTENDED_IDENTIFIER_MASK)
311 .with_identifier_extension_flag(true),
312 Id::Standard(sid) => Self::new()
313 .with_data_length_code(DLC::Eight)
314 .with_standard_identifier(sid.as_raw()),
315 }
316 }
317}