|
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 "../config.h" |
|
27 #include "mbselib.h" |
|
28 |
|
29 #ifdef HAVE_WIRINGPI_H |
|
30 |
|
31 unsigned long rcReceivedValue = 0; |
|
32 unsigned int rcReceivedBitlength = 0; |
|
33 unsigned int rcReceivedDelay = 0; |
|
34 unsigned int rcReceivedProtocol = 0; |
|
35 int rcReceiveTolerance = 60; |
|
36 int rcReceiverInterrupt = -1; |
|
37 |
|
38 unsigned int timings[RCSWITCH_MAX_CHANGES]; |
|
39 int rcTransmitterPin = -1; |
|
40 int rcPulseLength = 350; |
|
41 int rcRepeatTransmit = 10; |
|
42 int rcProtocol = 1; |
|
43 |
|
44 |
|
45 char *getCodeWordA(char*, char*, bool); |
|
46 char *getCodeWordB(int, int, bool); |
|
47 char *getCodeWordC(char, int, int, bool); |
|
48 char *getCodeWordD(char, int, bool); |
|
49 void sendTriState(char*); |
|
50 void transmit(int, int); |
|
51 void send0(void); |
|
52 void send1(void); |
|
53 void sendT0(void); |
|
54 void sendT1(void); |
|
55 void sendTF(void); |
|
56 void sendSync(void); |
|
57 bool receiveProtocol1(unsigned int); |
|
58 bool receiveProtocol2(unsigned int); |
|
59 bool receiveProtocol3(unsigned int); |
|
60 void handleInterrupt(void); |
|
61 char *dec2binWzerofill(unsigned long, unsigned int); |
|
62 char *dec2binWcharfill(unsigned long, unsigned int, char); |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 /* |
|
68 * Sets the protocol to send. |
|
69 */ |
|
70 void setProtocol(int nProtocol) { |
|
71 rcProtocol = nProtocol; |
|
72 if (nProtocol == 1){ |
|
73 setPulseLength(350); |
|
74 } |
|
75 else if (nProtocol == 2) { |
|
76 setPulseLength(650); |
|
77 } |
|
78 else if (nProtocol == 3) { |
|
79 setPulseLength(100); |
|
80 } |
|
81 } |
|
82 |
|
83 |
|
84 |
|
85 /** |
|
86 * Sets the protocol to send with pulse length in microseconds. |
|
87 */ |
|
88 /*void RCSwitch::setProtocol(int nProtocol, int nPulseLength) { |
|
89 this->nProtocol = nProtocol; |
|
90 this->setPulseLength(nPulseLength); |
|
91 }*/ |
|
92 |
|
93 |
|
94 |
|
95 /* |
|
96 * Sets pulse length in microseconds |
|
97 */ |
|
98 void setPulseLength(int nPulseLength) { |
|
99 rcPulseLength = nPulseLength; |
|
100 } |
|
101 |
|
102 |
|
103 |
|
104 /* |
|
105 * Sets Repeat Transmits |
|
106 */ |
|
107 void setRepeatTransmit(int nRepeatTransmit) { |
|
108 rcRepeatTransmit = nRepeatTransmit; |
|
109 } |
|
110 |
|
111 |
|
112 |
|
113 /* |
|
114 * Set Receiving Tolerance |
|
115 */ |
|
116 void setReceiveTolerance(int nPercent) { |
|
117 rcReceiveTolerance = nPercent; |
|
118 } |
|
119 |
|
120 |
|
121 /* |
|
122 * Enable transmissions |
|
123 * |
|
124 * @param nTransmitterPin Pin to which the sender is connected to |
|
125 */ |
|
126 void enableTransmit(int nTransmitterPin) { |
|
127 rcTransmitterPin = nTransmitterPin; |
|
128 pinMode(rcTransmitterPin, OUTPUT); |
|
129 } |
|
130 |
|
131 |
|
132 |
|
133 /* |
|
134 * Disable transmissions |
|
135 */ |
|
136 void disableTransmit(void) { |
|
137 rcTransmitterPin = -1; |
|
138 } |
|
139 |
|
140 |
|
141 |
|
142 /* |
|
143 * Switch a remote switch on (Type D REV) |
|
144 * |
|
145 * @param sGroup Code of the switch group (A,B,C,D) |
|
146 * @param nDevice Number of the switch itself (1..3) |
|
147 */ |
|
148 /*void RCSwitch::switchOn(char sGroup, int nDevice) { |
|
149 this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) ); |
|
150 }*/ |
|
151 |
|
152 /** |
|
153 * Switch a remote switch off (Type D REV) |
|
154 * |
|
155 * @param sGroup Code of the switch group (A,B,C,D) |
|
156 * @param nDevice Number of the switch itself (1..3) |
|
157 */ |
|
158 /*void RCSwitch::switchOff(char sGroup, int nDevice) { |
|
159 this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) ); |
|
160 }*/ |
|
161 |
|
162 /** |
|
163 * Switch a remote switch on (Type C Intertechno) |
|
164 * |
|
165 * @param sFamily Familycode (a..f) |
|
166 * @param nGroup Number of group (1..4) |
|
167 * @param nDevice Number of device (1..4) |
|
168 */ |
|
169 /*void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) { |
|
170 this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) ); |
|
171 }*/ |
|
172 |
|
173 /** |
|
174 * Switch a remote switch off (Type C Intertechno) |
|
175 * |
|
176 * @param sFamily Familycode (a..f) |
|
177 * @param nGroup Number of group (1..4) |
|
178 * @param nDevice Number of device (1..4) |
|
179 */ |
|
180 /*void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) { |
|
181 this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) ); |
|
182 }*/ |
|
183 |
|
184 |
|
185 |
|
186 /* |
|
187 * Switch a remote switch on (Type B with two rotary/sliding switches) |
|
188 * |
|
189 * @param nAddressCode Number of the switch group (1..4) |
|
190 * @param nChannelCode Number of the switch itself (1..4) |
|
191 */ |
|
192 void switchOn(int nAddressCode, int nChannelCode) { |
|
193 sendTriState( getCodeWordB(nAddressCode, nChannelCode, true) ); |
|
194 } |
|
195 |
|
196 |
|
197 |
|
198 /* |
|
199 * Switch a remote switch off (Type B with two rotary/sliding switches) |
|
200 * |
|
201 * @param nAddressCode Number of the switch group (1..4) |
|
202 * @param nChannelCode Number of the switch itself (1..4) |
|
203 */ |
|
204 void switchOff(int nAddressCode, int nChannelCode) { |
|
205 sendTriState( getCodeWordB(nAddressCode, nChannelCode, false) ); |
|
206 } |
|
207 |
|
208 |
|
209 |
|
210 /** |
|
211 * Deprecated, use switchOn(char* sGroup, char* sDevice) instead! |
|
212 * Switch a remote switch on (Type A with 10 pole DIP switches) |
|
213 * |
|
214 * @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") |
|
215 * @param nChannelCode Number of the switch itself (1..5) |
|
216 */ |
|
217 /*void RCSwitch::switchOn(char* sGroup, int nChannel) { |
|
218 char* code[6] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"00001" }; |
|
219 this->switchOn(sGroup, code[nChannel]); |
|
220 }*/ |
|
221 |
|
222 /** |
|
223 * Deprecated, use switchOff(char* sGroup, char* sDevice) instead! |
|
224 * Switch a remote switch off (Type A with 10 pole DIP switches) |
|
225 * |
|
226 * @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") |
|
227 * @param nChannelCode Number of the switch itself (1..5) |
|
228 */ |
|
229 /*void RCSwitch::switchOff(char* sGroup, int nChannel) { |
|
230 char* code[6] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"00001" }; |
|
231 this->switchOff(sGroup, code[nChannel]); |
|
232 }*/ |
|
233 |
|
234 /** |
|
235 * Switch a remote switch on (Type A with 10 pole DIP switches) |
|
236 * |
|
237 * @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") |
|
238 * @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") |
|
239 */ |
|
240 /*void RCSwitch::switchOn(char* sGroup, char* sDevice) { |
|
241 this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) ); |
|
242 }*/ |
|
243 |
|
244 /** |
|
245 * Switch a remote switch off (Type A with 10 pole DIP switches) |
|
246 * |
|
247 * @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") |
|
248 * @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") |
|
249 */ |
|
250 /*void RCSwitch::switchOff(char* sGroup, char* sDevice) { |
|
251 this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) ); |
|
252 }*/ |
|
253 |
|
254 |
|
255 |
|
256 /* |
|
257 * Returns a char[13], representing the Code Word to be send. |
|
258 * 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. |
|
259 * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit) |
|
260 * |
|
261 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ |
|
262 * | 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 | |
|
263 * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S | |
|
264 * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+ |
|
265 * |
|
266 * @param nAddressCode Number of the switch group (1..4) |
|
267 * @param nChannelCode Number of the switch itself (1..4) |
|
268 * @param bStatus Wether to switch on (true) or off (false) |
|
269 * |
|
270 * @return char[13] |
|
271 */ |
|
272 char *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) |
|
273 { |
|
274 int i, nReturnPos = 0; |
|
275 static char sReturn[13]; |
|
276 |
|
277 char* code[5] = { (char *)"FFFF", (char *)"0FFF", (char *)"F0FF", (char *)"FF0F", (char *)"FFF0" }; |
|
278 if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { |
|
279 return '\0'; |
|
280 } |
|
281 for (i = 0; i<4; i++) { |
|
282 sReturn[nReturnPos++] = code[nAddressCode][i]; |
|
283 } |
|
284 |
|
285 for (i = 0; i<4; i++) { |
|
286 sReturn[nReturnPos++] = code[nChannelCode][i]; |
|
287 } |
|
288 |
|
289 sReturn[nReturnPos++] = 'F'; |
|
290 sReturn[nReturnPos++] = 'F'; |
|
291 sReturn[nReturnPos++] = 'F'; |
|
292 |
|
293 if (bStatus) { |
|
294 sReturn[nReturnPos++] = 'F'; |
|
295 } else { |
|
296 sReturn[nReturnPos++] = '0'; |
|
297 } |
|
298 |
|
299 sReturn[nReturnPos] = '\0'; |
|
300 return sReturn; |
|
301 } |
|
302 |
|
303 |
|
304 |
|
305 /* |
|
306 * Returns a char[13], representing the Code Word to be send. |
|
307 * |
|
308 * getCodeWordA(char*, char*) |
|
309 * |
|
310 */ |
|
311 char *getCodeWordA(char* sGroup, char* sDevice, bool bOn) |
|
312 { |
|
313 static char sDipSwitches[13]; |
|
314 int i = 0; |
|
315 int j = 0; |
|
316 |
|
317 for (i=0; i < 5; i++) { |
|
318 if (sGroup[i] == '0') { |
|
319 sDipSwitches[j++] = 'F'; |
|
320 } else { |
|
321 sDipSwitches[j++] = '0'; |
|
322 } |
|
323 } |
|
324 |
|
325 for (i=0; i < 5; i++) { |
|
326 if (sDevice[i] == '0') { |
|
327 sDipSwitches[j++] = 'F'; |
|
328 } else { |
|
329 sDipSwitches[j++] = '0'; |
|
330 } |
|
331 } |
|
332 |
|
333 if ( bOn ) { |
|
334 sDipSwitches[j++] = '0'; |
|
335 sDipSwitches[j++] = 'F'; |
|
336 } else { |
|
337 sDipSwitches[j++] = 'F'; |
|
338 sDipSwitches[j++] = '0'; |
|
339 } |
|
340 |
|
341 sDipSwitches[j] = '\0'; |
|
342 return sDipSwitches; |
|
343 } |
|
344 |
|
345 |
|
346 |
|
347 /* |
|
348 * Like getCodeWord (Type C = Intertechno) |
|
349 */ |
|
350 char *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) |
|
351 { |
|
352 static char sReturn[13]; |
|
353 int i, nReturnPos = 0; |
|
354 |
|
355 if ( (uint8_t)sFamily < 97 || (uint8_t)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { |
|
356 return '\0'; |
|
357 } |
|
358 |
|
359 char* sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 ); |
|
360 char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" }; |
|
361 for (i = 0; i<4; i++) { |
|
362 sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i]; |
|
363 } |
|
364 for (i = 0; i<4; i++) { |
|
365 sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0'); |
|
366 } |
|
367 |
|
368 sReturn[nReturnPos++] = '0'; |
|
369 sReturn[nReturnPos++] = 'F'; |
|
370 sReturn[nReturnPos++] = 'F'; |
|
371 |
|
372 if (bStatus) { |
|
373 sReturn[nReturnPos++] = 'F'; |
|
374 } else { |
|
375 sReturn[nReturnPos++] = '0'; |
|
376 } |
|
377 |
|
378 sReturn[nReturnPos] = '\0'; |
|
379 return sReturn; |
|
380 } |
|
381 |
|
382 |
|
383 |
|
384 /* |
|
385 * Decoding for the REV Switch Type |
|
386 * |
|
387 * Returns a char[13], representing the Tristate to be send. |
|
388 * A Code Word consists of 7 address bits and 5 command data bits. |
|
389 * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high) |
|
390 * |
|
391 * +-------------------------------+--------------------------------+-----------------------+ |
|
392 * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) | |
|
393 * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 | |
|
394 * +-------------------------------+--------------------------------+-----------------------+ |
|
395 * |
|
396 * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/ |
|
397 * |
|
398 * @param sGroup Name of the switch group (A..D, resp. a..d) |
|
399 * @param nDevice Number of the switch itself (1..3) |
|
400 * @param bStatus Wether to switch on (true) or off (false) |
|
401 * |
|
402 * @return char[13] |
|
403 */ |
|
404 char *getCodeWordD(char sGroup, int nDevice, bool bStatus){ |
|
405 static char sReturn[13]; |
|
406 int i, nReturnPos = 0; |
|
407 |
|
408 // Building 4 bits address |
|
409 // (Potential problem if dec2binWcharfill not returning correct string) |
|
410 char *sGroupCode; |
|
411 switch(sGroup){ |
|
412 case 'a': |
|
413 case 'A': |
|
414 sGroupCode = dec2binWcharfill(8, 4, 'F'); break; |
|
415 case 'b': |
|
416 case 'B': |
|
417 sGroupCode = dec2binWcharfill(4, 4, 'F'); break; |
|
418 case 'c': |
|
419 case 'C': |
|
420 sGroupCode = dec2binWcharfill(2, 4, 'F'); break; |
|
421 case 'd': |
|
422 case 'D': |
|
423 sGroupCode = dec2binWcharfill(1, 4, 'F'); break; |
|
424 default: |
|
425 return '\0'; |
|
426 } |
|
427 |
|
428 for (i = 0; i<4; i++) { |
|
429 sReturn[nReturnPos++] = sGroupCode[i]; |
|
430 } |
|
431 |
|
432 |
|
433 // Building 3 bits address |
|
434 // (Potential problem if dec2binWcharfill not returning correct string) |
|
435 char *sDevice; |
|
436 switch(nDevice) { |
|
437 case 1: |
|
438 sDevice = dec2binWcharfill(4, 3, 'F'); break; |
|
439 case 2: |
|
440 sDevice = dec2binWcharfill(2, 3, 'F'); break; |
|
441 case 3: |
|
442 sDevice = dec2binWcharfill(1, 3, 'F'); break; |
|
443 default: |
|
444 return '\0'; |
|
445 } |
|
446 |
|
447 for (i = 0; i<3; i++) |
|
448 sReturn[nReturnPos++] = sDevice[i]; |
|
449 |
|
450 // fill up rest with zeros |
|
451 for (i = 0; i<5; i++) |
|
452 sReturn[nReturnPos++] = '0'; |
|
453 |
|
454 // encode on or off |
|
455 if (bStatus) |
|
456 sReturn[10] = '1'; |
|
457 else |
|
458 sReturn[11] = '1'; |
|
459 |
|
460 // last position terminate string |
|
461 sReturn[12] = '\0'; |
|
462 return sReturn; |
|
463 |
|
464 } |
|
465 |
|
466 |
|
467 |
|
468 /* |
|
469 * @param sCodeWord /^[10FS]*$/ -> see getCodeWord |
|
470 */ |
|
471 void sendTriState(char* sCodeWord) { |
|
472 int nRepeat; |
|
473 |
|
474 for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) { |
|
475 int i = 0; |
|
476 while (sCodeWord[i] != '\0') { |
|
477 switch(sCodeWord[i]) { |
|
478 case '0': |
|
479 sendT0(); |
|
480 break; |
|
481 case 'F': |
|
482 sendTF(); |
|
483 break; |
|
484 case '1': |
|
485 sendT1(); |
|
486 break; |
|
487 } |
|
488 i++; |
|
489 } |
|
490 sendSync(); |
|
491 } |
|
492 } |
|
493 |
|
494 |
|
495 |
|
496 /* |
|
497 void RCSwitch::send(unsigned long Code, unsigned int length) { |
|
498 this->send( this->dec2binWzerofill(Code, length) ); |
|
499 } |
|
500 |
|
501 void RCSwitch::send(char* sCodeWord) { |
|
502 for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) { |
|
503 int i = 0; |
|
504 while (sCodeWord[i] != '\0') { |
|
505 switch(sCodeWord[i]) { |
|
506 case '0': |
|
507 this->send0(); |
|
508 break; |
|
509 case '1': |
|
510 this->send1(); |
|
511 break; |
|
512 } |
|
513 i++; |
|
514 } |
|
515 this->sendSync(); |
|
516 } |
|
517 } |
|
518 */ |
|
519 |
|
520 |
|
521 void transmit(int nHighPulses, int nLowPulses) |
|
522 { |
|
523 bool disabled_Receive = false; |
|
524 int nReceiverInterrupt_backup = rcReceiverInterrupt; |
|
525 |
|
526 if (rcTransmitterPin != -1) { |
|
527 if (rcReceiverInterrupt != -1) { |
|
528 disableReceive(); |
|
529 disabled_Receive = true; |
|
530 } |
|
531 digitalWrite(rcTransmitterPin, HIGH); |
|
532 delayMicroseconds( rcPulseLength * nHighPulses); |
|
533 digitalWrite(rcTransmitterPin, LOW); |
|
534 delayMicroseconds( rcPulseLength * nLowPulses); |
|
535 |
|
536 if (disabled_Receive) { |
|
537 enableReceiveIRQ(nReceiverInterrupt_backup); |
|
538 } |
|
539 } |
|
540 } |
|
541 |
|
542 |
|
543 |
|
544 /* |
|
545 * Sends a "0" Bit |
|
546 * _ |
|
547 * Waveform Protocol 1: | |___ |
|
548 * _ |
|
549 * Waveform Protocol 2: | |__ |
|
550 * ____ |
|
551 * Waveform Protocol 3: | |___________ |
|
552 */ |
|
553 void send0(void) { |
|
554 if (rcProtocol == 1){ |
|
555 transmit(1,3); |
|
556 } |
|
557 else if (rcProtocol == 2) { |
|
558 transmit(1,2); |
|
559 } |
|
560 else if (rcProtocol == 3) { |
|
561 transmit(4,11); |
|
562 } |
|
563 } |
|
564 |
|
565 |
|
566 |
|
567 /* |
|
568 * Sends a "1" Bit |
|
569 * ___ |
|
570 * Waveform Protocol 1: | |_ |
|
571 * __ |
|
572 * Waveform Protocol 2: | |_ |
|
573 * _________ |
|
574 * Waveform Protocol 3: | |______ |
|
575 */ |
|
576 void send1(void) { |
|
577 if (rcProtocol == 1){ |
|
578 transmit(3,1); |
|
579 } |
|
580 else if (rcProtocol == 2) { |
|
581 transmit(2,1); |
|
582 } |
|
583 else if (rcProtocol == 3) { |
|
584 transmit(9,6); |
|
585 } |
|
586 } |
|
587 |
|
588 |
|
589 |
|
590 /* |
|
591 * Sends a Tri-State "0" Bit |
|
592 * _ _ |
|
593 * Waveform: | |___| |___ |
|
594 */ |
|
595 void sendT0(void) { |
|
596 transmit(1,3); |
|
597 transmit(1,3); |
|
598 } |
|
599 |
|
600 |
|
601 |
|
602 /* |
|
603 * Sends a Tri-State "1" Bit |
|
604 * ___ ___ |
|
605 * Waveform: | |_| |_ |
|
606 */ |
|
607 void sendT1(void) { |
|
608 transmit(3,1); |
|
609 transmit(3,1); |
|
610 } |
|
611 |
|
612 |
|
613 |
|
614 /* |
|
615 * Sends a Tri-State "F" Bit |
|
616 * _ ___ |
|
617 * Waveform: | |___| |_ |
|
618 */ |
|
619 void sendTF(void) { |
|
620 transmit(1,3); |
|
621 transmit(3,1); |
|
622 } |
|
623 |
|
624 |
|
625 |
|
626 /* |
|
627 * Sends a "Sync" Bit |
|
628 * _ |
|
629 * Waveform Protocol 1: | |_______________________________ |
|
630 * _ |
|
631 * Waveform Protocol 2: | |__________ |
|
632 * _ |
|
633 * Waveform Protocol 3: | |_______________________________________________________________________ |
|
634 */ |
|
635 void sendSync(void) { |
|
636 |
|
637 if (rcProtocol == 1){ |
|
638 transmit(1,31); |
|
639 } |
|
640 else if (rcProtocol == 2) { |
|
641 transmit(1,10); |
|
642 } |
|
643 else if (rcProtocol == 3) { |
|
644 transmit(1,71); |
|
645 } |
|
646 } |
|
647 |
|
648 |
|
649 |
|
650 /* |
|
651 * Enable receiving data |
|
652 */ |
|
653 void enableReceiveIRQ(int interrupt) { |
|
654 rcReceiverInterrupt = interrupt; |
|
655 enableReceive(); |
|
656 } |
|
657 |
|
658 void enableReceive(void) { |
|
659 if (rcReceiverInterrupt != -1) { |
|
660 rcReceivedValue = 0; |
|
661 rcReceivedBitlength = 0; |
|
662 wiringPiISR(rcReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); |
|
663 } |
|
664 } |
|
665 |
|
666 |
|
667 |
|
668 /* |
|
669 * Disable receiving data |
|
670 */ |
|
671 void disableReceive() { |
|
672 // wiringPi disable interrupts ??? |
|
673 rcReceiverInterrupt = -1; |
|
674 } |
|
675 |
|
676 |
|
677 |
|
678 bool available(void) { |
|
679 return rcReceivedValue != 0; |
|
680 } |
|
681 |
|
682 |
|
683 |
|
684 void resetAvailable(void) { |
|
685 rcReceivedValue = 0; |
|
686 } |
|
687 |
|
688 |
|
689 |
|
690 unsigned long getReceivedValue(void) { |
|
691 return rcReceivedValue; |
|
692 } |
|
693 |
|
694 |
|
695 |
|
696 unsigned int getReceivedBitlength(void) { |
|
697 return rcReceivedBitlength; |
|
698 } |
|
699 |
|
700 |
|
701 |
|
702 unsigned int getReceivedDelay(void) { |
|
703 return rcReceivedDelay; |
|
704 } |
|
705 |
|
706 |
|
707 |
|
708 unsigned int getReceivedProtocol(void) { |
|
709 return rcReceivedProtocol; |
|
710 } |
|
711 |
|
712 |
|
713 |
|
714 unsigned int* getReceivedRawdata(void) { |
|
715 return timings; |
|
716 } |
|
717 |
|
718 |
|
719 |
|
720 /* |
|
721 * ASK protool 1 |
|
722 */ |
|
723 bool receiveProtocol1(unsigned int changeCount) |
|
724 { |
|
725 unsigned long code = 0; |
|
726 unsigned long ldelay = timings[0] / 31; |
|
727 unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; |
|
728 int i; |
|
729 |
|
730 for (i = 1; i<changeCount ; i=i+2) { |
|
731 |
|
732 if (timings[i] > ldelay-delayTolerance && |
|
733 timings[i] < ldelay+delayTolerance && |
|
734 timings[i+1] > ldelay*3-delayTolerance && |
|
735 timings[i+1] < ldelay*3+delayTolerance) { |
|
736 code = code << 1; |
|
737 } else if (timings[i] > ldelay*3-delayTolerance && |
|
738 timings[i] < ldelay*3+delayTolerance && |
|
739 timings[i+1] > ldelay-delayTolerance && |
|
740 timings[i+1] < ldelay+delayTolerance) { |
|
741 code+=1; |
|
742 code = code << 1; |
|
743 } else { |
|
744 // Failed |
|
745 i = changeCount; |
|
746 code = 0; |
|
747 } |
|
748 } |
|
749 code = code >> 1; |
|
750 if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise |
|
751 rcReceivedValue = code; |
|
752 rcReceivedBitlength = changeCount / 2; |
|
753 rcReceivedDelay = ldelay; |
|
754 rcReceivedProtocol = 1; |
|
755 } |
|
756 |
|
757 if (code == 0) { |
|
758 return false; |
|
759 } |
|
760 return true; |
|
761 } |
|
762 |
|
763 |
|
764 |
|
765 bool receiveProtocol2(unsigned int changeCount) |
|
766 { |
|
767 unsigned long code = 0; |
|
768 unsigned long ldelay = timings[0] / 10; |
|
769 unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; |
|
770 int i; |
|
771 |
|
772 for (i = 1; i<changeCount ; i=i+2) { |
|
773 if (timings[i] > ldelay-delayTolerance && |
|
774 timings[i] < ldelay+delayTolerance && |
|
775 timings[i+1] > ldelay*2-delayTolerance && |
|
776 timings[i+1] < ldelay*2+delayTolerance) { |
|
777 code = code << 1; |
|
778 } else if (timings[i] > ldelay*2-delayTolerance && |
|
779 timings[i] < ldelay*2+delayTolerance && |
|
780 timings[i+1] > ldelay-delayTolerance && |
|
781 timings[i+1] < ldelay+delayTolerance) { |
|
782 code+=1; |
|
783 code = code << 1; |
|
784 } else { |
|
785 // Failed |
|
786 i = changeCount; |
|
787 code = 0; |
|
788 } |
|
789 } |
|
790 code = code >> 1; |
|
791 |
|
792 if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise |
|
793 rcReceivedValue = code; |
|
794 rcReceivedBitlength = changeCount / 2; |
|
795 rcReceivedDelay = ldelay; |
|
796 rcReceivedProtocol = 2; |
|
797 } |
|
798 |
|
799 if (code == 0) { |
|
800 return false; |
|
801 } |
|
802 return true; |
|
803 } |
|
804 |
|
805 |
|
806 |
|
807 /* |
|
808 * Protocol 3 is used by BL35P02. |
|
809 */ |
|
810 bool receiveProtocol3(unsigned int changeCount) |
|
811 { |
|
812 unsigned long code = 0; |
|
813 unsigned long ldelay = timings[0] / PROTOCOL3_SYNC_FACTOR; |
|
814 unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; |
|
815 int i; |
|
816 |
|
817 for (i = 1; i<changeCount ; i=i+2) { |
|
818 |
|
819 if (timings[i] > ldelay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance && |
|
820 timings[i] < ldelay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance && |
|
821 timings[i+1] > ldelay*PROTOCOL3_0_LOW_CYCLES - delayTolerance && |
|
822 timings[i+1] < ldelay*PROTOCOL3_0_LOW_CYCLES + delayTolerance) { |
|
823 code = code << 1; |
|
824 } else if (timings[i] > ldelay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance && |
|
825 timings[i] < ldelay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance && |
|
826 timings[i+1] > ldelay*PROTOCOL3_1_LOW_CYCLES - delayTolerance && |
|
827 timings[i+1] < ldelay*PROTOCOL3_1_LOW_CYCLES + delayTolerance) { |
|
828 code+=1; |
|
829 code = code << 1; |
|
830 } else { |
|
831 // Failed |
|
832 i = changeCount; |
|
833 code = 0; |
|
834 } |
|
835 } |
|
836 code = code >> 1; |
|
837 if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise |
|
838 rcReceivedValue = code; |
|
839 rcReceivedBitlength = changeCount / 2; |
|
840 rcReceivedDelay = ldelay; |
|
841 rcReceivedProtocol = 3; |
|
842 } |
|
843 |
|
844 if (code == 0) { |
|
845 return false; |
|
846 } |
|
847 return true; |
|
848 } |
|
849 |
|
850 |
|
851 |
|
852 void handleInterrupt() { |
|
853 |
|
854 static unsigned int duration; |
|
855 static unsigned int changeCount; |
|
856 static unsigned long lastTime; |
|
857 static unsigned int repeatCount; |
|
858 |
|
859 |
|
860 long time = micros(); |
|
861 duration = time - lastTime; |
|
862 |
|
863 if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) { |
|
864 repeatCount++; |
|
865 changeCount--; |
|
866 if (repeatCount == 2) { |
|
867 if (receiveProtocol1(changeCount) == false){ |
|
868 if (receiveProtocol2(changeCount) == false){ |
|
869 if (receiveProtocol3(changeCount) == false){ |
|
870 //failed |
|
871 } |
|
872 } |
|
873 } |
|
874 repeatCount = 0; |
|
875 } |
|
876 changeCount = 0; |
|
877 } else if (duration > 5000) { |
|
878 changeCount = 0; |
|
879 } |
|
880 |
|
881 if (changeCount >= RCSWITCH_MAX_CHANGES) { |
|
882 changeCount = 0; |
|
883 repeatCount = 0; |
|
884 } |
|
885 timings[changeCount++] = duration; |
|
886 lastTime = time; |
|
887 } |
|
888 |
|
889 |
|
890 |
|
891 /* |
|
892 * Turns a decimal value to its binary representation |
|
893 */ |
|
894 char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength) |
|
895 { |
|
896 return dec2binWcharfill(Dec, bitLength, '0'); |
|
897 } |
|
898 |
|
899 char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill) |
|
900 { |
|
901 static char bin[64]; |
|
902 unsigned int i = 0, j; |
|
903 |
|
904 while (Dec > 0) { |
|
905 bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill; |
|
906 Dec = Dec >> 1; |
|
907 } |
|
908 |
|
909 for (j = 0; j< bitLength; j++) { |
|
910 if (j >= bitLength - i) { |
|
911 bin[j] = bin[ 31 + i - (j - (bitLength - i)) ]; |
|
912 } else { |
|
913 bin[j] = fill; |
|
914 } |
|
915 } |
|
916 bin[bitLength] = '\0'; |
|
917 |
|
918 return bin; |
|
919 } |
|
920 |
|
921 |
|
922 #endif |
|
923 |