1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//!
//! Common Cyphal data types
//!

use core::convert::TryFrom;
use core::fmt;

use canadensis_core::InvalidValue;

/// Bit mask for a 29-bit CAN ID
const CAN_ID_MASK: u32 = 0x1f_ff_ff_ff;

/// A 29-bit extended CAN ID
#[derive(Eq, PartialEq, Copy, Clone, Ord, PartialOrd, Default)]
pub struct CanId(u32);

impl fmt::Debug for CanId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "CanId({:#010x})", self.0)
    }
}

impl TryFrom<u32> for CanId {
    type Error = InvalidValue;

    fn try_from(value: u32) -> core::result::Result<Self, Self::Error> {
        if (value & !CAN_ID_MASK) == 0 {
            // No bits set outside the mask, OK
            Ok(CanId(value))
        } else {
            Err(InvalidValue)
        }
    }
}

impl From<CanId> for u32 {
    fn from(id: CanId) -> Self {
        id.0
    }
}

/// Allowed maximum transmission unit (MTU) values
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum Mtu {
    /// 8 bytes, for standard CAN
    Can8 = 8,
    /// 64 bytes, for CAN FD
    #[cfg(feature = "can-fd")]
    CanFd64 = 64,
}

impl Mtu {
    /// Returns the number of bytes that this MTU represents
    pub fn as_bytes(&self) -> usize {
        *self as usize
    }
}

/// Maximum number of bytes in a frame
#[cfg(feature = "can-fd")]
pub const FRAME_CAPACITY: usize = 64;
/// Maximum number of bytes in a frame
#[cfg(not(feature = "can-fd"))]
pub const FRAME_CAPACITY: usize = 8;

/// CAN or CAN FD data frame with up to 64 bytes of data and an extended 29-bit ID
///
/// RTR/Error frames are not used and therefore not modeled here.
/// CAN frames with 11-bit ID are not used by Cyphal/CAN and so they are not supported by the library.
///
/// # Loopback
///
/// Each frame has a loopback flag.
///
/// For an outgoing frame, if loopback is true the driver should place a copy of this frame
/// in the received frame path (as if it had been received on the bus) with the copy's timestamp
/// set to the time the frame was transmitted.
///
/// For an incoming frame, if loopback is true this frame was not actually received from
/// another device. The frame timestamp is the time the original frame was sent.
///
/// This is useful for time synchronization.
///
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Frame<I> {
    /// For RX frames: reception timestamp.
    /// For TX frames: transmission deadline.
    /// The time system may be arbitrary as long as the clock is monotonic (steady).
    timestamp: I,
    /// 29-bit extended ID
    id: CanId,
    /// See "Loopback" in the struct documentation
    loopback: bool,
    /// The frame data
    data: heapless::Vec<u8, FRAME_CAPACITY>,
}

impl<I> Frame<I> {
    /// Creates a frame
    ///
    /// The loopback flag is set to false.
    ///
    /// # Panics
    /// This function will panic if the length of data is greater than FRAME_CAPACITY.
    pub fn new(timestamp: I, id: CanId, data: &[u8]) -> Self {
        Frame {
            timestamp,
            id,
            loopback: false,
            data: heapless::Vec::from_slice(data).expect("Data to large for a frame"),
        }
    }

    /// Sets the timestamp
    #[inline]
    pub fn set_timestamp(&mut self, timestamp: I) {
        self.timestamp = timestamp;
    }

    /// Sets the loopback flag
    #[inline]
    pub fn set_loopback(&mut self, loopback: bool) {
        self.loopback = loopback
    }

    /// Returns the loopback flag
    #[inline]
    pub fn loopback(&self) -> bool {
        self.loopback
    }

    /// Returns the ID of this frame
    #[inline]
    pub fn id(&self) -> CanId {
        self.id
    }
    /// Returns the data in this frame
    #[inline]
    pub fn data(&self) -> &[u8] {
        &self.data
    }
}

impl<I: Clone> Frame<I> {
    /// Returns the timestamp when this frame was received (for incoming frames)
    /// or the transmission deadline (for outgoing frames)
    #[inline]
    pub fn timestamp(&self) -> I {
        self.timestamp.clone()
    }
}