Bugfixes
[rtl-433.git] / src / devices / newkaku.c
1 #include "rtl_433.h"
2 #include "util.h"
3 #include "data.h"
4
5 static int newkaku_callback(bitbuffer_t *bitbuffer) {
6     /* Two bits map to 2 states, 0 1 -> 0 and 1 1 -> 1 */
7     /* Status bit can be 1 1 -> 1 which indicates DIM value. 4 extra bits are present with value */
8     /*start pulse: 1T high, 10.44T low */
9     /*- 26 bit:  Address */
10     /*- 1  bit:  group bit*/
11     /*- 1  bit:  Status bit on/off/[dim]*/
12     /*- 4  bit:  unit*/
13     /*- [4 bit:  dim level. Present if [dim] is used, but might be present anyway...]*/
14     /*- stop pulse: 1T high, 40T low */
15     data_t *data;
16     bitrow_t *bb = bitbuffer->bb;
17     int i;
18     uint8_t tmp = 0;
19     uint8_t unit = 0;
20     uint8_t packet = 0;
21     uint8_t bitcount = 0;
22     uint32_t kakuid = 0;
23     uint8_t dv = 0;
24     char *group_call, *command, *dim;
25     char time_str[LOCAL_TIME_BUFLEN];
26     local_time_str(0, time_str);
27
28     if (bb[0][0] == 0xac || bb[0][0] == 0xb2) {//allways starts with ac or b2
29         // first bit is from startbit sequence, not part of payload!
30         // check protocol if value is 10 or 01, else stop processing as it is no vallid KAKU packet!
31         //get id=24bits, remember 1st 1 bit = startbit, no payload!
32         for (packet = 0; packet < 6; packet++) {//get first part kakuid
33             tmp = bb[0][packet] << 1;
34             if ((bb[0][packet + 1]&(1 << 7)) != 0) {// if set add bit to current
35                 tmp++;
36             }
37
38             for (bitcount = 0; bitcount < 8; bitcount += 2) {//process bitstream, check protocol!
39
40                 if (((tmp << bitcount & (0x80)) == 0x80)&((tmp << bitcount & (0x40)) == 0)) {
41                     //add 1
42                     kakuid = kakuid << 1;
43                     kakuid++;
44                 } else
45                     if (((tmp << bitcount & (0x80)) == 0)&((tmp << bitcount & (0x40)) == 0x40)) {
46                     kakuid = kakuid << 1;
47                     //add 0
48                 } else {
49                     return 0; //00 and 11 indicates packet error. Do exit, no valid packet
50                 }
51             }
52         }
53         tmp = bb[0][6] << 1; //Get last part ID
54         for (bitcount = 0; bitcount < 4; bitcount += 2) {
55             if (((tmp << bitcount & (0x80)) == 0x80)&((tmp << bitcount & (0x40)) == 0)) {
56                 //add 1
57                 kakuid = kakuid << 1;
58                 kakuid++;
59             } else
60                 if (((tmp << bitcount & (0x80)) == 0)&((tmp << bitcount & (0x40)) == 0x40)) {
61                 //= add bit on kakuid
62                 kakuid = kakuid << 1;
63                 //add 0
64             } else {
65                 return 0; //00 and 11 indicates packet error. no valid packet! do exit
66             }
67         }
68         //Get unit ID
69         tmp = bb[0][7] << 1;
70         if ((bb[0][8]&(1 << 7)) != 0) {// if set add bit to current
71             tmp++;
72         }
73         for (bitcount = 0; bitcount < 8; bitcount += 2) {//process bitstream, check protocol!
74             if (((tmp << bitcount & (0x80)) == 0x80)&((tmp << bitcount & (0x40)) == 0)) {
75                 //add 1
76                 unit = unit << 1;
77                 unit++;
78             } else
79                 if (((tmp << bitcount & (0x80)) == 0)&((tmp << bitcount & (0x40)) == 0x40)) {
80                 unit = unit << 1;
81                 //add 0
82             } else {
83                 return 0; //00 and 11 indicates packet error. Do exit, no valid packet
84             }
85         }
86         group_call = (((bb[0][6] & (0x04)) == 0x04)&((bb[0][6] & (0x02)) == 0)) ? "Yes" : "No";
87         command = (((bb[0][6] & (0x01)) == 0x01)&((bb[0][7] & (0x80)) == 0)) ? "On" : "Off";
88         if (((bb[0][6] & (0x01)) == 0x01)&((bb[0][7] & (0x80)) == 0x80)) {//11 indicates DIM command, 4 extra bits indicate DIM value
89             dim = "Yes";
90             tmp = bb[0][8] << 1; // get packet, loose first bit
91
92             if ((bb[0][9]&(1 << 7)) != 0) {// if bit is set Add to current packet
93                 tmp++;
94                 for (bitcount = 0; bitcount < 8; bitcount += 2) {//process last bit outside
95                     if (((tmp << bitcount & (0x80)) == 0x80)&((tmp << bitcount & (0x40)) == 0)) {
96                         //add 1
97                         dv = dv << 1;
98                         dv++;
99                     } else
100                         if (((tmp << bitcount & (0x80)) == 0)&((tmp << bitcount & (0x40)) == 0x40)) {
101                         dv = dv << 1;
102                         //add 0
103                     } else {
104                         return 0; //00 and 11 indicates packet error. Do exit, no valid packet
105                     }
106                 }
107             }
108         } else {
109             dim = "No";
110         }
111
112         data = data_make("time",          "",            DATA_STRING, time_str,
113                          "model",         "",            DATA_STRING, "KlikAanKlikUit Wireless Switch",
114                          "id",            "",            DATA_INT, kakuid,
115                          "unit",          "Unit",        DATA_INT, unit,
116                          "group_call",    "Group Call",  DATA_STRING, group_call,
117                          "command",       "Command",     DATA_STRING, command,
118                          "dim",           "Dim",         DATA_STRING, dim,
119                          "dim_value",     "Dim Value",   DATA_INT, dv,
120                          NULL);
121         data_acquired_handler(data);
122
123         return 1;
124     }
125     return 0;
126 }
127
128 static char *output_fields[] = {
129     "time",
130     "model",
131     "id",
132     "unit",
133     "group_call",
134     "command",
135     "dim",
136     "dim_value",
137     NULL
138 };
139
140 r_device newkaku = {
141     .name           = "KlikAanKlikUit Wireless Switch",
142     .modulation     = OOK_PULSE_PPM_RAW,
143     .short_limit    = 800,
144     .long_limit     = 3200,
145     .reset_limit    = 10000,
146     .json_callback  = &newkaku_callback,
147     .disabled       = 0,
148     .demod_arg      = 0,
149     .fields         = output_fields
150 };