Wed, 02 Jul 2014 17:57:06 +0200
Added unit command and list unit command
/***************************************************************************** * 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 "rc433.h" #ifdef HAVE_WIRINGPI_H #define TYPE_UNDEF 0 #define TYPE_MINIMUM 0 #define TYPE_A 1 #define TYPE_B 2 #define TYPE_C 3 #define TYPE_D 4 #define TYPE_E 3 // TODO: Which Protocol does REV use? #define TYPE_MAXIMUM 4 // Number of maximum High/Low changes per packet. // We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync #define RCSWITCH_MAX_CHANGES 67 // i.e. ProtocolCount + 1 (for TYPE_UNDEF) #define MAX_PROTOCOLS 5 #define PROTOCOL_A_SYNC_FACTOR 31 #define PROTOCOL_A_ZERO_FIRST_CYCLES 1 #define PROTOCOL_A_ZERO_SECOND_CYCLES 3 #define PROTOCOL_A_ONE_FIRST_CYCLES 3 #define PROTOCOL_A_ONE_SECOND_CYCLES 1 #define PROTOCOL_A_HIGH_FIRST true #define PROTOCOL_B_SYNC_FACTOR 10 #define PROTOCOL_B_ZERO_FIRST_CYCLES 1 #define PROTOCOL_B_ZERO_SECOND_CYCLES 2 #define PROTOCOL_B_ONE_FIRST_CYCLES 2 #define PROTOCOL_B_ONE_SECOND_CYCLES 1 #define PROTOCOL_B_HIGH_FIRST true #define PROTOCOL_C_SYNC_FACTOR 71 #define PROTOCOL_C_ZERO_FIRST_CYCLES 4 #define PROTOCOL_C_ZERO_SECOND_CYCLES 11 #define PROTOCOL_C_ONE_FIRST_CYCLES 9 #define PROTOCOL_C_ONE_SECOND_CYCLES 6 #define PROTOCOL_C_HIGH_FIRST true // I think, this will work for receive, however, I haven't tested, as I don't own a receiver... // As Type D doesn't sync acc. to https://github.com/d-a-n/433-codes/blob/master/database.md#quigg // the sync factor is totally undetermined. // Malte Diers, 22.11.2013 #define PROTOCOL_D_SYNC_FACTOR 1 #define PROTOCOL_D_ZERO_FIRST_CYCLES 1 #define PROTOCOL_D_ZERO_SECOND_CYCLES 2 #define PROTOCOL_D_ONE_FIRST_CYCLES 2 #define PROTOCOL_D_ONE_SECOND_CYCLES 1 #define PROTOCOL_D_HIGH_FIRST false #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 unsigned long rcReceivedValue = 0; unsigned int rcReceivedBitlength = 0; unsigned int rcReceivedDelay = 0; unsigned int rcReceivedProtocol = 0; int rcReceiveTolerance = 60; int rcReceiverInterruptPin = -1; unsigned int timings[RCSWITCH_MAX_CHANGES]; int rcTransmitterPin = -1; int rcPulseLength = 350; // thermometers 2.4 msec = 2400 int rcRepeatTransmit = 10; int rcProtocol = 1; int backupProtocol; int backupPulseLength; int backupRepeatTransmit; //const char TYPE_A_CODE[ 6][6] = { "00000", "10000", "01000", "00100", "00010", "00001"}; const char TYPE_B_CODE[ 5][5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" }; const char TYPE_C_CODE[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" }; const char TYPE_D_CODE[5][2][9] = { { "11100001", "11110000" }, { "00000000", "00010001" }, { "10000010", "10010011" }, { "11000011", "11010010" }, { "01000001", "01010000" } }; /* Type A Type D */ const int PULSE_LENGTH[MAX_PROTOCOLS] = { 0, 350, 650, 100, 666, }; const int REPEAT_TRANSMIT[MAX_PROTOCOLS] = { 0, 10, 10, 10, 4, }; const int SYNC_FACTOR[MAX_PROTOCOLS] = { 0, PROTOCOL_A_SYNC_FACTOR, PROTOCOL_B_SYNC_FACTOR, PROTOCOL_C_SYNC_FACTOR, PROTOCOL_D_SYNC_FACTOR, }; const int ZERO_FIRST_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_FIRST_CYCLES, PROTOCOL_B_ZERO_FIRST_CYCLES, PROTOCOL_C_ZERO_FIRST_CYCLES, PROTOCOL_D_ZERO_FIRST_CYCLES, }; const int ZERO_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ZERO_SECOND_CYCLES, PROTOCOL_B_ZERO_SECOND_CYCLES, PROTOCOL_C_ZERO_SECOND_CYCLES, PROTOCOL_D_ZERO_SECOND_CYCLES, }; const int ONE_FIRST_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_FIRST_CYCLES, PROTOCOL_B_ONE_FIRST_CYCLES, PROTOCOL_C_ONE_FIRST_CYCLES, PROTOCOL_D_ONE_FIRST_CYCLES, }; const int ONE_SECOND_CYCLES[MAX_PROTOCOLS] = { 0, PROTOCOL_A_ONE_SECOND_CYCLES, PROTOCOL_B_ONE_SECOND_CYCLES, PROTOCOL_C_ONE_SECOND_CYCLES, PROTOCOL_D_ONE_SECOND_CYCLES, }; const bool HIGH_FIRST[MAX_PROTOCOLS] = { 0, PROTOCOL_A_HIGH_FIRST, PROTOCOL_B_HIGH_FIRST, PROTOCOL_C_HIGH_FIRST, PROTOCOL_D_HIGH_FIRST, }; char *getCodeWordA(char*, char*, bool); char *getCodeWordB(int, int, bool); char *getCodeWordC(char, int, int, bool); char *getCodeWordE(char, int, bool); void sendTriState(char*); void transmit(int, int, bool); void send0(void); void send1(void); void sendT0(void); void sendT1(void); void sendTF(void); void sendSync(void); bool receiveProtocol(int, unsigned int); void handleInterrupt(void); char *dec2binWcharfill(unsigned long, unsigned int, char); void setReceiveTolerance(int); void setProtocol(int); void saveProtocol(int); void loadProtocol(void); /* * Sets the protocol to send. */ void setProtocol(int nProtocol) { if ((nProtocol < TYPE_MINIMUM) || (nProtocol > TYPE_MAXIMUM)) { return; } rcProtocol = nProtocol; rcPulseLength = PULSE_LENGTH[nProtocol]; rcRepeatTransmit = REPEAT_TRANSMIT[nProtocol]; } /* * 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; } /* * Toggle switch, a command looks like B,3,2,1 which means switch type B, * group 3, device 2, status on. */ int toggleSwitch(char *command) { static char *cmd = NULL; char *s, cType; int rc, iGroup, iDevice, iState; cmd = xstrcpy(command); s = strtok(cmd, ",\0"); cType = s[0]; if (cType == 'A') { } else if (cType == 'B') { s = strtok(NULL, ",\0"); rc = sscanf(s, "%d", &iGroup); if (rc != 1) return 1; s = strtok(NULL, ",\0"); rc = sscanf(s, "%d", &iDevice); if (rc != 1) return 1; s = strtok(NULL, ",\0"); rc = sscanf(s, "%d", &iState); if (rc != 1) return 1; free(cmd); return toggleTypeB(iGroup, iDevice, iState); } free(cmd); return 1; } /* * Switch a remote switch on (Type E REV) * * @param sGroup Code of the switch group (A,B,C,D) * @param nDevice Number of the switch itself (1..3) * @param bStatus Status to toggle to */ int toggleTypeE(char sGroup, int nDevice, bool bStatus) { sendTriState( getCodeWordE(sGroup, nDevice, bStatus) ); return 0; } /* * 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) * @param bStatus Status to toggle to */ int toggleTypeC(char sFamily, int nGroup, int nDevice, bool bStatus) { char *str = xstrcpy(getCodeWordC(sFamily, nGroup, nDevice, bStatus)); if (strlen(str) == 0) return 1; saveProtocol(TYPE_A); // ??? sendTriState( str ); loadProtocol(); free(str); return 0; } /* * Switch a remote switch on/off (Type B with two rotary/sliding switches) * * @param iGroup Number of the switch group (1..4) * @param iDevice Number of the switch itself (1..4) * @param bStatus Status to toggle to */ int toggleTypeB(int iGroup, int iDevice, bool bStatus) { char *str = xstrcpy(getCodeWordB(iGroup, iDevice, bStatus)); if (strlen(str) == 0) return 1; saveProtocol(TYPE_A); // They do better with protocol A timings. sendTriState( str ); loadProtocol(); free(str); return 0; } /* * 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") * @param bStatus Status to toggle to */ int toggleTypeA(char* sGroup, char* sDevice, bool bStatus) { char *str = xstrcpy(getCodeWordA(sGroup, sDevice, bStatus)); if (strlen(str) == 0) return 1; saveProtocol(TYPE_A); sendTriState( str ); loadProtocol(); free(str); return 0; } /* * 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]; if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) { return '\0'; } for (i = 0; i<4; i++) { sReturn[nReturnPos++] = TYPE_B_CODE[nAddressCode][i]; } for (i = 0; i<4; i++) { sReturn[nReturnPos++] = TYPE_B_CODE[nChannelCode][i]; } sReturn[nReturnPos++] = 'F'; sReturn[nReturnPos++] = 'F'; sReturn[nReturnPos++] = 'F'; sReturn[nReturnPos++] = bStatus ? 'F' : '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, j = 0; for (i=0; i < 5; i++) { sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0'; } for (i=0; i < 5; i++) { sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '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 (sFamily < 'a') { // To also enable capital 'A' to 'F' sFamily += 32; } if ( sFamily < 'a' || sFamily > 'f' || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) { return '\0'; } for (i = 0; i<4; i++) { sReturn[nReturnPos++] = TYPE_C_CODE[ sFamily - 'a' ][i]; } char *sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 ); for (i = 0; i<4; i++) { sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0'); } sReturn[nReturnPos++] = '0'; sReturn[nReturnPos++] = 'F'; sReturn[nReturnPos++] = 'F'; sReturn[nReturnPos++] = bStatus ? 'F' : '0'; sReturn[nReturnPos] = '\0'; return sReturn; } /* * Decoding for the Quigg Switch Type * * Returns a char[22], representing the States to be send. * A Code Word consists of 1 start bit, 12 address bits and 8 command data bits. * A Code Bit can have 2 different states: "0" (low), "1" (high) * * +--------------+--------------------------------+------------------------------+ * | 1 bits start | 12 bits address (device group) | 8 bits (command/switch data) | * | 1 | 110011001100 | 00010001 | * +--------------+--------------------------------+------------------------------+ * * Source: https://github.com/d-a-n/433-codes/blob/master/database.md#quigg * * @param sGroup 12-bit Binary ID of the Device Group * @param nDevice Number of the switch itself (1..4, or 0 to switch the entire Group) * @param bStatus Wether to switch on (true) or off (false) * * @return char[22] */ char *getCodeWordD(char *sGroup, int nDevice, bool bStatus) { static char sReturn[22]; int i, nReturnPos = 0; /* Startbit */ sReturn[nReturnPos++] = '1'; /* 12 bit Group */ for (i = 0; i < 12; ++i) { sReturn[nReturnPos++] = sGroup[i]; } /* 8 Bit Device Identifier + Status (undividable!) */ for (i = 0; i < 8; ++i) { sReturn[nReturnPos++] = TYPE_D_CODE[nDevice][bStatus][i]; } 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 *getCodeWordE(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 nFirstPulses, int nSecondPulses, bool bHighFirst) { bool disabled_Receive = false; int nReceiverInterrupt_backup = rcReceiverInterruptPin; if (rcTransmitterPin != -1) { if (rcReceiverInterruptPin != -1) { disableReceive(); disabled_Receive = true; } digitalWrite(rcTransmitterPin, bHighFirst ? HIGH : LOW); delayMicroseconds( rcPulseLength * nFirstPulses); digitalWrite(rcTransmitterPin, bHighFirst ? LOW : HIGH); delayMicroseconds( rcPulseLength * nSecondPulses); 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(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); // transmit(1,3,true); // transmit(1,3,true); } /* * Sends a Tri-State "1" Bit * ___ ___ * Waveform: | |_| |_ */ void sendT1(void) { transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); // transmit(3,1,true); // transmit(3,1,true); } /* * Sends a Tri-State "F" Bit * _ ___ * Waveform: | |___| |_ */ void sendTF(void) { transmit(ZERO_FIRST_CYCLES[rcProtocol], ZERO_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); transmit(ONE_FIRST_CYCLES[rcProtocol], ONE_SECOND_CYCLES[rcProtocol], HIGH_FIRST[rcProtocol]); // transmit(1,3,true); // transmit(3,1,true); } /* * Sends a "Sync" Bit * _ * Waveform Protocol 1: | |_______________________________ * _ * Waveform Protocol 2: | |__________ * ____ * Waveform Protocol 3: | |_______________________________________________________________________ * * Waveform Protocol D: (none, just pause 80 msecs) */ void sendSync(void) { if (rcProtocol == TYPE_A) { transmit(1,31,true); } else if (rcProtocol == TYPE_B) { transmit(1,10,true); } else if (rcProtocol == TYPE_C) { transmit(4,71,true); } else if (rcProtocol == TYPE_D) { transmit(0,1,false); delayMicroseconds(80000); } } /* * Enable receiving data */ void enableReceiveIRQ(int Pin) { rcReceiverInterruptPin = Pin; enableReceive(); } void enableReceive(void) { if (rcReceiverInterruptPin != -1) { rcReceivedValue = 0; rcReceivedBitlength = 0; wiringPiISR(rcReceiverInterruptPin, INT_EDGE_BOTH, &handleInterrupt); } } /* * Disable receiving data */ void disableReceive() { // wiringPi disable interrupts ??? rcReceiverInterruptPin = -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 receiveProtocol(int prot, unsigned int changeCount) { unsigned long code = 0; unsigned long ldelay = timings[0] / SYNC_FACTOR[prot]; unsigned long delayTolerance = ldelay * rcReceiveTolerance * 0.01; int i; if (prot < TYPE_MINIMUM || prot > TYPE_MAXIMUM) { return false; } for (i = 1; i<changeCount ; i=i+2) { if (timings[i] > ldelay * ZERO_FIRST_CYCLES[prot] - delayTolerance && timings[i] < ldelay * ZERO_FIRST_CYCLES[prot] + delayTolerance && timings[i+1] > ldelay * ZERO_SECOND_CYCLES[prot] - delayTolerance && timings[i+1] < ldelay * ZERO_SECOND_CYCLES[prot] + delayTolerance) { code = code << 1; } else if (timings[i] > ldelay * ONE_FIRST_CYCLES[prot] - delayTolerance && timings[i] < ldelay * ONE_FIRST_CYCLES[prot] + delayTolerance && timings[i+1] > ldelay * ONE_SECOND_CYCLES[prot] - delayTolerance && timings[i+1] < ldelay * ONE_SECOND_CYCLES[prot] + 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 = prot; } return (code != 0); } void handleInterrupt() { static unsigned int duration; static unsigned int changeCount; static unsigned long lastTime; static unsigned int repeatCount; long thistime = micros(); duration = thistime - lastTime; if (duration > 5000 && duration > timings[0] - 200 && duration < timings[0] + 200) { repeatCount++; changeCount--; if (repeatCount == 2) { if (receiveProtocol(TYPE_A, changeCount) == false) { if (receiveProtocol(TYPE_B, changeCount) == false) { if (receiveProtocol(TYPE_C, changeCount) == false) { if (receiveProtocol(TYPE_D, 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 = thistime; } /* * 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; } void saveProtocol(int prot) { backupProtocol = rcProtocol; backupPulseLength = rcPulseLength; backupRepeatTransmit = rcRepeatTransmit; setProtocol(prot); } void loadProtocol(void) { rcProtocol = backupProtocol; rcPulseLength = backupPulseLength; rcRepeatTransmit = backupRepeatTransmit; } #endif