diff --git a/RCSwitch.cpp b/RCSwitch.cpp
index d0440aab5a185640eaabd6ed1852aca4bee7fcc3..9b069eb4a5a683f2483d414fcecdb05d4b2a0fd7 100644
--- a/RCSwitch.cpp
+++ b/RCSwitch.cpp
@@ -9,9 +9,10 @@
   - Dominik Fischer / dom_fischer(at)web(dot)de
   - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
   - Andreas Steinel / A.<lastname>(at)gmail(dot)com
+  - Max Horn / max(at)quendi(dot)de
   - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
   
-  Project home: http://code.google.com/p/rc-switch/
+  Project home: https://github.com/sui77/rc-switch/
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -30,54 +31,62 @@
 
 #include "RCSwitch.h"
 
+static const RCSwitch::Protocol PROGMEM proto[] = {
+    { 350, {  1, 31 }, {  1,  3 }, {  3,  1 } },    // protocol 1
+    { 650, {  1, 10 }, {  1,  2 }, {  2,  1 } },    // protocol 2
+    { 100, {  1, 71 }, {  4, 11 }, {  9,  6 } },    // protocol 3
+    { 380, {  1,  6 }, {  1,  3 }, {  3,  1 } },    // protocol 4
+    { 500, {  6, 14 }, {  1,  2 }, {  2,  1 } },    // protocol 5
+};
+
+static const int numProto = sizeof(proto) / sizeof(proto[0]);
+
 #if not defined( RCSwitchDisableReceiving )
-unsigned long RCSwitch::nReceivedValue = NULL;
+unsigned long RCSwitch::nReceivedValue = 0;
 unsigned int RCSwitch::nReceivedBitlength = 0;
 unsigned int RCSwitch::nReceivedDelay = 0;
 unsigned int RCSwitch::nReceivedProtocol = 0;
 int RCSwitch::nReceiveTolerance = 60;
-#endif
+const unsigned int RCSwitch::nSeparationLimit = 4600;
+// separationLimit: minimum microseconds between received codes, closer codes are ignored.
+// according to discussion on issue #14 it might be more suitable to set the separation
+// limit to the same time as the 'low' part of the sync signal for the current protocol.
 unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
+#endif
 
 RCSwitch::RCSwitch() {
   this->nTransmitterPin = -1;
-  this->setPulseLength(350);
   this->setRepeatTransmit(10);
   this->setProtocol(1);
   #if not defined( RCSwitchDisableReceiving )
   this->nReceiverInterrupt = -1;
   this->setReceiveTolerance(60);
-  RCSwitch::nReceivedValue = NULL;
+  RCSwitch::nReceivedValue = 0;
   #endif
 }
 
 /**
   * Sets the protocol to send.
   */
+void RCSwitch::setProtocol(Protocol protocol) {
+  this->protocol = protocol;
+}
+
+/**
+  * Sets the protocol to send, from a list of predefined protocols
+  */
 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);
-  }
-  else if (nProtocol == 4) {
-    this->setPulseLength(380);
-  }
-  else if (nProtocol == 5) {
-    this->setPulseLength(500);
+  if (nProtocol < 1 || nProtocol > numProto) {
+    nProtocol = 1;  // TODO: trigger an error, e.g. "bad protocol" ???
   }
+  memcpy_P(&this->protocol, &proto[nProtocol-1], sizeof(Protocol));
 }
 
 /**
   * Sets the protocol to send with pulse length in microseconds.
   */
 void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
-  this->nProtocol = nProtocol;
+  setProtocol(nProtocol);
   this->setPulseLength(nPulseLength);
 }
 
