Skip to content

Commit

Permalink
minor: Cleanup LaCrosse-TX style, add TFA 30.3121 note
Browse files Browse the repository at this point in the history
  • Loading branch information
zuckschwerdt committed Sep 20, 2022
1 parent 5174596 commit 73f5a84
Showing 1 changed file with 44 additions and 63 deletions.
107 changes: 44 additions & 63 deletions src/devices/lacrosse.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
*/
/** @fn int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
/**
LaCrosse TX 433 Mhz Temperature and Humidity Sensors.
- Tested: TX-7U and TX-6U (Temperature only)
- Not Tested but should work: TX-3, TX-4
- also TFA Dostmann 30.3120.90 sensor (for e.g. 35.1018.06 (WS-9015) station)
- also TFA Dostmann 30.3121 sensor
Protocol Documentation: http://www.f6fbb.org/domo/sensors/tx3_th.php
Expand All @@ -37,50 +38,51 @@ Message is 44 bits, 11 x 4 bit nybbles:
- Frequency for each sensor may be could be off by as much as 50-75 khz
- LaCrosse Sensors in other frequency ranges (915 Mhz) use FSK not OOK
so they can't be decoded by rtl_433 currently.
- Temperature and Humidity are sent in different messages bursts.
TO DO:
- Now that we have a demodulator that isn't stripping the first bit
the detect and decode could be collapsed into a single reasonably
readable function.
*/

#include "decoder.h"

#define LACROSSE_TX_BITLEN 44
#define LACROSSE_NYBBLE_CNT 11

// Check for a valid LaCrosse TX Packet
//
// Return message nybbles broken out into bytes
// for clarity. The LaCrosse protocol is based
// on 4 bit nybbles.
//
// Demodulation
// Long bits = 0
// short bits = 1
//
static int lacrossetx_detect(r_device *decoder, uint8_t *pRow, uint8_t *msg_nybbles, int16_t rowlen)
static int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
int i;
uint8_t rbyte_no, rbit_no, mnybble_no, mbit_no;
uint8_t bit, checksum, parity_bit, parity = 0;
int events = 0;
int result = 0;

