1 /** @file
2 A two-dimensional bit buffer consisting of bytes.
3
4 Copyright (C) 2015 Tommy Vestermark
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "bitbuffer.h"
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16
bitbuffer_clear(bitbuffer_t * bits)17 void bitbuffer_clear(bitbuffer_t *bits)
18 {
19 memset(bits, 0, sizeof(*bits));
20 }
21
bitbuffer_add_bit(bitbuffer_t * bits,int bit)22 void bitbuffer_add_bit(bitbuffer_t *bits, int bit)
23 {
24 if (bits->num_rows == 0)
25 bits->free_row = bits->num_rows = 1; // Add first row automatically
26
27 if (bits->bits_per_row[bits->num_rows - 1] == UINT16_MAX) {
28 // fprintf(stderr, "%s: Could not add more bits\n", __func__);
29 return;
30 }
31 if (bits->bits_per_row[bits->num_rows - 1] == UINT16_MAX - 1) {
32 fprintf(stderr, "%s: Warning: row length limit (%u bits) reached\n", __func__, UINT16_MAX);
33 }
34
35 uint16_t col_index = bits->bits_per_row[bits->num_rows - 1] / 8;
36 uint16_t bit_index = bits->bits_per_row[bits->num_rows - 1] % 8;
37 if (bits->bits_per_row[bits->num_rows - 1] > 0
38 && bits->bits_per_row[bits->num_rows - 1] % (BITBUF_COLS * 8) == 0) {
39 // spill into next row
40 // fprintf(stderr, "%s: row spill [%d] to %d (%d)\n", __func__, bits->num_rows - 1, col_index, bits->free_row);
41 if (bits->free_row == BITBUF_ROWS - 1) {
42 fprintf(stderr, "%s: Warning: row count limit (%d rows) reached\n", __func__, BITBUF_ROWS);
43 }
44 if (bits->free_row < BITBUF_ROWS) {
45 bits->free_row++;
46 }
47 else {
48 // fprintf(stderr, "%s: Could not add more rows\n", __func__);
49 return;
50 }
51 }
52 uint8_t *b = bits->bb[bits->num_rows - 1];
53 b[col_index] |= (bit << (7 - bit_index));
54 bits->bits_per_row[bits->num_rows - 1]++;
55
56 /*
57 // preamble compression
58 if (bits->bits_per_row[bits->num_rows - 1] == 60 * 8) {
59 uint8_t *b = bits->bb[bits->num_rows - 1];
60 for (int i = 21; i < 60; ++i) {
61 if (b[20] != b[i]) {
62 return;
63 }
64 }
65 // fprintf(stderr, "%s: preamble compression\n", __func__);
66 memset(&b[30], 0, 30);
67 bits->bits_per_row[bits->num_rows - 1] = 30 * 8;
68 }
69 */
70 }
71
72 /// Set the width of the current (last) row by expanding or truncating as needed.
bitbuffer_set_width(bitbuffer_t * bits,uint16_t width)73 static void bitbuffer_set_width(bitbuffer_t *bits, uint16_t width)
74 {
75 if (bits->num_rows == 0)
76 bits->free_row = bits->num_rows = 1; // Add first row automatically
77
78 unsigned remaining_rows = BITBUF_ROWS - bits->num_rows + 1;
79 unsigned remaining_bits = remaining_rows * BITBUF_COLS * 8;
80 if (width > remaining_bits) {
81 // fprintf(stderr, "%s: Could not add more bits\n", __func__);
82 width = remaining_bits;
83 }
84
85 // clear bits when truncating
86 if (bits->bits_per_row[bits->num_rows - 1] > width) {
87 uint8_t *b = bits->bb[bits->num_rows - 1];
88 unsigned clr_from = (width + 7) / 8;
89 unsigned clr_end = (bits->bits_per_row[bits->num_rows - 1] + 7) / 8;
90 memset(&b[clr_from], 0, clr_end - clr_from);
91
92 // note that width became strictly smaller, that way we don't overflow
93 b[width / 8] &= 0xff00 >> (width % 8);
94 }
95
96 bits->bits_per_row[bits->num_rows - 1] = width;
97
98 unsigned extra_rows = width == 0 ? 0 : (width - 1) / (BITBUF_COLS * 8);
99 bits->free_row = bits->num_rows + extra_rows;
100 }
101
bitbuffer_add_row(bitbuffer_t * bits)102 void bitbuffer_add_row(bitbuffer_t *bits)
103 {
104 if (bits->num_rows == 0)
105 bits->free_row = bits->num_rows = 1; // Add first row automatically
106 if (bits->free_row == BITBUF_ROWS - 1) {
107 // fprintf(stderr, "%s: Warning: row count limit (%d rows) reached\n", __func__, BITBUF_ROWS);
108 }
109 if (bits->free_row < BITBUF_ROWS) {
110 bits->free_row++;
111 bits->num_rows = bits->free_row;
112 }
113 else {
114 bits->bits_per_row[bits->num_rows - 1] = 0; // Clear last row to handle overflow somewhat gracefully
115 // fprintf(stderr, "ERROR: bitbuffer:: Could not add more rows\n"); // Some decoders may add many rows...
116 }
117 }
118
bitbuffer_add_sync(bitbuffer_t * bits)119 void bitbuffer_add_sync(bitbuffer_t *bits)
120 {
121 if (bits->num_rows == 0)
122 bits->free_row = bits->num_rows = 1; // Add first row automatically
123 if (bits->bits_per_row[bits->num_rows - 1]) {
124 bitbuffer_add_row(bits);
125 }
126 bits->syncs_before_row[bits->num_rows - 1]++;
127 }
128
bitbuffer_invert(bitbuffer_t * bits)129 void bitbuffer_invert(bitbuffer_t *bits)
130 {
131 for (unsigned row = 0; row < bits->num_rows; ++row) {
132 if (bits->bits_per_row[row] > 0) {
133 uint8_t *b = bits->bb[row];
134
135 const unsigned last_col = (bits->bits_per_row[row] - 1) / 8;
136 const unsigned last_bits = ((bits->bits_per_row[row] - 1) % 8) + 1;
137 for (unsigned col = 0; col <= last_col; ++col) {
138 b[col] = ~b[col]; // Invert
139 }
140 b[last_col] ^= 0xFF >> last_bits; // Re-invert unused bits in last byte
141 }
142 }
143 }
144
bitbuffer_nrzs_decode(bitbuffer_t * bits)145 void bitbuffer_nrzs_decode(bitbuffer_t *bits)
146 {
147 for (unsigned row = 0; row < bits->num_rows; ++row) {
148 if (bits->bits_per_row[row] > 0) {
149 uint8_t *b = bits->bb[row];
150
151 const unsigned last_col = (bits->bits_per_row[row] - 1) / 8;
152 const unsigned last_bits = ((bits->bits_per_row[row] - 1) % 8) + 1;
153
154 int prev = 0;
155 for (unsigned col = 0; col <= last_col; ++col) {
156 int mask = (prev << 7) | b[col] >> 1;
157 prev = b[col];
158 b[col] = b[col] ^ ~mask;
159 }
160 b[last_col] &= 0xFF << (8 - last_bits); // Clear unused bits in last byte
161 }
162 }
163 }
164
bitbuffer_nrzm_decode(bitbuffer_t * bits)165 void bitbuffer_nrzm_decode(bitbuffer_t *bits)
166 {
167 for (unsigned row = 0; row < bits->num_rows; ++row) {
168 if (bits->bits_per_row[row] > 0) {
169 uint8_t *b = bits->bb[row];
170
171 const unsigned last_col = (bits->bits_per_row[row] - 1) / 8;
172 const unsigned last_bits = ((bits->bits_per_row[row] - 1) % 8) + 1;
173
174 int prev = 0;
175 for (unsigned col = 0; col <= last_col; ++col) {
176 int mask = (prev << 7) | b[col] >> 1;
177 prev = b[col];
178 b[col] = b[col] ^ mask;
179 }
180 b[last_col] &= 0xFF << (8 - last_bits); // Clear unused bits in last byte
181 }
182 }
183 }
184
bitbuffer_extract_bytes(bitbuffer_t * bitbuffer,unsigned row,unsigned pos,uint8_t * out,unsigned len)185 void bitbuffer_extract_bytes(bitbuffer_t *bitbuffer, unsigned row,
186 unsigned pos, uint8_t *out, unsigned len)
187 {
188 uint8_t *bits = bitbuffer->bb[row];
189 if (len == 0)
190 return;
191 if ((pos & 7) == 0) {
192 memcpy(out, bits + (pos / 8), (len + 7) / 8);
193 }
194 else {
195 unsigned shift = 8 - (pos & 7);
196 unsigned bytes = (len + 7) >> 3;
197 uint8_t *p = out;
198 uint16_t word;
199 pos = pos >> 3; // Convert to bytes
200
201 word = bits[pos];
202
203 while (bytes--) {
204 word <<= 8;
205 word |= bits[++pos];
206 *(p++) = word >> shift;
207 }
208 }
209 if (len & 7)
210 out[(len - 1) / 8] &= 0xff00 >> (len & 7); // mask off bottom bits
211 }
212
213 // If we make this an inline function instead of a macro, it means we don't
214 // have to worry about using bit numbers with side-effects (bit++).
bit_at(const uint8_t * bytes,unsigned bit)215 static inline uint8_t bit_at(const uint8_t *bytes, unsigned bit)
216 {
217 return (uint8_t)(bytes[bit >> 3] >> (7 - (bit & 7)) & 1);
218 }
219
bitbuffer_search(bitbuffer_t * bitbuffer,unsigned row,unsigned start,const uint8_t * pattern,unsigned pattern_bits_len)220 unsigned bitbuffer_search(bitbuffer_t *bitbuffer, unsigned row, unsigned start,
221 const uint8_t *pattern, unsigned pattern_bits_len)
222 {
223 uint8_t *bits = bitbuffer->bb[row];
224 unsigned len = bitbuffer->bits_per_row[row];
225 unsigned ipos = start;
226 unsigned ppos = 0; // cursor on init pattern
227
228 while (ipos < len && ppos < pattern_bits_len) {
229 if (bit_at(bits, ipos) == bit_at(pattern, ppos)) {
230 ppos++;
231 ipos++;
232 if (ppos == pattern_bits_len)
233 return ipos - pattern_bits_len;
234 }
235 else {
236 ipos -= ppos;
237 ipos++;
238 ppos = 0;
239 }
240 }
241
242 // Not found
243 return len;
244 }
245
bitbuffer_manchester_decode(bitbuffer_t * inbuf,unsigned row,unsigned start,bitbuffer_t * outbuf,unsigned max)246 unsigned bitbuffer_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned start,
247 bitbuffer_t *outbuf, unsigned max)
248 {
249 uint8_t *bits = inbuf->bb[row];
250 unsigned int len = inbuf->bits_per_row[row];
251 unsigned int ipos = start;
252
253 if (max && len > start + (max * 2))
254 len = start + (max * 2);
255
256 while (ipos < len) {
257 uint8_t bit1, bit2;
258
259 bit1 = bit_at(bits, ipos++);
260 bit2 = bit_at(bits, ipos++);
261
262 if (bit1 == bit2)
263 break;
264
265 bitbuffer_add_bit(outbuf, bit2);
266 }
267
268 return ipos;
269 }
270
bitbuffer_differential_manchester_decode(bitbuffer_t * inbuf,unsigned row,unsigned start,bitbuffer_t * outbuf,unsigned max)271 unsigned bitbuffer_differential_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned start,
272 bitbuffer_t *outbuf, unsigned max)
273 {
274 uint8_t *bits = inbuf->bb[row];
275 unsigned int len = inbuf->bits_per_row[row];
276 unsigned int ipos = start;
277 uint8_t bit1, bit2 = 0;
278
279 if (max && len > start + (max * 2))
280 len = start + (max * 2);
281
282 // the first long pulse will determine the clock
283 // if needed skip one short pulse to get in synch
284 while (ipos < len) {
285 bit1 = bit_at(bits, ipos++);
286 bit2 = bit_at(bits, ipos++);
287 uint8_t bit3 = bit_at(bits, ipos);
288
289 if (bit1 != bit2) {
290 if (bit2 != bit3) {
291 bitbuffer_add_bit(outbuf, 0);
292 }
293 else {
294 bit2 = bit1;
295 ipos -= 1;
296 break;
297 }
298 }
299 else {
300 bit2 = 1 - bit1;
301 ipos -= 2;
302 break;
303 }
304 }
305
306 while (ipos < len) {
307 bit1 = bit_at(bits, ipos++);
308 if (bit1 == bit2)
309 break; // clock missing, abort
310 bit2 = bit_at(bits, ipos++);
311
312 if (bit1 == bit2)
313 bitbuffer_add_bit(outbuf, 1);
314 else
315 bitbuffer_add_bit(outbuf, 0);
316 }
317
318 return ipos;
319 }
320
print_bitrow(uint8_t const * bitrow,unsigned bit_len,unsigned highest_indent,int always_binary)321 static void print_bitrow(uint8_t const *bitrow, unsigned bit_len, unsigned highest_indent, int always_binary)
322 {
323 unsigned row_len = 0;
324
325 fprintf(stderr, "{%2u} ", bit_len);
326 for (unsigned col = 0; col < (bit_len + 7) / 8; ++col) {
327 row_len += fprintf(stderr, "%02x ", bitrow[col]);
328 }
329 // Print binary values also?
330 if (always_binary || bit_len <= BITBUF_MAX_PRINT_BITS) {
331 fprintf(stderr, "%-*s: ", highest_indent > row_len ? highest_indent - row_len : 0, "");
332 for (unsigned bit = 0; bit < bit_len; ++bit) {
333 if (bitrow[bit / 8] & (0x80 >> (bit % 8))) {
334 fprintf(stderr, "1");
335 }
336 else {
337 fprintf(stderr, "0");
338 }
339 if ((bit % 8) == 7) // Add byte separators
340 fprintf(stderr, " ");
341 }
342 }
343 fprintf(stderr, "\n");
344 }
345
print_bitbuffer(const bitbuffer_t * bits,int always_binary)346 static void print_bitbuffer(const bitbuffer_t *bits, int always_binary)
347 {
348 unsigned highest_indent, indent_this_col, indent_this_row;
349 unsigned col, row;
350
351 /* Figure out the longest row of bit to get the highest_indent
352 */
353 highest_indent = sizeof("[dd] {dd} ") - 1;
354 for (row = indent_this_row = 0; row < bits->num_rows; ++row) {
355 for (col = indent_this_col = 0; col < (unsigned)(bits->bits_per_row[row] + 7) / 8; ++col) {
356 indent_this_col += 2 + 1;
357 }
358 indent_this_row = indent_this_col;
359 if (indent_this_row > highest_indent)
360 highest_indent = indent_this_row;
361 }
362
363 fprintf(stderr, "bitbuffer:: Number of rows: %u \n", bits->num_rows);
364 for (row = 0; row < bits->num_rows; ++row) {
365 fprintf(stderr, "[%02u] ", row);
366 print_bitrow(bits->bb[row], bits->bits_per_row[row], highest_indent, always_binary);
367 }
368 if (bits->num_rows >= BITBUF_ROWS) {
369 fprintf(stderr, "... Maximum number of rows reached. Message is likely truncated.\n");
370 }
371 }
372
bitbuffer_print(const bitbuffer_t * bits)373 void bitbuffer_print(const bitbuffer_t *bits)
374 {
375 print_bitbuffer(bits, 0);
376 }
377
bitbuffer_debug(const bitbuffer_t * bits)378 void bitbuffer_debug(const bitbuffer_t *bits)
379 {
380 print_bitbuffer(bits, 1);
381 }
382
bitrow_print(uint8_t const * bitrow,unsigned bit_len)383 void bitrow_print(uint8_t const *bitrow, unsigned bit_len)
384 {
385 print_bitrow(bitrow, bit_len, 0, 0);
386 }
387
bitrow_debug(uint8_t const * bitrow,unsigned bit_len)388 void bitrow_debug(uint8_t const *bitrow, unsigned bit_len)
389 {
390 print_bitrow(bitrow, bit_len, 0, 1);
391 }
392
bitrow_snprint(uint8_t const * bitrow,unsigned bit_len,char * str,unsigned size)393 int bitrow_snprint(uint8_t const *bitrow, unsigned bit_len, char *str, unsigned size)
394 {
395 if (bit_len == 0 && size > 0) {
396 str[0] = '\0';
397 }
398 int len = 0;
399 for (unsigned i = 0; size > (unsigned)len && i < (bit_len + 7) / 8; ++i) {
400 len += snprintf(str + len, size - len, "%02x", bitrow[i]);
401 }
402 return len;
403 }
404
bitbuffer_parse(bitbuffer_t * bits,const char * code)405 void bitbuffer_parse(bitbuffer_t *bits, const char *code)
406 {
407 const char *c;
408 int data = 0;
409 int width = -1;
410
411 bitbuffer_clear(bits);
412
413 for (c = code; *c; ++c) {
414
415 if (*c == ' ') {
416 continue;
417 }
418 else if (*c == '0' && (*(c + 1) == 'x' || *(c + 1) == 'X')) {
419 ++c;
420 continue;
421 }
422 else if (*c == '{') {
423 if (width >= 0) {
424 bitbuffer_set_width(bits, width);
425 }
426 if (bits->num_rows > 0) {
427 bitbuffer_add_row(bits);
428 }
429
430 width = strtol(c + 1, (char **)&c, 0);
431 if (width > BITBUF_MAX_ROW_BITS)
432 width = BITBUF_MAX_ROW_BITS;
433 if (!*c)
434 break; // no closing brace and end of string
435 continue;
436 }
437 else if (*c == '/') {
438 if (width >= 0) {
439 bitbuffer_set_width(bits, width);
440 width = -1;
441 }
442 bitbuffer_add_row(bits);
443 continue;
444 }
445 else if (*c >= '0' && *c <= '9') {
446 data = *c - '0';
447 }
448 else if (*c >= 'A' && *c <= 'F') {
449 data = *c - 'A' + 10;
450 }
451 else if (*c >= 'a' && *c <= 'f') {
452 data = *c - 'a' + 10;
453 }
454 bitbuffer_add_bit(bits, data >> 3 & 0x01);
455 bitbuffer_add_bit(bits, data >> 2 & 0x01);
456 bitbuffer_add_bit(bits, data >> 1 & 0x01);
457 bitbuffer_add_bit(bits, data >> 0 & 0x01);
458 }
459 if (width >= 0) {
460 bitbuffer_set_width(bits, width);
461 }
462 }
463
compare_rows(bitbuffer_t * bits,unsigned row_a,unsigned row_b)464 int compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b)
465 {
466 return (bits->bits_per_row[row_a] == bits->bits_per_row[row_b]
467 && !memcmp(bits->bb[row_a], bits->bb[row_b],
468 (bits->bits_per_row[row_a] + 7) / 8));
469 }
470
count_repeats(bitbuffer_t * bits,unsigned row)471 unsigned count_repeats(bitbuffer_t *bits, unsigned row)
472 {
473 unsigned cnt = 0;
474 for (int i = 0; i < bits->num_rows; ++i) {
475 if (compare_rows(bits, row, i)) {
476 ++cnt;
477 }
478 }
479 return cnt;
480 }
481
bitbuffer_find_repeated_row(bitbuffer_t * bits,unsigned min_repeats,unsigned min_bits)482 int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits)
483 {
484 for (int i = 0; i < bits->num_rows; ++i) {
485 if (bits->bits_per_row[i] >= min_bits &&
486 count_repeats(bits, i) >= min_repeats) {
487 return i;
488 }
489 }
490 return -1;
491 }
492
493 // Unit testing
494 #ifdef _TEST
495
496 #define ASSERT(expr) \
497 do { \
498 if (expr) { \
499 ++passed; \
500 } else { \
501 ++failed; \
502 fprintf(stderr, "FAIL: line %d: %s\n", __LINE__, #expr); \
503 } \
504 } while (0)
505
main(void)506 int main(void)
507 {
508 unsigned passed = 0;
509 unsigned failed = 0;
510
511 fprintf(stderr, "bitbuffer:: test\n");
512
513 bitbuffer_t bits = {0};
514
515 fprintf(stderr, "TEST: bitbuffer:: The empty buffer\n");
516 bitbuffer_print(&bits);
517 ASSERT(bits.num_rows == 0);
518
519 fprintf(stderr, "TEST: bitbuffer:: Add 1 bit\n");
520 bitbuffer_add_bit(&bits, 1);
521 bitbuffer_print(&bits);
522 ASSERT(bits.num_rows == 1);
523
524 fprintf(stderr, "TEST: bitbuffer:: Add 1 new row\n");
525 bitbuffer_add_row(&bits);
526 bitbuffer_print(&bits);
527 ASSERT(bits.num_rows == 2);
528
529 fprintf(stderr, "TEST: bitbuffer:: Fill row\n");
530 for (int i = 0; i < BITBUF_COLS * 8; ++i) {
531 bitbuffer_add_bit(&bits, i % 2);
532 }
533 bitbuffer_print(&bits);
534 ASSERT(bits.num_rows == 2);
535
536 fprintf(stderr, "TEST: bitbuffer:: Add row and fill 1 column too many\n");
537 bitbuffer_add_row(&bits);
538 for (int i = 0; i <= BITBUF_COLS * 8; ++i) {
539 bitbuffer_add_bit(&bits, i % 2);
540 }
541 bitbuffer_print(&bits);
542 ASSERT(bits.num_rows == 3);
543
544 fprintf(stderr, "TEST: bitbuffer:: invert\n");
545 bitbuffer_invert(&bits);
546 bitbuffer_print(&bits);
547
548 fprintf(stderr, "TEST: bitbuffer:: nrzs_decode\n");
549 bits.num_rows = 1;
550 bits.bb[0][0] = 0x74;
551 bits.bb[0][1] = 0x60;
552 bits.bits_per_row[0] = 12;
553 bitbuffer_nrzs_decode(&bits);
554 bitbuffer_print(&bits);
555 ASSERT(bits.bb[0][0] == 0xB1);
556 ASSERT(bits.bb[0][1] == 0xA0);
557
558 fprintf(stderr, "TEST: bitbuffer:: Clear\n");
559 bitbuffer_clear(&bits);
560 ASSERT(bits.num_rows == 0);
561 bitbuffer_print(&bits);
562
563 fprintf(stderr, "TEST: bitbuffer:: Add 1 row too many\n");
564 for (int i = 0; i <= BITBUF_ROWS; ++i) {
565 bitbuffer_add_row(&bits);
566 }
567 bitbuffer_add_bit(&bits, 1);
568 bitbuffer_print(&bits);
569
570 fprintf(stderr, "bitbuffer:: test (%u/%u) passed, (%u) failed.\n", passed, passed + failed, failed);
571
572 return failed > 0 ? 1 : 0;
573 }
574 #endif /* _TEST */
575