EV3UartGenerator
/home/shenghao/eclipse-workspace/EV3UartGenerator/framing.cpp
Go to the documentation of this file.
1 
11 #include <simple_endian.hpp>
12 #include <framing.hpp>
13 #include <string.h> // Need to include bare string.h for compatibility with Arduino platforms
14 
15 namespace EV3UartGenerator {
16 namespace Framing {
17  int8_t frame_sys_message(uint8_t* dest, Magics::SYS sys_type) {
18  *dest = (static_cast<uint8_t>(sys_type)
19  | static_cast<uint8_t>(Magics::SYS::SYS_BASE));
20  return 0x01;
21  }
22 
23  int8_t frame_cmd_type_message(uint8_t* dest, const uint8_t type) {
24  const uint8_t* orig_dest { dest };
25  *(dest++) = (static_cast<uint8_t>(Magics::CMD::CMD_BASE)
26  | static_cast<uint8_t>(Magics::CMD::TYPE)
27  | length_code(0x01));
28  *(dest++) = type;
29  *dest = checksum(orig_dest, 0x02);
30  return 0x03;
31  }
32 
33  int8_t frame_cmd_modes_message(uint8_t* dest, const uint8_t modes,
34  const uint8_t modes_available) {
35  const uint8_t* orig_dest { dest };
36  *(dest++) = (static_cast<uint8_t>(Magics::CMD::CMD_BASE)
37  | static_cast<uint8_t>(Magics::CMD::MODES)
38  | length_code(0x02));
39  *(dest++) = (0x07 & modes); // Mask out unused bits
40  *(dest++) = (0x07 & modes_available); // Mask out unused bits
41  *dest = checksum(orig_dest, 0x03);
42  return 0x04;
43  }
44 
45  int8_t frame_cmd_speed_message(uint8_t* dest, const uint32_t speed) {
46  const uint8_t* orig_dest { dest };
47  *(dest++) = (static_cast<uint8_t>(Magics::CMD::CMD_BASE)
48  | static_cast<uint8_t>(Magics::CMD::SPEED)
49  | length_code(sizeof(speed)));
50  uint32_t speed_conv = SimpleEndian::htole32(speed);
51  memcpy(reinterpret_cast<void*>(dest),
52  reinterpret_cast<const void*>(&speed_conv), sizeof(speed_conv));
53  dest += 4;
54  *dest = checksum(orig_dest, 0x05);
55  return 0x06;
56  }
57 
58  int8_t frame_cmd_select_message(uint8_t* dest, const uint8_t mode) {
59  const uint8_t* orig_dest { dest };
60  *(dest++) = (static_cast<uint8_t>(Magics::CMD::CMD_BASE)
61  | static_cast<uint8_t>(Magics::CMD::SELECT)
62  | length_code(sizeof(mode)));
63  *(dest++) = (0x07 & mode); // Mask out unused bits
64  *dest = checksum(orig_dest, 0x02);
65  return 0x03;
66  }
67 
68  int8_t frame_cmd_write_message(uint8_t* dest, const uint8_t* data,
69  const uint8_t len) {
70  if ((len < PAYLOAD_MIN) || (len > PAYLOAD_EV3_TO_SENSOR_MAX)) {
71  return -1; // Payload size doesn't fall into limits
72  } else {
73  const uint8_t* orig_dest { dest };
74  *(dest++) = (static_cast<uint8_t>(Magics::CMD::CMD_BASE)
75  | static_cast<uint8_t>(Magics::CMD::WRITE)
76  | length_code(len));
77  memcpy(reinterpret_cast<void*>(dest),
78  reinterpret_cast<const void*>(data), len);
79  dest += len;
80  const uint8_t padding { insert_padding(dest, len) };
81  dest += padding;
82  *dest = checksum(orig_dest, 0x01 + len + padding);
83  return (0x02 + len + padding);
84  }
85  }
86 
87  int8_t frame_info_message_name(uint8_t* dest, const uint8_t mode,
88  const char* name) {
89  const size_t name_length { name != nullptr ? strlen(name) : 0 };
90  if ((name_length < PAYLOAD_MIN) ||
91  (name_length > PAYLOAD_SENSOR_TO_EV3_MAX)) {
92  return -1; // Name length doesn't fall into limits
93  } else {
94  const uint8_t* orig_dest { dest };
95  *(dest++) = (static_cast<uint8_t>(Magics::INFO::INFO_BASE)
96  | (0x07 & mode)
97  | length_code(name_length));
98  *(dest++) = 0x00; // Special case for INFO messages - INFO type byte after type byte
99  memcpy(reinterpret_cast<void*>(dest),
100  reinterpret_cast<const void*>(name), name_length);
101  dest += name_length;
102  const uint8_t padding { insert_padding(dest, name_length) };
103  dest += padding;
104  *dest = checksum(orig_dest, 0x02 + name_length + padding);
105  return (0x03 + name_length + padding);
106  }
107  }
108 
109  int8_t frame_info_message_span(uint8_t* dest, const uint8_t mode,
110  Magics::INFO_SPAN span_type, const float lower, const float upper) {
111  const uint8_t* orig_dest { dest };
112  *(dest++) = (static_cast<uint8_t>(Magics::INFO::INFO_BASE)
113  | (0x07 & mode)
114  | length_code(sizeof(lower) + sizeof(upper)));
115  *(dest++) = static_cast<uint8_t>(span_type); // Special case for INFO messages - INFO type byte after type byte
116 
117  uint32_t temp; // Memcpying between two temporaries is needed in case float is not aligned the same as a 4-byte integer
118  float tempf;
119 
120  memcpy(reinterpret_cast<void*>(&temp),
121  reinterpret_cast<const void*>(&lower), sizeof(lower));
122  temp = SimpleEndian::htole32(temp);
123  memcpy(reinterpret_cast<void*>(&tempf),
124  reinterpret_cast<const void*>(&temp), sizeof(temp));
125  memcpy(reinterpret_cast<void*>(dest),
126  reinterpret_cast<const void*>(&tempf), sizeof(tempf));
127  dest += sizeof(tempf);
128 
129  memcpy(reinterpret_cast<void*>(&temp),
130  reinterpret_cast<const void*>(&upper), sizeof(upper));
131  temp = SimpleEndian::htole32(temp);
132  memcpy(reinterpret_cast<void*>(&tempf),
133  reinterpret_cast<const void*>(&temp), sizeof(temp));
134  memcpy(reinterpret_cast<void*>(dest),
135  reinterpret_cast<const void*>(&tempf), sizeof(tempf));
136  dest += sizeof(tempf);
137 
138  *dest = checksum(orig_dest, 0x0a);
139  return 0x0b;
140  }
141 
142  int8_t frame_info_message_symbol(uint8_t* dest, const uint8_t mode,
143  const char* symbol) {
144  const size_t symbol_length { symbol != nullptr ? strlen(symbol) : 0 };
145  if ((symbol_length < PAYLOAD_MIN) ||
146  (symbol_length > SYMBOL_MAX)) {
147  return -1; // Name length doesn't fall into limits
148  } else {
149  const uint8_t* orig_dest { dest };
150  *(dest++) = (static_cast<uint8_t>(Magics::INFO::INFO_BASE)
151  | (0x07 & mode)
152  | length_code(0x08)); // Length hardcoded to 8
153  *(dest++) = 0x04; // Special case for INFO messages - INFO type byte after type byte
154  memcpy(reinterpret_cast<void*>(dest),
155  reinterpret_cast<const void*>(symbol), symbol_length);
156  dest += symbol_length;
157 
158  const uint8_t padding { 0x08 - symbol_length };
159  for (uint8_t i = 0; i < padding; i++)
160  *(dest++) = 0x00;
161 
162  *dest = checksum(orig_dest, 0x02 + symbol_length + padding);
163  return (0x03 + symbol_length + padding);
164  }
165  }
166 
167  int8_t frame_info_message_format(uint8_t* dest, const uint8_t mode,
168  const uint8_t elems,
169  Magics::INFO_DTYPE data_type, const uint8_t width,
170  const uint8_t decimals) {
171  const uint8_t* orig_dest { dest };
172  *(dest++) = (static_cast<uint8_t>(Magics::INFO::INFO_BASE)
173  | (0x07 & mode)
174  | length_code(0x04));
175  *(dest++) = 0x80; // Special case for INFO messages - INFO type byte after type byte
176  *(dest++) = (0x3f & elems);
177  *(dest++) = (0x03 & static_cast<uint8_t>(data_type));
178  *(dest++) = (0x0f & width);
179  *(dest++) = (0x0f & decimals);
180  *dest = checksum(orig_dest, 0x02 + 0x04);
181  return (0x07);
182  }
183 
184  int8_t frame_data_message(uint8_t* dest, const uint8_t mode,
185  const uint8_t* data, const uint8_t len) {
186  if ((len < PAYLOAD_MIN) || (len > PAYLOAD_SENSOR_TO_EV3_MAX)) {
187  return -1;
188  } else {
189  const uint8_t* orig_dest { dest };
190  *(dest++) = (static_cast<uint8_t>(Magics::DATA::DATA_BASE)
191  | (0x07 & mode)
192  | length_code(len));
193  memcpy(reinterpret_cast<void*>(dest),
194  reinterpret_cast<const void*>(data), len);
195  dest += len;
196  const uint8_t padding { insert_padding(dest, len) };
197  dest += padding;
198  *dest = checksum(orig_dest, 0x01 + len + padding);
199  return (0x02 + len + padding);
200  }
201  }
202 
203  uint8_t checksum(const uint8_t* buf, const uint8_t len) {
204  uint8_t acc { 0xff };
205  for (uint8_t i = 0; i < len; i++) {
206  acc ^= buf[i];
207  }
208  return acc;
209  }
210 
211  uint8_t insert_padding(uint8_t* dest, uint8_t len) {
212  const uint8_t padding = { ((0x01 << log2(len)) - len) };
213  for (uint8_t i = 0; i < padding; i++) {
214  *(dest++) = 0x00;
215  }
216  return padding;
217  }
218 
219 }
220 }
221 
222 
223 
224 
int8_t frame_data_message(uint8_t *dest, const uint8_t mode, const uint8_t *data, const uint8_t len)
Definition: framing.cpp:184
uint8_t checksum(const uint8_t *buf, const uint8_t len)
Definition: framing.cpp:203
int8_t frame_info_message_format(uint8_t *dest, const uint8_t mode, const uint8_t elems, Magics::INFO_DTYPE data_type, const uint8_t width, const uint8_t decimals)
Definition: framing.cpp:167
int8_t frame_cmd_modes_message(uint8_t *dest, const uint8_t modes, const uint8_t modes_available)
Definition: framing.cpp:33
constexpr uint8_t log2(uint8_t val)
Definition: framing.hpp:256
int8_t frame_cmd_write_message(uint8_t *dest, const uint8_t *data, const uint8_t len)
Definition: framing.cpp:68
constexpr uint8_t PAYLOAD_EV3_TO_SENSOR_MAX
Maximum size of any payload sent in the EV3 UART sensor protocol, in bytes, from the EV3 to the senso...
Definition: framing.hpp:40
int8_t frame_info_message_name(uint8_t *dest, const uint8_t mode, const char *name)
Definition: framing.cpp:87
int8_t frame_cmd_select_message(uint8_t *dest, const uint8_t mode)
Definition: framing.cpp:58
constexpr uint8_t PAYLOAD_SENSOR_TO_EV3_MAX
Maximum size of any payload sent in the EV3 UART sensor protocol, in bytes, to the EV3...
Definition: framing.hpp:39
int8_t frame_sys_message(uint8_t *dest, Magics::SYS sys_type)
Definition: framing.cpp:17
int8_t frame_info_message_symbol(uint8_t *dest, const uint8_t mode, const char *symbol)
Definition: framing.cpp:142
constexpr uint8_t PAYLOAD_MIN
Minimum size of any payload sent in the EV3 UART sensor protocol, regardless of direction, in bytes.
Definition: framing.hpp:41
int8_t frame_info_message_span(uint8_t *dest, const uint8_t mode, Magics::INFO_SPAN span_type, const float lower, const float upper)
Definition: framing.cpp:109
int8_t frame_cmd_speed_message(uint8_t *dest, const uint32_t speed)
Definition: framing.cpp:45
constexpr uint8_t length_code(uint8_t len)
Definition: framing.hpp:270
int8_t frame_cmd_type_message(uint8_t *dest, const uint8_t type)
Definition: framing.cpp:23
constexpr uint8_t SYMBOL_MAX
Maximum length of the string representation (ASCII) of any symbol referencing a the SI unit used to r...
Definition: framing.hpp:42
uint8_t insert_padding(uint8_t *dest, uint8_t len)
Definition: framing.cpp:211