lib/rc-switch.c

Sun, 04 May 2014 17:18:27 +0200

author
Michiel Broek <mbroek@mbse.eu>
date
Sun, 04 May 2014 17:18:27 +0200
changeset 20
f7f9463cdefd
child 22
a3b058c67289
permissions
-rw-r--r--

Added 433 MHz transmitter and receiver library and demo programs

/*****************************************************************************
 * Copyright (C) 2014
 *   
 * Michiel Broek <mbroek at mbse dot eu>
 *
 * This file is part of the mbsePi-apps
 *
 * Based on the Arduino libary for remote control outlet switches.
 * Project home: http://code.google.com/p/rc-switch/
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2, or (at your option) any
 * later version.
 *
 * mbsePi-apps 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
 * General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with EC-65K; see the file COPYING.  If not, write to the Free
 * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 *****************************************************************************/

#include "../config.h"
#include "mbselib.h"

#ifdef HAVE_WIRINGPI_H

unsigned long	rcReceivedValue = 0;
unsigned int	rcReceivedBitlength = 0;
unsigned int	rcReceivedDelay = 0;
unsigned int	rcReceivedProtocol = 0;
int		rcReceiveTolerance = 60;
int		rcReceiverInterrupt = -1;

unsigned int	timings[RCSWITCH_MAX_CHANGES];
int		rcTransmitterPin = -1;
int		rcPulseLength = 350;
int		rcRepeatTransmit = 10;
int		rcProtocol = 1;


char *getCodeWordA(char*, char*, bool);
char *getCodeWordB(int, int, bool);
char *getCodeWordC(char, int, int, bool);
char *getCodeWordD(char, int, bool);
void sendTriState(char*);
void transmit(int, int);
void send0(void);
void send1(void);
void sendT0(void);
void sendT1(void);
void sendTF(void);
void sendSync(void);
bool receiveProtocol1(unsigned int);
bool receiveProtocol2(unsigned int);
bool receiveProtocol3(unsigned int);
void handleInterrupt(void);
char *dec2binWzerofill(unsigned long, unsigned int);
char *dec2binWcharfill(unsigned long, unsigned int, char);




/*
 * Sets the protocol to send.
 */
void setProtocol(int nProtocol) {
  rcProtocol = nProtocol;
  if (nProtocol == 1){
	  setPulseLength(350);
  }
  else if (nProtocol == 2) {
	  setPulseLength(650);
  }
  else if (nProtocol == 3) {
    setPulseLength(100);
  }
}



/**
  * Sets the protocol to send with pulse length in microseconds.
  */
/*void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
  this->nProtocol = nProtocol;
  this->setPulseLength(nPulseLength);
}*/



/*
 * Sets pulse length in microseconds
 */
void setPulseLength(int nPulseLength) {
    rcPulseLength = nPulseLength;
}



/*
 * Sets Repeat Transmits
 */
void setRepeatTransmit(int nRepeatTransmit) {
    rcRepeatTransmit = nRepeatTransmit;
}



/*
 * Set Receiving Tolerance
 */
void setReceiveTolerance(int nPercent) {
    rcReceiveTolerance = nPercent;
}


/*
 * Enable transmissions
 *
 * @param nTransmitterPin    Pin to which the sender is connected to
 */
void enableTransmit(int nTransmitterPin) {
    rcTransmitterPin = nTransmitterPin;
    pinMode(rcTransmitterPin, OUTPUT);
}



/*
 * Disable transmissions
 */
void disableTransmit(void) {
    rcTransmitterPin = -1;
}



/*
 * 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 switchOn(int nAddressCode, int nChannelCode) {
    sendTriState( 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 switchOff(int nAddressCode, int nChannelCode) {
    sendTriState( 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] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"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] = { (char *)"00000", (char *)"10000", (char *)"01000", (char *)"00100", (char *)"00010", (char *)"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 *getCodeWordB(int nAddressCode, int nChannelCode, bool bStatus)
{
    int		i, nReturnPos = 0;
    static char sReturn[13];
   
    char* code[5] = { (char *)"FFFF", (char *)"0FFF", (char *)"F0FF", (char *)"FF0F", (char *)"FFF0" };
    if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
    	return '\0';
    }
    for (i = 0; i<4; i++) {
	sReturn[nReturnPos++] = code[nAddressCode][i];
    }

    for (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 *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 *getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus)
{
    static char sReturn[13];
    int		i, nReturnPos = 0;
  
    if ( (uint8_t)sFamily < 97 || (uint8_t)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 (i = 0; i<4; i++) {
    	sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i];
    }
    for (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 *getCodeWordD(char sGroup, int nDevice, bool bStatus){
    static char sReturn[13];
    int		i, 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 (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 (i = 0; i<3; i++)
        sReturn[nReturnPos++] = sDevice[i];

    // fill up rest with zeros
    for (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;

}



/*
 * @param sCodeWord   /^[10FS]*$/  -> see getCodeWord
 */
