Skip to content

Commit

Permalink
Add decode_uart util (#1376)
Browse files Browse the repository at this point in the history
  • Loading branch information
zuckschwerdt committed May 14, 2020
1 parent 3484441 commit 67ff22c
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 3 deletions.
10 changes: 10 additions & 0 deletions include/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 12 additions & 0 deletions src/devices/flex.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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, &params->getter[get_count++]);
Expand Down
70 changes: 67 additions & 3 deletions src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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);

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 0;
return failed;
}
#endif /* _TEST */

0 comments on commit 67ff22c

Please sign in to comment.