@@ -86,7 +95,7 @@ void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
   * Sets pulse length in microseconds
   */
 void RCSwitch::setPulseLength(int nPulseLength) {
-  this->nPulseLength = nPulseLength;
+  this->protocol.pulseLength = nPulseLength;
 }
 
 /**
@@ -186,26 +195,26 @@ void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
 }
 
 /**
- * Deprecated, use switchOn(char* sGroup, char* sDevice) instead!
+ * Deprecated, use switchOn(const char* sGroup, const 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" };
+void RCSwitch::switchOn(const char* sGroup, int nChannel) {
+  const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
   this->switchOn(sGroup, code[nChannel]);
 }
 
 /**
- * Deprecated, use switchOff(char* sGroup, char* sDevice) instead!
+ * Deprecated, use switchOff(const char* sGroup, const 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" };
+void RCSwitch::switchOff(const char* sGroup, int nChannel) {
+  const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
   this->switchOff(sGroup, code[nChannel]);
 }
 
@@ -215,7 +224,7 @@ void RCSwitch::switchOff(char* sGroup, int nChannel) {
  * @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) {
+void RCSwitch::switchOn(const char* sGroup, const char* sDevice) {
     this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
 }
 
@@ -225,23 +234,25 @@ void RCSwitch::switchOn(char* sGroup, char* sDevice) {
  * @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) {
+void RCSwitch::switchOff(const char* sGroup, const 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)
+ * Returns a char[13], representing the code word to be sent.
+ * 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" (sync 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          |
- * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
+ * +-----------------------------+-----------------------------+----------+----------+--------------+----------+
+ * | 4 bits address              | 4 bits address              | 1 bit    | 1 bit    | 2 bits       | 1 bit    |
+ * | switch group                | switch number               | not used | not used | on / off     | 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)
+ * @param bStatus       Whether to switch on (true) or off (false)
  *
  * @return char[13]
  */
@@ -249,7 +260,7 @@ char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus
    int nReturnPos = 0;
    static char sReturn[13];
    
-   char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
+   const char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
    if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
     return '\0';
    }
@@ -277,33 +288,23 @@ char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus
 }
 
 /**
- * Returns a char[13], representing the Code Word to be send.
- *
- * getCodeWordA(char*, char*)
+ * Returns a char[13], representing the code word to be send.
  *
  */