void sendTriState(char* sCodeWord) {
    int nRepeat;

    for (nRepeat = 0; nRepeat < rcRepeatTransmit; nRepeat++) {
	int i = 0;
	while (sCodeWord[i] != '\0') {
	    switch(sCodeWord[i]) {
		case '0':
			    sendT0();
			    break;
		case 'F':
			    sendTF();
			    break;
		case '1':
			    sendT1();
			    break;
	    }
	    i++;
	}
	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 transmit(int nHighPulses, int nLowPulses)
{
    bool	disabled_Receive = false;
    int		nReceiverInterrupt_backup = rcReceiverInterrupt;
    
    if (rcTransmitterPin != -1) {
        if (rcReceiverInterrupt != -1) {
            disableReceive();
            disabled_Receive = true;
        }
        digitalWrite(rcTransmitterPin, HIGH);
	delayMicroseconds( rcPulseLength * nHighPulses);
        digitalWrite(rcTransmitterPin, LOW);
	delayMicroseconds( rcPulseLength * nLowPulses);
        
        if (disabled_Receive) {
            enableReceiveIRQ(nReceiverInterrupt_backup);
        }
    }
}



/*
 * Sends a "0" Bit
 *                       _    
 * Waveform Protocol 1: | |___
 *                       _  
 * Waveform Protocol 2: | |__
 *                       ____
 * Waveform Protocol 3: |    |___________
 */
void send0(void) {
	if (rcProtocol == 1){
		transmit(1,3);
	}
	else if (rcProtocol == 2) {
		transmit(1,2);
	}
    else if (rcProtocol == 3) {
        transmit(4,11);
    }
}



/*
 * Sends a "1" Bit
 *                       ___  
 * Waveform Protocol 1: |   |_
 *                       __  
 * Waveform Protocol 2: |  |_
 *                       _________
 * Waveform Protocol 3: |         |______
 */
void send1(void) {
  	if (rcProtocol == 1){
		transmit(3,1);
	}
	else if (rcProtocol == 2) {
		transmit(2,1);
	}
    else if (rcProtocol == 3) {
        transmit(9,6);
    }
}



/*
 * Sends a Tri-State "0" Bit
 *            _     _
 * Waveform: | |___| |___
 */
void sendT0(void) {
    transmit(1,3);
    transmit(1,3);
}



/*
 * Sends a Tri-State "1" Bit
 *            ___   ___
 * Waveform: |   |_|   |_
 */
void sendT1(void) {
    transmit(3,1);
    transmit(3,1);
}



/*
 * Sends a Tri-State "F" Bit
 *            _     ___
 * Waveform: | |___|   |_
 */
void sendTF(void) {
    transmit(1,3);
    transmit(3,1);
}



/*
 * Sends a "Sync" Bit
 *                       _
 * Waveform Protocol 1: | |_______________________________
 *                       _
 * Waveform Protocol 2: | |__________
 *                       _
 * Waveform Protocol 3: | |_______________________________________________________________________
 */
void sendSync(void) {

    if (rcProtocol == 1){
		transmit(1,31);
	}
	else if (rcProtocol == 2) {
		transmit(1,10);
	}
    else if (rcProtocol == 3) {
        transmit(1,71);
    }
}



/*
 * Enable receiving data
 */
void enableReceiveIRQ(int interrupt) {
    rcReceiverInterrupt = interrupt;
    enableReceive();
}

void enableReceive(void) {
    if (rcReceiverInterrupt != -1) {
	rcReceivedValue = 0;
	rcReceivedBitlength = 0;
	wiringPiISR(rcReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt);
    }
}



/*
 * Disable receiving data
 */
void disableReceive() {
    // wiringPi disable interrupts ???
    rcReceiverInterrupt = -1;
}



bool available(void) {
    return rcReceivedValue != 0;
}



void resetAvailable(void) {
    rcReceivedValue = 0;
}



unsigned long getReceivedValue(void) {
    return rcReceivedValue;
}



unsigned int getReceivedBitlength(void) {
    return rcReceivedBitlength;
}



unsigned int getReceivedDelay(void) {
    return rcReceivedDelay;
}



unsigned int getReceivedProtocol(void) {
    return rcReceivedProtocol;
}



unsigned int* getReceivedRawdata(void) {
    return timings;
}



/*
 * ASK protool 1
 */
bool receiveProtocol1(unsigned int changeCount)
{
    unsigned long	code = 0;
    unsigned long	ldelay = timings[0] / 31;
    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
    int			i;

    for (i = 1; i<changeCount ; i=i+2) {
      
	if (timings[i] > ldelay-delayTolerance && 
	    timings[i] < ldelay+delayTolerance && 
	    timings[i+1] > ldelay*3-delayTolerance && 
	    timings[i+1] < ldelay*3+delayTolerance) {
      	    code = code << 1;
    	}  else if (timings[i] > ldelay*3-delayTolerance &&
		    timings[i] < ldelay*3+delayTolerance &&
		    timings[i+1] > ldelay-delayTolerance &&
		    timings[i+1] < ldelay+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
    	rcReceivedValue = code;
    	rcReceivedBitlength = changeCount / 2;
    	rcReceivedDelay = ldelay;
    	rcReceivedProtocol = 1;
    }

    if (code == 0) {
    	return false;
    }
    return true;
}



bool receiveProtocol2(unsigned int changeCount)
{
    unsigned long	code = 0;
    unsigned long	ldelay = timings[0] / 10;
    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
    int			i;

    for (i = 1; i<changeCount ; i=i+2) {
	if (timings[i] > ldelay-delayTolerance &&
	    timings[i] < ldelay+delayTolerance &&
	    timings[i+1] > ldelay*2-delayTolerance &&
	    timings[i+1] < ldelay*2+delayTolerance) {
            code = code << 1;
        } else if (timings[i] > ldelay*2-delayTolerance &&
		   timings[i] < ldelay*2+delayTolerance &&
		   timings[i+1] > ldelay-delayTolerance &&
		   timings[i+1] < ldelay+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
	rcReceivedValue = code;
	rcReceivedBitlength = changeCount / 2;
	rcReceivedDelay = ldelay;
	rcReceivedProtocol = 2;
    }

    if (code == 0) {
	return false;
    } 
    return true;
}



/*
 * Protocol 3 is used by BL35P02.
 */
bool receiveProtocol3(unsigned int changeCount)
{
    unsigned long	code = 0;
    unsigned long	ldelay = timings[0] / PROTOCOL3_SYNC_FACTOR;
    unsigned long	delayTolerance = ldelay * rcReceiveTolerance * 0.01;    
    int			i;

    for (i = 1; i<changeCount ; i=i+2) {
      
	if (timings[i]   > ldelay*PROTOCOL3_0_HIGH_CYCLES - delayTolerance &&
            timings[i]   < ldelay*PROTOCOL3_0_HIGH_CYCLES + delayTolerance &&
            timings[i+1] > ldelay*PROTOCOL3_0_LOW_CYCLES  - delayTolerance &&
            timings[i+1] < ldelay*PROTOCOL3_0_LOW_CYCLES  + delayTolerance) {
            code = code << 1;
        } else if (timings[i]   > ldelay*PROTOCOL3_1_HIGH_CYCLES - delayTolerance &&
                   timings[i]   < ldelay*PROTOCOL3_1_HIGH_CYCLES + delayTolerance &&
                   timings[i+1] > ldelay*PROTOCOL3_1_LOW_CYCLES  - delayTolerance &&
                   timings[i+1] < ldelay*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
        rcReceivedValue = code;
        rcReceivedBitlength = changeCount / 2;
        rcReceivedDelay = ldelay;
        rcReceivedProtocol = 3;
    }

    if (code == 0) {
    	return false;
    } 
    return true;
}



void handleInterrupt() {

  static unsigned int duration;
  static unsigned int changeCount;
  static unsigned long lastTime;
  static unsigned int repeatCount;

 
  long time = micros();
  duration = time - lastTime;

  if (duration > 5000 && duration > timings[0] - 200 && duration < 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;
  }
  timings[changeCount++] = duration;
  lastTime = time;  
}



/*
 * Turns a decimal value to its binary representation
 */
char *dec2binWzerofill(unsigned long Dec, unsigned int bitLength)
{
    return dec2binWcharfill(Dec, bitLength, '0');
}

char *dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill)
{
    static char		bin[64];
    unsigned int	i = 0, j;

    while (Dec > 0) {
    	bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
    	Dec = Dec >> 1;
    }

    for (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;
}


#endif

mercurial