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()
}
}