Skip to content

Commit 416ea6d

Browse files
authored
Add extract_bytes_uart_8n2 util (#3422)
1 parent dbf5609 commit 416ea6d

9 files changed

Lines changed: 106 additions & 17 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -478,7 +478,7 @@ Available options are:
478478
use opt>=n to match at least <n> and opt<=n to match at most <n>
479479
invert : invert all bits
480480
reflect : reflect each byte (MSB first to MSB last)
481-
decode_uart : UART 8n1 (10-to-8) decode
481+
decode_uart=<8n1|8n2|8o1> : UART 8n1 (10-to-8), 8n2, 8o1 (11-to-8) decode
482482
decode_dm : Differential Manchester decode
483483
decode_mc : Manchester decode
484484
match=<bits> : only match if the <bits> are found

include/bit_util.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,18 @@ unsigned extract_nibbles_4b1s(uint8_t const *message, unsigned offset_bits, unsi
6161
/// @param num_bits message length in bits
6262
/// @param dst target buffer for extracted bytes, at least num_bits/10 size
6363
/// @return number of successful decoded bytes
64-
unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
64+
unsigned extract_bytes_uart_8n1(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
65+
66+
/// UART "8n2" (11-to-8) decoder with 1 start bit (0), no parity, 2 stop bits (1), LSB-first bit-order.
67+
///
68+
/// Skips (1) bits until the first start bit (0) is found.
69+
///
70+
/// @param message bytes of message data
71+
/// @param offset_bits start offset of message in bits
72+
/// @param num_bits message length in bits
73+
/// @param dst target buffer for extracted bytes, at least num_bits/11 size
74+
/// @return number of successful decoded bytes
75+
unsigned extract_bytes_uart_8n2(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
6576

6677
/// UART "8o1" (11-to-8) decoder with 1 start bit (1), odd parity, 1 stop bit (0), MSB-first bit-order.
6778
///
@@ -70,7 +81,7 @@ unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsign
7081
/// @param num_bits message length in bits
7182
/// @param dst target buffer for extracted bytes, at least num_bits/11 size
7283
/// @return number of successful decoded bytes
73-
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
84+
unsigned extract_bytes_uart_8o1(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);
7485

7586
/// Decode symbols to bits.
7687
///

man/man1/rtl_433.1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,7 @@ invert : invert all bits
301301
reflect : reflect each byte (MSB first to MSB last)
302302
.RE
303303
.RS
304-
decode_uart : UART 8n1 (10\-to\-8) decode
304+
decode_uart=<8n1|8n2|8o1> : UART 8n1 (10\-to\-8), 8n2, 8o1 (11\-to\-8) decode
305305
.RE
306306
.RS
307307
decode_dm : Differential Manchester decode

src/bit_util.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ unsigned extract_nibbles_4b1s(uint8_t const *message, unsigned offset_bits, unsi
7070
return ret;
7171
}
7272

73-
unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
73+
unsigned extract_bytes_uart_8n1(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
7474
{
7575
unsigned ret = 0;
7676

@@ -97,7 +97,48 @@ unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsign
9797
return ret;
9898
}
9999

100-
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
100+
unsigned extract_bytes_uart_8n2(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
101+
{
102+
unsigned ret = 0;
103+
104+
// skip until first start bit
105+
while (num_bits > 11) {
106+
int startb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
107+
if ((startb & 1) == 0) {
108+
break; // start bit found
109+
}
110+
offset_bits += 1;
111+
num_bits -= 1;
112+
}
113+
// get framed bytes
114+
while (num_bits >= 11) {
115+
int startb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
116+
offset_bits += 1;
117+
int datab = message[offset_bits / 8];
118+
if (offset_bits % 8) {
119+
datab = (message[offset_bits / 8] << 8) | message[offset_bits / 8 + 1];
120+
datab >>= 8 - (offset_bits % 8);
121+
}
122+
offset_bits += 8;
123+
int stopb1 = message[offset_bits / 8] >> (7 - (offset_bits % 8));
124+
offset_bits += 1;
125+
int stopb2 = message[offset_bits / 8] >> (7 - (offset_bits % 8));
126+
offset_bits += 1;
127+
if ((startb & 1) != 0)
128+
break; // start-bit error
129+
if ((stopb1 & 1) != 1)
130+
break; // stop-bit error
131+
if ((stopb2 & 1) != 1)
132+
break; // stop-bit error
133+
*dst++ = reverse8(datab & 0xff);
134+
ret += 1;
135+
num_bits -= 11;
136+
}
137+
138+
return ret;
139+
}
140+
141+
unsigned extract_bytes_uart_8o1(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
101142
{
102143
unsigned ret = 0;
103144

@@ -568,18 +609,28 @@ int main(void) {
568609
// y0 xff y1 y0 xcc y1 y0 x80 y1 y0 x40 y1 y0 xc0 y1
569610
uint8_t uart123[] = {0x07, 0xfd, 0x99, 0x40, 0x48, 0x16, 0x04, 0x00};
570611

571-
fprintf(stderr, "util::extract_bytes_uart():\n");
572-
ASSERT_EQUALS(extract_bytes_uart(uart, 0, 24, bytes), 2);
612+
fprintf(stderr, "util::extract_bytes_uart_8n1():\n");
613+
ASSERT_EQUALS(extract_bytes_uart_8n1(uart, 0, 24, bytes), 2);
573614
ASSERT_EQUALS(bytes[0], 0xff);
574615
ASSERT_EQUALS(bytes[1], 0x33);
575616

576-
ASSERT_EQUALS(extract_bytes_uart(uart123, 4, 60, bytes), 5);
617+
ASSERT_EQUALS(extract_bytes_uart_8n1(uart123, 4, 60, bytes), 5);
577618
ASSERT_EQUALS(bytes[0], 0xff);
578619
ASSERT_EQUALS(bytes[1], 0x33);
579620
ASSERT_EQUALS(bytes[2], 0x01);
580621
ASSERT_EQUALS(bytes[3], 0x02);
581622
ASSERT_EQUALS(bytes[4], 0x03);
582623

624+
// y0 xD1 y11 y0 x11 y11 y0 x4D y11 y0 xEE y11
625+
uint8_t uart8n2[] = {0x45, 0xe8, 0x8d, 0x65, 0x9d, 0xf0};
626+
627+
fprintf(stderr, "util::extract_bytes_uart_8n2():\n");
628+
ASSERT_EQUALS(extract_bytes_uart_8n2(uart8n2, 0, 44, bytes), 4);
629+
ASSERT_EQUALS(bytes[0], 0xd1);
630+
ASSERT_EQUALS(bytes[1], 0x11);
631+
ASSERT_EQUALS(bytes[2], 0x4d);
632+
ASSERT_EQUALS(bytes[3], 0xee);
633+
583634
fprintf(stderr, "util::ccitt_whitening():\n");
584635
uint8_t buf1[16] = {0};
585636
uint8_t chk1[16] = {0xff, 0x87, 0xb8, 0x59, 0xb7, 0xa1, 0xcc, 0x24, 0x57, 0x5e, 0x4b, 0x9c, 0x0e, 0xe9, 0xea, 0x50};

src/devices/flex.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,12 @@
1414
#include "fatal.h"
1515
#include <stdlib.h>
1616

17+
enum uart_mode {
18+
UART_MODE_8N1 = 1,
19+
UART_MODE_8N2,
20+
UART_MODE_8O1,
21+
};
22+
1723
static inline int bit(const uint8_t *bytes, unsigned b)
1824
{
1925
return bytes[b >> 3] >> (7 - (b & 7)) & 1;
@@ -240,7 +246,13 @@ static int flex_callback(r_device *decoder, bitbuffer_t *bitbuffer)
240246
// TODO: refactor to bitbuffer_decode_uart_row()
241247
unsigned len = bitbuffer->bits_per_row[i];
242248
bitbuffer_t tmp = {0};
243-
len = extract_bytes_uart(bitbuffer->bb[i], 0, len, tmp.bb[0]);
249+
if (params->decode_uart == UART_MODE_8N1) {
250+
len = extract_bytes_uart_8n1(bitbuffer->bb[i], 0, len, tmp.bb[0]);
251+
} else if (params->decode_uart == UART_MODE_8N2) {
252+
len = extract_bytes_uart_8n2(bitbuffer->bb[i], 0, len, tmp.bb[0]);
253+
} else if (params->decode_uart == UART_MODE_8O1) {
254+
len = extract_bytes_uart_8o1(bitbuffer->bb[i], 0, len, tmp.bb[0]);
255+
}
244256
memcpy(bitbuffer->bb[i], tmp.bb[0], len); // safe to write over: can only be shorter
245257
bitbuffer->bits_per_row[i] = len * 8;
246258
}
@@ -418,7 +430,7 @@ static void help(void)
418430
"\t\tuse opt>=n to match at least <n> and opt<=n to match at most <n>\n"
419431
"\tinvert : invert all bits\n"
420432
"\treflect : reflect each byte (MSB first to MSB last)\n"
421-
"\tdecode_uart : UART 8n1 (10-to-8) decode\n"
433+
"\tdecode_uart=<8n1|8n2|8o1> : UART 8n1 (10-to-8), 8n2, 8o1 (11-to-8) decode\n"
422434
"\tdecode_dm : Differential Manchester decode\n"
423435
"\tdecode_mc : Manchester decode\n"
424436
"\tmatch=<bits> : only match if the <bits> are found\n"
@@ -630,6 +642,21 @@ static void parse_getter(const char *arg, struct flex_get *getter)
630642
*/
631643
}
632644

645+
static unsigned parse_uart_mode(char const *str)
646+
{
647+
if (!strcasecmp(str, "8n1"))
648+
return UART_MODE_8N1;
649+
else if (!strcasecmp(str, "8n2"))
650+
return UART_MODE_8N2;
651+
else if (!strcasecmp(str, "8o1"))
652+
return UART_MODE_8O1;
653+
else {
654+
fprintf(stderr, "Bad flex spec, unknown uart mode!\n");
655+
usage();
656+
}
657+
return 0;
658+
}
659+
633660
// NOTE: this is declared in rtl_433.c also.
634661
r_device *flex_create_device(char *spec);
635662

@@ -728,7 +755,7 @@ r_device *flex_create_device(char *spec)
728755
params->unique = parse_atoiv(val, 1, "unique: ");
729756

730757
else if (!strcasecmp(key, "decode_uart"))
731-
params->decode_uart = parse_atoiv(val, 1, "decode_uart: ");
758+
params->decode_uart = parse_uart_mode(val);
732759
else if (!strcasecmp(key, "decode_dm"))
733760
params->decode_dm = parse_atoiv(val, 1, "decode_dm: ");
734761
else if (!strcasecmp(key, "decode_mc"))

src/devices/gridstream.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,12 +141,12 @@ static int gridstream_decode(r_device *decoder, bitbuffer_t *bitbuffer)
141141
return DECODE_FAIL_SANITY;
142142
}
143143
unsigned num_bits = MIN(bitbuffer->bits_per_row[0] - offset, sizeof(b) * 10);
144-
decoded_len = extract_bytes_uart(bitbuffer->bb[0], offset, num_bits, b);
144+
decoded_len = extract_bytes_uart_8n1(bitbuffer->bb[0], offset, num_bits, b);
145145
protocol_version = 5;
146146
}
147147
else {
148148
unsigned num_bits = MIN(bitbuffer->bits_per_row[0] - offset, sizeof(b) * 10);
149-
decoded_len = extract_bytes_uart(bitbuffer->bb[0], offset, num_bits, b);
149+
decoded_len = extract_bytes_uart_8n1(bitbuffer->bb[0], offset, num_bits, b);
150150
protocol_version = 4;
151151
}
152152

src/devices/rosstech_dcu706.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ static int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)
6969
bitbuffer_extract_bytes(bitbuffer, 0, start_pos, msg, sizeof(msg) * 8);
7070

7171
uint8_t b[5] = {0};
72-
unsigned r = extract_bytes_uart_parity(msg, 0, 55, b);
72+
unsigned r = extract_bytes_uart_8o1(msg, 0, 55, b);
7373
if (r != 5) {
7474
decoder_logf(decoder, 2, __func__, "UART decoding failed. Got %d of 5 bytes", r);
7575
return DECODE_ABORT_LENGTH;

src/devices/sainlogic_sa8.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ static int sainlogic_sa8_decode(r_device *decoder, bitbuffer_t *bitbuffer)
8181

8282
int num_bits = bitbuffer->bits_per_row[0] - offset;
8383
num_bits = MIN((size_t)num_bits, sizeof (b) * 10);
84-
int len = extract_bytes_uart(bitbuffer->bb[0], offset, num_bits, b);
84+
int len = extract_bytes_uart_8n1(bitbuffer->bb[0], offset, num_bits, b);
8585

8686
if (len < 41) {
8787
decoder_log(decoder, 2, __func__, "Message too short");

src/devices/somfy_iohc.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ static int somfy_iohc_decode(r_device *decoder, bitbuffer_t *bitbuffer)
107107

108108
num_bits = MIN((size_t)num_bits, sizeof (b) * 10);
109109

110-
int len = extract_bytes_uart(bitbuffer->bb[0], offset, num_bits, b);
110+
int len = extract_bytes_uart_8n1(bitbuffer->bb[0], offset, num_bits, b);
111111
if (len < 11)
112112
return DECODE_ABORT_LENGTH;
113113

0 commit comments

Comments
 (0)