|
1 /***************************************************************************** |
|
2 * Copyright (C) 2014 |
|
3 * |
|
4 * Michiel Broek <mbroek at mbse dot eu> |
|
5 * |
|
6 * This file is part of the mbsePi-apps |
|
7 * |
|
8 * Based on the Arduino libary for remote control outlet switches. |
|
9 * Project home: http://code.google.com/p/rc-switch/ |
|
10 * |
|
11 * This is free software; you can redistribute it and/or modify it |
|
12 * under the terms of the GNU General Public License as published by the |
|
13 * Free Software Foundation; either version 2, or (at your option) any |
|
14 * later version. |
|
15 * |
|
16 * mbsePi-apps is distributed in the hope that it will be useful, but |
|
17 * WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
19 * General Public License for more details. |
|
20 * |
|
21 * You should have received a copy of the GNU General Public License |
|
22 * along with EC-65K; see the file COPYING. If not, write to the Free |
|
23 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. |
|
24 *****************************************************************************/ |
|
25 |
|
26 #include "thermferm.h" |
|
27 #include "xutil.h" |
|
28 #include "rc-switch.h" |
|
29 |
|
30 #ifdef HAVE_WIRINGPI_H |
|
31 |
|
32 |
|
33 #define TYPE_UNDEF 0 |
|
34 #define TYPE_MINIMUM 0 |
|
35 #define TYPE_A 1 |
|
36 #define TYPE_B 2 |
|
37 #define TYPE_C 3 |
|
38 #define TYPE_D 4 |
|
39 #define TYPE_E 3 // TODO: Which Protocol does REV use? |
|
40 #define TYPE_MAXIMUM 4 |
|
41 |
|
42 // Number of maximum High/Low changes per packet. |
|
43 // We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync |
|
44 #define RCSWITCH_MAX_CHANGES 67 |
|
45 |
|
46 // i.e. ProtocolCount + 1 (for TYPE_UNDEF) |
|
47 #define MAX_PROTOCOLS 5 |
|
48 |
|
49 #define PROTOCOL_A_SYNC_FACTOR 31 |
|
50 #define PROTOCOL_A_ZERO_FIRST_CYCLES 1 |
|
51 #define PROTOCOL_A_ZERO_SECOND_CYCLES 3 |
|
52 #define PROTOCOL_A_ONE_FIRST_CYCLES 3 |
|
53 #define PROTOCOL_A_ONE_SECOND_CYCLES 1 |
|
54 #define PROTOCOL_A_HIGH_FIRST TRUE |
|
55 |
|
56 #define PROTOCOL_B_SYNC_FACTOR 10 |
|
57 #define PROTOCOL_B_ZERO_FIRST_CYCLES 1 |
|
58 #define PROTOCOL_B_ZERO_SECOND_CYCLES 2 |
|
59 #define PROTOCOL_B_ONE_FIRST_CYCLES 2 |
|
60 #define PROTOCOL_B_ONE_SECOND_CYCLES 1 |
|
61 #define PROTOCOL_B_HIGH_FIRST TRUE |
|
62 |
|
63 #define PROTOCOL_C_SYNC_FACTOR 71 |
|
64 #define PROTOCOL_C_ZERO_FIRST_CYCLES 4 |
|
65 #define PROTOCOL_C_ZERO_SECOND_CYCLES 11 |
|
66 #define PROTOCOL_C_ONE_FIRST_CYCLES 9 |
|
67 #define PROTOCOL_C_ONE_SECOND_CYCLES 6 |
|
68 #define PROTOCOL_C_HIGH_FIRST TRUE |
|
69 |
|
70 // I think, this will work for receive, however, I haven't tested, as I don't own a receiver... |
|
71 // As Type D doesn't sync acc. to https://github.com/d-a-n/433-codes/blob/master/database.md#quigg |
|
72 // the sync factor is totally undetermined. |
|
73 // Malte Diers, 22.11.2013 |
|
74 #define PROTOCOL_D_SYNC_FACTOR 1 |
|
75 #define PROTOCOL_D_ZERO_FIRST_CYCLES 1 |
|
76 #define PROTOCOL_D_ZERO_SECOND_CYCLES 2 |
|
77 #define PROTOCOL_D_ONE_FIRST_CYCLES 2 |
|
78 #define PROTOCOL_D_ONE_SECOND_CYCLES 1 |
|
79 #define PROTOCOL_D_HIGH_FIRST FALSE |
|
80 |
|
81 |
|
82 #define PROTOCOL3_SYNC_FACTOR 71 |
|
83 #define PROTOCOL3_0_HIGH_CYCLES 4 |
|
84 #define PROTOCOL3_0_LOW_CYCLES 11 |
|
85 #define PROTOCOL3_1_HIGH_CYCLES 9 |
|
86 #define PROTOCOL3_1_LOW_CYCLES 6 |
|
87 |
|
88 |
|
89 |
|
90 unsigned long rcReceivedValue = 0; |
|
91 unsigned int rcReceivedBitlength = 0; |
|
92 unsigned int rcReceivedDelay = 0; |
|
93 unsigned int rcReceivedProtocol = 0; |
|
94 int rcReceiveTolerance = 60; |
|
95 int rcReceiverInterruptPin = -1; |
|
96 |
|
97 unsigned int timings[RCSWITCH_MAX_CHANGES]; |
|
98 int rcTransmitterPin = -1; |
|
99 int rcPulseLength = 350; // thermometers 2.4 msec = 2400 |
|
100 int rcRepeatTransmit = 10; |
|
101 int rcProtocol = 1; |
|
102 |
|
103 int backupProtocol; |
|
104 int backupPulseLength; |
|
105 int backupRepeatTransmit; |
|
106 |
|
107 |
|
108 //const char TYPE_A_CODE[ 6][6] = { "00000", "10000", "01000", "00100", "00010", "00001"}; |
|
109 const char TYPE_B_CODE[ 5][5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" }; |
|
110 const char TYPE_C_CODE[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", |
|
111 "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" }; |
|
112 const char TYPE_D_CODE[5][2][9] = { { "11100001", "11110000" }, { "00000000", "00010001" }, { "10000010", "10010011" }, |
|
113 { "11000011", "11010010" }, { "01000001", "01010000" } }; |
|
114 /* Type A Type D */ |
|
115 const int PULSE_LENGTH[MAX_PROTOCOLS] = { 0, 350, 650, 100, 666, }; |
|
116 const int REPEAT_TRANSMIT[MAX_PROTOCOLS] = { 0, 10, 10, 10, 4, }; |
|
117 const int SYNC_FACTOR[MAX_PROTOCOLS] = { 0, PROTOCOL_A_SYNC_FACTOR, PROTOCOL_B_SYNC_FACTOR, PROTOCOL_C_SYNC_FACTOR, PROTOCOL_D_SYNC_FACTOR, }; |
|
118 const int ZERO_FIRST_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_FIRST_CYCLES, PROTOCOL_B_ZERO_FIRST_CYCLES, PROTOCOL_C_ZERO_FIRST_CYCLES, PROTOCOL_D_ZERO_FIRST_CYCLES, }; |
|
119 const int ZERO_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_SECOND_CYCLES, PROTOCOL_B_ZERO_SECOND_CYCLES, PROTOCOL_C_ZERO_SECOND_CYCLES, PROTOCOL_D_ZERO_SECOND_CYCLES, }; |
|
120 const int ONE_FIRST_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_FIRST_CYCLES, PROTOCOL_B_ONE_FIRST_CYCLES, PROTOCOL_C_ONE_FIRST_CYCLES, PROTOCOL_D_ONE_FIRST_CYCLES, }; |
|
121 const int ONE_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_SECOND_CYCLES, PROTOCOL_B_ONE_SECOND_CYCLES, PROTOCOL_C_ONE_SECOND_CYCLES, PROTOCOL_D_ONE_SECOND_CYCLES, }; |
|
122 const int HIGH_FIRST[MAX_PROTOCOLS] = { 0, PROTOCOL_A_HIGH_FIRST, PROTOCOL_B_HIGH_FIRST, PROTOCOL_C_HIGH_FIRST, PROTOCOL_D_HIGH_FIRST, }; |
|
123 |
|
124 |
|
125 char *getCodeWordA(char*, char*, int); |
|
126 char *getCodeWordB(int, int, int); |
|
127 char *getCodeWordC(char, int, int, int); |
|
128 |
|
129 char *getCodeWordE(char, int, int); |
|
130 void sendTriState(char*); |
|
131 void transmit(int, int, int); |
|
132 void send0(void); |
|
133 void send1(void); |
|
134 void sendT0(void); |
|
135 void sendT1(void); |
|
136 void sendTF(void); |
|
137 void sendSync(void); |
|
138 int receiveProtocol(int, unsigned int); |
|
139 void handleInterrupt(void); |
|
140 char *dec2binWcharfill(unsigned long, unsigned int, char); |
|
141 |
|
142 void setReceiveTolerance(int); |
|
143 void setProtocol(int); |
|
144 |
|
145 void saveProtocol(int); |
|
146 void loadProtocol(void); |
|
147 |
|
148 |
|
149 |
|
150 /* |
|
151 * Sets the protocol to send. |
|
152 */ |
|
153 void setProtocol(int nProtocol) { |
|
154 |
|
155 if ((nProtocol < TYPE_MINIMUM) || (nProtocol > TYPE_MAXIMUM)) { |
|
156 return; |
|
157 } |
|
158 |
|
159 rcProtocol = nProtocol; |
|
160 rcPulseLength = PULSE_LENGTH[nProtocol]; |
|
161 rcRepeatTransmit = REPEAT_TRANSMIT[nProtocol]; |
|
162 } |
|
163 |
|
164 |
|
165 |
|
166 /* |
|
167 * Set Receiving Tolerance |
|
168 */ |
|
169 void setReceiveTolerance(int nPercent) { |
|
170 rcReceiveTolerance = nPercent; |
|
171 } |
|
172 |
|
173 |
|
174 |
|
175 /* |
|
176 * Enable transmissions |
|
177 * |
|
178 * @param nTransmitterPin Pin to which the sender is connected to |
|
179 */ |
|
180 void enableTransmit(int nTransmitterPin) { |
|
181 rcTransmitterPin = nTransmitterPin; |
|
182 pinMode(rcTransmitterPin, OUTPUT); |
|
183 } |
|
184 |
|
185 |
|
186 |
|
187 /* |
|
188 * Disable transmissions |
|
189 */ |
|
190 void disableTransmit(void) { |
|
191 rcTransmitterPin = -1; |
|
192 } |
|
193 |
|
194 |
|
195 |
|
196 /* |
|
197 * Toggle switch, a command looks like B,3,2,1 which means switch type B, |
|
198 * group 3, device 2, status on. |
|
199 */ |
|
200 int toggleSwitch(char *command) |
|
201 { |
|
202 static char *cmd = NULL; |
|
203 char *s, cType; |
|
204 int rc, iGroup, iDevice, iState; |
|
205 |
|
206 cmd = xstrcpy(command); |
|
207 s = strtok(cmd, ",\0"); |
|
208 cType = s[0]; |
|
209 |
|
210 if (cType == 'A') { |
|
211 |
|
212 } else if (cType == 'B') { |
|
213 s = strtok(NULL, ",\0"); |
|
214 rc = sscanf(s, "%d", &iGroup); |
|
215 if (rc != 1) |
|
216 return 1; |
|
217 s = strtok(NULL, ",\0"); |
|
218 rc = sscanf(s, "%d", &iDevice); |
|
219 if (rc != 1) |
|
220 return 1; |
|
221 s = strtok(NULL, ",\0"); |
|
222 rc = sscanf(s, "%d", &iState); |
|
223 if (rc != 1) |
|
224 return 1; |
|
225 free(cmd); |
|
226 return toggleTypeB(iGroup, iDevice, iState); |
|
227 } |
|
228 |
|
229 free(cmd); |
|
230 return 1; |
|
231 } |
|
232 |
|
233 |
|
234 |
|
235 /* |
|
236 * Switch a remote switch on (Type E REV) |
|
237 * |
|
238 * @param sGroup Code of the switch group (A,B,C,D) |
|
239 * @param nDevice Number of the switch itself (1..3) |
|
240 * @param bStatus Status to toggle to |
|
241 */ |
|
242 int toggleTypeE(char sGroup, int nDevice, int bStatus) { |
|
243 sendTriState( getCodeWordE(sGroup, nDevice, bStatus) ); |
|
244 return 0; |
|
245 } |
|
246 |
|
247 |
|
248 |
|
249 /* |
|
250 * Switch a remote switch on (Type C Intertechno) |
|
251 * |
|
252 * @param sFamily Familycode (a..f) |
|
253 * @param nGroup Number of group (1..4) |
|
254 * @param nDevice Number of device (1..4) |
|
255 * @param bStatus Status to toggle to |
|
256 */ |
|
257 int toggleTypeC(char sFamily, int nGroup, int nDevice, int bStatus) { |
|
258 char *str = xstrcpy(getCodeWordC(sFamily, nGroup, nDevice, bStatus)); |
|
259 |
|
260 if (strlen(str) == 0) |
|
261 return 1; |
|
262 |
|
263 saveProtocol(TYPE_A); // ??? |
|
264 sendTriState( str ); |
|
265 loadProtocol(); |
|
266 free(str); |
|
267 return 0; |
|
268 } |
|
269 |
|
270 |
|
271 |
|
272 /* |
|
273 * Switch a remote switch on/off (Type B with two rotary/sliding switches) |
|
274 * |
|
275 * @param iGroup Number of the switch group (1..4) |
|
276 * @param iDevice Number of the switch itself (1..4) |
|
277 * @param bStatus Status to toggle to |
|
278 */ |
|
279 int toggleTypeB(int iGroup, int iDevice, int bStatus) |
|
280 { |
|
281 char *str = xstrcpy(getCodeWordB(iGroup, iDevice, bStatus)); |
|
282 |
|
283 if (strlen(str) == 0) |
|
284 return 1; |
|
285 |
|
286 saveProtocol(TYPE_A); // They do better with protocol A timings. |
|
287 sendTriState( str ); |
|
288 loadProtocol(); |
|
289 free(str); |
|
290 return 0; |
|
291 } |
|
292 |
|
293 |
|
294 |
|
295 /* |
|
296 * Switch a remote switch on (Type A with 10 pole DIP switches) |
|
297 * |
|
298 * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111") |
|
299 * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111") |
|
300 * @param bStatus Status to toggle to |
|
301 */ |
|
302 int toggleTypeA(char* sGroup, char* sDevice, int bStatus) { |
|
303 char *str = xstrcpy(getCodeWordA(sGroup, sDevice, bStatus)); |
|
304 |
|
305 if (strlen(str) == 0) |
|
306 return 1; |
|
307 |
|
308 saveProtocol(TYPE_A); |
|
309 sendTriState( str ); |
|
310 loadProtocol(); |
|
311 free(str); |
|
312 return 0; |
|
313 } |
|
314 |
|
315 |
|
316 |
|
317 /* |
|
318 * Returns a char[13], representing the Code Word to be send. |
|
319 * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used. |
|
320 * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit) |
|
321 * |
|
322 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ |
|
323 * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit | |
|
324 * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S | |
|
325 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ |
|
326 * |
|
327 * @param nAddressCode Number of the switch group (1..4) |
|
328 * @param nChannelCode Number of the switch itself (1..4) |
|
329 * @param bStatus Wether to switch on (true) or off (false) |
|
330 * |
|
331 * @return char[13] |
|
332 */ |
|
333 char *getCodeWordB(int nAddressCode, int nChannelCode, int bStatus) |
|
334 { |
|
335 int i, nReturnPos = 0; |
|
336 static char sReturn[13]; |
|
337 |
|
338 if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { |
|
339 return '\0'; |
|
340 } |
|
341 for (i = 0; i<4; i++) { |
|
342 sReturn[nReturnPos++] = TYPE_B_CODE[nAddressCode][i]; |
|
343 } |
|
344 |
|
345 for (i = 0; i<4; i++) { |
|
346 sReturn[nReturnPos++] = TYPE_B_CODE[nChannelCode][i]; |
|
347 } |
|
348 |
|
349 sReturn[nReturnPos++] = 'F'; |
|
350 sReturn[nReturnPos++] = 'F'; |
|
351 sReturn[nReturnPos++] = 'F'; |
|
352 sReturn[nReturnPos++] = bStatus ? 'F' : '0'; |
|
353 sReturn[nReturnPos] = '\0'; |
|
354 |
|
355 return sReturn; |
|
356 } |
|
357 |
|
358 |
|
359 |
|
360 /* |
|
361 * Returns a char[13], representing the Code Word to be send. |
|
362 * |
|
363 * getCodeWordA(char*, char*) |
|
364 * |
|
365 */ |
|
366 char *getCodeWordA(char* sGroup, char* sDevice, int bOn) |
|
367 { |
|
368 static char sDipSwitches[13]; |
|
369 int i, j = 0; |
|
370 |
|
371 for (i=0; i < 5; i++) { |
|
372 sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0'; |
|
373 } |
|
374 |
|
375 for (i=0; i < 5; i++) { |
|
376 sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0'; |
|
377 } |
|
378 |
|
379 if ( bOn ) { |
|
380 sDipSwitches[j++] = '0'; |
|
381 sDipSwitches[j++] = 'F'; |
|
382 } else { |
|
383 sDipSwitches[j++] = 'F'; |
|
384 sDipSwitches[j++] = '0'; |
|
385 } |
|
386 |
|
387 sDipSwitches[j] = '\0'; |
|
388 return sDipSwitches; |
|
389 } |
|
390 |
|
391 |
|
392 |
|
393 /* |
|
394 * Like getCodeWord (Type C = Intertechno) |
|
395 */ |
|
396 char *getCodeWordC(char sFamily, int nGroup, int nDevice, int bStatus) |
|
397 { |
|
398 static char sReturn[13]; |
|
399 int i, nReturnPos = 0; |
|
400 |
|
401 if (sFamily < 'a') { |
|
402 // To also enable capital 'A' to 'F' |
|
403 sFamily += 32; |
|
404 } |
|
405 |
|
406 if ( sFamily < 'a' || sFamily > 'f' || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { |
|
407 return '\0'; |
|
408 } |
|
409 |
|
410 for (i = 0; i<4; i++) { |
|
411 sReturn[nReturnPos++] = TYPE_C_CODE[ sFamily - 'a' ][i]; |
|
412 } |
|
413 |
|
414 char *sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 ); |
|
415 for (i = 0; i<4; i++) { |
|
416 sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0'); |
|
417 } |
|
418 |
|
419 sReturn[nReturnPos++] = '0'; |
|
420 sReturn[nReturnPos++] = 'F'; |
|
421 sReturn[nReturnPos++] = 'F'; |
|
422 sReturn[nReturnPos++] = bStatus ? 'F' : '0'; |
|
423 sReturn[nReturnPos] = '\0'; |
|
424 |
|
425 return sReturn; |
|
426 } |
|
427 |
|
428 |
|
429 |
|
430 /* |
|
431 * Decoding for the Quigg Switch Type |
|
432 * |
|
433 * Returns a char[22], representing the States to be send. |
|
434 * A Code Word consists of 1 start bit, 12 address bits and 8 command data bits. |
|
435 * A Code Bit can have 2 different states: "0" (low), "1" (high) |
|
436 * |
|
437 * +--------------+--------------------------------+------------------------------+ |
|
438 * | 1 bits start | 12 bits address (device group) | 8 bits (command/switch data) | |
|
439 * | 1 | 110011001100 | 00010001 | |
|
440 * +--------------+--------------------------------+------------------------------+ |
|
441 * |
|
442 * Source: https://github.com/d-a-n/433-codes/blob/master/database.md#quigg |
|
443 * |
|
444 * @param sGroup 12-bit Binary ID of the Device Group |
|
445 * @param nDevice Number of the switch itself (1..4, or 0 to switch the entire Group) |
|
446 * @param bStatus Wether to switch on (true) or off (false) |
|
447 * |
|
448 * @return char[22] |
|
449 */ |
|
450 char *getCodeWordD(char *sGroup, int nDevice, int bStatus) |
|
451 { |
|
452 static char sReturn[22]; |
|
453 int i, nReturnPos = 0; |
|
454 |
|
455 /* Startbit */ |
|
456 sReturn[nReturnPos++] = '1'; |
|
457 |
|
458 /* 12 bit Group */ |
|
459 for (i = 0; i < 12; ++i) { |
|
460 sReturn[nReturnPos++] = sGroup[i]; |
|
461 } |
|
462 |
|
463 /* 8 Bit Device Identifier + Status (undividable!) */ |
|
464 for (i = 0; i < 8; ++i) { |
|
465 sReturn[nReturnPos++] = TYPE_D_CODE[nDevice][bStatus][i]; |
|
466 } |
|
467 sReturn[nReturnPos] = 0; |
|
468 |
|
469 return sReturn; |
|
470 } |
|
471 |
|
472 |
|
473 |
|
474 /* |
|
475 * Decoding for the REV Switch Type |
|
476 * |
|
477 * Returns a char[13], representing the Tristate to be send. |
|
478 * A Code Word consists of 7 address bits and 5 command data bits. |
|
479 * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high) |
|
480 * |
|
481 * +-------------------------------+--------------------------------+-----------------------+ |
|
482 * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) | |
|
483 * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 | |
|
484 * +-------------------------------+--------------------------------+-----------------------+ |
|
485 * |
|
486 * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ |
|
487 * |
|
488 * @param sGroup Name of the switch group (A..D, resp. a..d) |
|
489 * @param nDevice Number of the switch itself (1..3) |
|
490 * @param bStatus Wether to switch on (true) or off (false) |
|
491 * |
|
492 * @return char[13] |
|
493 */ |
|
494 char *getCodeWordE(char sGroup, int nDevice, int bStatus){ |
|
495 static char sReturn[13]; |
|
496 int i, nReturnPos = 0; |
|
497 |
|
498 // Building 4 bits address |
|
499 // (Potential problem if dec2binWcharfill not returning correct string) |
|
500 char *sGroupCode; |
|
501 switch(sGroup){ |
|
502 case 'a': |
|
503 case 'A': |
|
504 sGroupCode = dec2binWcharfill(8, 4, 'F'); break; |
|
505 case 'b': |
|
506 case 'B': |
|
507 sGroupCode = dec2binWcharfill(4, 4, 'F'); break; |
|
508 case 'c': |
|
509 case 'C': |
|
510 sGroupCode = dec2binWcharfill(2, 4, 'F'); break; |
|
511 case 'd': |
|
512 case 'D': |
|
513 sGroupCode = dec2binWcharfill(1, 4, 'F'); break; |
|
514 default: |
|
515 return '\0'; |
|
516 } |
|
517 |
|
518 for (i = 0; i<4; i++) { |
|
519 sReturn[nReturnPos++] = sGroupCode[i]; |
|
520 } |
|
521 |
|
522 |
|
523 // Building 3 bits address |
|
524 // (Potential problem if dec2binWcharfill not returning correct string) |
|
525 char *sDevice; |
|
526 switch(nDevice) { |
|
527 case 1: |
|
528 sDevice = dec2binWcharfill(4, 3, 'F'); break; |
|
529 case 2: |
|
530 sDevice = dec2binWcharfill(2, 3, 'F'); break; |
|
531 case 3: |
|
532 sDevice = dec2binWcharfill(1, 3, 'F'); break; |
|
533 default: |
|
534 return '\0'; |
|
535 } |
|
536 |
|
537 for (i = 0; i<3; i++) |
|
538 sReturn[nReturnPos++] = sDevice[i]; |
|
539 |
|
540 // fill up rest with zeros |
|
541 for (i = 0; i<5; i++) |
|
542 sReturn[nReturnPos++] = '0'; |
|
543 |
|
544 // encode on or off |
|
545 if (bStatus) |
|
546 sReturn[10] = '1'; |
|
547 else |
|
548 sReturn[11] = '1'; |
|
549 |
|
550 // last position terminate string |
|
551 sReturn[12] = '\0'; |
|
552 return sReturn; |
|
553 |
|
554 } |
|
555 |
|
556 |
|
557 |
|
558 /* |
|
559 * @param sCodeWord /^[10FS]*$/ -> see getCodeWord |
|
560 */ |
|
561 void sendTriState(char* sCodeWord) { |
|
562 int nRepeat; |
|
563 |
|
564 for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) { |
|
565 int i = 0; |
|
566 while (sCodeWord[i] != '\0') { |
|
567 switch(sCodeWord[i]) { |
|
568 case '0': |
|
569 sendT0(); |
|
570 break; |
|
571 case 'F': |
|
572 sendTF(); |
|
573 break; |
|
574 case '1': |
|
575 sendT1(); |
|
576 break; |
|
577 } |
|
578 i++; |
|
579 } |
|
580 sendSync(); |
|
581 } |
|
582 } |
|
583 |
|
584 |
|
585 |
|
586 /* |
|
587 void RCSwitch::send(unsigned long Code, unsigned int length) { |
|
588 this->send( this->dec2binWzerofill(Code, length) ); |
|
589 } |
|
590 |
|
591 void RCSwitch::send(char* sCodeWord) { |
|
592 for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) { |
|
593 int i = 0; |
|
594 while (sCodeWord[i] != '\0') { |
|
595 switch(sCodeWord[i]) { |
|
596 case '0': |
|
597 this->send0(); |
|
598 break; |
|
599 case '1': |
|
600 this->send1(); |
|
601 break; |
|
602 } |
|
603 i++; |
|
604 } |
|
605 this->sendSync(); |
|
606 } |
|
607 } |
|
608 */ |
|
609 |
|
610 |
|
611 void transmit(int nFirstPulses, int nSecondPulses, int bHighFirst) |
|
612 { |
|
613 int disabled_Receive = FALSE; |
|
614 int nReceiverInterrupt_backup = rcReceiverInterruptPin; |
|
615 |
|
616 if (rcTransmitterPin != -1) { |
|
617 if (rcReceiverInterruptPin != -1) { |
|
618 disableReceive(); |
|
619 disabled_Receive = TRUE; |
|
620 } |
|
621 digitalWrite(rcTransmitterPin, bHighFirst ? HIGH : LOW); |
|
622 delayMicroseconds( rcPulseLength * nFirstPulses); |
|
623 digitalWrite(rcTransmitterPin, bHighFirst ? LOW : HIGH); |
|
624 delayMicroseconds( rcPulseLength * nSecondPulses); |
|
625 |
|
626 if (disabled_Receive) { |
|
627 enableReceiveIRQ(nReceiverInterrupt_backup); |
|
628 } |
|
629 } |
|
630 } |
|
631 |
|
632 |
|
633 |
|
634 /* |
|
635 * Sends a "0" Bit |
|
636 * _ |
|
637 * Waveform Protocol 1: | |___ |
|
638 * _ |
|
639 * Waveform Protocol 2: | |__ |
|
640 * ____ |
|
641 * Waveform Protocol 3: | |___________ |
|
642 */ |
|
643 //void send0(void) { |
|
644 // if (rcProtocol == 1){ |
|
645 // transmit(1,3); |
|
646 // } |
|
647 // else if (rcProtocol == 2) { |
|
648 // transmit(1,2); |
|
649 // } |
|
650 // else if (rcProtocol == 3) { |
|
651 // transmit(4,11); |
|
652 // } |
|
653 //} |
|
654 |
|
655 |
|
656 |
|
657 /* |
|
658 * Sends a "1" Bit |
|
659 * ___ |
|
660 * Waveform Protocol 1: | |_ |
|
661 * __ |
|
662 * Waveform Protocol 2: | |_ |
|
663 * _________ |
|
664 * Waveform Protocol 3: | |______ |
|
665 */ |
|
666 //void send1(void) { |
|
667 // if (rcProtocol == 1){ |
|
668 // transmit(3,1); |
|
669 // } |
|
670 // else if (rcProtocol == 2) { |
|
671 // transmit(2,1); |
|
672 // } |
|
673 // else if (rcProtocol == 3) { |
|
674 // transmit(9,6); |
|
675 // } |
|
676 //} |
|
677 |
|
678 |
|
679 |
|
680 /* |
|
681 * Sends a Tri-State "0" Bit |
|
682 * _ _ |
|
683 * Waveform: | |___| |___ |
|
684 */ |
|
685 void sendT0(void) { |
|
686 transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
687 transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
688 // transmit(1,3,true); |
|
689 // transmit(1,3,true); |
|
690 } |
|
691 |
|
692 |
|
693 |
|
694 /* |
|
695 * Sends a Tri-State "1" Bit |
|
696 * ___ ___ |
|
697 * Waveform: | |_| |_ |
|
698 */ |
|
699 void sendT1(void) { |
|
700 transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
701 transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
702 // transmit(3,1,true); |
|
703 // transmit(3,1,true); |
|
704 } |
|
705 |
|
706 |
|
707 |
|
708 /* |
|
709 * Sends a Tri-State "F" Bit |
|
710 * _ ___ |
|
711 * Waveform: | |___| |_ |
|
712 */ |
|
713 void sendTF(void) { |
|
714 transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
715 transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); |
|
716 // transmit(1,3,true); |
|
717 // transmit(3,1,true); |
|
718 } |
|
719 |
|
720 |
|
721 |
|
722 /* |
|
723 * Sends a "Sync" Bit |
|
724 * _ |
|
725 * Waveform Protocol 1: | |_______________________________ |
|
726 * _ |
|
727 * Waveform Protocol 2: | |__________ |
|
728 * ____ |
|
729 * Waveform Protocol 3: | |_______________________________________________________________________ |
|
730 * |
|
731 * Waveform Protocol D: (none, just pause 80 msecs) |
|
732 */ |
|
733 void sendSync(void) { |
|
734 |
|
735 if (rcProtocol == TYPE_A) { |
|
736 transmit(1,31,TRUE); |
|
737 } else if (rcProtocol == TYPE_B) { |
|
738 transmit(1,10,TRUE); |
|
739 } else if (rcProtocol == TYPE_C) { |
|
740 transmit(4,71,TRUE); |
|
741 } else if (rcProtocol == TYPE_D) { |
|
742 transmit(0,1,FALSE); |
|
743 delayMicroseconds(80000); |
|
744 } |
|
745 } |
|
746 |
|
747 |
|
748 |
|
749 /* |
|
750 * Enable receiving data |
|
751 */ |
|
752 void enableReceiveIRQ(int Pin) { |
|
753 rcReceiverInterruptPin = Pin; |
|
754 enableReceive(); |
|
755 } |
|
756 |
|
757 void enableReceive(void) { |
|
758 if (rcReceiverInterruptPin != -1) { |
|
759 rcReceivedValue = 0; |
|
760 rcReceivedBitlength = 0; |
|
761 wiringPiISR(rcReceiverInterruptPin, INT_EDGE_BOTH, &handleInterrupt); |
|
762 } |
|
763 } |
|
764 |
|
765 |
|
766 |
|
767 /* |
|
768 * Disable receiving data |
|
769 */ |
|
770 void disableReceive() { |
|
771 // wiringPi disable interrupts ??? |
|
772 rcReceiverInterruptPin = -1; |
|
773 } |
|
774 |
|
775 |
|
776 |
|
777 int available(void) { |
|
778 return rcReceivedValue != 0; |
|
779 } |
|
780 |
|
781 |
|
782 |
|
783 void resetAvailable(void) { |
|
784 rcReceivedValue = 0; |
|
785 } |
|
786 |
|
787 |
|
788 |
|
789 unsigned long getReceivedValue(void) { |
|
790 return rcReceivedValue; |
|
791 } |
|
792 |
|
793 |
|
794 |
|
795 unsigned int getReceivedBitlength(void) { |
|
796 return rcReceivedBitlength; |
|
797 } |
|
798 |
|
799 |
|
800 |
|
801 unsigned int getReceivedDelay(void) { |
|
802 return rcReceivedDelay; |
|
803 } |
|
804 |
|
805 |
|
806 |
|
807 unsigned int getReceivedProtocol(void) { |
|
808 return rcReceivedProtocol; |
|
809 } |
|
810 |
|
811 |
|
812 |
|
813 unsigned int* getReceivedRawdata(void) { |
|
814 return timings; |
|
815 } |
|
816 |
|
817 |
|
818 |
|
819 /* |
|
820 * ASK protool 1 |
|
821 */ |
|
822 int receiveProtocol(int prot, unsigned int changeCount) |
|
823 { |
|
824 unsigned long code = 0; |
|
825 unsigned long ldelay = timings[0] / SYNC_FACTOR[prot]; |
|
826 unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; |
|
827 int i; |
|
828 |
|
829 if (prot < TYPE_MINIMUM || prot > TYPE_MAXIMUM) { |
|
830 return FALSE; |
|
831 } |
|
832 |
|
833 for (i = 1; i<changeCount ; i=i+2) { |
|
834 |
|
835 if (timings[i] > ldelay * ZERO_FIRST_CYCLES[prot] - delayTolerance && |
|
836 timings[i] < ldelay * ZERO_FIRST_CYCLES[prot] + delayTolerance && |
|
837 timings[i+1] > ldelay * ZERO_SECOND_CYCLES[prot] - delayTolerance && |
|
838 timings[i+1] < ldelay * ZERO_SECOND_CYCLES[prot] + delayTolerance) { |
|
839 code = code << 1; |
|
840 } else if (timings[i] > ldelay * ONE_FIRST_CYCLES[prot] - delayTolerance && |
|
841 timings[i] < ldelay * ONE_FIRST_CYCLES[prot] + delayTolerance && |
|
842 timings[i+1] > ldelay * ONE_SECOND_CYCLES[prot] - delayTolerance && |
|
843 timings[i+1] < ldelay * ONE_SECOND_CYCLES[prot] + delayTolerance) { |
|
844 code+=1; |
|
845 code = code << 1; |
|
846 } else { |
|
847 // Failed |
|
848 i = changeCount; |
|
849 code = 0; |
|
850 } |
|
851 } |
|
852 code = code >> 1; |
|
853 if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise |
|
854 rcReceivedValue = code; |
|
855 rcReceivedBitlength = changeCount / 2; |
|
856 rcReceivedDelay = ldelay; |
|
857 rcReceivedProtocol = prot; |
|
858 } |
|
859 |
|
860 return (code != 0); |
|
861 } |
|
862 |
|
863 |
|
864 |
|
865 void handleInterrupt() { |
|
866 |
|
867 static unsigned int duration; |
|
868 static unsigned int changeCount; |
|
869 static unsigned long lastTime; |
|
870 static unsigned int repeatCount; |
|
871 |
|
872 |
|
873 long thistime = micros(); |
|
874 duration = thistime - lastTime; |
|
875 |
|
876 if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) { |
|
877 repeatCount++; |
|
878 changeCount--; |
|
879 if (repeatCount == 2) { |
|
880 if (receiveProtocol(TYPE_A, changeCount) == FALSE) { |
|
881 if (receiveProtocol(TYPE_B, changeCount) == FALSE) { |
|
882 if (receiveProtocol(TYPE_C, changeCount) == FALSE) { |
|
883 if (receiveProtocol(TYPE_D, changeCount) == FALSE) { |
|
884 //failed |
|
885 } |
|
886 } |
|
887 } |
|
888 } |
|
889 repeatCount = 0; |
|
890 } |
|
891 changeCount = 0; |
|
892 } else if (duration > 5000) { |
|
893 changeCount = 0; |
|
894 } |
|
895 |
|
896 if (changeCount >= RCSWITCH_MAX_CHANGES) { |
|
897 changeCount = 0; |
|
898 repeatCount = 0; |
|
899 } |
|
900 timings[changeCount++] = duration; |
|
901 lastTime = thistime; |
|
902 } |
|
903 |
|
904 |
|
905 |
|
906 /* |
|
907 * Turns a decimal value to its binary representation |
|
908 */ |
|
909 char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength) |
|
910 { |
|
911 return dec2binWcharfill(Dec, bitLength, '0'); |
|
912 } |
|
913 |
|
914 char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill) |
|
915 { |
|
916 static char bin[64]; |
|
917 unsigned int i = 0, j; |
|
918 |
|
919 while (Dec > 0) { |
|
920 bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill; |
|
921 Dec = Dec >> 1; |
|
922 } |
|
923 |
|
924 for (j = 0; j< bitLength; j++) { |
|
925 if (j >= bitLength - i) { |
|
926 bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; |
|
927 } else { |
|
928 bin[j] = fill; |
|
929 } |
|
930 } |
|
931 bin[bitLength] = '\0'; |
|
932 |
|
933 return bin; |
|
934 } |
|
935 |
|
936 |
|
937 void saveProtocol(int prot) |
|
938 { |
|
939 backupProtocol = rcProtocol; |
|
940 backupPulseLength = rcPulseLength; |
|
941 backupRepeatTransmit = rcRepeatTransmit; |
|
942 |
|
943 setProtocol(prot); |
|
944 } |
|
945 |
|
946 |
|
947 |
|
948 void loadProtocol(void) |
|
949 { |
|
950 rcProtocol = backupProtocol; |
|
951 rcPulseLength = backupPulseLength; |
|
952 rcRepeatTransmit = backupRepeatTransmit; |
|
953 } |
|
954 |
|
955 |
|
956 #endif |
|
957 |