Bugfixes
[rtl-433.git] / src / devices / elv.c
1 #include "rtl_433.h"
2
3 uint16_t AD_POP(uint8_t bb[BITBUF_COLS], uint8_t bits, uint8_t bit) {
4     uint16_t val = 0;
5     uint8_t i, byte_no, bit_no;
6     for (i=0;i<bits;i++) {
7         byte_no=   (bit+i)/8 ;
8         bit_no =7-((bit+i)%8);
9         if (bb[byte_no]&(1<<bit_no)) val = val | (1<<i);
10     }
11     return val;
12 }
13
14 static int em1000_callback(bitbuffer_t *bitbuffer) {
15     // based on fs20.c
16     bitrow_t *bb = bitbuffer->bb;
17     uint8_t dec[10];
18     uint8_t bytes=0;
19     uint8_t bit=18; // preamble
20     uint8_t bb_p[14];
21     char* types[] = {"S", "?", "GZ"};
22     uint8_t checksum_calculated = 0;
23     uint8_t i;
24         uint8_t stopbit;
25         uint8_t checksum_received;
26
27     // check and combine the 3 repetitions
28     for (i = 0; i < 14; i++) {
29         if(bb[0][i]==bb[1][i] || bb[0][i]==bb[2][i]) bb_p[i]=bb[0][i];
30         else if(bb[1][i]==bb[2][i])                  bb_p[i]=bb[1][i];
31         else return 0;
32     }
33
34     // read 9 bytes with stopbit ...
35     for (i = 0; i < 9; i++) {
36         dec[i] = AD_POP (bb_p, 8, bit); bit+=8;
37         stopbit=AD_POP (bb_p, 1, bit); bit+=1;
38         if (!stopbit) {
39 //            fprintf(stdout, "!stopbit: %i\n", i);
40             return 0;
41         }
42         checksum_calculated ^= dec[i];
43         bytes++;
44     }
45
46     // Read checksum
47     checksum_received = AD_POP (bb_p, 8, bit); bit+=8;
48     if (checksum_received != checksum_calculated) {
49 //        fprintf(stdout, "checksum_received != checksum_calculated: %d %d\n", checksum_received, checksum_calculated);
50         return 0;
51     }
52
53 //for (i = 0; i < bytes; i++) fprintf(stdout, "%02X ", dec[i]); fprintf(stdout, "\n");
54
55     // based on 15_CUL_EM.pm
56     fprintf(stdout, "Energy sensor event:\n");
57     fprintf(stdout, "protocol      = ELV EM 1000, %d bits\n",bitbuffer->bits_per_row[1]);
58     fprintf(stdout, "type          = EM 1000-%s\n",dec[0]>=1&&dec[0]<=3?types[dec[0]-1]:"?");
59     fprintf(stdout, "code          = %d\n",dec[1]);
60     fprintf(stdout, "seqno         = %d\n",dec[2]);
61     fprintf(stdout, "total cnt     = %d\n",dec[3]|dec[4]<<8);
62     fprintf(stdout, "current cnt   = %d\n",dec[5]|dec[6]<<8);
63     fprintf(stdout, "peak cnt      = %d\n",dec[7]|dec[8]<<8);
64
65     return 1;
66 }
67
68 static int ws2000_callback(bitbuffer_t *bitbuffer) {
69     // based on http://www.dc3yc.privat.t-online.de/protocol.htm
70     bitrow_t *bb = bitbuffer->bb;
71     uint8_t dec[13];
72     uint8_t nibbles=0;
73     uint8_t bit=11; // preamble
74     char* types[]={"!AS3", "AS2000/ASH2000/S2000/S2001A/S2001IA/ASH2200/S300IA", "!S2000R", "!S2000W", "S2001I/S2001ID", "!S2500H", "!Pyrano", "!KS200/KS300"};
75     uint8_t length[16]={8, 8, 5, 8, 12, 9, 8, 8, 8};
76     uint8_t check_calculated=0, sum_calculated=0;
77     uint8_t i;
78     uint8_t stopbit;
79         uint8_t sum_received;
80
81     dec[0] = AD_POP (bb[0], 4, bit); bit+=4;
82     stopbit= AD_POP (bb[0], 1, bit); bit+=1;
83     if (!stopbit) {
84         if(debug_output) fprintf(stdout, "!stopbit\n");
85         return 0;
86     }
87     check_calculated ^= dec[0];
88     sum_calculated   += dec[0];
89
90     // read nibbles with stopbit ...
91     for (i = 1; i <= length[dec[0]]; i++) {
92         dec[i] = AD_POP (bb[0], 4, bit); bit+=4;
93         stopbit= AD_POP (bb[0], 1, bit); bit+=1;
94         if (!stopbit) {
95             if(debug_output) fprintf(stdout, "!stopbit %i\n", bit);
96             return 0;
97         }
98         check_calculated ^= dec[i];
99         sum_calculated   += dec[i];
100         nibbles++;
101     }
102     if(debug_output) { for (i = 0; i < nibbles; i++) fprintf(stdout, "%02X ", dec[i]); fprintf(stdout, "\n"); }
103
104     if (check_calculated) {
105         if(debug_output) fprintf(stdout, "check_calculated (%d) != 0\n", check_calculated);
106         return 0;
107     }
108
109     // Read sum
110     sum_received = AD_POP (bb[0], 4, bit); bit+=4;
111     sum_calculated+=5;
112     sum_calculated&=0xF;
113     if (sum_received != sum_calculated) {
114         if(debug_output) fprintf(stdout, "sum_received (%d) != sum_calculated (%d) ", sum_received, sum_calculated);
115         return 0;
116     }
117
118
119     fprintf(stdout, "Weather station sensor event:\n");
120     fprintf(stdout, "protocol      = ELV WS 2000, %d bits\n",bitbuffer->bits_per_row[1]);
121     fprintf(stdout, "type (!=ToDo) = %s\n", dec[0]<=7?types[dec[0]]:"?");
122     fprintf(stdout, "code          = %d\n", dec[1]&7);
123     fprintf(stdout, "temp          = %s%d.%d\n", dec[1]&8?"-":"", dec[4]*10+dec[3], dec[2]);
124     fprintf(stdout, "humidity      = %d.%d\n", dec[7]*10+dec[6], dec[5]);
125     if(dec[0]==4) {
126         fprintf(stdout, "pressure      = %d\n", 200+dec[10]*100+dec[9]*10+dec[8]);
127     }
128
129     return 1;
130 }
131
132 r_device elv_em1000 = {
133     .name           = "ELV EM 1000",
134     .modulation     = OOK_PULSE_PPM_RAW,
135     .short_limit    = 750,
136     .long_limit     = 7250,
137     .reset_limit    = 30000,
138     .json_callback  = &em1000_callback,
139     .disabled       = 1,
140     .demod_arg      = 0,
141 };
142
143 r_device elv_ws2000 = {
144     .name           = "ELV WS 2000",
145     .modulation     = OOK_PULSE_PWM_RAW,
146     .short_limit    = (854+366)/2,  // 0 => 854us, 1 => 366us according to link in top
147     .long_limit     = 1000, // no repetitions
148     .reset_limit    = 1000, // Longest pause is 854us according to link
149     .json_callback  = &ws2000_callback,
150     .disabled       = 1,
151     .demod_arg      = 0,
152 };