rs_can/frame/
mod.rs

1mod identifier;
2pub use identifier::*;
3
4use crate::utils::can_dlc;
5use std::fmt::{Display, Formatter, Write};
6
7#[repr(C)]
8#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
9pub enum Type {
10    #[default]
11    Can,
12    CanFd,
13    CanXl,
14}
15
16#[repr(C)]
17#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
18pub enum Direct {
19    #[default]
20    Transmit,
21    Receive,
22}
23
24impl Display for Direct {
25    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
26        match self {
27            Self::Transmit => f.write_str("Tx"),
28            Self::Receive => f.write_str("Rx"),
29        }
30    }
31}
32
33/// CAN 2.0 | CAN 1.0
34pub trait Frame: Send + Sync {
35    type Channel: Display;
36
37    fn new(id: impl Into<Id>, data: &[u8]) -> Option<Self>
38    where
39        Self: Sized;
40
41    fn new_remote(id: impl Into<Id>, len: usize) -> Option<Self>
42    where
43        Self: Sized;
44
45    fn timestamp(&self) -> u64;
46
47    fn set_timestamp(&mut self, value: Option<u64>) -> &mut Self
48    where
49        Self: Sized;
50
51    /// Prioritizes returning J1939Id if j1939 is true.
52    fn id(&self) -> Id;
53
54    fn can_type(&self) -> Type;
55
56    fn set_can_type(&mut self, r#type: Type) -> &mut Self
57    where
58        Self: Sized;
59
60    fn is_remote(&self) -> bool;
61
62    fn is_extended(&self) -> bool;
63
64    fn direct(&self) -> Direct;
65
66    fn set_direct(&mut self, direct: Direct) -> &mut Self
67    where
68        Self: Sized;
69
70    fn is_bitrate_switch(&self) -> bool;
71
72    fn set_bitrate_switch(&mut self, value: bool) -> &mut Self
73    where
74        Self: Sized;
75
76    fn is_error_frame(&self) -> bool;
77
78    fn set_error_frame(&mut self, value: bool) -> &mut Self
79    where
80        Self: Sized;
81
82    /// Error state indicator
83    fn is_esi(&self) -> bool;
84
85    /// Set error state indicator
86    fn set_esi(&mut self, value: bool) -> &mut Self
87    where
88        Self: Sized;
89
90    fn channel(&self) -> Self::Channel;
91
92    fn set_channel(&mut self, value: Self::Channel) -> &mut Self
93    where
94        Self: Sized;
95
96    /// ensure return the actual length of data.
97    fn data(&self) -> &[u8];
98
99    fn dlc(&self) -> isize {
100        can_dlc(self.length(), self.can_type())
101    }
102
103    fn length(&self) -> usize;
104}
105
106impl<T: Display> Display for dyn Frame<Channel = T> {
107    /// Output Frame as `asc` String.
108    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
109        let data_str = if self.is_remote() {
110            " ".to_owned()
111        } else {
112            self.data().iter().fold(String::new(), |mut out, &b| {
113                let _ = write!(out, "{b:02x} ");
114                out
115            })
116        };
117
118        match self.can_type() {
119            Type::Can => {
120                write!(
121                    f,
122                    "{:.3} {} {}{: <4} {} {} {} {}",
123                    self.timestamp() as f64 / 1000.,
124                    self.channel(),
125                    format!("{: >8x}", self.id().into_bits()),
126                    if self.is_extended() { "x" } else { "" },
127                    self.direct(),
128                    // if self.is_rx() { "Rx" } else { "Tx" },
129                    if self.is_remote() { "r" } else { "d" },
130                    format!("{: >2}", self.length()),
131                    data_str,
132                )
133            }
134            Type::CanFd => {
135                let mut flags = 1 << 12;
136                write!(
137                    f,
138                    "{:.3} CANFD {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}",
139                    self.timestamp() as f64 / 1000.,
140                    self.channel(),
141                    self.direct(),
142                    // if self.is_rx() { "Rx" } else { "Tx" },
143                    format!("{: >8x}", self.id().into_bits()),
144                    if self.is_bitrate_switch() {
145                        flags |= 1 << 13;
146                        1
147                    } else {
148                        0
149                    },
150                    if self.is_esi() {
151                        flags |= 1 << 14;
152                        1
153                    } else {
154                        0
155                    },
156                    format!("{: >2}", self.dlc()),
157                    format!("{: >2}", self.length()),
158                    data_str,
159                    format!("{: >8}", 0), // message_duration
160                    format!("{: <4}", 0), // message_length
161                    format!("{: >8x}", flags),
162                    format!("{: >8}", 0), // crc
163                    format!("{: >8}", 0), // bit_timing_conf_arb
164                    format!("{: >8}", 0), // bit_timing_conf_data
165                    format!("{: >8}", 0), // bit_timing_conf_ext_arb
166                    format!("{: >8}", 0), // bit_timing_conf_ext_data
167                )
168            }
169            Type::CanXl => {
170                // TODO
171                write!(f, "CANXL Frame")
172            }
173        }
174    }
175}