From 1b691f2d47bf63bda19286b7516aec795545d9f7 Mon Sep 17 00:00:00 2001 From: "Christian W. Zuckschwerdt" Date: Tue, 1 Mar 2022 10:08:20 +0100 Subject: [PATCH] Add bitbuffer_find_repeated_prefix function --- include/bitbuffer.h | 22 ++++++++++++++++----- src/bitbuffer.c | 37 +++++++++++++++++++++++++++++------- src/devices/generic_motion.c | 2 +- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/include/bitbuffer.h b/include/bitbuffer.h index cff68d07..581c7486 100644 --- a/include/bitbuffer.h +++ b/include/bitbuffer.h @@ -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) { diff --git a/src/bitbuffer.c b/src/bitbuffer.c index be4e1a28..1298c914 100644 --- a/src/bitbuffer.c +++ b/src/bitbuffer.c @@ -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; } } diff --git a/src/devices/generic_motion.c b/src/devices/generic_motion.c index 5854515b..824c525a 100644 --- a/src/devices/generic_motion.c +++ b/src/devices/generic_motion.c @@ -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);