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