-
Notifications
You must be signed in to change notification settings - Fork 0
/
lacrosse.cpp
108 lines (94 loc) · 3.02 KB
/
lacrosse.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#include "lacrosse.h"
/*
* Message Format:
*
* .- [0] -. .- [1] -. .- [2] -. .- [3] -. .- [4] -.
* SSSS.DDDD DDN_.TTTT TTTT.TTTT WHHH.HHHH CCCC.CCCC
* | | | || | | | | | | || | | |
* | | | || | | | | | | || | `--------- CRC
* | | | || | | | | | | |`-------- humidity%
* | | | || | | | | | | `---- weak battery
* | | | || `--------------- Temperature BCD, T = X/10-40
* | | | | `--- new battery
* | | `-------- sensor ID
* `---- start byte
*
* more details:
* https://github.com/merbanan/rtl_433/blob/master/src/devices/lacrosse_tx35.c
*/
void LaCrosse::DecodeFrame(byte *bytes, struct Frame *f)
{
f->valid = true;
if (bytes[4] != CalculateCRC(bytes, FRAME_LENGTH - 1))
f->valid = false;
if ((bytes[0] & 0xF0) != 0x90)
f->valid = false;
// SSSS.DDDD DDN_.TTTT TTTT.TTTT WHHH.HHHH CCCC.CCCC
f->ID = (bytes[0] & 0xF) << 2;
f->ID |= (bytes[1] & 0xC0) >> 6;
f->init = (bytes[1] & 0x20) ? 1 : 0;
byte bcd[3];
bcd[0] = bytes[1] & 0xF;
bcd[1] = (bytes[2] & 0xF0) >> 4;
bcd[2] = (bytes[2] & 0xF);
f->temp = ((bcd[0] * 100 + bcd[1] * 10 + bcd[2]) - 400) / 10.0;
f->batlo = (bytes[3] & 0x80) ? 1 : 0;
f->humi = bytes[3] & 0x7f;
if (f->humi == 0x7d) /* indicates that temperature is second channel */
f->ID |= 0x40; /* => increase ID by 64 to indicate difference */
if (f->rate == 9579) /* slow rate sensors => increase ID by 128 */
f->ID |= 0x80;
}
bool LaCrosse::DisplayFrame(byte *data, struct Frame *f)
{
static unsigned long last[SENSOR_NUM]; /* one for each sensor ID */
if (!f->valid) {
Serial.println("LaCrosse::DisplayFrame FRAME INVALD");
return false;
}
DisplayRaw(last[f->ID], "Sensor ", data, FRAME_LENGTH, f->rssi, f->rate);
Serial.printf(" ID:%-3d Temp:%-5.1f init:%d batlo:%d", f->ID, f->temp, f->init, f->batlo);
if (f->humi > 0 && f->humi <= 100)
Serial.printf(" Hum:%d", f->humi);
Serial.println();
return true;
}
bool LaCrosse::TryHandleData(byte *data, struct Frame *f)
{
if ((data[0] & 0xF0) != 0x90)
return false;
DecodeFrame(data, f);
return f->valid;
}
byte LaCrosse::UpdateCRC(byte res, uint8_t val)
{
for (int i = 0; i < 8; i++) {
uint8_t tmp = (uint8_t)((res ^ val) & 0x80);
res <<= 1;
if (0 != tmp) {
res ^= 0x31;
}
val <<= 1;
}
return res;
}
byte LaCrosse::CalculateCRC(byte *data, byte len)
{
byte res = 0;
for (int j = 0; j < len; j++) {
uint8_t val = data[j];
res = UpdateCRC(res, val);
}
return res;
}
void LaCrosse::DisplayRaw(unsigned long &last, const char *dev, uint8_t *data, uint8_t len, int8_t rssi, int rate)
{
unsigned long now = millis();
if (last == 0)
last = now;
Serial.printf("%6ld %s [", (now - last), dev);
last = now;
for (uint8_t i = 0; i < len; i++)
Serial.printf("%02X%s", data[i],(i==len-1)?"":" ");
Serial.printf("] rssi:%-4d rate:%-5d", rssi, rate);
}