uc_frame.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Pavel Kirienko <pavel.kirienko@gmail.com>
3  */
4 
8 #include <uavcan/debug.hpp>
9 #include <cassert>
10 
11 namespace uavcan
12 {
16 uint8_t Frame::setPayload(const uint8_t* data, unsigned len)
17 {
18  const uint8_t maxlen = getPayloadCapacity();
19  len = min(unsigned(maxlen), len);
20  (void)copy(data, data + len, payload_);
21  payload_len_ = uint_fast8_t(len);
22  return static_cast<uint8_t>(len);
23 }
24 
25 template <int OFFSET, int WIDTH>
26 inline static uint32_t bitunpack(uint32_t val)
27 {
28  StaticAssert<(OFFSET >= 0)>::check();
29  StaticAssert<(WIDTH > 0)>::check();
30  StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
31  return (val >> OFFSET) & ((1UL << WIDTH) - 1);
32 }
33 
34 bool Frame::parse(const CanFrame& can_frame)
35 {
36  if (can_frame.isErrorFrame() || can_frame.isRemoteTransmissionRequest() || !can_frame.isExtended())
37  {
38  UAVCAN_TRACE("Frame", "Parsing failed at line %d", __LINE__);
39  return false;
40  }
41 
42  if (can_frame.dlc > sizeof(can_frame.data))
43  {
44  UAVCAN_ASSERT(0); // This is not a protocol error, so UAVCAN_ASSERT() is ok
45  return false;
46  }
47 
48  if (can_frame.dlc < 1)
49  {
50  UAVCAN_TRACE("Frame", "Parsing failed at line %d", __LINE__);
51  return false;
52  }
53 
54  /*
55  * CAN ID parsing
56  */
57  const uint32_t id = can_frame.id & CanFrame::MaskExtID;
58 
59  transfer_priority_ = static_cast<uint8_t>(bitunpack<24, 5>(id));
60  src_node_id_ = static_cast<uint8_t>(bitunpack<0, 7>(id));
61 
62  const bool service_not_message = bitunpack<7, 1>(id) != 0U;
63  if (service_not_message)
64  {
65  const bool request_not_response = bitunpack<15, 1>(id) != 0U;
67 
68  dst_node_id_ = static_cast<uint8_t>(bitunpack<8, 7>(id));
69  data_type_id_ = static_cast<uint16_t>(bitunpack<16, 8>(id));
70  }
71  else
72  {
75 
76  data_type_id_ = static_cast<uint16_t>(bitunpack<8, 16>(id));
77 
79  {
80  // Removing the discriminator
81  data_type_id_ = static_cast<uint16_t>(data_type_id_.get() & 3U);
82  }
83  }
84 
85  /*
86  * CAN payload parsing
87  */
88  payload_len_ = static_cast<uint8_t>(can_frame.dlc - 1U);
89  (void)copy(can_frame.data, can_frame.data + payload_len_, payload_);
90 
91  const uint8_t tail = can_frame.data[can_frame.dlc - 1U];
92 
93  start_of_transfer_ = (tail & (1U << 7)) != 0;
94  end_of_transfer_ = (tail & (1U << 6)) != 0;
95  toggle_ = (tail & (1U << 5)) != 0;
96 
98 
99  return isValid();
100 }
101 
102 template <int OFFSET, int WIDTH>
103 inline static uint32_t bitpack(uint32_t field)
104 {
105  StaticAssert<(OFFSET >= 0)>::check();
106  StaticAssert<(WIDTH > 0)>::check();
107  StaticAssert<((OFFSET + WIDTH) <= 29)>::check();
108  UAVCAN_ASSERT((field & ((1UL << WIDTH) - 1)) == field);
109  return uint32_t((field & ((1UL << WIDTH) - 1)) << OFFSET);
110 }
111 
112 bool Frame::compile(CanFrame& out_can_frame) const
113 {
114  if (!isValid())
115  {
116  UAVCAN_ASSERT(0); // This is an application error, so we need to maximize it.
117  return false;
118  }
119 
120  /*
121  * CAN ID field
122  */
123  out_can_frame.id = CanFrame::FlagEFF |
124  bitpack<0, 7>(src_node_id_.get()) |
125  bitpack<24, 5>(transfer_priority_.get());
126 
128  {
129  out_can_frame.id |=
130  bitpack<7, 1>(0U) |
131  bitpack<8, 16>(data_type_id_.get());
132  }
133  else
134  {
135  const bool request_not_response = transfer_type_ == TransferTypeServiceRequest;
136  out_can_frame.id |=
137  bitpack<7, 1>(1U) |
138  bitpack<8, 7>(dst_node_id_.get()) |
139  bitpack<15, 1>(request_not_response ? 1U : 0U) |
140  bitpack<16, 8>(data_type_id_.get());
141  }
142 
143  /*
144  * Payload
145  */
146  uint8_t tail = transfer_id_.get();
147  if (start_of_transfer_)
148  {
149  tail |= (1U << 7);
150  }
151  if (end_of_transfer_)
152  {
153  tail |= (1U << 6);
154  }
155  if (toggle_)
156  {
157  tail |= (1U << 5);
158  }
159 
160  UAVCAN_ASSERT(payload_len_ < sizeof(static_cast<CanFrame*>(UAVCAN_NULLPTR)->data));
161 
162  out_can_frame.dlc = static_cast<uint8_t>(payload_len_);
163  (void)copy(payload_, payload_ + payload_len_, out_can_frame.data);
164 
165  out_can_frame.data[out_can_frame.dlc] = tail;
166  out_can_frame.dlc++;
167 
168  /*
169  * Discriminator
170  */
172  {
173  TransferCRC crc;
174  crc.add(out_can_frame.data, out_can_frame.dlc);
175  out_can_frame.id |= bitpack<10, 14>(crc.get() & ((1U << 14) - 1U));
176  }
177 
178  return true;
179 }
180 
181 bool Frame::isValid() const
182 {
183  /*
184  * Toggle
185  */
187  {
188  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
189  return false;
190  }
191 
192  /*
193  * Node ID
194  */
196  {
197  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
198  return false;
199  }
200 
202  {
203  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
204  return false;
205  }
206 
207  /*
208  * Transfer type
209  */
211  {
212  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
213  return false;
214  }
215 
217  {
218  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
219  return false;
220  }
221 
222  // Anonymous transfers
223  if (src_node_id_.isBroadcast() &&
225  {
226  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
227  return false;
228  }
229 
230  /*
231  * Payload
232  */
234  {
235  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
236  return false;
237  }
238 
239  /*
240  * Data type ID
241  */
243  {
244  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
245  return false;
246  }
247 
248  /*
249  * Priority
250  */
252  {
253  UAVCAN_TRACE("Frame", "Validness check failed at line %d", __LINE__);
254  return false;
255  }
256 
257  return true;
258 }
259 
260 bool Frame::operator==(const Frame& rhs) const
261 {
262  return
264  (transfer_type_ == rhs.transfer_type_) &&
265  (data_type_id_ == rhs.data_type_id_) &&
266  (src_node_id_ == rhs.src_node_id_) &&
267  (dst_node_id_ == rhs.dst_node_id_) &&
268  (transfer_id_ == rhs.transfer_id_) &&
269  (toggle_ == rhs.toggle_) &&
272  (payload_len_ == rhs.payload_len_) &&
274 }
275 
276 #if UAVCAN_TOSTRING
277 std::string Frame::toString() const
278 {
279  static const int BUFLEN = 100;
280  char buf[BUFLEN];
281  int ofs = snprintf(buf, BUFLEN, "prio=%d dtid=%d tt=%d snid=%d dnid=%d sot=%d eot=%d togl=%d tid=%d payload=[",
283  int(src_node_id_.get()), int(dst_node_id_.get()),
284  int(start_of_transfer_), int(end_of_transfer_), int(toggle_), int(transfer_id_.get()));
285 
286  for (unsigned i = 0; i < payload_len_; i++)
287  {
288  // Coverity Scan complains about payload_ being not default initialized. This is OK.
289  // coverity[read_parm_fld]
290  ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), "%02x", payload_[i]);
291  if ((i + 1) < payload_len_)
292  {
293  ofs += snprintf(buf + ofs, unsigned(BUFLEN - ofs), " ");
294  }
295  }
296  (void)snprintf(buf + ofs, unsigned(BUFLEN - ofs), "]");
297  return std::string(buf);
298 }
299 #endif
300 
304 bool RxFrame::parse(const CanRxFrame& can_frame)
305 {
306  if (!Frame::parse(can_frame))
307  {
308  return false;
309  }
310  if (can_frame.ts_mono.isZero()) // Monotonic timestamps are mandatory.
311  {
312  UAVCAN_ASSERT(0); // If it is not set, it's a driver failure.
313  return false;
314  }
315  ts_mono_ = can_frame.ts_mono;
316  ts_utc_ = can_frame.ts_utc;
317  iface_index_ = can_frame.iface_index;
318  return true;
319 }
320 
321 #if UAVCAN_TOSTRING
322 std::string RxFrame::toString() const
323 {
324  std::string out = Frame::toString();
325  out.reserve(128);
326  out += " ts_m=" + ts_mono_.toString();
327  out += " ts_utc=" + ts_utc_.toString();
328  out += " iface=";
329  out += char('0' + iface_index_);
330  return out;
331 }
332 #endif
333 
334 }
uavcan::Frame::setPayload
uint8_t setPayload(const uint8_t *data, unsigned len)
Definition: uc_frame.cpp:16
check
ROSCPP_DECL bool check()
uavcan::RxFrame::parse
bool parse(const CanRxFrame &can_frame)
Definition: uc_frame.cpp:304
uavcan::CanFrame::FlagEFF
static const uint32_t FlagEFF
Extended frame format.
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:28
UAVCAN_NULLPTR
#define UAVCAN_NULLPTR
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:51
uavcan::Frame::getPayloadCapacity
uint8_t getPayloadCapacity() const
Definition: frame.hpp:69
uavcan::NodeID::isValid
bool isValid() const
Definition: transfer.hpp:134
debug.hpp
uavcan::Frame::transfer_type_
TransferType transfer_type_
Definition: frame.hpp:23
crc.hpp
uavcan::uint32_t
std::uint32_t uint32_t
Definition: std.hpp:26
uavcan::Frame::compile
bool compile(CanFrame &can_frame) const
Definition: uc_frame.cpp:112
uavcan::RxFrame::iface_index_
uint8_t iface_index_
Definition: frame.hpp:108
uavcan::NodeID::get
uint8_t get() const
Definition: transfer.hpp:132
uavcan::TransferTypeServiceResponse
@ TransferTypeServiceResponse
Definition: transfer.hpp:20
uavcan::RxFrame::ts_mono_
MonotonicTime ts_mono_
Definition: frame.hpp:106
uavcan::TransferCRC::add
void add(uint8_t byte)
Definition: crc.hpp:60
uavcan::CanFrame
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:24
uavcan::CanFrame::dlc
uint8_t dlc
Data Length Code.
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:36
UAVCAN_TRACE
#define UAVCAN_TRACE(...)
Definition: libuavcan/libuavcan/include/uavcan/debug.hpp:31
uavcan::CanRxFrame
Definition: can_io.hpp:25
uavcan::StaticAssert
struct UAVCAN_EXPORT StaticAssert
Definition: templates.hpp:29
uavcan::Frame::transfer_id_
TransferID transfer_id_
Definition: frame.hpp:28
uavcan::CanFrame::id
uint32_t id
CAN ID with flags (above)
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:34
uavcan::TransferID::Max
static const uint8_t Max
Definition: transfer.hpp:77
uavcan::TransferTypeServiceRequest
@ TransferTypeServiceRequest
Definition: transfer.hpp:21
uavcan::TransferID::get
uint8_t get() const
Definition: transfer.hpp:99
uavcan::CanFrame::isErrorFrame
bool isErrorFrame() const
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:72
uavcan::NumTransferTypes
static const uint8_t NumTransferTypes
Definition: transfer.hpp:25
uavcan::uint16_t
std::uint16_t uint16_t
Definition: std.hpp:25
uavcan::CanRxFrame::ts_utc
UtcTime ts_utc
Definition: can_io.hpp:28
uavcan::uint8_t
std::uint8_t uint8_t
Definition: std.hpp:24
frame.hpp
uavcan::Frame::transfer_priority_
TransferPriority transfer_priority_
Definition: frame.hpp:22
uavcan::bitpack
static uint32_t bitpack(uint32_t field)
Definition: uc_frame.cpp:103
uavcan::snprintf
int snprintf(char *out, std::size_t maxlen, const char *format,...)
Definition: std.hpp:73
uavcan::TransferTypeMessageBroadcast
@ TransferTypeMessageBroadcast
Definition: transfer.hpp:22
uavcan::DataTypeID::get
uint16_t get() const
Definition: data_type.hpp:69
can_io.hpp
uavcan::equal
UAVCAN_EXPORT bool equal(InputIt1 first1, InputIt1 last1, InputIt2 first2)
Definition: templates.hpp:324
uavcan::TransferPriority::get
uint8_t get() const
Definition: transfer.hpp:62
uavcan::CanFrame::MaskExtID
static const uint32_t MaskExtID
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:27
uavcan::bitunpack
static uint32_t bitunpack(uint32_t val)
Definition: uc_frame.cpp:26
uavcan::NodeID::isUnicast
bool isUnicast() const
Definition: transfer.hpp:136
uavcan::TransferPriority::isValid
bool isValid() const
Definition: transfer.hpp:64
uavcan::Frame::dst_node_id_
NodeID dst_node_id_
Definition: frame.hpp:27
toString
static std::string toString(long x)
Definition: multiset.cpp:16
uavcan::CanFrame::isRemoteTransmissionRequest
bool isRemoteTransmissionRequest() const
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:71
uavcan::Frame::src_node_id_
NodeID src_node_id_
Definition: frame.hpp:26
uavcan::TimeBase::isZero
bool isZero() const
Definition: time.hpp:123
uavcan::min
const UAVCAN_EXPORT T & min(const T &a, const T &b)
Definition: templates.hpp:281
uavcan::NodeID::Broadcast
static const NodeID Broadcast
Definition: transfer.hpp:122
uavcan::Frame::operator==
bool operator==(const Frame &rhs) const
Definition: uc_frame.cpp:260
uavcan::getDataTypeKindForTransferType
static DataTypeKind getDataTypeKindForTransferType(const TransferType tt)
Definition: data_type.hpp:28
uavcan::CanRxFrame::iface_index
uint8_t iface_index
Definition: can_io.hpp:29
uavcan::CanFrame::data
uint8_t data[MaxDataLen]
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:35
uavcan::Frame::payload_
uint8_t payload_[PayloadCapacity]
Definition: frame.hpp:21
uavcan::CanFrame::isExtended
bool isExtended() const
Definition: libuavcan/libuavcan/include/uavcan/driver/can.hpp:70
uavcan::DataTypeID::isValidForDataTypeKind
bool isValidForDataTypeKind(DataTypeKind dtkind) const
Definition: data_type.hpp:64
uavcan::Frame
Definition: frame.hpp:17
uavcan::Frame::parse
bool parse(const CanFrame &can_frame)
Definition: uc_frame.cpp:34
uavcan::Frame::isValid
bool isValid() const
Definition: uc_frame.cpp:181
uavcan::RxFrame::ts_utc_
UtcTime ts_utc_
Definition: frame.hpp:107
uavcan
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:204
uavcan::TimeBase::toString
void toString(char buf[StringBufSize]) const
Prints time in seconds with microsecond resolution.
Definition: time.hpp:238
uavcan::Frame::data_type_id_
DataTypeID data_type_id_
Definition: frame.hpp:24
uavcan::copy
UAVCAN_EXPORT OutputIt copy(InputIt first, InputIt last, OutputIt result)
Definition: templates.hpp:238
uavcan::CanRxFrame::ts_mono
MonotonicTime ts_mono
Definition: can_io.hpp:27
uavcan::Frame::toggle_
bool toggle_
Definition: frame.hpp:31
uavcan::TransferCRC
Definition: crc.hpp:28
uavcan::Frame::end_of_transfer_
bool end_of_transfer_
Definition: frame.hpp:30
uavcan::NodeID::isBroadcast
bool isBroadcast() const
Definition: transfer.hpp:135
UAVCAN_ASSERT
#define UAVCAN_ASSERT(x)
Definition: libuavcan/libuavcan/include/uavcan/build_config.hpp:184
uavcan::Frame::start_of_transfer_
bool start_of_transfer_
Definition: frame.hpp:29
uavcan::Frame::payload_len_
uint_fast8_t payload_len_
Definition: frame.hpp:25
uavcan::TransferCRC::get
uint16_t get() const
Definition: crc.hpp:75


uavcan_communicator
Author(s):
autogenerated on Fri Dec 13 2024 03:10:03