Add extract_bytes_uart_parity utility function

This commit is contained in:
Christian W. Zuckschwerdt 2024-10-16 03:40:41 +02:00
parent a8d35e3820
commit 4736276bd4
3 changed files with 66 additions and 44 deletions

View file

@ -52,7 +52,7 @@ void reflect_nibbles(uint8_t message[], unsigned num_bytes);
/// @param num_bits message length in bits /// @param num_bits message length in bits
/// @param dst target buffer for extracted nibbles, at least num_bits/5 size /// @param dst target buffer for extracted nibbles, at least num_bits/5 size
/// @return number of successfully unstuffed nibbles. /// @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. /// UART "8n1" (10-to-8) decoder with 1 start bit (0), no parity, 1 stop bit (1), LSB-first bit-order.
/// ///
@ -61,7 +61,16 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
/// @param num_bits message length in bits /// @param num_bits message length in bits
/// @param dst target buffer for extracted bytes, at least num_bits/10 size /// @param dst target buffer for extracted bytes, at least num_bits/10 size
/// @return number of successful decoded bytes /// @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. /// Decode symbols to bits.
/// ///
@ -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 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 /// @param dst target buffer for extracted bits, at least num_bits/symbol_x_len size
/// @return number of successful decoded bits /// @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. /// CRC-4.
/// ///

View file

@ -26,7 +26,7 @@ uint8_t reverse8(uint8_t x)
uint32_t reverse32(uint32_t x) uint32_t reverse32(uint32_t x)
{ {
uint32_t ret; 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]); ret = (uint32_t) reverse8(xp[0]) << 24 | reverse8(xp[1]) << 16 | reverse8(xp[2]) << 8 | reverse8(xp[3]);
return ret; return ret;
} }
@ -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; unsigned ret = 0;
@ -70,7 +70,7 @@ unsigned extract_nibbles_4b1s(uint8_t *message, unsigned offset_bits, unsigned n
return ret; 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; unsigned ret = 0;
@ -97,7 +97,39 @@ unsigned extract_bytes_uart(uint8_t *message, unsigned offset_bits, unsigned num
return ret; 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; unsigned symbol_len = symbol & 0x1f;
@ -119,7 +151,7 @@ static unsigned symbol_match(uint8_t *message, unsigned offset_bits, unsigned nu
return symbol_len; 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 zero_len = zero & 0x1f;
unsigned one_len = one & 0x1f; unsigned one_len = one & 0x1f;

View file

@ -18,6 +18,10 @@ Supported Models:
Sundance DCU-6560-131, SD-880 Series, PN 6560-131 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 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: Data layout:
SS IIII TT CC SS IIII TT CC
@ -28,29 +32,8 @@ Data layout:
- C: 8 bit Checksum: Count 1s for each bit of each element: - C: 8 bit Checksum: Count 1s for each bit of each element:
Set bit to 1 if number is even 0 if odd 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) static int rosstech_dcu706_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{ {
uint8_t const preamble_data_transmission[] = {0xDD, 0x40}; uint8_t const preamble_data_transmission[] = {0xDD, 0x40};
@ -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); bitbuffer_extract_bytes(bitbuffer, 0, start_pos, msg, sizeof(msg) * 8);
uint8_t msg_type = (msg[0] << 1) | (msg[1] >> 7); // S uint8_t b[5] = {0};
uint8_t id_high = (msg[1] << 4) | (msg[2] >> 4); unsigned r = extract_bytes_uart_parity(msg, 0, 55, b);
uint8_t id_low = (msg[2] << 7) | (msg[3] >> 1); if (r != 5) {
uint16_t id = (id_high << 8) | id_low; // I decoder_logf(decoder, 2, __func__, "UART decoding failed. Got %d of 5 bytes", r);
uint8_t temp_f = (msg[4] << 2) | (msg[5] >> 6); // T return DECODE_ABORT_LENGTH;
uint8_t checksum = (msg[5] << 5) | (msg[6] >> 3); // C }
// Create a uint8_t array to hold the extracted values int msg_type = b[0]; // S
uint8_t extracted_data[4]; int id = (b[1] << 8) | (b[2]); // I
extracted_data[0] = msg_type; int temp_f = b[3]; // T
extracted_data[1] = id_high; int checksum = b[4]; // C
extracted_data[2] = id_low;
extracted_data[3] = temp_f;
uint8_t calculated_checksum = calculateChecksum(extracted_data, sizeof(extracted_data) / sizeof(extracted_data[0])); uint8_t calculated = 0xff ^ xor_bytes(b, 4);
if (calculated_checksum != checksum) { if (calculated != checksum) {
decoder_logf(decoder, 2, __func__, "Checksum failed. Expected: %02x, Calculated: %02x.", checksum, calculated_checksum); decoder_logf(decoder, 2, __func__, "Checksum failed. Expected: %02x, Calculated: %02x", checksum, calculated);
return DECODE_FAIL_MIC; return DECODE_FAIL_MIC;
} }