knx
ETS configurable knx-stack
bits.cpp
Go to the documentation of this file.
1 #include "bits.h"
2 #include <cstring> // for memcpy()
3 
4 const uint8_t* popByte(uint8_t& b, const uint8_t* data)
5 {
6  b = *data;
7  data += 1;
8  return data;
9 }
10 
11 #ifndef KNX_NO_PRINT
12 void printHex(const char* suffix, const uint8_t* data, size_t length, bool newline)
13 {
14  print(suffix);
15 
16  for (size_t i = 0; i < length; i++)
17  {
18  if (data[i] < 0x10)
19  {
20  print("0");
21  }
22 
23  print(data[i], HEX);
24  print(" ");
25  }
26 
27  if (newline)
28  {
29  println();
30  }
31 }
32 #endif
33 
34 const uint8_t* popWord(uint16_t& w, const uint8_t* data)
35 {
36  w = getWord(data);
37  data += 2;
38  return data;
39 }
40 
41 const uint8_t* popInt(uint32_t& i, const uint8_t* data)
42 {
43  i = getInt(data);
44  data += 4;
45  return data;
46 }
47 
48 const uint8_t* popByteArray(uint8_t* dst, uint32_t size, const uint8_t* data)
49 {
50  for (uint32_t i = 0; i < size; i++)
51  dst[i] = data[i];
52 
53  data += size;
54  return data;
55 }
56 
57 uint8_t* pushByte(uint8_t b, uint8_t* data)
58 {
59  data[0] = b;
60  data += 1;
61  return data;
62 }
63 
64 uint8_t* pushWord(uint16_t w, uint8_t* data)
65 {
66  data[0] = ((w >> 8) & 0xff);
67  data[1] = (w & 0xff);
68  data += 2;
69  return data;
70 }
71 
72 uint8_t* pushInt(uint32_t i, uint8_t* data)
73 {
74  data[0] = ((i >> 24) & 0xff);
75  data[1] = ((i >> 16) & 0xff);
76  data[2] = ((i >> 8) & 0xff);
77  data[3] = (i & 0xff);
78  data += 4;
79  return data;
80 }
81 
82 uint8_t* pushByteArray(const uint8_t* src, uint32_t size, uint8_t* data)
83 {
84  for (uint32_t i = 0; i < size; i++)
85  data[i] = src[i];
86 
87  data += size;
88  return data;
89 }
90 
91 uint16_t getWord(const uint8_t* data)
92 {
93  return (data[0] << 8) + data[1];
94 }
95 
96 uint32_t getInt(const uint8_t* data)
97 {
98  return (data[0] << 24) + (data[1] << 16) + (data[2] << 8) + data[3];
99 }
100 
101 void sixBytesFromUInt64(uint64_t num, uint8_t* toByteArray)
102 {
103  toByteArray[0] = ((num >> 40) & 0xff);
104  toByteArray[1] = ((num >> 32) & 0xff);
105  toByteArray[2] = ((num >> 24) & 0xff);
106  toByteArray[3] = ((num >> 16) & 0xff);
107  toByteArray[4] = ((num >> 8) & 0xff);
108  toByteArray[5] = (num & 0xff);
109 }
110 
111 uint64_t sixBytesToUInt64(uint8_t* data)
112 {
113  uint64_t l = 0;
114 
115  for (uint8_t i = 0; i < 6; i++)
116  {
117  l = (l << 8) + data[i];
118  }
119 
120  return l;
121 }
122 
123 // The CRC of the Memory Control Block Table Property is a CRC16-CCITT with the following
124 // parameters:
125 // Width = 16 bit
126 // Truncated polynomial = 1021h
127 // Initial value = FFFFh
128 // Input date is NOT reflected.
129 // Output CRC is NOT reflected.
130 // No XOR is performed on the output CRC.
131 // EXAMPLE The correct CRC16-CCITT of the string ‘123456789’ is E5CCh.
132 
133 uint16_t crc16Ccitt(uint8_t* input, uint16_t length)
134 {
135  uint32_t polynom = 0x1021;
136 
137  uint32_t result = 0xffff;
138 
139  for (uint32_t i = 0; i < 8 * ((uint32_t)length + 2); i++)
140  {
141  result <<= 1;
142  uint32_t nextBit;
143  nextBit = ((i / 8) < length) ? ((input[i / 8] >> (7 - (i % 8))) & 0x1) : 0;
144  result |= nextBit;
145 
146  if ((result & 0x10000) != 0)
147  result ^= polynom;
148  }
149 
150  return result & 0xffff;
151 }
152 
153 uint16_t crc16Dnp(uint8_t* input, uint16_t length)
154 {
155  // CRC-16-DNP
156  // generator polynomial = 2^16 + 2^13 + 2^12 + 2^11 + 2^10 + 2^8 + 2^6 + 2^5 + 2^2 + 2^0
157  uint32_t pn = 0x13d65; // 1 0011 1101 0110 0101
158 
159  // for much data, using a lookup table would be a way faster CRC calculation
160  uint32_t crc = 0;
161 
162  for (uint32_t i = 0; i < length; i++)
163  {
164  uint8_t bite = input[i] & 0xff;
165 
166  for (uint8_t b = 8; b -- > 0;)
167  {
168  bool bit = ((bite >> b) & 1) == 1;
169  bool one = (crc >> 15 & 1) == 1;
170  crc <<= 1;
171 
172  if (one ^ bit)
173  crc ^= pn;
174  }
175  }
176 
177  return (~crc) & 0xffff;
178 }
179 
180 // Produce Arduino print and println in ESP IDF for ESP32 family using printf().
181 #ifndef ARDUINO
182 #ifdef ESP_PLATFORM
183  // Helper function to print a number in binary format
184  static void print_binary(unsigned long long n)
185  {
186  if (n == 0)
187  {
188  printf("0");
189  return;
190  }
191 
192  // Buffer for the maximum possible bits in an unsigned long long
193  char binary_string[65];
194  int i = 0;
195  while (n > 0)
196  {
197  binary_string[i++] = (n % 2) + '0';
198  n /= 2;
199  }
200  binary_string[i] = '\0';
201 
202  // Reverse the string to get the correct binary representation
203  for (int j = 0; j < i / 2; ++j)
204  {
205  char temp = binary_string[j];
206  binary_string[j] = binary_string[i - j - 1];
207  binary_string[i - j - 1] = temp;
208  }
209  printf("%s", binary_string);
210  }
211 
212 // --- print function implementations ---
213 
214 void print(const char str[]) {
215  printf("%s", str);
216 }
217 
218 void print(char c) {
219  printf("%c", c);
220 }
221 
222 void print(unsigned char b, int base) {
223  if (base == BIN) {
224  print_binary(b);
225  } else if (base == DEC) {
226  printf("%u", (unsigned int)b);
227  } else if (base == HEX) {
228  printf("%x", (unsigned int)b);
229  } else if (base == OCT) {
230  printf("%o", (unsigned int)b);
231  }
232 }
233 
234 void print(int n, int base) {
235  if (base == BIN) {
236  print_binary(n);
237  } else if (base == DEC) {
238  printf("%d", n);
239  } else if (base == HEX) {
240  printf("%x", n);
241  } else if (base == OCT) {
242  printf("%o", n);
243  }
244 }
245 
246 void print(unsigned int n, int base) {
247  if (base == BIN) {
248  print_binary(n);
249  } else if (base == DEC) {
250  printf("%u", n);
251  } else if (base == HEX) {
252  printf("%x", n);
253  } else if (base == OCT) {
254  printf("%o", n);
255  }
256 }
257 
258 void print(long n, int base) {
259  if (base == BIN) {
260  print_binary(n);
261  } else if (base == DEC) {
262  printf("%ld", n);
263  } else if (base == HEX) {
264  printf("%lx", n);
265  } else if (base == OCT) {
266  printf("%lo", n);
267  }
268 }
269 
270 void print(unsigned long n, int base) {
271  if (base == BIN) {
272  print_binary(n);
273  } else if (base == DEC) {
274  printf("%lu", n);
275  } else if (base == HEX) {
276  printf("%lx", n);
277  } else if (base == OCT) {
278  printf("%lo", n);
279  }
280 }
281 
282 void print(long long n, int base) {
283  if (base == BIN) {
284  print_binary(n);
285  } else if (base == DEC) {
286  printf("%lld", n);
287  } else if (base == HEX) {
288  printf("%llx", n);
289  } else if (base == OCT) {
290  printf("%llo", n);
291  }
292 }
293 
294 void print(unsigned long long n, int base) {
295  if (base == BIN) {
296  print_binary(n);
297  } else if (base == DEC) {
298  printf("%llu", n);
299  } else if (base == HEX) {
300  printf("%llx", n);
301  } else if (base == OCT) {
302  printf("%llo", n);
303  }
304 }
305 
306 void print(double n) {
307  printf("%f", n);
308 }
309 
310 void println(void) {
311  printf("\n");
312 }
313 
314 void println(const char c[]) {
315  print(c);
316  println();
317 }
318 
319 void println(char c) {
320  print(c);
321  println();
322 }
323 
324 void println(unsigned char b, int base) {
325  print(b, base);
326  println();
327 }
328 
329 void println(int num, int base) {
330  print(num, base);
331  println();
332 }
333 
334 void println(unsigned int num, int base) {
335  print(num, base);
336  println();
337 }
338 
339 void println(long num, int base) {
340  print(num, base);
341  println();
342 }
343 
344 void println(unsigned long num, int base) {
345  print(num, base);
346  println();
347 }
348 
349 void println(long long num, int base) {
350  print(num, base);
351  println();
352 }
353 
354 void println(unsigned long long num, int base) {
355  print(num, base);
356  println();
357 }
358 
359 void println(double num) {
360  print(num);
361  println();
362 }
363 #endif // ESP_PLATFORM
364 #endif // !ARDUINO
uint16_t crc16Dnp(uint8_t *input, uint16_t length)
Definition: bits.cpp:153
const uint8_t * popByte(uint8_t &b, const uint8_t *data)
Definition: bits.cpp:4
uint8_t * pushInt(uint32_t i, uint8_t *data)
Definition: bits.cpp:72
void printHex(const char *suffix, const uint8_t *data, size_t length, bool newline)
Definition: bits.cpp:12
uint8_t * pushByteArray(const uint8_t *src, uint32_t size, uint8_t *data)
Definition: bits.cpp:82
const uint8_t * popByteArray(uint8_t *dst, uint32_t size, const uint8_t *data)
Definition: bits.cpp:48
void sixBytesFromUInt64(uint64_t num, uint8_t *toByteArray)
Definition: bits.cpp:101
uint8_t * pushWord(uint16_t w, uint8_t *data)
Definition: bits.cpp:64
uint16_t getWord(const uint8_t *data)
Definition: bits.cpp:91
void print(const char str[])
Definition: bits.cpp:214
uint8_t * pushByte(uint8_t b, uint8_t *data)
Definition: bits.cpp:57
void println(void)
Definition: bits.cpp:310
const uint8_t * popInt(uint32_t &i, const uint8_t *data)
Definition: bits.cpp:41
uint16_t crc16Ccitt(uint8_t *input, uint16_t length)
Definition: bits.cpp:133
uint64_t sixBytesToUInt64(uint8_t *data)
Definition: bits.cpp:111
uint32_t getInt(const uint8_t *data)
Definition: bits.cpp:96
const uint8_t * popWord(uint16_t &w, const uint8_t *data)
Definition: bits.cpp:34