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>"); }