Add bitbuffer_find_repeated_prefix function

This commit is contained in:
Christian W. Zuckschwerdt
2022-03-01 10:08:20 +01:00
parent ca4df453e2
commit 1b691f2d47
3 changed files with 48 additions and 13 deletions

View File

@@ -116,15 +116,27 @@ unsigned bitbuffer_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned
unsigned bitbuffer_differential_manchester_decode(bitbuffer_t *inbuf, unsigned row, unsigned start,
bitbuffer_t *outbuf, unsigned max);
/// Function to compare bitbuffer rows and count repetitions.
int compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b);
/// Compares two given rows of a bitbuffer.
///
/// If @p max_bits is greater than 0 then only up that many bits are compared.
int bitbuffer_compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b, unsigned max_bits);
unsigned count_repeats(bitbuffer_t *bits, unsigned row);
/// Count the number of repeats of row at index @p row.
///
/// If @p max_bits is greater than 0 then only up that many bits are compared.
/// The returned count will include the given row and will be at least 1.
unsigned bitbuffer_count_repeats(bitbuffer_t *bits, unsigned row, unsigned max_bits);
/// Find a repeated row that has a minimum count of bits.
/// Return the row index or -1.
/// Find a row repeated at least @p min_repeats times and with at least @p min_bits bits length,
/// all bits in the repeats need to match.
/// @return the row index or -1.
int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits);
/// Find a row repeated at least @p min_repeats times and with at least @p min_bits bits length,
/// a prefix of at most @p min_bits bits will be compared.
/// @return the row index or -1.
int bitbuffer_find_repeated_prefix(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits);
/// Return a single bit from a bitrow at bit_idx position.
static inline uint8_t bitrow_get_bit(uint8_t const *bitrow, unsigned bit_idx)
{

View File

@@ -461,18 +461,30 @@ void bitbuffer_parse(bitbuffer_t *bits, const char *code)
}
}
int compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b)
int bitbuffer_compare_rows(bitbuffer_t *bits, unsigned row_a, unsigned row_b, unsigned max_bits)
{
return (bits->bits_per_row[row_a] == bits->bits_per_row[row_b]
&& !memcmp(bits->bb[row_a], bits->bb[row_b],
(bits->bits_per_row[row_a] + 7) / 8));
if (max_bits == 0 || bits->bits_per_row[row_a] < max_bits || bits->bits_per_row[row_b] < max_bits) {
// full compare, no max_bits or rows too short
return (bits->bits_per_row[row_a] == bits->bits_per_row[row_b]
&& !memcmp(bits->bb[row_a], bits->bb[row_b],
(bits->bits_per_row[row_a] + 7) / 8));
}
else {
// prefix-only compare, both rows are at least max_bits long
uint8_t *a = bits->bb[row_a];
uint8_t *b = bits->bb[row_b];
unsigned last = (max_bits - 1) / 8; // max_bits is at least 1
unsigned mask = 0xff00 >> (max_bits & 7); // mask off bottom bits
return (!memcmp(bits->bb[row_a], bits->bb[row_b], max_bits / 8)
&& (a[last] & mask) == (b[last] & mask));
}
}
unsigned count_repeats(bitbuffer_t *bits, unsigned row)
unsigned bitbuffer_count_repeats(bitbuffer_t *bits, unsigned row, unsigned max_bits)
{
unsigned cnt = 0;
for (int i = 0; i < bits->num_rows; ++i) {
if (compare_rows(bits, row, i)) {
if (bitbuffer_compare_rows(bits, row, i, max_bits)) {
++cnt;
}
}
@@ -483,7 +495,18 @@ int bitbuffer_find_repeated_row(bitbuffer_t *bits, unsigned min_repeats, unsigne
{
for (int i = 0; i < bits->num_rows; ++i) {
if (bits->bits_per_row[i] >= min_bits &&
count_repeats(bits, i) >= min_repeats) {
bitbuffer_count_repeats(bits, i, 0) >= min_repeats) {
return i;
}
}
return -1;
}
int bitbuffer_find_repeated_prefix(bitbuffer_t *bits, unsigned min_repeats, unsigned min_bits)
{
for (int i = 0; i < bits->num_rows; ++i) {
if (bits->bits_per_row[i] >= min_bits &&
bitbuffer_count_repeats(bits, i, min_bits) >= min_repeats) {
return i;
}
}

View File

@@ -43,7 +43,7 @@ static int generic_motion_callback(r_device *decoder, bitbuffer_t *bitbuffer)
if ((bitbuffer->bits_per_row[i] != 20)
|| ((b[1] == 0) && (b[2] == 0))
|| ((b[1] == 0xff) && (b[2] == 0xff))
|| count_repeats(bitbuffer, i) < 3)
|| bitbuffer_count_repeats(bitbuffer, i, 0) < 3)
continue; // DECODE_ABORT_EARLY
code = (b[0] << 12) | (b[1] << 4) | (b[2] >> 4);