// Actual Packet should start with 0x0A and be 6 bytes
// actual message is 44 bit, 11 x 4 bit nybbles.
if (rowlen == LACROSSE_TX_BITLEN && pRow[0] == 0x0a) {
for (int row = 0; row < bitbuffer->num_rows; ++row) {
// break out the message nybbles into separate bytes
// The LaCrosse protocol is based on 4 bit nybbles.
uint8_t *pRow = bitbuffer->bb[row];
uint8_t msg_nybbles[LACROSSE_NYBBLE_CNT];
int16_t rowlen = bitbuffer->bits_per_row[row];

// Actual Packet should start with 0x0A and be 6 bytes
// actual message is 44 bit, 11 x 4 bit nybbles.
if (rowlen != LACROSSE_TX_BITLEN) {
result = DECODE_ABORT_LENGTH;
continue; // DECODE_ABORT_LENGTH
}
if (pRow[0] != 0x0a) {
result = DECODE_ABORT_EARLY;
continue; // DECODE_ABORT_EARLY
}

for (i = 0; i < LACROSSE_NYBBLE_CNT; i++) {
for (int i = 0; i < LACROSSE_NYBBLE_CNT; i++) {
msg_nybbles[i] = 0;
}

// Move nybbles into a byte array
// Compute parity and checksum at the same time.
for (i = 0; i < 44; i++) {
rbyte_no = i / 8;
rbit_no = 7 - (i % 8);
mnybble_no = i / 4;
mbit_no = 3 - (i % 4);
bit = (pRow[rbyte_no] & (1 << rbit_no)) ? 1 : 0;
uint8_t parity = 0;
for (int i = 0; i < 44; i++) {
uint8_t rbyte_no = i / 8;
uint8_t rbit_no = 7 - (i % 8);
uint8_t mnybble_no = i / 4;
uint8_t mbit_no = 3 - (i % 4);
uint8_t bit = (pRow[rbyte_no] & (1 << rbit_no)) ? 1 : 0;
msg_nybbles[mnybble_no] |= (bit << mbit_no);

// Check parity on three bytes of data value
Expand All @@ -90,50 +92,28 @@ static int lacrossetx_detect(r_device *decoder, uint8_t *pRow, uint8_t *msg_nybb
parity += bit;
}

// decoder_logf(decoder, 0, __func__, "recv: [%d/%d] %d -> msg [%d/%d] %02x, Parity: %d %s", rbyte_no, rbit_no,
// bit, mnybble_no, mbit_no, msg_nybbles[mnybble_no], parity,
// ( mbit_no == 0 ) ? "\n" : "" );
//decoder_logf(decoder, 0, __func__, "recv: [%d/%d] %d -> msg [%d/%d] %02x, Parity: %d %s", rbyte_no, rbit_no,
// bit, mnybble_no, mbit_no, msg_nybbles[mnybble_no], parity,
// ( mbit_no == 0 ) ? "\n" : "" );
}

parity_bit = msg_nybbles[4] & 0x01;
uint8_t parity_bit = msg_nybbles[4] & 0x01;
parity += parity_bit;

// Validate Checksum (4 bits in last nybble)
checksum = 0;
for (i = 0; i < 10; i++) {
uint8_t checksum = 0;
for (int i = 0; i < 10; i++) {
checksum = (checksum + msg_nybbles[i]) & 0x0F;
}

// decoder_logf(decoder, 0, __func__,"Parity: %d, parity bit %d, Good %d", parity, parity_bit, parity % 2);

if (checksum == msg_nybbles[10] && (parity % 2 == 0)) {
return 1;
} else {
if (checksum != msg_nybbles[10] || (parity % 2 != 0)) {
decoder_logf(decoder, 2, __func__,
"LaCrosse TX Checksum/Parity error: Comp. %d != Recv. %d, Parity %d",
checksum, msg_nybbles[10], parity);
return DECODE_FAIL_MIC;
}
}

return DECODE_ABORT_LENGTH;
}

// LaCrosse TX-6u, TX-7u, Temperature and Humidity Sensors
// Temperature and Humidity are sent in different messages bursts.
static int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
{
int events = 0;
uint8_t msg_nybbles[LACROSSE_NYBBLE_CNT];
data_t *data;

int result = 0;

for (int row = 0; row < bitbuffer->num_rows; ++row) {
// break out the message nybbles into separate bytes
if (lacrossetx_detect(decoder, bitbuffer->bb[row], msg_nybbles, bitbuffer->bits_per_row[row]) <= 0) {
result = DECODE_ABORT_EARLY;
continue; // DECODE_ABORT_EARLY
result = DECODE_FAIL_MIC;
continue; // DECODE_FAIL_MIC
}

// TODO: check if message length is a valid value
Expand All @@ -157,7 +137,7 @@ static int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
if (msg_type == 0x00) {
float temp_c = msg_value - 50.0f;
/* clang-format off */
data = data_make(
data_t *data = data_make(
"model", "", DATA_STRING, "LaCrosse-TX",
"id", "", DATA_INT, sensor_id,
"temperature_C", "Temperature", DATA_FORMAT, "%.1f C", DATA_DOUBLE, temp_c,
Expand All @@ -169,7 +149,7 @@ static int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
}
else if (msg_type == 0x0E) {
/* clang-format off */
data = data_make(
data_t *data = data_make(
"model", "", DATA_STRING, "LaCrosse-TX",
"id", "", DATA_INT, sensor_id,
"humidity", "Humidity", DATA_FORMAT, "%.1f %%", DATA_DOUBLE, msg_value,
Expand All @@ -187,8 +167,9 @@ static int lacrossetx_decode(r_device *decoder, bitbuffer_t *bitbuffer)
}
}

if (events)
if (events) {
return events;
}

return result;
}
Expand Down

0 comments on commit 73f5a84

Please sign in to comment.