Skip to content

Commit

Permalink
Add extract_bytes_uart_parity utility function
Browse files Browse the repository at this point in the history
  • Loading branch information
zuckschwerdt committed Oct 16, 2024
1 parent a8d35e3 commit 4736276
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 46 deletions.
15 changes: 12 additions & 3 deletions include/bit_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes);
/// @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);
unsigned extract_nibbles_4b1s(uint8_t const *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.
///
Expand All @@ -61,7 +61,16 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
/// @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);
unsigned extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);

/// UART "8o1" (11-to-8) decoder with 1 start bit (1), odd parity, 1 stop bit (0), MSB-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/11 size
/// @return number of successful decoded bytes
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst);

/// Decode symbols to bits.
///
Expand All @@ -73,7 +82,7 @@ unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num
/// @param sync symbol for sync bit, ignored at start, terminates at end
/// @param dst target buffer for extracted bits, at least num_bits/symbol_x_len size
/// @return number of successful decoded bits
unsigned extract_bits_symbols(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst);
unsigned extract_bits_symbols(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst);

/// CRC-4.
///
Expand Down
42 changes: 37 additions & 5 deletions src/bit_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ uint8_t reverse8(uint8_t x)
uint32_t reverse32(uint32_t x)
{
uint32_t ret;
uint8_t* xp = (uint8_t*)&x;
uint8_t const* xp = (uint8_t*)&x;
ret = (uint32_t) reverse8(xp[0]) << 24 | reverse8(xp[1]) << 16 | reverse8(xp[2]) << 8 | reverse8(xp[3]);
return ret;
}
Expand All @@ -52,7 +52,7 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes)
}
}

unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
unsigned extract_nibbles_4b1s(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

Expand All @@ -70,7 +70,7 @@ 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 extract_bytes_uart(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

Expand All @@ -97,7 +97,39 @@ unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num
return ret;
}

static unsigned symbol_match(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t symbol)
unsigned extract_bytes_uart_parity(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint8_t *dst)
{
unsigned ret = 0;

while (num_bits >= 11) {
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 parityb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
offset_bits += 1;
int stopb = message[offset_bits / 8] >> (7 - (offset_bits % 8));
offset_bits += 1;
int data_parity = parity8(datab);
if ((startb & 1) != 1)
break; // start-bit error
if ((parityb & 1) != data_parity)
break; // parity-bit error
if ((stopb & 1) != 0)
break; // stop-bit error
*dst++ = (datab & 0xff);
ret += 1;
num_bits -= 11;
}

return ret;
}

static unsigned symbol_match(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t symbol)
{
unsigned symbol_len = symbol & 0x1f;

Expand All @@ -119,7 +151,7 @@ static unsigned symbol_match(uint8_t *message, unsigned offset_bits, unsigned nu
return symbol_len;
}

unsigned extract_bits_symbols(uint8_t *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst)
unsigned extract_bits_symbols(uint8_t const *message, unsigned offset_bits, unsigned num_bits, uint32_t zero, uint32_t one, uint32_t sync, uint8_t *dst)
{
unsigned zero_len = zero & 0x1f;
unsigned one_len = one & 0x1f;
Expand Down
57 changes: 19 additions & 38 deletions src/devices/rosstech_dcu706.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ Supported Models:
Sundance DCU-6560-131, SD-880 Series, PN 6560-131
Jacuzzi DCU-2560-131, Jac-J300/J400 and SD-780 series, PN 6560-132/2560-131
Data coding:
UART 8o1: 11 bits/byte: 1 start bit (1), odd parity, 1 stop bit (0).
Data layout:
SS IIII TT CC
Expand All @@ -28,29 +32,8 @@ Data layout:
- C: 8 bit Checksum: Count 1s for each bit of each element:
Set bit to 1 if number is even 0 if odd
11 bits/byte: 1 start bit, 0 stop bits and odd parity
*/

static uint8_t calculateChecksum(const uint8_t *data, size_t size)
{
uint8_t checksum = 0;

for (int bit = 0; bit < 8; bit++) {
int count = 0;

for (size_t i = 0; i < size; i++) {
count += (data[i] >> bit) & 1;
}

if (count % 2 == 0) {
checksum |= (1 << bit);
}
}

return checksum;
}

static int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
uint8_t const preamble_data_transmission[] = {0xDD, 0x40};
Expand Down Expand Up @@ -85,23 +68,21 @@ static int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)

bitbuffer_extract_bytes(bitbuffer, 0, start_pos, msg, sizeof(msg) * 8);

uint8_t msg_type = (msg[0] << 1) | (msg[1] >> 7); // S
uint8_t id_high = (msg[1] << 4) | (msg[2] >> 4);
uint8_t id_low = (msg[2] << 7) | (msg[3] >> 1);
uint16_t id = (id_high << 8) | id_low; // I
uint8_t temp_f = (msg[4] << 2) | (msg[5] >> 6); // T
uint8_t checksum = (msg[5] << 5) | (msg[6] >> 3); // C

// Create a uint8_t array to hold the extracted values
uint8_t extracted_data[4];
extracted_data[0] = msg_type;
extracted_data[1] = id_high;
extracted_data[2] = id_low;
extracted_data[3] = temp_f;

uint8_t calculated_checksum = calculateChecksum(extracted_data, sizeof(extracted_data) / sizeof(extracted_data[0]));
if (calculated_checksum != checksum) {
decoder_logf(decoder, 2, __func__, "Checksum failed. Expected: %02x, Calculated: %02x.", checksum, calculated_checksum);
uint8_t b[5] = {0};
unsigned r = extract_bytes_uart_parity(msg, 0, 55, b);
if (r != 5) {
decoder_logf(decoder, 2, __func__, "UART decoding failed. Got %d of 5 bytes", r);
return DECODE_ABORT_LENGTH;
}

int msg_type = b[0]; // S
int id = (b[1] << 8) | (b[2]); // I
int temp_f = b[3]; // T
int checksum = b[4]; // C

uint8_t calculated = 0xff ^ xor_bytes(b, 4);
if (calculated != checksum) {
decoder_logf(decoder, 2, __func__, "Checksum failed. Expected: %02x, Calculated: %02x", checksum, calculated);
return DECODE_FAIL_MIC;
}

Expand Down

0 comments on commit 4736276

Please sign in to comment.