mod fd_flags;
#[cfg(feature = "can")]
mod simple_fd_frame;
pub use fd_flags::FdFlags;
#[cfg(feature = "can")]
pub use simple_fd_frame::SimpleFdFrame;
pub const MAX_FD_DATA_LEN: usize = 64;
#[inline]
pub const fn dlc_to_len(dlc: u8) -> usize {
match dlc {
0..=8 => dlc as usize,
9 => 12,
10 => 16,
11 => 20,
12 => 24,
13 => 32,
14 => 48,
15 => 64,
_ => 64, }
}
#[inline]
pub const fn len_to_dlc(len: usize) -> u8 {
match len {
0 => 0,
1 => 1,
2 => 2,
3 => 3,
4 => 4,
5 => 5,
6 => 6,
7 => 7,
8 => 8,
9..=12 => 9,
13..=16 => 10,
17..=20 => 11,
21..=24 => 12,
25..=32 => 13,
33..=48 => 14,
_ => 15, }
}
#[cfg(feature = "can")]
pub trait FdFrame: Sized {
fn new_fd(id: impl Into<embedded_can::Id>, data: &[u8], flags: FdFlags) -> Option<Self>;
fn is_fd(&self) -> bool;
fn fd_flags(&self) -> FdFlags;
fn id(&self) -> embedded_can::Id;
fn dlc(&self) -> usize;
fn data_len(&self) -> usize {
if self.is_fd() {
dlc_to_len(self.dlc() as u8)
} else {
self.dlc().min(8)
}
}
fn data(&self) -> &[u8];
fn is_extended(&self) -> bool {
matches!(self.id(), embedded_can::Id::Extended(_))
}
fn is_standard(&self) -> bool {
!self.is_extended()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_dlc_to_len() {
assert_eq!(dlc_to_len(0), 0);
assert_eq!(dlc_to_len(8), 8);
assert_eq!(dlc_to_len(9), 12);
assert_eq!(dlc_to_len(10), 16);
assert_eq!(dlc_to_len(11), 20);
assert_eq!(dlc_to_len(12), 24);
assert_eq!(dlc_to_len(13), 32);
assert_eq!(dlc_to_len(14), 48);
assert_eq!(dlc_to_len(15), 64);
}
#[test]
fn test_len_to_dlc() {
assert_eq!(len_to_dlc(0), 0);
assert_eq!(len_to_dlc(8), 8);
assert_eq!(len_to_dlc(12), 9);
assert_eq!(len_to_dlc(16), 10);
assert_eq!(len_to_dlc(20), 11);
assert_eq!(len_to_dlc(24), 12);
assert_eq!(len_to_dlc(32), 13);
assert_eq!(len_to_dlc(48), 14);
assert_eq!(len_to_dlc(64), 15);
assert_eq!(len_to_dlc(10), 9); assert_eq!(len_to_dlc(50), 15); }
#[test]
fn test_fd_flags() {
let flags = FdFlags::new(true, false);
assert!(flags.brs());
assert!(!flags.esi());
assert_eq!(flags.to_byte(), 0x01);
let flags = FdFlags::new(false, true);
assert!(!flags.brs());
assert!(flags.esi());
assert_eq!(flags.to_byte(), 0x02);
let flags = FdFlags::new(true, true);
assert_eq!(flags.to_byte(), 0x03);
let flags = FdFlags::from_byte(0x03);
assert!(flags.brs());
assert!(flags.esi());
}
#[cfg(feature = "can")]
#[test]
fn test_simple_fd_frame_classic() {
use embedded_can::StandardId;
let id = StandardId::new(0x100).unwrap();
let frame = SimpleFdFrame::new_classic(id, &[1, 2, 3, 4, 5, 6, 7, 8]).unwrap();
assert!(!frame.is_fd());
assert_eq!(frame.data(), &[1, 2, 3, 4, 5, 6, 7, 8]);
assert!(!frame.fd_flags().brs());
assert!(!frame.fd_flags().esi());
}
#[cfg(feature = "can")]
#[test]
fn test_simple_fd_frame_fd() {
use embedded_can::StandardId;
let id = StandardId::new(0x100).unwrap();
let data = [0xAAu8; 32];
let flags = FdFlags::new(true, false);
let frame = SimpleFdFrame::new_fd_frame(id, &data, flags).unwrap();
assert!(frame.is_fd());
assert_eq!(frame.data().len(), 32);
assert!(frame.fd_flags().brs());
assert!(!frame.fd_flags().esi());
}
#[cfg(feature = "can")]
#[test]
fn test_simple_fd_frame_max_size() {
use embedded_can::StandardId;
let id = StandardId::new(0x100).unwrap();
let data = [0xBBu8; 64];
let frame = SimpleFdFrame::new_fd_frame(id, &data, FdFlags::default()).unwrap();
assert!(frame.is_fd());
assert_eq!(frame.data().len(), 64);
}
#[cfg(feature = "can")]
#[test]
fn test_simple_fd_frame_too_large() {
use embedded_can::StandardId;
let id = StandardId::new(0x100).unwrap();
let data = [0u8; 65]; assert!(SimpleFdFrame::new_fd_frame(id, &data, FdFlags::default()).is_none());
}
}