|
| 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 | +#ifndef INCLUDE_BITBUFFER_H_ |
| 13 | +#define INCLUDE_BITBUFFER_H_ |
| 14 | + |
| 15 | +#include <stdint.h> |
| 16 | + |
| 17 | +// NOTE: Wireless mbus protocol needs at least ((256+16*2+3)*12)/8 => 437 bytes |
| 18 | +// which fits even if RTL_433_REDUCE_STACK_USE is defined because of row spilling |
| 19 | +#ifdef RTL_433_REDUCE_STACK_USE |
| 20 | +#define BITBUF_COLS 40 // Number of bytes in a column |
| 21 | +#define BITBUF_ROWS 25 |
| 22 | +#else |
| 23 | +#define BITBUF_COLS 128 // Number of bytes in a column |
| 24 | +#define BITBUF_ROWS 50 |
| 25 | +#endif |
| 26 | +#define BITBUF_MAX_ROW_BITS (BITBUF_ROWS * BITBUF_COLS * 8) // Maximum number of bits per row, max UINT16_MAX |
| 27 | +#define BITBUF_MAX_PRINT_BITS 50 // Maximum number of bits to print (in addition to hex values) |
| 28 | + |
| 29 | +typedef uint8_t bitrow_t[BITBUF_COLS]; |
| 30 | +typedef bitrow_t bitarray_t[BITBUF_ROWS]; |
| 31 | + |
| 32 | +/// Bit buffer. |
| 33 | +typedef struct bitbuffer { |
| 34 | + uint16_t num_rows; ///< Number of active rows |
| 35 | + uint16_t free_row; ///< Index of next free row |
| 36 | + uint16_t bits_per_row[BITBUF_ROWS]; ///< Number of active bits per row |
| 37 | + uint16_t syncs_before_row[BITBUF_ROWS]; ///< Number of sync pulses before row |
| 38 | + bitarray_t bb; ///< The actual bits buffer |
| 39 | +} bitbuffer_t; |
| 40 | + |
| 41 | +/// Clear the content of the bitbuffer. |
| 42 | +void bitbuffer_clear(bitbuffer_t *bits); |
| 43 | + |
| 44 | +/// Add a single bit at the end of the bitbuffer (MSB first). |
| 45 | +void bitbuffer_add_bit(bitbuffer_t *bits, int bit); |
| 46 | + |
| 47 | +/// Add a new row to the bitbuffer. |
| 48 | +void bitbuffer_add_row(bitbuffer_t *bits); |
| 49 | + |
| 50 | +/// Increment sync counter, add new row if not empty. |
| 51 | +void bitbuffer_add_sync(bitbuffer_t *bits); |
| 52 | + |
| 53 | +/// Extract (potentially unaligned) bytes from the bit buffer. Len is bits. |
| 54 | +void bitbuffer_extract_bytes(bitbuffer_t *bitbuffer, unsigned row, |
| 55 | + unsigned pos, uint8_t *out, unsigned len); |
| 56 | + |
| 57 | +/// Invert all bits in the bitbuffer (do not invert the empty bits). |
| 58 | +void bitbuffer_invert(bitbuffer_t *bits); |
| 59 | + |
| 60 | +/// Non-Return-to-Zero Space (NRZI) decode the bitbuffer. |
| 61 | +/// "One" is represented by no change in level, "Zero" is represented by change in level. |
| 62 | +void bitbuffer_nrzs_decode(bitbuffer_t *bits); |
| 63 | + |
| 64 | +/// Non-Return-to-Zero Mark (NRZI) decode the bitbuffer. |
| 65 | +/// "One" is represented by change in level, "Zero" is represented by no change in level. |
| 66 | +void bitbuffer_nrzm_decode(bitbuffer_t *bits); |
| 67 | + |
| 68 | +/// Print the content of the bitbuffer. |
| 69 | +/// @deprecated For debug only, use decoder_log_bitbuffer otherwise |
| 70 | +void bitbuffer_print(const bitbuffer_t *bits); |
| 71 | + |
| 72 | +/// Debug the content of the bitbuffer. |
| 73 | +/// @deprecated For debug only, use decoder_log_bitbuffer otherwise |
| 74 | +void bitbuffer_debug(const bitbuffer_t *bits); |
| 75 | + |
| 76 | +/// Print the content of a bit row (byte buffer). |
| 77 | +/// @deprecated For debug only, use decoder_log_bitrow otherwise |
| 78 | +void bitrow_print(uint8_t const *bitrow, unsigned bit_len); |
| 79 | + |
| 80 | +/// Debug the content of a bit row (byte buffer). |
| 81 | +/// @deprecated For debug only, use decoder_log_bitrow otherwise |
| 82 | +void bitrow_debug(uint8_t const *bitrow, unsigned bit_len); |
| 83 | + |
| 84 | +/// Print the content of a bit row (byte buffer) to a string buffer. |
| 85 | +/// |
| 86 | +/// Write at most @p size - 1 characters, |
| 87 | +/// the output is always null-terminated, unless size is 0. |
| 88 | +/// |
| 89 | +/// @param bitrow the row of bytes to print |
| 90 | +/// @param bit_len the number of bits in @p bitrow to print |
| 91 | +/// @param str an output string buffer of sufficient size |
| 92 | +/// @param size the size of @p str |
| 93 | +/// |
| 94 | +/// @return the number of characters printed (not including the trailing `\0`). |
| 95 | +int bitrow_snprint(uint8_t const *bitrow, unsigned bit_len, char *str, unsigned size); |
| 96 | + |
| 97 | +/// Parse a string into a bitbuffer. |
| 98 | +/// |
| 99 | +/// The (optionally "0x" prefixed) hex code is processed into a bitbuffer_t. |
| 100 | +/// Each row is optionally prefixed with a length enclosed in braces "{}" or |
| 101 | +/// separated with a slash "/" character. Whitespace is ignored. |
| 102 | +void bitbuffer_parse(bitbuffer_t *bits, const char *code); |
| 103 | + |
| 104 | +/// Search the specified row of the bitbuffer, starting from bit 'start', for |
| 105 | +/// the pattern provided. Return the location of the first match, or the end |
| 106 | +/// of the row if no match is found. |
| 107 | +/// The pattern starts in the high bit. For example if searching for 011011 |
| 108 | +/// the byte pointed to by 'pattern' would be 0xAC. (011011xx). |
| 109 | +unsigned bitbuffer_search(bitbuffer_t *bitbuffer, unsigned row, unsigned start, |
| 110 | + const uint8_t *pattern, unsigned pattern_bits_len); |
| 111 | + |
| 112 | +/// Manchester decoding from one bitbuffer into another, starting at the |
| 113 | +/// specified row and start bit. Decode at most 'max' data bits (i.e. 2*max) |
| 114 | +/// bits from the input buffer). Return the bit position in the input row |
| 115 | +/// (i.e. returns start + 2*outbuf->bits_per_row[0]). |
| 116 | +/// per IEEE 802.3 conventions, i.e. high-low is a 0 bit, low-high is a 1 bit. |
| 117 | +unsigned bitbuffer_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned start, |
| 118 | + bitbuffer_t *outbuf, unsigned max); |
| 119 | + |
| 120 | +/// Differential Manchester decoding from one bitbuffer into another, starting at the |
| 121 | +/// specified row and start bit. Decode at most 'max' data bits (i.e. 2*max) |
| 122 | +/// bits from the input buffer). Return the bit position in the input row |
| 123 | +/// (i.e. returns start + 2*outbuf->bits_per_row[0]). |
| 124 | +unsigned bitbuffer_differential_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned start, |
| 125 | + bitbuffer_t *outbuf, unsigned max); |
| 126 | + |
| 127 | +/// Compares two given rows of a bitbuffer. |
| 128 | +/// |
| 129 | +/// If @p max_bits is greater than 0 then only up that many bits are compared. |
| 130 | +int bitbuffer_compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b, unsigned max_bits); |
| 131 | + |
| 132 | +/// Count the number of repeats of row at index @p row. |
| 133 | +/// |
| 134 | +/// If @p max_bits is greater than 0 then only up that many bits are compared. |
| 135 | +/// The returned count will include the given row and will be at least 1. |
| 136 | +unsigned bitbuffer_count_repeats(bitbuffer_t *bits, unsigned row, unsigned max_bits); |
| 137 | + |
| 138 | +/// Find a row repeated at least @p min_repeats times and with at least @p min_bits bits length, |
| 139 | +/// all bits in the repeats need to match. |
| 140 | +/// @return the row index or -1. |
| 141 | +int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits); |
| 142 | + |
| 143 | +/// Find a row repeated at least @p min_repeats times and with at least @p min_bits bits length, |
| 144 | +/// a prefix of at most @p min_bits bits will be compared. |
| 145 | +/// @return the row index or -1. |
| 146 | +int bitbuffer_find_repeated_prefix(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits); |
| 147 | + |
| 148 | +/// Return a single bit from a bitrow at bit_idx position. |
| 149 | +static inline uint8_t bitrow_get_bit(uint8_t const *bitrow, unsigned bit_idx) |
| 150 | +{ |
| 151 | + return bitrow[bit_idx >> 3] >> (7 - (bit_idx & 7)) & 1; |
| 152 | +} |
| 153 | + |
| 154 | +/// Return a single byte from a bitrow at bit_idx position (which may be unaligned). |
| 155 | +static inline uint8_t bitrow_get_byte(uint8_t const *bitrow, unsigned bit_idx) |
| 156 | +{ |
| 157 | + return (uint8_t)((bitrow[(bit_idx >> 3)] << (bit_idx & 7)) | |
| 158 | + (bitrow[(bit_idx >> 3) + 1] >> (8 - (bit_idx & 7)))); |
| 159 | +} |
| 160 | + |
| 161 | +#endif /* INCLUDE_BITBUFFER_H_ */ |
0 commit comments