-char* RCSwitch::getCodeWordA(char* sGroup, char* sDevice, boolean bOn) {
+char* RCSwitch::getCodeWordA(const char* sGroup, const char* sDevice, boolean 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++) {
+        sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0';
     }
 
-    for (i=0; i < 5; i++) {
-        if (sDevice[i] == '0') {
-            sDipSwitches[j++] = 'F';
-        } else {
-            sDipSwitches[j++] = '0';
-        }
+    for (i = 0; i < 5; i++) {
+        sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0';
     }
 
-    if ( bOn ) {
+    if (bOn) {
         sDipSwitches[j++] = '0';
         sDipSwitches[j++] = 'F';
     } else {
@@ -327,8 +328,13 @@ char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bSta
     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" };
+  const char* sDeviceGroupCode =  dec2binWcharfill(  (nDevice-1) + (nGroup-1)*4, 4, '0'  );
+  const 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];
   }
@@ -363,7 +369,7 @@ char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bSta
  *
  * @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)
+ * @param bStatus       Whether to switch on (true) or off (false)
  *
  * @return char[13]
  */
@@ -392,8 +398,7 @@ char* RCSwitch::getCodeWordD(char sGroup, int nDevice, boolean bStatus){
             return '\0';
     }
     
-    for (int i = 0; i<4; i++)
-    {
+    for (int i = 0; i<4; i++) {
         sReturn[nReturnPos++] = sGroupCode[i];
     }
 
@@ -434,7 +439,7 @@ char* RCSwitch::getCodeWordD(char sGroup, int nDevice, boolean bStatus){
 /**
  * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
  */
-void RCSwitch::sendTriState(char* sCodeWord) {
+void RCSwitch::sendTriState(const char* sCodeWord) {
   for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
     int i = 0;
     while (sCodeWord[i] != '\0') {
@@ -455,11 +460,11 @@ void RCSwitch::sendTriState(char* sCodeWord) {
   }
 }
 
-void RCSwitch::send(unsigned long Code, unsigned int length) {
-  this->send( this->dec2binWzerofill(Code, length) );
+void RCSwitch::send(unsigned long code, unsigned int length) {
+  this->send( this->dec2binWcharfill(code, length, '0') );
 }
 
-void RCSwitch::send(char* sCodeWord) {
+void RCSwitch::send(const char* sCodeWord) {
   for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
     int i = 0;
     while (sCodeWord[i] != '\0') {
@@ -478,29 +483,30 @@ void RCSwitch::send(char* sCodeWord) {
 }
 
 void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
-    #if not defined ( RCSwitchDisableReceiving )
-    boolean disabled_Receive = false;
-    int nReceiverInterrupt_backup = nReceiverInterrupt;
-    #endif
     if (this->nTransmitterPin != -1) {
         #if not defined( RCSwitchDisableReceiving )
-        if (this->nReceiverInterrupt != -1) {
+        int nReceiverInterrupt_backup = nReceiverInterrupt;
+        if (nReceiverInterrupt_backup != -1) {
             this->disableReceive();
-            disabled_Receive = true;
         }
         #endif
         digitalWrite(this->nTransmitterPin, HIGH);
-        delayMicroseconds( this->nPulseLength * nHighPulses);
+        delayMicroseconds( this->protocol.pulseLength * nHighPulses);
         digitalWrite(this->nTransmitterPin, LOW);
-        delayMicroseconds( this->nPulseLength * nLowPulses);
+        delayMicroseconds( this->protocol.pulseLength * nLowPulses);
         
         #if not defined( RCSwitchDisableReceiving )
-        if(disabled_Receive){
+        if (nReceiverInterrupt_backup != -1) {
             this->enableReceive(nReceiverInterrupt_backup);
         }
         #endif
     }
 }
+
+void RCSwitch::transmit(HighLow pulses) {
+    transmit(pulses.high, pulses.low);
+}
+
 /**
  * Sends a "0" Bit
  *                       _    
@@ -509,21 +515,7 @@ void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
  * 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);
-    }
-    else if (this->nProtocol == 4) {
-        this->transmit(1,3);
-    }
-    else if (this->nProtocol == 5) {
-        this->transmit(1,2);
-    }
+    this->transmit(protocol.zero);
 }
 
 /**
@@ -534,21 +526,7 @@ void RCSwitch::send0() {
  * 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);
-    }
-    else if (this->nProtocol == 4) {
-        this->transmit(3,1);
-    }
-	else if (this->nProtocol == 5) {
-        this->transmit(2,1);
-    }
+    this->transmit(protocol.one);
 }
 
 
@@ -558,8 +536,8 @@ void RCSwitch::send1() {
  * Waveform: | |___| |___
  */
 void RCSwitch::sendT0() {
-  this->transmit(1,3);
-  this->transmit(1,3);
+  this->send0();
+  this->send0();
 }
 
 /**
@@ -568,8 +546,8 @@ void RCSwitch::sendT0() {
  * Waveform: |   |_|   |_
  */
 void RCSwitch::sendT1() {
-  this->transmit(3,1);
-  this->transmit(3,1);
+  this->send1();
+  this->send1();
 }
 
 /**
@@ -578,8 +556,8 @@ void RCSwitch::sendT1() {
  * Waveform: | |___|   |_
  */
 void RCSwitch::sendTF() {
-  this->transmit(1,3);
-  this->transmit(3,1);
+  this->send0();
+  this->send1();
 }
 
 /**
@@ -590,22 +568,7 @@ void RCSwitch::sendTF() {
  * 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);
-    }
-    else if (this->nProtocol == 4) {
-        this->transmit(1,6);
-    }
-    else if (this->nProtocol == 5) {
-        this->transmit(6,14);
-    }
+    this->transmit(protocol.syncFactor);
 }
 
 #if not defined( RCSwitchDisableReceiving )
@@ -619,8 +582,8 @@ void RCSwitch::enableReceive(int interrupt) {
 
 void RCSwitch::enableReceive() {
   if (this->nReceiverInterrupt != -1) {
-    RCSwitch::nReceivedValue = NULL;
-    RCSwitch::nReceivedBitlength = NULL;
+    RCSwitch::nReceivedValue = 0;
+    RCSwitch::nReceivedBitlength = 0;
 #if defined(RaspberryPi) // Raspberry Pi
     wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt);
 #else // Arduino
@@ -640,11 +603,11 @@ void RCSwitch::disableReceive() {
 }
 
 bool RCSwitch::available() {
-  return RCSwitch::nReceivedValue != NULL;
+  return RCSwitch::nReceivedValue != 0;
 }
 
 void RCSwitch::resetAvailable() {
-  RCSwitch::nReceivedValue = NULL;
+  RCSwitch::nReceivedValue = 0;
 }
 
 unsigned long RCSwitch::getReceivedValue() {
@@ -667,121 +630,46 @@ unsigned int* RCSwitch::getReceivedRawdata() {
     return RCSwitch::timings;
 }
 
+/* helper function for the various receiveProtocol methods */
+static inline unsigned int diff(int A, int B) {
+    return abs(A - B);
+}
+
 /**
  *
  */
-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 {
+bool RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
+
+    Protocol pro;
+    memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
+
+    unsigned long code = 0;
+    const unsigned int delay = RCSwitch::timings[0] / pro.syncFactor.low;
+    const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100;
+
+    for (unsigned int i = 1; i < changeCount; i += 2) {
+        code <<= 1;
+        if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance &&
+            diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {
+            // zero
+        } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance &&
+                   diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) {
+            // one
+            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;
-      RCSwitch::nReceivedDelay = delay;
-      RCSwitch::nReceivedProtocol = 1;
-    }
-
-    if (code == 0){
-        return false;
-    }else if (code != 0){
-        return true;
+            return false;
+        }
     }
-    
-
-}
 
-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;
-      RCSwitch::nReceivedDelay = delay;
-      RCSwitch::nReceivedProtocol = 2;
-    }
-
-    if (code == 0){
-        return false;
-    }else if (code != 0){
-        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;
         RCSwitch::nReceivedDelay = delay;
-        RCSwitch::nReceivedProtocol = 3;
-      }
+        RCSwitch::nReceivedProtocol = p;
+    }
 
-      if (code == 0){
-        return false;
-      }else if (code != 0){
-        return true;
-      }
+    return true;
 }
 
 void RCSwitch::handleInterrupt() {
@@ -795,13 +683,13 @@ void RCSwitch::handleInterrupt() {
   long time = micros();
   duration = time - lastTime;
  
-  if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {
+  if (duration > RCSwitch::nSeparationLimit && diff(duration, RCSwitch::timings[0]) < 200) {
     repeatCount++;
     changeCount--;
     if (repeatCount == 2) {
-      if (receiveProtocol1(changeCount) == false){
-        if (receiveProtocol2(changeCount) == false){
-          if (receiveProtocol3(changeCount) == false){
+      if (receiveProtocol(1, changeCount) == false) {
+        if (receiveProtocol(2, changeCount) == false) {
+          if (receiveProtocol(3, changeCount) == false) {
             //failed
           }
         }
@@ -809,7 +697,7 @@ void RCSwitch::handleInterrupt() {
       repeatCount = 0;
     }
     changeCount = 0;
-  } else if (duration > 5000) {
+  } else if (duration > RCSwitch::nSeparationLimit) {
     changeCount = 0;
   }
  
@@ -825,30 +713,15 @@ void RCSwitch::handleInterrupt() {
 /**
   * 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[32];
 
-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;
+  bin[bitLength] = '\0';
+  while (bitLength > 0) {
+    bitLength--;
+    bin[bitLength] = (dec & 1) ? '1' : fill;
+    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;
 }
-
-
-
diff --git a/RCSwitch.h b/RCSwitch.h
index 69b449b8d3fa485a68fae60d14c7281ba96abf70..598e9398d6254700b801dbfc3728880b25c99620 100644
--- a/RCSwitch.h
+++ b/RCSwitch.h
@@ -8,8 +8,10 @@
   - 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
+  - Max Horn / max(at)quendi(dot)de
+  - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
   
-  Project home: http://code.google.com/p/rc-switch/
+  Project home: https://github.com/sui77/rc-switch/
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -48,7 +50,7 @@ typedef uint8_t byte;
 #endif
 #ifdef __cplusplus
 }
-#endif // Last line inside Raspberry Pi block
+#endif // Last line within Raspberry Pi block
 #else
     #include "WProgram.h"
 #endif
@@ -64,12 +66,6 @@ typedef uint8_t byte;
 // We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
 #define RCSWITCH_MAX_CHANGES 67
 
-#define PROTOCOL3_SYNC_FACTOR   71
-#define PROTOCOL3_0_HIGH_CYCLES  4
-#define PROTOCOL3_0_LOW_CYCLES  11
-#define PROTOCOL3_1_HIGH_CYCLES  9
-#define PROTOCOL3_1_LOW_CYCLES   6
-
 class RCSwitch {
 
   public:
@@ -77,18 +73,18 @@ class RCSwitch {
     
     void switchOn(int nGroupNumber, int nSwitchNumber);
     void switchOff(int nGroupNumber, int nSwitchNumber);
-    void switchOn(char* sGroup, int nSwitchNumber);
-    void switchOff(char* sGroup, int nSwitchNumber);
+    void switchOn(const char* sGroup, int nSwitchNumber);
+    void switchOff(const char* sGroup, int nSwitchNumber);
     void switchOn(char sFamily, int nGroup, int nDevice);
     void switchOff(char sFamily, int nGroup, int nDevice);
-    void switchOn(char* sGroup, char* sDevice);
-    void switchOff(char* sGroup, char* sDevice);
+    void switchOn(const char* sGroup, const char* sDevice);
+    void switchOff(const char* sGroup, const char* sDevice);
     void switchOn(char sGroup, int nDevice);
     void switchOff(char sGroup, int nDevice);
 
-    void sendTriState(char* Code);
+    void sendTriState(const char* Code);
     void send(unsigned long Code, unsigned int length);
-    void send(char* Code);
+    void send(const char* Code);
     
     #if not defined( RCSwitchDisableReceiving )
     void enableReceive(int interrupt);
@@ -111,13 +107,27 @@ class RCSwitch {
     #if not defined( RCSwitchDisableReceiving )
     void setReceiveTolerance(int nPercent);
     #endif
+
+    struct HighLow {
+        byte high;
+        byte low;
+    };
+
+    struct Protocol {
+        int pulseLength;
+        HighLow syncFactor;
+        HighLow zero;
+        HighLow one;
+    };
+
+    void setProtocol(Protocol protocol);
     void setProtocol(int nProtocol);
     void setProtocol(int nProtocol, int nPulseLength);
-  
+
   private:
     char* getCodeWordB(int nGroupNumber, int nSwitchNumber, boolean bStatus);
-    char* getCodeWordA(char* sGroup, int nSwitchNumber, boolean bStatus);
-    char* getCodeWordA(char* sGroup, char* sDevice, boolean bStatus);
+    char* getCodeWordA(const char* sGroup, int nSwitchNumber, boolean bStatus);
+    char* getCodeWordA(const char* sGroup, const char* sDevice, boolean bStatus);
     char* getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus);
     char* getCodeWordD(char group, int nDevice, boolean bStatus);
     void sendT0();
@@ -127,21 +137,19 @@ class RCSwitch {
     void send1();
     void sendSync();
     void transmit(int nHighPulses, int nLowPulses);
+    void transmit(HighLow pulses);
 
-    static char* dec2binWzerofill(unsigned long dec, unsigned int length);
     static char* dec2binWcharfill(unsigned long dec, unsigned int length, char fill);
     
     #if not defined( RCSwitchDisableReceiving )
     static void handleInterrupt();
-    static bool receiveProtocol1(unsigned int changeCount);
-    static bool receiveProtocol2(unsigned int changeCount);
-    static bool receiveProtocol3(unsigned int changeCount);
+    static bool receiveProtocol(const int p, unsigned int changeCount);
     int nReceiverInterrupt;
     #endif
     int nTransmitterPin;
-    int nPulseLength;
     int nRepeatTransmit;
-    char nProtocol;
+    
+    Protocol protocol;
 
     #if not defined( RCSwitchDisableReceiving )
     static int nReceiveTolerance;
@@ -149,11 +157,12 @@ class RCSwitch {
     static unsigned int nReceivedBitlength;
     static unsigned int nReceivedDelay;
     static unsigned int nReceivedProtocol;
-    #endif
+    const static unsigned int nSeparationLimit;
     /* 
      * timings[0] contains sync timing, followed by a number of bits
      */
     static unsigned int timings[RCSWITCH_MAX_CHANGES];
+    #endif
 
     
 };
diff --git a/README.md b/README.md
index 8a0a01066d040074f22dc2cbf0d06f2409075799..9aa5efe8645883d846c39c0bbf21154f073e3d4b 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,9 @@ Use your Arduino or Raspberry Pi to operate remote radio controlled devices
 ##Download
 https://github.com/sui77/rc-switch/releases/latest
 
+##Wiki
+https://github.com/sui77/rc-switch/wiki
+
 ##Info
 ###Send RC codes
 
diff --git a/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde b/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde
index 89cbbc9141b4d8a674684851f52c0f26e7095faf..18380d336606be09ee6f2ebe8b28283cfc6a041b 100644
--- a/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde
+++ b/examples/ReceiveDemo_Advanced/ReceiveDemo_Advanced.pde
@@ -1,7 +1,7 @@
 /*
   Example for receiving
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
   
   If you want to visualize a telegram copy the raw data and 
   paste it into http://test.sui.li/oszi/
@@ -13,7 +13,7 @@ RCSwitch mySwitch = RCSwitch();
 
 void setup() {
   Serial.begin(9600);
-  mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin #2
+  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
 }
 
 void loop() {
diff --git a/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde b/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde
index b55e5d7d09920ce40314ca9ff3965fcabe10156e..ed1d180d702f18db22614c4d4d31265f7bd18ebf 100644
--- a/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde
+++ b/examples/ReceiveDemo_Simple/ReceiveDemo_Simple.pde
@@ -1,7 +1,7 @@
 /*
   Simple example for receiving
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 #include <RCSwitch.h>
@@ -10,7 +10,7 @@ RCSwitch mySwitch = RCSwitch();
 
 void setup() {
   Serial.begin(9600);
-  mySwitch.enableReceive(0);  // Receiver on inerrupt 0 => that is pin #2
+  mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2
 }
 
 void loop() {
diff --git a/examples/SendDemo/SendDemo.pde b/examples/SendDemo/SendDemo.pde
index 9ee54cebb0fac68136cbb6308640ecf3fec5ab1e..d1e1cd259df750523054ae63373a05753828dd24 100644
--- a/examples/SendDemo/SendDemo.pde
+++ b/examples/SendDemo/SendDemo.pde
@@ -1,7 +1,7 @@
 /*
   Example for different sending methods
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
   
 */
 
diff --git a/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde b/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde
index b36215181bce86b6da78eb5ecf545cbf71326134..14f7d2a6c276b15c6d485b9f7794cbcb8a4089cc 100644
--- a/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde
+++ b/examples/TypeA_WithDIPSwitches/TypeA_WithDIPSwitches.pde
@@ -1,7 +1,7 @@
 /*
   Example for outlets which are configured with a 10 pole DIP switch.
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 #include <RCSwitch.h>
diff --git a/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino b/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino
index 5796624b11967adcfe9b823dde9218a45aba556b..214daf41a2cab9dd147c3c439454e8e4a1737ff3 100644
--- a/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino
+++ b/examples/TypeA_WithDIPSwitches_Lightweight/TypeA_WithDIPSwitches_Lightweight.ino
@@ -3,7 +3,7 @@
   the 10 pole dip switch sockets. It saves a lot of memory and thus might be 
   very useful to use with ATTinys :)
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 int RCLpin = 7;
diff --git a/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde b/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde
index 61e0d76cf8c97d0ff31e6cdf6a1b5f73610df908..e8568e25bfc29ab46966fc4ba09835ea2b01d8fd 100644
--- a/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde
+++ b/examples/TypeB_WithRotaryOrSlidingSwitches/TypeB_WithRotaryOrSlidingSwitches.pde
@@ -1,7 +1,7 @@
 /*
   Example for outlets which are configured with two rotary/sliding switches.
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 #include <RCSwitch.h>
diff --git a/examples/TypeC_Intertechno/TypeC_Intertechno.pde b/examples/TypeC_Intertechno/TypeC_Intertechno.pde
index 012a93a6645aef03b8fb49d8090e85f4ab74bc1e..0fc69c7c80c91e20fdf4e5f38d1e0f94bfc95aa2 100644
--- a/examples/TypeC_Intertechno/TypeC_Intertechno.pde
+++ b/examples/TypeC_Intertechno/TypeC_Intertechno.pde
@@ -1,7 +1,7 @@
 /*
   Example for Intertechno outlets
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 #include <RCSwitch.h>
diff --git a/examples/TypeD_REV/TypeD_REV.ino b/examples/TypeD_REV/TypeD_REV.ino
index 446bc8a6b26f56f8e7da54cb8c8c7c840a728068..8782729451866440497eb40629909c30df59d88e 100644
--- a/examples/TypeD_REV/TypeD_REV.ino
+++ b/examples/TypeD_REV/TypeD_REV.ino
@@ -1,7 +1,7 @@
 /*
   Example for REV outlets (e.g. 8342L)
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
   
   Need help? http://forum.ardumote.com
 */
diff --git a/examples/Webserver/Webserver.pde b/examples/Webserver/Webserver.pde
index ee2c74a840d1937cbb6b4bd85a464e11879c3d13..7b3e2274a577990ab3bcc06c275c9dc31581a46e 100644
--- a/examples/Webserver/Webserver.pde
+++ b/examples/Webserver/Webserver.pde
@@ -1,7 +1,7 @@
 /*
   A simple RCSwitch/Ethernet/Webserver demo
   
-  http://code.google.com/p/rc-switch/
+  https://github.com/sui77/rc-switch/
 */
 
 #include <SPI.h>
@@ -79,7 +79,7 @@ void httpResponseHome(EthernetClient c) {
   c.println(        "<li><a href=\"./?2-off\">Switch #2 off</a></li>");
   c.println(    "</ul>");
   c.println(    "<hr>");
-  c.println(    "<a href=\"http://code.google.com/p/rc-switch/\">http://code.google.com/p/rc-switch/</a>");
+  c.println(    "<a href=\"https://github.com/sui77/rc-switch/\">https://github.com/sui77/rc-switch/</a>");
   c.println("</body>");
   c.println("</html>");
 }