Library to switch 433MHz remote controlled sockets.

Dependents:   RCswitch_example

Revision:
0:6f4be1a7962c
diff -r 000000000000 -r 6f4be1a7962c RCSwitch.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/RCSwitch.cpp	Sun Oct 12 09:57:12 2014 +0000
@@ -0,0 +1,858 @@
+/*
+   RCSwitch - Ported from the Arduino libary for remote control outlet switches
+  Copyright (c) 2011 Suat Özgür.  All right reserved.
+
+  Contributors:
+  - Andre Koehler / info(at)tomate-online(dot)de
+  - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
+  - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
+  - Dominik Fischer / dom_fischer(at)web(dot)de
+  - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
+  - Chris Dick / Porting to mbed
+  
+  Project home: http://code.google.com/p/rc-switch/
+
+  This library is free software; you can redistribute it and/or
+  modify it under the terms of the GNU Lesser General Public
+  License as published by the Free Software Foundation; either
+  version 2.1 of the License, or (at your option) any later version.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "RCSwitch.h"
+
+    unsigned long RCSwitch::nReceivedValue = NULL;
+    unsigned int RCSwitch::nReceivedBitlength = 0;
+    unsigned int RCSwitch::nReceivedDelay = 0;
+    unsigned int RCSwitch::nReceivedProtocol = 0;
+    int RCSwitch::nReceiveTolerance = 60;
+    unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
+    bool RCSwitch::TransmitEnablePin = false;
+    bool RCSwitch::ReceiveEnabled = true;
+    bool RCSwitch::TransmitEnable = true;
+
+/** Class constructor.
+ * The constructor assigns the specified pinout, attatches 
+ * an Interrupt to the receive pin. for the LPC1768 this must not 
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx Transmitter pin of the RF module.
+ * @param rx Receiver pin of the RF module.
+ */
+RCSwitch::RCSwitch(PinName tx, PinName rx) 
+:
+        _tx(DigitalOut(tx)),
+        _rx(InterruptIn(rx)),
+        _tx_en(NC)
+{
+  nReceivedDelay = 0;
+  RCSwitch::nReceivedValue = NULL;
+  nReceivedBitlength = 0;
+  ReceiveEnabled = true;
+  TransmitEnable = true;
+  TransmitEnablePin = false;
+  setRepeatTransmit(15);
+  setProtocol(1);
+  setReceiveTolerance(60);
+  _rx.rise(this, &RCSwitch::RCSwitchRxPinChange);
+  _rx.fall(this, &RCSwitch::RCSwitchRxPinChange);
+  timer.start();
+}
+
+ /** Class constructor.
+ * The constructor assigns the specified pinout, attatches 
+ * an Interrupt to the receive pin. for the LPC1768 this must not 
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx    Transmitter pin of the RF module.
+ * @param rx    Receiver pin of the RF module.
+ * @param tx_en Enable pin of the transmitter
+ */
+RCSwitch::RCSwitch(PinName tx, PinName rx, PinName tx_en) 
+:
+        _tx(DigitalOut(tx)),
+        _rx(InterruptIn(rx)),
+        _tx_en(DigitalOut(tx_en))
+{
+  nReceivedDelay = 0;
+  RCSwitch::nReceivedValue = NULL;
+  nReceivedBitlength = 0;
+  ReceiveEnabled = true;
+  TransmitEnable = false;
+  TransmitEnablePin = true;
+  setRepeatTransmit(15);
+  setProtocol(1);
+  setReceiveTolerance(60);
+  _rx.rise(this, &RCSwitch::RCSwitchRxPinChange);
+  _rx.fall(this, &RCSwitch::RCSwitchRxPinChange);
+  timer.start();
+ 
+}
+ 
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ */ 
+void RCSwitch::setProtocol(int nProtocol) {
+  this->nProtocol = nProtocol;
+  if (nProtocol == 1){
+    this->setPulseLength(350);
+  }
+  else if (nProtocol == 2) {
+    this->setPulseLength(650);
+  }
+  else if (nProtocol == 3) {
+    this->setPulseLength(100);
+  }
+}
+
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ * @param nPulseLength Length of each pulse
+ */  
+void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
+  this->nProtocol = nProtocol;
+  this->setPulseLength(nPulseLength);
+}
+
+
+/**
+ *  Set pulse length in micro seconds
+ * @param nPulseLength the Length of the pulse
+ */  
+void RCSwitch::setPulseLength(int nPulseLength) {
+  this->nPulseLength = nPulseLength;
+}
+
+/**
+ * Set number of times to repeat transmission
+ * @param nRepeat Number of repeats
+ */  
+void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
+  this->nRepeatTransmit = nRepeatTransmit;
+}
+
+/**
+ * Set receive tolerance
+ * @param nPercent Percentage tolerance of the receiver
+ */  
+void RCSwitch::setReceiveTolerance(int nPercent) {
+  RCSwitch::nReceiveTolerance = nPercent;
+}
+  
+
+/**
+ * Enable the transmitter
+ */  
+void RCSwitch::enableTransmit() { 
+    if (TransmitEnablePin == true)
+    {
+        _tx_en = true;
+    }
+    TransmitEnable = true;
+}
+
+/**
+ * Disable the transmitter
+ */
+void RCSwitch::disableTransmit() {
+    if (TransmitEnablePin == true)
+    {
+        _tx_en = false;
+    }
+    TransmitEnable = false;
+}
+
+/**
+ * Switch a remote switch on (Type D REV)
+ *
+ * @param sGroup        Code of the switch group (A,B,C,D)
+ * @param nDevice       Number of the switch itself (1..3)
+ */
+void RCSwitch::switchOn(char sGroup, int nDevice) {
+  this->sendTriState( this->getCodeWordD(sGroup, nDevice, true) );
+}
+
+/**
+ * Switch a remote switch off (Type D REV)
+ *
+ * @param sGroup        Code of the switch group (A,B,C,D)
+ * @param nDevice       Number of the switch itself (1..3)
+ */
+void RCSwitch::switchOff(char sGroup, int nDevice) {
+  this->sendTriState( this->getCodeWordD(sGroup, nDevice, false) );
+}
+
+/**
+ * Switch a remote switch on (Type C Intertechno)
+ *
+ * @param sFamily  Familycode (a..f)
+ * @param nGroup   Number of group (1..4)
+ * @param nDevice  Number of device (1..4)
+  */
+void RCSwitch::switchOn(char sFamily, int nGroup, int nDevice) {
+  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, true) );
+}
+
+/**
+ * Switch a remote switch off (Type C Intertechno)
+ *
+ * @param sFamily  Familycode (a..f)
+ * @param nGroup   Number of group (1..4)
+ * @param nDevice  Number of device (1..4)
+ */
+void RCSwitch::switchOff(char sFamily, int nGroup, int nDevice) {
+  this->sendTriState( this->getCodeWordC(sFamily, nGroup, nDevice, false) );
+}
+
+/**
+ * Switch a remote switch on (Type B with two rotary/sliding switches)
+ *
+ * @param nAddressCode  Number of the switch group (1..4)
+ * @param nChannelCode  Number of the switch itself (1..4)
+ */
+void RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
+  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
+}
+
+/**
+ * Switch a remote switch off (Type B with two rotary/sliding switches)
+ *
+ * @param nAddressCode  Number of the switch group (1..4)
+ * @param nChannelCode  Number of the switch itself (1..4)
+ */
+void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
+  this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
+}
+
+/**
+ * Deprecated, use switchOn(char* sGroup, char* sDevice) instead!
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
+ *
+ * @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")
+ * @param nChannelCode  Number of the switch itself (1..5)
+ */
+void RCSwitch::switchOn(char* sGroup, int nChannel) {
+  char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
+  this->switchOn(sGroup, code[nChannel]);
+}
+
+/**
+ * Deprecated, use switchOff(char* sGroup, char* sDevice) instead!
+ * Switch a remote switch off (Type A with 10 pole DIP switches)
+ *
+ * @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")
+ * @param nChannelCode  Number of the switch itself (1..5)
+ */
+void RCSwitch::switchOff(char* sGroup, int nChannel) {
+  char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
+  this->switchOff(sGroup, code[nChannel]);
+}
+
+/**
+ * Switch a remote switch on (Type A with 10 pole DIP switches)
+ *
+ * @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")
+ * @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")
+ */
+void RCSwitch::switchOn(char* sGroup, char* sDevice) {
+    this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
+}
+
+/**
+ * Switch a remote switch off (Type A with 10 pole DIP switches)
+ *
+ * @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")
+ * @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")
+ */
+void RCSwitch::switchOff(char* sGroup, char* sDevice) {
+    this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
+}
+
+/**
+ * Returns a char[13], representing the Code Word to be send.
+ * 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.
+ * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
+ *
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ * | 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 |
+ * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | F                                       | F                                       | on=FF off=F0         | S          |
+ * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ *
+ * @param nAddressCode  Number of the switch group (1..4)
+ * @param nChannelCode  Number of the switch itself (1..4)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus) {
+   int nReturnPos = 0;
+   static char sReturn[13];
+   
+   char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
+   if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
+    return '\0';
+   }
+   for (int i = 0; i<4; i++) {
+     sReturn[nReturnPos++] = code[nAddressCode][i];
+   }
+
+   for (int i = 0; i<4; i++) {
+     sReturn[nReturnPos++] = code[nChannelCode][i];
+   }
+   
+   sReturn[nReturnPos++] = 'F';
+   sReturn[nReturnPos++] = 'F';
+   sReturn[nReturnPos++] = 'F';
+   
+   if (bStatus) {
+      sReturn[nReturnPos++] = 'F';
+   } else {
+      sReturn[nReturnPos++] = '0';
+   }
+   
+   sReturn[nReturnPos] = '\0';
+   
+   return sReturn;
+}
+
+/**
+ * Returns a char[13], representing the Code Word to be send.
+ *
+ * getCodeWordA(char*, char*)
+ *
+ */
+char* RCSwitch::getCodeWordA(char* sGroup, char* sDevice, bool bOn) {
+    static char sDipSwitches[13];
+    int i = 0;
+    int j = 0;
+    
+    for (i=0; i < 5; i++) {
+        if (sGroup[i] == '0') {
+            sDipSwitches[j++] = 'F';
+        } else {
+            sDipSwitches[j++] = '0';
+        }
+    }
+
+    for (i=0; i < 5; i++) {
+        if (sDevice[i] == '0') {
+            sDipSwitches[j++] = 'F';
+        } else {
+            sDipSwitches[j++] = '0';
+        }
+    }
+
+    if ( bOn ) {
+        sDipSwitches[j++] = '0';
+        sDipSwitches[j++] = 'F';
+    } else {
+        sDipSwitches[j++] = 'F';
+        sDipSwitches[j++] = '0';
+    }
+
+    sDipSwitches[j] = '\0';
+
+    return sDipSwitches;
+}
+
+/**
+ * Like getCodeWord (Type C = Intertechno)
+ */
+char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
+  static char sReturn[13];
+  int nReturnPos = 0;
+  
+  if ( (char)sFamily < 97 || (char)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
+    return '\0';
+  }
+  
+  char* sDeviceGroupCode =  dec2binWzerofill(  (nDevice-1) + (nGroup-1)*4, 4  );
+  char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
+  for (int i = 0; i<4; i++) {
+    sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i];
+  }
+  for (int i = 0; i<4; i++) {
+    sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
+  }
+  sReturn[nReturnPos++] = '0';
+  sReturn[nReturnPos++] = 'F';
+  sReturn[nReturnPos++] = 'F';
+  if (bStatus) {
+    sReturn[nReturnPos++] = 'F';
+  } else {
+    sReturn[nReturnPos++] = '0';
+  }
+  sReturn[nReturnPos] = '\0';
+  return sReturn;
+}
+
+/**
+ * Decoding for the REV Switch Type
+ *
+ * Returns a char[13], representing the Tristate to be send.
+ * A Code Word consists of 7 address bits and 5 command data bits.
+ * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
+ *
+ * +-------------------------------+--------------------------------+-----------------------+
+ * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
+ * | A=1FFF B=F1FF C=FF1F D=FFF1   | 1=0FFF 2=F0FF 3=FF0F 4=FFF0    | on=00010 off=00001    |
+ * +-------------------------------+--------------------------------+-----------------------+
+ *
+ * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
+ *
+ * @param sGroup        Name of the switch group (A..D, resp. a..d) 
+ * @param nDevice       Number of the switch itself (1..3)
+ * @param bStatus       Wether to switch on (true) or off (false)
+ *
+ * @return char[13]
+ */
+
+char* RCSwitch::getCodeWordD(char sGroup, int nDevice, bool bStatus){
+    static char sReturn[13];
+    int nReturnPos = 0;
+
+    // Building 4 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sGroupCode;
+    switch(sGroup){
+        case 'a':
+        case 'A':
+            sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
+        case 'b':
+        case 'B':
+            sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
+        case 'c':
+        case 'C':
+            sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
+        case 'd':
+        case 'D':
+            sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
+        default:
+            return '\0';
+    }
+    
+    for (int i = 0; i<4; i++)
+    {
+        sReturn[nReturnPos++] = sGroupCode[i];
+    }
+
+
+    // Building 3 bits address
+    // (Potential problem if dec2binWcharfill not returning correct string)
+    char *sDevice;
+    switch(nDevice) {
+        case 1:
+            sDevice = dec2binWcharfill(4, 3, 'F'); break;
+        case 2:
+            sDevice = dec2binWcharfill(2, 3, 'F'); break;
+        case 3:
+            sDevice = dec2binWcharfill(1, 3, 'F'); break;
+        default:
+            return '\0';
+    }
+
+    for (int i = 0; i<3; i++)
+        sReturn[nReturnPos++] = sDevice[i];
+
+    // fill up rest with zeros
+    for (int i = 0; i<5; i++)
+        sReturn[nReturnPos++] = '0';
+
+    // encode on or off
+    if (bStatus)
+        sReturn[10] = '1';
+    else
+        sReturn[11] = '1';
+
+    // last position terminate string
+    sReturn[12] = '\0';
+    return sReturn;
+
+}
+
+/**
+ * Sends a codeword
+ * @param sCodeWord   Codeword to be sent
+ */
+void RCSwitch::sendTriState(char* sCodeWord) {
+  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
+    int i = 0;
+    while (sCodeWord[i] != '\0') {
+      switch(sCodeWord[i]) {
+        case '0':
+          this->sendT0();
+        break;
+        case 'F':
+          this->sendTF();
+        break;
+        case '1':
+          this->sendT1();
+        break;
+      }
+      i++;
+    }
+    this->sendSync();    
+  }
+}
+
+void RCSwitch::send(unsigned long Code, unsigned int length) {
+  this->send( this->dec2binWzerofill(Code, length) );
+}
+
+void RCSwitch::send(char* sCodeWord) {
+  for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
+    int i = 0;
+    while (sCodeWord[i] != '\0') {
+      switch(sCodeWord[i]) {
+        case '0':
+          this->send0();
+        break;
+        case '1':
+          this->send1();
+        break;
+      }
+      i++;
+    }
+    this->sendSync();
+  }
+}
+
+void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
+    bool disabled_Receive = false;
+    
+    if (TransmitEnable) {
+        if (ReceiveEnabled) {
+            this->disableReceive();
+            disabled_Receive = true;
+        }
+        _tx = 1;
+        wait_us(this->nPulseLength * nHighPulses);
+        _tx = 0;
+        wait_us(this->nPulseLength *nLowPulses);
+        if(disabled_Receive){
+            this->enableReceive();
+        }
+    }
+}
+/**
+ * Sends a "0" Bit
+ *                       _    
+ * Waveform Protocol 1: | |___
+ *                       _  
+ * Waveform Protocol 2: | |__
+ */
+void RCSwitch::send0() {
+    if (this->nProtocol == 1){
+        this->transmit(1,3);
+    }
+    else if (this->nProtocol == 2) {
+        this->transmit(1,2);
+    }
+    else if (this->nProtocol == 3) {
+        this->transmit(4,11);
+    }
+}
+
+/**
+ * Sends a "1" Bit
+ *                       ___  
+ * Waveform Protocol 1: |   |_
+ *                       __  
+ * Waveform Protocol 2: |  |_
+ */
+void RCSwitch::send1() {
+      if (this->nProtocol == 1){
+        this->transmit(3,1);
+    }
+    else if (this->nProtocol == 2) {
+        this->transmit(2,1);
+    }
+    else if (this->nProtocol == 3) {
+        this->transmit(9,6);
+    }
+}
+
+
+/**
+ * Sends a Tri-State "0" Bit
+ *            _     _
+ * Waveform: | |___| |___
+ */
+void RCSwitch::sendT0() {
+  this->transmit(1,3);
+  this->transmit(1,3);
+}
+
+/**
+ * Sends a Tri-State "1" Bit
+ *            ___   ___
+ * Waveform: |   |_|   |_
+ */
+void RCSwitch::sendT1() {
+  this->transmit(3,1);
+  this->transmit(3,1);
+}
+
+/**
+ * Sends a Tri-State "F" Bit
+ *            _     ___
+ * Waveform: | |___|   |_
+ */
+void RCSwitch::sendTF() {
+  this->transmit(1,3);
+  this->transmit(3,1);
+}
+
+/**
+ * Sends a "Sync" Bit
+ *                       _
+ * Waveform Protocol 1: | |_______________________________
+ *                       _
+ * Waveform Protocol 2: | |__________
+ */
+void RCSwitch::sendSync() {
+
+    if (this->nProtocol == 1){
+        this->transmit(1,31);
+    }
+    else if (this->nProtocol == 2) {
+        this->transmit(1,10);
+    }
+    else if (this->nProtocol == 3) {
+        this->transmit(1,71);
+    }
+}
+
+/**
+ * Enable receiving data
+ */
+void RCSwitch::enableReceive() {
+    RCSwitch::nReceivedValue = NULL;
+    RCSwitch::nReceivedBitlength = NULL;
+    _rx.enable_irq();
+    ReceiveEnabled = true;
+}
+
+/**
+ * Disable receiving data This disables the interrupt
+ * which may disable the port
+ */
+void RCSwitch::disableReceive() {
+    _rx.disable_irq();
+    ReceiveEnabled = false;
+}
+
+bool RCSwitch::available() {
+    return RCSwitch::nReceivedValue != NULL;
+}
+
+void RCSwitch::resetAvailable() {
+  RCSwitch::nReceivedValue = NULL;
+}
+
+unsigned long RCSwitch::getReceivedValue() {
+    return RCSwitch::nReceivedValue;
+}
+
+unsigned int RCSwitch::getReceivedBitlength() {
+  return RCSwitch::nReceivedBitlength;
+}
+
+unsigned int RCSwitch::getReceivedDelay() {
+  return nReceivedDelay;
+}
+
+unsigned int RCSwitch::getReceivedProtocol() {
+  return RCSwitch::nReceivedProtocol;
+}
+
+unsigned int* RCSwitch::getReceivedRawdata() {
+    return RCSwitch::timings;
+}
+
+/**
+ *
+ */
+bool RCSwitch::receiveProtocol1(unsigned int changeCount){
+    
+      unsigned long code = 0;
+      unsigned long delay = RCSwitch::timings[0] / 31;
+      unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;    
+
+      for (int i = 1; i<changeCount ; i=i+2) {
+      
+          if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*3-delayTolerance && RCSwitch::timings[i+1] < delay*3+delayTolerance) {
+            code = code << 1;
+          } else if (RCSwitch::timings[i] > delay*3-delayTolerance && RCSwitch::timings[i] < delay*3+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
+            code+=1;
+            code = code << 1;
+          } else {
+            // Failed
+            i = changeCount;
+            code = 0;
+          }
+      }      
+      code = code >> 1;
+    if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
+      RCSwitch::nReceivedValue = code;
+      RCSwitch::nReceivedBitlength = changeCount / 2;
+      nReceivedDelay = delay;
+      RCSwitch::nReceivedProtocol = 1;
+    }
+
+    if (code == 0){
+        return false;
+    }
+    return true;
+}
+
+bool RCSwitch::receiveProtocol2(unsigned int changeCount){
+    
+      unsigned long code = 0;
+      unsigned long delay = RCSwitch::timings[0] / 10;
+      unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;    
+
+      for (int i = 1; i<changeCount ; i=i+2) {
+      
+          if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*2-delayTolerance && RCSwitch::timings[i+1] < delay*2+delayTolerance) {
+            code = code << 1;
+          } else if (RCSwitch::timings[i] > delay*2-delayTolerance && RCSwitch::timings[i] < delay*2+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
+            code+=1;
+            code = code << 1;
+          } else {
+            // Failed
+            i = changeCount;
+            code = 0;
+          }
+      }      
+      code = code >> 1;
+    if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
+      RCSwitch::nReceivedValue = code;
+      RCSwitch::nReceivedBitlength = changeCount / 2;
+      nReceivedDelay = delay;
+      RCSwitch::nReceivedProtocol = 2;
+    }
+
+    if (code == 0){
+        return false;
+    }
+    return true;
+}
+
+/** Protocol 3 is used by BL35P02.
+ *
+ */
+bool RCSwitch::receiveProtocol3(unsigned int changeCount){
+    
+      unsigned long code = 0;
+      unsigned long delay = RCSwitch::timings[0] / PROTOCOL3_SYNC_FACTOR;
+      unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;    
+
+      for (int i = 1; i<changeCount ; i=i+2) {
+      
+          if  (RCSwitch::timings[i]   > delay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance
+            && RCSwitch::timings[i]   < delay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance
+            && RCSwitch::timings[i+1] > delay*PROTOCOL3_0_LOW_CYCLES  - delayTolerance
+            && RCSwitch::timings[i+1] < delay*PROTOCOL3_0_LOW_CYCLES  + delayTolerance) {
+            code = code << 1;
+          } else if (RCSwitch::timings[i]   > delay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance
+                  && RCSwitch::timings[i]   < delay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance
+                  && RCSwitch::timings[i+1] > delay*PROTOCOL3_1_LOW_CYCLES  - delayTolerance
+                  && RCSwitch::timings[i+1] < delay*PROTOCOL3_1_LOW_CYCLES  + delayTolerance) {
+            code+=1;
+            code = code << 1;
+          } else {
+            // Failed
+            i = changeCount;
+            code = 0;
+          }
+      }      
+      code = code >> 1;
+      if (changeCount > 6) {    // ignore < 4bit values as there are no devices sending 4bit values => noise
+        RCSwitch::nReceivedValue = code;
+        RCSwitch::nReceivedBitlength = changeCount / 2;
+        nReceivedDelay = delay;
+        RCSwitch::nReceivedProtocol = 3;
+      }
+
+      if (code == 0){
+        return false;
+      }
+      return true;
+}
+
+void RCSwitch::RCSwitchRxPinChange() {
+
+  static unsigned int duration;
+  static unsigned int changeCount;
+  static unsigned int repeatCount;
+  timer.stop();
+  duration = timer.read_us();
+  timer.reset();
+  timer.start();
+  
+ 
+  if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {
+    repeatCount++;
+    changeCount--;
+    
+    if (repeatCount == 2) {
+      if (receiveProtocol1(changeCount) == false){
+        if (receiveProtocol2(changeCount) == false){
+          if (receiveProtocol3(changeCount) == false){
+            //failed
+          }
+        }
+      }
+      repeatCount = 0;
+    }
+    changeCount = 0;
+  } else if (duration > 5000) {
+    
+    changeCount = 0;
+  }
+ 
+  if (changeCount >= RCSWITCH_MAX_CHANGES) {
+    changeCount = 0;
+    repeatCount = 0;
+  }
+  RCSwitch::timings[changeCount++] = duration;
+}
+
+/**
+  * Turns a decimal value to its binary representation
+  */
+char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
+    return dec2binWcharfill(Dec, bitLength, '0');
+}
+
+char* RCSwitch::dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill){
+  static char bin[64];
+  unsigned int i=0;
+
+  while (Dec > 0) {
+    bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
+    Dec = Dec >> 1;
+  }
+
+  for (unsigned int j = 0; j< bitLength; j++) {
+    if (j >= bitLength - i) {
+      bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
+    }else {
+      bin[j] = fill;
+    }
+  }
+  bin[bitLength] = '\0';
+  
+  return bin;
+}
+
+
+