2 #include "pulse_demod.h"
6 #define HIDEKI_BYTES_PER_ROW 14
8 // 11111001 0 11110101 0 01110011 1 01111010 1 11001100 0 01000011 1 01000110 1 00111111 0 00001001 0 00010111 0
9 // SYNC+HEAD P RC cha P P Nr.? P .1° 1° P 10° BV P 1% 10% P ????SYNC -------Check?------- P
12 // 00000000 11111111 22222222 33333333 44444444 55555555 66666666 77777777 88888888 99999999
13 // SYNC+HEAD cha RC Nr.? 1° .1° VB 10° 10% 1% SYNC???? -----Check?------
16 // 00000000 11111111 22222222 33333333 44444444 55555555 66666666 77777777 88888888 99999999 AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD
17 // SYNC+HEAD cha RC Nr.? 1° .1° VB 10° 1° .1° VB 10° .1mh 1mh ?? 10mh ???? w° ?? ???? ????
19 enum sensortypes { HIDEKI_UNKNOWN, HIDEKI_TS04, HIDEKI_WIND, HIDEKI_RAIN };
21 static int hideki_ts04_callback(bitbuffer_t *bitbuffer) {
22 bitrow_t *bb = bitbuffer->bb;
23 uint8_t *b = bb[0];//TODO: handle the 3 row, need change in PULSE_CLOCK decoding
25 char time_str[LOCAL_TIME_BUFLEN];
27 local_time_str(0, time_str);
29 uint8_t packet[HIDEKI_BYTES_PER_ROW];
30 int sensortype = HIDEKI_WIND; // default for 14 valid bytes
31 uint8_t channel, humidity, rc, battery_ok;
32 int temp, wind_strength, wind_direction, rain_units;
34 // Transform the incoming data:
35 // * change endianness
37 // * Remove (and check) parity bit
38 // TODO this may be factorise as a bitbuffer method (as for bitbuffer_manchester_decode)
39 for(int i=0; i<HIDEKI_BYTES_PER_ROW; i++){
40 unsigned int offset = i/8;
41 packet[i] = b[i+offset] << (i%8);
42 packet[i] |= b[i+offset+1] >> (8 - i%8);
43 // reverse as it is litle endian...
44 packet[i] = reverse8(packet[i]);
48 uint8_t parity = ((b[i+offset+1] >> (7 - i%8)) ^ 0xFF) & 0x01;
49 if(parity != byteParity(packet[i]))
52 sensortype = HIDEKI_TS04;
56 sensortype = HIDEKI_RAIN;
64 if(packet[0] == 0x9f){ //Note: it may exist other valid id
65 channel = (packet[1] >> 5) & 0x0F;
66 if(channel >= 5) channel -= 1;
67 rc = packet[1] & 0x0F;
68 temp = (packet[5] & 0x0F) * 100 + ((packet[4] & 0xF0) >> 4) * 10 + (packet[4] & 0x0F);
69 if(((packet[5]>>7) & 0x01) == 0){
72 battery_ok = (packet[5]>>6) & 0x01;
73 if (sensortype == HIDEKI_TS04) {
74 humidity = ((packet[6] & 0xF0) >> 4) * 10 + (packet[6] & 0x0F);
75 data = data_make("time", "", DATA_STRING, time_str,
76 "model", "", DATA_STRING, "HIDEKI TS04 sensor",
77 "rc", "Rolling Code", DATA_INT, rc,
78 "channel", "Channel", DATA_INT, channel,
79 "battery", "Battery", DATA_STRING, battery_ok ? "OK": "LOW",
80 "temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, temp/10.f,
81 "humidity", "Humidity", DATA_FORMAT, "%u %%", DATA_INT, humidity,
83 data_acquired_handler(data);
86 if (sensortype == HIDEKI_WIND) {
87 const uint8_t wd[] = { 0, 15, 13, 14, 9, 10, 12, 11, 1, 2, 4, 3, 8, 7, 5, 6 };
88 wind_direction = wd[((packet[11] & 0xF0) >> 4)] * 225;
89 wind_strength = (packet[9] & 0x0F) * 100 + ((packet[8] & 0xF0) >> 4) * 10 + (packet[8] & 0x0F);
90 data = data_make("time", "", DATA_STRING, time_str,
91 "model", "", DATA_STRING, "HIDEKI Wind sensor",
92 "rc", "Rolling Code", DATA_INT, rc,
93 "channel", "Channel", DATA_INT, channel,
94 "battery", "Battery", DATA_STRING, battery_ok ? "OK": "LOW",
95 "temperature_C", "Temperature", DATA_FORMAT, "%.01f C", DATA_DOUBLE, temp/10.f,
96 "windstrength", "Wind Strength", DATA_FORMAT, "%.02f km/h", DATA_DOUBLE, wind_strength*0.160934f,
97 "winddirection", "Direction", DATA_FORMAT, "%.01f °", DATA_DOUBLE, wind_direction/10.f,
99 data_acquired_handler(data);
102 if (sensortype == HIDEKI_RAIN) {
103 rain_units = (packet[5] << 8) + packet[4];
104 battery_ok = (packet[2]>>6) & 0x01;
105 data = data_make("time", "", DATA_STRING, time_str,
106 "model", "", DATA_STRING, "HIDEKI Rain sensor",
107 "rc", "Rolling Code", DATA_INT, rc,
108 "channel", "Channel", DATA_INT, channel,
109 "battery", "Battery", DATA_STRING, battery_ok ? "OK": "LOW",
110 "rain", "Rain", DATA_FORMAT, "%.01f mm", DATA_DOUBLE, rain_units*0.7f,
112 data_acquired_handler(data);
120 PWM_Precise_Parameters hideki_ts04_clock_bits_parameters = {
121 .pulse_tolerance = 60,
122 .pulse_sync_width = 0, // No sync bit used
125 static char *output_fields[] = {
139 r_device hideki_ts04 = {
140 .name = "HIDEKI TS04 Temperature, Humidity, Wind and Rain Sensor",
141 .modulation = OOK_PULSE_CLOCK_BITS,
143 .long_limit = 1040, // not used
145 .json_callback = &hideki_ts04_callback,
147 .demod_arg = (uintptr_t)&hideki_ts04_clock_bits_parameters,
148 .fields = output_fields,