Skip to main content

rs_can/frame/
mod.rs

1pub(crate) mod identifier;
2
3use self::identifier::{CanFdFlags, Id};
4use crate::utils;
5use crate::CanResult;
6use std::fmt::{Display, Formatter, Write};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9pub enum TimestampSource {
10    System,
11    Hardware,
12    Unknown,
13}
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct Timestamp {
17    pub nanos: u128,
18    pub source: TimestampSource,
19}
20
21#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
22pub enum FrameFormat {
23    #[default]
24    Data,
25    Remote,
26    Error,
27}
28
29#[repr(C)]
30#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
31pub enum Kind {
32    #[default]
33    Classical,
34    FD,
35    XL,
36}
37
38#[repr(C)]
39#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
40pub enum Direction {
41    #[default]
42    Transmit,
43    Receive,
44}
45
46impl Display for Direction {
47    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
48        match self {
49            Self::Transmit => f.write_str("Tx"),
50            Self::Receive => f.write_str("Rx"),
51        }
52    }
53}
54
55/// CAN 2.0 | CAN 1.0
56pub trait Frame: Send + Sync {
57    type Channel: Display;
58
59    fn new_can(id: Id, data: &[u8]) -> CanResult<Self>
60    where
61        Self: Sized;
62
63    fn new_remote(id: Id, dlc: u8) -> CanResult<Self>
64    where
65        Self: Sized;
66
67    fn new_can_fd(id: Id, data: &[u8], flags: CanFdFlags) -> CanResult<Self>
68    where
69        Self: Sized;
70
71    fn id(&self) -> Id;
72    fn channel(&self) -> Self::Channel;
73    fn set_channel(&mut self, v: Self::Channel) -> &mut Self
74    where
75        Self: Sized;
76
77    fn kind(&self) -> Kind;
78    fn format(&self) -> FrameFormat;
79
80    fn data(&self) -> &[u8];
81    fn len(&self) -> usize;
82    fn dlc(&self) -> CanResult<u8> {
83        utils::can_dlc(self.len(), self.kind())
84    }
85
86    fn direction(&self) -> Direction;
87    fn set_direction(&mut self, d: Direction) -> &mut Self
88    where
89        Self: Sized;
90
91    fn timestamp(&self) -> Option<Timestamp>;
92    fn set_timestamp(&mut self, ts: Option<Timestamp>) -> &mut Self
93    where
94        Self: Sized;
95
96    fn is_bitrate_switch(&self) -> bool;
97    fn set_bitrate_switch(&mut self, v: bool) -> &mut Self
98    where
99        Self: Sized;
100
101    fn is_remote(&self) -> bool {
102        matches!(self.format(), FrameFormat::Remote)
103    }
104
105    fn is_error_frame(&self) -> bool {
106        matches!(self.format(), FrameFormat::Error)
107    }
108
109    fn is_extended(&self) -> bool {
110        matches!(self.id(), Id::Extended(_))
111    }
112
113    fn is_esi(&self) -> bool;
114    fn set_esi(&mut self, v: bool) -> &mut Self
115    where
116        Self: Sized;
117}
118
119impl<T: Display> Display for dyn Frame<Channel = T> {
120    /// Output Frame as `asc` String.
121    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
122        let data_str = if self.is_remote() {
123            " ".to_owned()
124        } else {
125            self.data().iter().fold(String::new(), |mut out, &b| {
126                let _ = write!(out, "{b:02x} ");
127                out
128            })
129        };
130
131        match self.kind() {
132            Kind::Classical => {
133                let timestamp_secs = self
134                    .timestamp()
135                    .map(|ts| ts.nanos as f64 / 1_000_000_000.)
136                    .unwrap_or_default();
137                write!(
138                    f,
139                    "{:.3} {} {}{: <4} {} {} {} {}",
140                    timestamp_secs,
141                    self.channel(),
142                    format!("{: >8x}", self.id().as_raw()),
143                    if self.is_extended() { "x" } else { "" },
144                    self.direction(),
145                    // if self.is_rx() { "Rx" } else { "Tx" },
146                    if self.is_remote() { "r" } else { "d" },
147                    format!("{: >2}", self.len()),
148                    data_str,
149                )
150            }
151            Kind::FD => {
152                let timestamp_secs = self
153                    .timestamp()
154                    .map(|ts| ts.nanos as f64 / 1_000_000_000.)
155                    .unwrap_or_default();
156                let dlc = self.dlc().map_err(|_| std::fmt::Error)?;
157                let mut flags = 1 << 12;
158                write!(
159                    f,
160                    "{:.3} CANFD {} {} {} {} {} {} {} {} {} {} {} {} {} {} {} {}",
161                    timestamp_secs,
162                    self.channel(),
163                    self.direction(),
164                    // if self.is_rx() { "Rx" } else { "Tx" },
165                    format!("{: >8x}", self.id().as_raw()),
166                    if self.is_bitrate_switch() {
167                        flags |= 1 << 13;
168                        1
169                    } else {
170                        0
171                    },
172                    if self.is_esi() {
173                        flags |= 1 << 14;
174                        1
175                    } else {
176                        0
177                    },
178                    format!("{: >2}", dlc),
179                    format!("{: >2}", self.len()),
180                    data_str,
181                    format!("{: >8}", 0), // message_duration
182                    format!("{: <4}", 0), // message_length
183                    format!("{: >8x}", flags),
184                    format!("{: >8}", 0), // crc
185                    format!("{: >8}", 0), // bit_timing_conf_arb
186                    format!("{: >8}", 0), // bit_timing_conf_data
187                    format!("{: >8}", 0), // bit_timing_conf_ext_arb
188                    format!("{: >8}", 0), // bit_timing_conf_ext_data
189                )
190            }
191            Kind::XL => {
192                // TODO
193                write!(f, "CANXL Frame")
194            }
195        }
196    }
197}