Uploaded from my local repository
[433Utils_NP] / rc-switch / RCSwitch.cpp
1 /*
2   RCSwitch - Arduino libary for remote control outlet switches
3   Copyright (c) 2011 Suat Özgür.  All right reserved.
4   
5   Contributors:
6   - Andre Koehler / info(at)tomate-online(dot)de
7   - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
8   - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
9   - Dominik Fischer / dom_fischer(at)web(dot)de
10   - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
11   - Andreas Steinel / A.<lastname>(at)gmail(dot)com
12   - Max Horn / max(at)quendi(dot)de
13   - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
14   - Johann Richard / <first name>.<last name>(at)gmail(dot)com
15   - Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo
16   - Dmitry Shalnov / <last name>(at)interplaymedium(dot)org
17   
18   Project home: https://github.com/sui77/rc-switch/
19
20   This library is free software; you can redistribute it and/or
21   modify it under the terms of the GNU Lesser General Public
22   License as published by the Free Software Foundation; either
23   version 2.1 of the License, or (at your option) any later version.
24
25   This library is distributed in the hope that it will be useful,
26   but WITHOUT ANY WARRANTY; without even the implied warranty of
27   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28   Lesser General Public License for more details.
29
30   You should have received a copy of the GNU Lesser General Public
31   License along with this library; if not, write to the Free Software
32   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
33 */
34
35 #define noInterrupts
36
37 #include "RCSwitch.h"
38
39 #ifdef RaspberryPi
40     // PROGMEM and _P functions are for AVR based microprocessors,
41     // so we must normalize these for the ARM processor:
42     #define PROGMEM
43     #define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
44 #endif
45
46 #ifdef ESP8266
47     // interrupt handler and related code must be in RAM on ESP8266,
48     // according to issue #46.
49     #define RECEIVE_ATTR ICACHE_RAM_ATTR
50 #else
51     #define RECEIVE_ATTR
52 #endif
53
54
55 /* Format for protocol definitions:
56  * {pulselength, Sync bit, "0" bit, "1" bit}
57  * 
58  * pulselength: pulse length in microseconds, e.g. 350
59  * Sync bit: {1, 31} means 1 high pulse and 31 low pulses
60  *     (perceived as a 31*pulselength long pulse, total length of sync bit is
61  *     32*pulselength microseconds), i.e:
62  *      _
63  *     | |_______________________________ (don't count the vertical bars)
64  * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
65  *     and 3 low pulses, total length (1+3)*pulselength, i.e:
66  *      _
67  *     | |___
68  * "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
69  *      ___
70  *     |   |_
71  *
72  * These are combined to form Tri-State bits when sending or receiving codes.
73  */
74 #ifdef ESP8266
75 static const RCSwitch::Protocol proto[] = {
76 #else
77 static const RCSwitch::Protocol PROGMEM proto[] = {
78 #endif
79     { 350, {  1, 31 }, {  1,  3 }, {  3,  1 } },    // protocol 1
80     { 650, {  1, 10 }, {  1,  2 }, {  2,  1 } },    // protocol 2
81     { 100, { 30, 71 }, {  4, 11 }, {  9,  6 } },    // protocol 3
82     { 380, {  1,  6 }, {  1,  3 }, {  3,  1 } },    // protocol 4
83     { 500, {  6, 14 }, {  1,  2 }, {  2,  1 } },    // protocol 5
84 };
85
86 enum {
87    numProto = sizeof(proto) / sizeof(proto[0])
88 };
89
90 #if not defined( RCSwitchDisableReceiving )
91 unsigned long RCSwitch::nReceivedValue = 0;
92 unsigned int RCSwitch::nReceivedBitlength = 0;
93 unsigned int RCSwitch::nReceivedDelay = 0;
94 unsigned int RCSwitch::nReceivedProtocol = 0;
95 int RCSwitch::nReceiveTolerance = 60;
96 const unsigned int RCSwitch::nSeparationLimit = 4600;
97 // separationLimit: minimum microseconds between received codes, closer codes are ignored.
98 // according to discussion on issue #14 it might be more suitable to set the separation
99 // limit to the same time as the 'low' part of the sync signal for the current protocol.
100 unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
101 #endif
102
103 RCSwitch::RCSwitch() {
104   this->nTransmitterPin = -1;
105   this->setRepeatTransmit(10);
106   this->setProtocol(1);
107   #if not defined( RCSwitchDisableReceiving )
108   this->nReceiverInterrupt = -1;
109   this->setReceiveTolerance(60);
110   RCSwitch::nReceivedValue = 0;
111   #endif
112 }
113
114 /**
115   * Sets the protocol to send.
116   */
117 void RCSwitch::setProtocol(Protocol protocol) {
118   this->protocol = protocol;
119 }
120
121 /**
122   * Sets the protocol to send, from a list of predefined protocols
123   */
124 void RCSwitch::setProtocol(int nProtocol) {
125   if (nProtocol < 1 || nProtocol > numProto) {
126     nProtocol = 1;  // TODO: trigger an error, e.g. "bad protocol" ???
127   }
128 #ifdef ESP8266
129   this->protocol = proto[nProtocol-1];
130 #else
131   memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol));
132 #endif
133 }
134
135 /**
136   * Sets the protocol to send with pulse length in microseconds.
137   */
138 void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
139   setProtocol(nProtocol);
140   this->setPulseLength(nPulseLength);
141 }
142
143
144 /**
145   * Sets pulse length in microseconds
146   */
147 void RCSwitch::setPulseLength(int nPulseLength) {
148   this->protocol.pulseLength = nPulseLength;
149 }
150
151 /**
152  * Sets Repeat Transmits
153  */
154 void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
155   this->nRepeatTransmit = nRepeatTransmit;
156 }
157
158 /**
159  * Set Receiving Tolerance
160  */
161 #if not defined( RCSwitchDisableReceiving )
162 void RCSwitch::setReceiveTolerance(int nPercent) {
163   RCSwitch::nReceiveTolerance = nPercent;
164 }
165 #endif
166   
167
168 /**
169  * Enable transmissions
170  *
171  * @param nTransmitterPin    Arduino Pin to which the sender is connected to
172  */
173 void RCSwitch::enableTransmit(int nTransmitterPin) {
174   this->nTransmitterPin = nTransmitterPin;
175   pinMode(this->nTransmitterPin, OUTPUT);
176 }
177
178 /**
179   * Disable transmissions
180   */
181 void RCSwitch::disableTransmit() {
182   this->nTransmitterPin = -1;
183 }
184
185 /**
186  * Switch a remote switch on (Type D REV)
187  *
188  * @param sGroup        Code of the switch group (A,B,C,D)
189  * @param nDevice       Number of the switch itself (1..3)
190  */
191 void RCSwitch::switchOn(char sGroup, int nDevice) {
192   this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
193 }
194
195 /**
196  * Switch a remote switch off (Type D REV)
197  *
198  * @param sGroup        Code of the switch group (A,B,C,D)
199  * @param nDevice       Number of the switch itself (1..3)
200  */
201 void RCSwitch::switchOff(char sGroup, int nDevice) {
202   this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
203 }
204
205 /**
206  * Switch a remote switch on (Type C Intertechno)
207  *
208  * @param sFamily  Familycode (a..f)
209  * @param nGroup   Number of group (1..4)
210  * @param nDevice  Number of device (1..4)
211   */
212 void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
213   this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
214 }
215
216 /**
217  * Switch a remote switch off (Type C Intertechno)
218  *
219  * @param sFamily  Familycode (a..f)
220  * @param nGroup   Number of group (1..4)
221  * @param nDevice  Number of device (1..4)
222  */
223 void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
224   this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
225 }
226
227 /**
228  * Switch a remote switch on (Type B with two rotary/sliding switches)
229  *
230  * @param nAddressCode  Number of the switch group (1..4)
231  * @param nChannelCode  Number of the switch itself (1..4)
232  */
233 void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
234   this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
235 }
236
237 /**
238  * Switch a remote switch off (Type B with two rotary/sliding switches)
239  *
240  * @param nAddressCode  Number of the switch group (1..4)
241  * @param nChannelCode  Number of the switch itself (1..4)
242  */
243 void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
244   this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
245 }
246
247 /**
248  * Deprecated, use switchOn(const char* sGroup, const char* sDevice) instead!
249  * Switch a remote switch on (Type A with 10 pole DIP switches)
250  *
251  * @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")
252  * @param nChannelCode  Number of the switch itself (1..5)
253  */
254 void RCSwitch::switchOn(const char* sGroup, int nChannel) {
255   const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
256   this->switchOn(sGroup, code[nChannel]);
257 }
258
259 /**
260  * Deprecated, use switchOff(const char* sGroup, const char* sDevice) instead!
261  * Switch a remote switch off (Type A with 10 pole DIP switches)
262  *
263  * @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")
264  * @param nChannelCode  Number of the switch itself (1..5)
265  */
266 void RCSwitch::switchOff(const char* sGroup, int nChannel) {
267   const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
268   this->switchOff(sGroup, code[nChannel]);
269 }
270
271 /**
272  * Switch a remote switch on (Type A with 10 pole DIP switches)
273  *
274  * @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")
275  * @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")
276  */
277 void RCSwitch::switchOn(const char* sGroup, const char* sDevice) {
278   this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
279 }
280
281 /**
282  * Switch a remote switch off (Type A with 10 pole DIP switches)
283  *
284  * @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")
285  * @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")
286  */
287 void RCSwitch::switchOff(const char* sGroup, const char* sDevice) {
288   this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
289 }
290
291
292 /**
293  * Returns a char[13], representing the code word to be send.
294  *
295  */
296 char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, bool bStatus) {
297   static char sReturn[13];
298   int nReturnPos = 0;
299
300   for (int i = 0; i < 5; i++) {
301     sReturn[nReturnPos++] = (sGroup[i] == '0') ? 'F' : '0';
302   }
303
304   for (int i = 0; i < 5; i++) {
305     sReturn[nReturnPos++] = (sDevice[i] == '0') ? 'F' : '0';
306   }
307
308   sReturn[nReturnPos++] = bStatus ? '0' : 'F';
309   sReturn[nReturnPos++] = bStatus ? 'F' : '0';
310
311   sReturn[nReturnPos] = '\0';
312   return sReturn;
313 }
314
315 /**
316  * Encoding for type B switches with two rotary/sliding switches.
317  *
318  * The code word is a tristate word and with following bit pattern:
319  *
320  * +-----------------------------+-----------------------------+----------+------------+
321  * | 4 bits address              | 4 bits address              | 3 bits   | 1 bit      |
322  * | switch group                | switch number               | not used | on / off   |
323  * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | FFF      | on=F off=0 |
324  * +-----------------------------+-----------------------------+----------+------------+
325  *
326  * @param nAddressCode  Number of the switch group (1..4)
327  * @param nChannelCode  Number of the switch itself (1..4)
328  * @param bStatus       Whether to switch on (true) or off (false)
329  *
330  * @return char[13], representing a tristate code word of length 12
331  */
332 char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) {
333   static char sReturn[13];
334   int nReturnPos = 0;
335
336   if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
337     return 0;
338   }
339
340   for (int i = 1; i <= 4; i++) {
341     sReturn[nReturnPos++] = (nAddressCode == i) ? '0' : 'F';
342   }
343
344   for (int i = 1; i <= 4; i++) {
345     sReturn[nReturnPos++] = (nChannelCode == i) ? '0' : 'F';
346   }
347
348   sReturn[nReturnPos++] = 'F';
349   sReturn[nReturnPos++] = 'F';
350   sReturn[nReturnPos++] = 'F';
351
352   sReturn[nReturnPos++] = bStatus ? 'F' : '0';
353
354   sReturn[nReturnPos] = '\0';
355   return sReturn;
356 }
357
358 /**
359  * Like getCodeWord (Type C = Intertechno)
360  */
361 char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
362   static char sReturn[13];
363   int nReturnPos = 0;
364
365   int nFamily = (int)sFamily - 'a';
366   if ( nFamily < 0 || nFamily > 15 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
367     return 0;
368   }
369   
370   // encode the family into four bits
371   sReturn[nReturnPos++] = (nFamily & 1) ? 'F' : '0';
372   sReturn[nReturnPos++] = (nFamily & 2) ? 'F' : '0';
373   sReturn[nReturnPos++] = (nFamily & 4) ? 'F' : '0';
374   sReturn[nReturnPos++] = (nFamily & 8) ? 'F' : '0';
375
376   // encode the device and group
377   sReturn[nReturnPos++] = ((nDevice-1) & 1) ? 'F' : '0';
378   sReturn[nReturnPos++] = ((nDevice-1) & 2) ? 'F' : '0';
379   sReturn[nReturnPos++] = ((nGroup-1) & 1) ? 'F' : '0';
380   sReturn[nReturnPos++] = ((nGroup-1) & 2) ? 'F' : '0';
381
382   // encode the status code
383   sReturn[nReturnPos++] = '0';
384   sReturn[nReturnPos++] = 'F';
385   sReturn[nReturnPos++] = 'F';
386   sReturn[nReturnPos++] = bStatus ? 'F' : '0';
387
388   sReturn[nReturnPos] = '\0';
389   return sReturn;
390 }
391
392 /**
393  * Encoding for the REV Switch Type
394  *
395  * The code word is a tristate word and with following bit pattern:
396  *
397  * +-----------------------------+-------------------+----------+--------------+
398  * | 4 bits address              | 3 bits address    | 3 bits   | 2 bits       |
399  * | switch group                | device number     | not used | on / off     |
400  * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FF 2=F0F 3=FF0 | 000      | on=10 off=01 |
401  * +-----------------------------+-------------------+----------+--------------+
402  *
403  * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
404  *
405  * @param sGroup        Name of the switch group (A..D, resp. a..d) 
406  * @param nDevice       Number of the switch itself (1..3)
407  * @param bStatus       Whether to switch on (true) or off (false)
408  *
409  * @return char[13], representing a tristate code word of length 12
410  */
411 char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus) {
412   static char sReturn[13];
413   int nReturnPos = 0;
414
415   // sGroup must be one of the letters in "abcdABCD"
416   int nGroup = (sGroup >= 'a') ? (int)sGroup - 'a' : (int)sGroup - 'A';
417   if ( nGroup < 0 || nGroup > 3 || nDevice < 1 || nDevice > 3) {
418     return 0;
419   }
420
421   for (int i = 0; i < 4; i++) {
422     sReturn[nReturnPos++] = (nGroup == i) ? '1' : 'F';
423   }
424
425   for (int i = 1; i <= 3; i++) {
426     sReturn[nReturnPos++] = (nDevice == i) ? '1' : 'F';
427   }
428
429   sReturn[nReturnPos++] = '0';
430   sReturn[nReturnPos++] = '0';
431   sReturn[nReturnPos++] = '0';
432
433   sReturn[nReturnPos++] = bStatus ? '1' : '0';
434   sReturn[nReturnPos++] = bStatus ? '0' : '1';
435
436   sReturn[nReturnPos] = '\0';
437   return sReturn;
438 }
439
440 /**
441  * @param sCodeWord   a tristate code word consisting of the letter 0, 1, F
442  */
443 void RCSwitch::sendTriState(const char* sCodeWord) {
444   // turn the tristate code word into the corresponding bit pattern, then send it
445   unsigned long code = 0;
446   unsigned int length = 0;
447   for (const char* p = sCodeWord; *p; p++) {
448     code <<= 2L;
449     switch (*p) {
450       case '0':
451         // bit pattern 00
452         break;
453       case 'F':
454         // bit pattern 01
455         code |= 1L;
456         break;
457       case '1':
458         // bit pattern 11
459         code |= 3L;
460         break;
461     }
462     length += 2;
463   }
464   this->send(code, length);
465 }
466
467 /**
468  * @param sCodeWord   a binary code word consisting of the letter 0, 1
469  */
470 void RCSwitch::send(const char* sCodeWord) {
471   // turn the tristate code word into the corresponding bit pattern, then send it
472   unsigned long code = 0;
473   unsigned int length = 0;
474   for (const char* p = sCodeWord; *p; p++) {
475     code <<= 1L;
476     if (*p != '0')
477       code |= 1L;
478     length++;
479   }
480   this->send(code, length);
481 }
482
483 /**
484  * Transmit the first 'length' bits of the integer 'code'. The
485  * bits are sent from MSB to LSB, i.e., first the bit at position length-1,
486  * then the bit at position length-2, and so on, till finally the bit at position 0.
487  */
488 void RCSwitch::send(unsigned long code, unsigned int length) {
489   if (this->nTransmitterPin == -1)
490     return;
491
492 #if not defined( RCSwitchDisableReceiving )
493   // make sure the receiver is disabled while we transmit
494   int nReceiverInterrupt_backup = nReceiverInterrupt;
495   if (nReceiverInterrupt_backup != -1) {
496     this->disableReceive();
497   }
498 #endif
499
500   for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
501     for (int i = length-1; i >= 0; i--) {
502       if (code & (1L << i))
503         this->transmit(protocol.one);
504       else
505         this->transmit(protocol.zero);
506     }
507     this->transmit(protocol.syncFactor);
508   }
509
510 #if not defined( RCSwitchDisableReceiving )
511   // enable receiver again if we just disabled it
512   if (nReceiverInterrupt_backup != -1) {
513     this->enableReceive(nReceiverInterrupt_backup);
514   }
515 #endif
516 }
517
518 /**
519  * Transmit a single high-low pulse.
520  */
521 void RCSwitch::transmit(HighLow pulses) {
522   digitalWrite(this->nTransmitterPin, HIGH);
523   delayMicroseconds( this->protocol.pulseLength * pulses.high);
524   digitalWrite(this->nTransmitterPin, LOW);
525   delayMicroseconds( this->protocol.pulseLength * pulses.low);
526 }
527
528
529 #if not defined( RCSwitchDisableReceiving )
530 /**
531  * Enable receiving data
532  */
533 void RCSwitch::enableReceive(int interrupt) {
534   this->nReceiverInterrupt = interrupt;
535   this->enableReceive();
536 }
537
538 void RCSwitch::enableReceive() {
539   if (this->nReceiverInterrupt != -1) {
540     RCSwitch::nReceivedValue = 0;
541     RCSwitch::nReceivedBitlength = 0;
542 #ifndef noInterrupts
543         #if defined(RaspberryPi) // Raspberry Pi
544         wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt);
545         #else // Arduino
546         attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
547         #endif
548 #endif
549   }
550 }
551
552 /**
553  * Disable receiving data
554  */
555 void RCSwitch::disableReceive() {
556 #if not defined(RaspberryPi) // Arduino
557   detachInterrupt(this->nReceiverInterrupt);
558 #endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
559   this->nReceiverInterrupt = -1;
560 }
561
562 bool RCSwitch::available() {
563   return RCSwitch::nReceivedValue != 0;
564 }
565
566 void RCSwitch::resetAvailable() {
567   RCSwitch::nReceivedValue = 0;
568 }
569
570 unsigned long RCSwitch::getReceivedValue() {
571   return RCSwitch::nReceivedValue;
572 }
573
574 unsigned int RCSwitch::getReceivedBitlength() {
575   return RCSwitch::nReceivedBitlength;
576 }
577
578 unsigned int RCSwitch::getReceivedDelay() {
579   return RCSwitch::nReceivedDelay;
580 }
581
582 unsigned int RCSwitch::getReceivedProtocol() {
583   return RCSwitch::nReceivedProtocol;
584 }
585
586 unsigned int* RCSwitch::getReceivedRawdata() {
587   return RCSwitch::timings;
588 }
589
590 /* helper function for the receiveProtocol method */
591 static inline unsigned int diff(int A, int B) {
592   return abs(A - B);
593 }
594
595 /**
596  *
597  */
598 bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
599 #ifdef ESP8266
600     const Protocol &pro = proto[p-1];
601 #else
602     Protocol pro;
603     memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
604 #endif
605
606     unsigned long code = 0;
607     const unsigned int delay = RCSwitch::timings[0] / pro.syncFactor.low;
608     const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
609
610     for (unsigned int i = 1; i < changeCount - 1; i += 2) {
611         code <<= 1;
612         if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
613             diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
614             // zero
615         } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance &&
616                    diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
617             // one
618             code |= 1;
619         } else {
620             // Failed
621             return false;
622         }
623     }
624
625     if (changeCount > 7) {    // ignore very short transmissions: no device sends them, so this must be noise
626         RCSwitch::nReceivedValue = code;
627         RCSwitch::nReceivedBitlength = (changeCount - 1) / 2;
628         RCSwitch::nReceivedDelay = delay;
629         RCSwitch::nReceivedProtocol = p;
630     }
631
632     return true;
633 }
634
635 void RECEIVE_ATTR RCSwitch::handleInterrupt() {
636
637   static unsigned int changeCount = 0;
638   static unsigned long lastTime = 0;
639   static unsigned int repeatCount = 0;
640
641   const long time = micros();
642   const unsigned int duration = time - lastTime;
643
644   if (duration > RCSwitch::nSeparationLimit) {
645     // A long stretch without signal level change occurred. This could
646     // be the gap between two transmission.
647     if (diff(duration, RCSwitch::timings[0]) < 200) {
648       // This long signal is close in length to the long signal which
649       // started the previously recorded timings; this suggests that
650       // it may indeed by a a gap between two transmissions (we assume
651       // here that a sender will send the signal multiple times,
652       // with roughly the same gap between them).
653       repeatCount++;
654       if (repeatCount == 2) {
655         for(unsigned int i = 1; i <= numProto; i++) {
656           if (receiveProtocol(i, changeCount)) {
657             // receive succeeded for protocol i
658             break;
659           }
660         }
661         repeatCount = 0;
662       }
663     }
664     changeCount = 0;
665   }
666  
667   // detect overflow
668   if (changeCount >= RCSWITCH_MAX_CHANGES) {
669     changeCount = 0;
670     repeatCount = 0;
671   }
672
673   RCSwitch::timings[changeCount++] = duration;
674   lastTime = time;  
675 }
676
677 // where no wiringPiISR supported (nanopi)
678
679 void RCSwitch::handleNoInterrupt( unsigned char PIN ){
680
681         static unsigned char dr, drPrev;
682
683         dr = digitalRead( PIN );
684
685         if (dr != drPrev) {
686                 handleInterrupt();
687                 drPrev = dr;
688         }
689 }
690
691 #endif
Contact me: dev (at) shalnoff (dot) com
PGP fingerprint: A6B8 3B23 6013 F18A 0C71 198B 83D8 C64D 917A 5717