mirror of
https://github.com/merbanan/rtl_433.git
synced 2026-05-19 07:15:15 -04:00
Add decode_uart util (#1376)
This commit is contained in:
@@ -52,8 +52,18 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes);
|
||||
/// @param offset_bits start offset of message in bits
|
||||
/// @param num_bits message length in bits
|
||||
/// @param dst target buffer for extracted nibbles, at least num_bits/5 size
|
||||
/// @return number of successfully unstuffed nibbles.
|
||||
unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
|
||||
|
||||
/// UART "8n1" (10-to-8) decoder with 1 start bit (0), no parity, 1 stop bit (1), LSB-first bit-order.
|
||||
///
|
||||
/// @param message bytes of message data
|
||||
/// @param offset_bits start offset of message in bits
|
||||
/// @param num_bits message length in bits
|
||||
/// @param dst target buffer for extracted bytes, at least num_bits/10 size
|
||||
/// @return number of successful decoded bytes
|
||||
unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
|
||||
|
||||
/// CRC-4.
|
||||
///
|
||||
/// @param message array of bytes to check
|
||||
|
||||
@@ -91,6 +91,7 @@ struct flex_params {
|
||||
unsigned preamble_len;
|
||||
bitrow_t preamble_bits;
|
||||
struct flex_get getter[GETTER_SLOTS];
|
||||
unsigned decode_uart;
|
||||
};
|
||||
|
||||
static void print_row_bytes(char *row_bytes, uint8_t *bits, int num_bits)
|
||||
@@ -213,6 +214,14 @@ static int flex_callback(r_device *decoder, bitbuffer_t *bitbuffer)
|
||||
return DECODE_FAIL_SANITY;
|
||||
}
|
||||
|
||||
if (params->decode_uart) {
|
||||
for (i = 0; i < bitbuffer->num_rows; i++) {
|
||||
int len = extract_bytes_uart(bitbuffer->bb[i], 0, bitbuffer->bits_per_row[i], tmp);
|
||||
memcpy(bitbuffer->bb[i], tmp, len);
|
||||
bitbuffer->bits_per_row[i] = len * 8;
|
||||
}
|
||||
}
|
||||
|
||||
if (decoder->verbose) {
|
||||
fprintf(stderr, "%s: ", params->name);
|
||||
bitbuffer_print(bitbuffer);
|
||||
@@ -658,6 +667,9 @@ r_device *flex_create_device(char *spec)
|
||||
else if (!strcasecmp(key, "unique"))
|
||||
params->unique = val ? atoi(val) : 1;
|
||||
|
||||
else if (!strcasecmp(key, "decode_uart"))
|
||||
params->decode_uart = val ? atoi(val) : 1;
|
||||
|
||||
else if (!strcasecmp(key, "get")) {
|
||||
if (get_count < GETTER_SLOTS)
|
||||
parse_getter(val, ¶ms->getter[get_count++]);
|
||||
|
||||
70
src/util.c
70
src/util.c
@@ -61,6 +61,33 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
|
||||
return ret;
|
||||
}
|
||||
|
||||
unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
|
||||
{
|
||||
unsigned ret = 0;
|
||||
|
||||
while (num_bits >= 10) {
|
||||
int startb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
|
||||
offset_bits += 1;
|
||||
int datab = message[offset_bits / 8];
|
||||
if (offset_bits % 8) {
|
||||
datab = (message[offset_bits / 8] << 8) | message[offset_bits / 8 + 1];
|
||||
datab >>= 8 - (offset_bits % 8);
|
||||
}
|
||||
offset_bits += 8;
|
||||
int stopb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
|
||||
offset_bits += 1;
|
||||
if ((startb & 1) != 0)
|
||||
break; // start-bit error
|
||||
if ((stopb & 1) != 1)
|
||||
break; // stop-bit error
|
||||
*dst++ = reverse8(datab & 0xff);
|
||||
ret += 1;
|
||||
num_bits -= 10;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t crc4(uint8_t const message[], unsigned nBytes, uint8_t polynomial, uint8_t init)
|
||||
{
|
||||
unsigned remainder = init << 4; // LSBs are unused
|
||||
@@ -316,14 +343,51 @@ int add_nibbles(uint8_t const message[], unsigned num_bytes)
|
||||
|
||||
// Unit testing
|
||||
#ifdef _TEST
|
||||
#define ASSERT_EQUALS(a, b) \
|
||||
do { \
|
||||
if ((a) == (b)) \
|
||||
++passed; \
|
||||
else { \
|
||||
++failed; \
|
||||
fprintf(stderr, "FAIL: %d <> %d\n", (a), (b)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
unsigned passed = 0;
|
||||
unsigned failed = 0;
|
||||
|
||||
fprintf(stderr, "util:: test\n");
|
||||
|
||||
uint8_t msg[] = {0x08, 0x0a, 0xe8, 0x80};
|
||||
|
||||
fprintf(stderr, "util::crc8(): odd parity: %02X\n", crc8(msg, 3, 0x80, 0x00));
|
||||
fprintf(stderr, "util::crc8(): even parity: %02X\n", crc8(msg, 4, 0x80, 0x00));
|
||||
fprintf(stderr, "util::crc8(): odd parity\n");
|
||||
ASSERT_EQUALS(crc8(msg, 3, 0x80, 0x00), 0x80);
|
||||
|
||||
return 0;
|
||||
fprintf(stderr, "util::crc8(): even parity\n");
|
||||
ASSERT_EQUALS(crc8(msg, 4, 0x80, 0x00), 0x00);
|
||||
|
||||
// sync-word 0b0 0xff 0b1 0b0 0x33 0b1 (i.e. 0x7fd99, note that 0x33 is 0xcc "on the wire")
|
||||
uint8_t uart[] = {0x7f, 0xd9, 0x90};
|
||||
uint8_t bytes[6] = {0};
|
||||
|
||||
// y0 xff y1 y0 xcc y1 y0 x80 y1 y0 x40 y1 y0 xc0 y1
|
||||
uint8_t uart123[] = {0x07, 0xfd, 0x99, 0x40, 0x48, 0x16, 0x04, 0x00};
|
||||
|
||||
fprintf(stderr, "util::extract_bytes_uart():\n");
|
||||
ASSERT_EQUALS(extract_bytes_uart(uart, 0, 24, bytes), 2);
|
||||
ASSERT_EQUALS(bytes[0], 0xff);
|
||||
ASSERT_EQUALS(bytes[1], 0x33);
|
||||
|
||||
ASSERT_EQUALS(extract_bytes_uart(uart123, 4, 60, bytes), 5);
|
||||
ASSERT_EQUALS(bytes[0], 0xff);
|
||||
ASSERT_EQUALS(bytes[1], 0x33);
|
||||
ASSERT_EQUALS(bytes[2], 0x01);
|
||||
ASSERT_EQUALS(bytes[3], 0x02);
|
||||
ASSERT_EQUALS(bytes[4], 0x03);
|
||||
|
||||
fprintf(stderr, "util:: test (%u/%u) passed, (%u) failed.\n", passed, passed + failed, failed);
|
||||
|
||||
return failed;
|
||||
}
|
||||
#endif /* _TEST */
|
||||
|
||||
Reference in New Issue
Block a user