Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /* ======================= .h =============================== */
- /*
- RCSwitch - Arduino libary for remote control outlet switches
- Copyright (c) 2011 Suat Özgür. All right reserved.
- Contributors:
- - Andre Koehler / info(at)tomate-online(dot)de
- - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
- - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
- - Dominik Fischer / dom_fischer(at)web(dot)de
- - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
- Project home: http://code.google.com/p/rc-switch/
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- #ifndef _RCSwitch_h
- #define _RCSwitch_h
- // https://community.sparkdevices.com/t/fix-for-include-arduino-h/953
- #define ARDUINO_H
- #include <stdint.h>
- #include <stddef.h>
- #include <stdlib.h>
- // to make it compile (by Frido)
- #define boolean bool
- #pragma GCC diagnostic ignored "-Wwrite-strings"
- #pragma GCC diagnostic ignored "-Wconversion-null"
- #pragma GCC diagnostic ignored "-Wpointer-arith"
- #pragma GCC diagnostic ignored "-Wsign-compare"
- #pragma GCC diagnostic ignored "-Wreturn-type"
- /*
- #if defined(ARDUINO) && ARDUINO >= 100
- #include "Arduino.h"
- #elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
- #include "Energia.h"
- #else
- #include "WProgram.h"
- #endif
- // At least for the ATTiny X4/X5, receiving has to be disabled due to
- // missing libm depencies (udivmodhi4)
- #if defined( __AVR_ATtinyX5__ ) or defined ( __AVR_ATtinyX4__ )
- #define RCSwitchDisableReceiving
- #endif
- */
- // 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
- #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:
- 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(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(char sGroup, int nDevice);
- void switchOff(char sGroup, int nDevice);
- void sendTriState(char* Code);
- void send(unsigned long Code, unsigned int length);
- void send(char* Code);
- #if not defined( RCSwitchDisableReceiving )
- void enableReceive(int interrupt);
- void enableReceive();
- void disableReceive();
- bool available();
- void resetAvailable();
- unsigned long getReceivedValue();
- unsigned int getReceivedBitlength();
- unsigned int getReceivedDelay();
- unsigned int getReceivedProtocol();
- unsigned int* getReceivedRawdata();
- #endif
- void enableTransmit(int nTransmitterPin);
- void disableTransmit();
- void setPulseLength(int nPulseLength);
- void setRepeatTransmit(int nRepeatTransmit);
- #if not defined( RCSwitchDisableReceiving )
- void setReceiveTolerance(int nPercent);
- #endif
- 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* getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus);
- char* getCodeWordD(char group, int nDevice, boolean bStatus);
- void sendT0();
- void sendT1();
- void sendTF();
- void send0();
- void send1();
- void sendSync();
- void transmit(int nHighPulses, int nLowPulses);
- 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);
- int nReceiverInterrupt;
- #endif
- int nTransmitterPin;
- int nPulseLength;
- int nRepeatTransmit;
- char nProtocol;
- #if not defined( RCSwitchDisableReceiving )
- static int nReceiveTolerance;
- static unsigned long nReceivedValue;
- static unsigned int nReceivedBitlength;
- static unsigned int nReceivedDelay;
- static unsigned int nReceivedProtocol;
- #endif
- /*
- * timings[0] contains sync timing, followed by a number of bits
- */
- static unsigned int timings[RCSWITCH_MAX_CHANGES];
- };
- #endif
- /* ========================= .cpp ================================= */
- /*
- RCSwitch - Arduino libary for remote control outlet switches
- Copyright (c) 2011 Suat Özgür. All right reserved.
- Contributors:
- - Andre Koehler / info(at)tomate-online(dot)de
- - Gordeev Andrey Vladimirovich / gordeev(at)openpyro(dot)com
- - Skineffect / http://forum.ardumote.com/viewtopic.php?f=2&t=46
- - Dominik Fischer / dom_fischer(at)web(dot)de
- - Frank Oltmanns / <first name>.<last name>(at)gmail(dot)com
- - Andreas Steinel / A.<lastname>(at)gmail(dot)com
- Project home: http://code.google.com/p/rc-switch/
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 2.1 of the License, or (at your option) any later version.
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Lesser General Public License for more details.
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
- */
- // #include "RCSwitch.h"
- #if not defined( RCSwitchDisableReceiving )
- unsigned long RCSwitch::nReceivedValue = NULL;
- unsigned int RCSwitch::nReceivedBitlength = 0;
- unsigned int RCSwitch::nReceivedDelay = 0;
- unsigned int RCSwitch::nReceivedProtocol = 0;
- int RCSwitch::nReceiveTolerance = 60;
- #endif
- unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
- 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;
- #endif
- }
- /**
- * Sets the protocol to send.
- */
- 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);
- }
- }
- /**
- * 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 RCSwitch::setPulseLength(int nPulseLength) {
- this->nPulseLength = nPulseLength;
- }
- /**
- * Sets Repeat Transmits
- */
- void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
- this->nRepeatTransmit = nRepeatTransmit;
- }
- /**
- * Set Receiving Tolerance
- */
- #if not defined( RCSwitchDisableReceiving )
- void RCSwitch::setReceiveTolerance(int nPercent) {
- RCSwitch::nReceiveTolerance = nPercent;
- }
- #endif
- /**
- * Enable transmissions
- *
- * @param nTransmitterPin Arduino Pin to which the sender is connected to
- */
- void RCSwitch::enableTransmit(int nTransmitterPin) {
- this->nTransmitterPin = nTransmitterPin;
- pinMode(this->nTransmitterPin, OUTPUT);
- }
- /**
- * Disable transmissions
- */
- void RCSwitch::disableTransmit() {
- this->nTransmitterPin = -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 RCSwitch::switchOn(int nAddressCode, int nChannelCode) {
- this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, true) );
- }
- /**
- * Switch a remote switch off (Type B with two rotary/sliding switches)
- *
- * @param nAddressCode Number of the switch group (1..4)
- * @param nChannelCode Number of the switch itself (1..4)
- */
- void RCSwitch::switchOff(int nAddressCode, int nChannelCode) {
- this->sendTriState( this->getCodeWordB(nAddressCode, nChannelCode, false) );
- }
- /**
- * Deprecated, use switchOn(char* sGroup, char* sDevice) instead!
- * Switch a remote switch on (Type A with 10 pole DIP switches)
- *
- * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param nChannelCode Number of the switch itself (1..5)
- */
- void RCSwitch::switchOn(char* sGroup, int nChannel) {
- char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
- this->switchOn(sGroup, code[nChannel]);
- }
- /**
- * Deprecated, use switchOff(char* sGroup, char* sDevice) instead!
- * Switch a remote switch off (Type A with 10 pole DIP switches)
- *
- * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param nChannelCode Number of the switch itself (1..5)
- */
- void RCSwitch::switchOff(char* sGroup, int nChannel) {
- char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
- this->switchOff(sGroup, code[nChannel]);
- }
- /**
- * Switch a remote switch on (Type A with 10 pole DIP switches)
- *
- * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- */
- void RCSwitch::switchOn(char* sGroup, char* sDevice) {
- this->sendTriState( this->getCodeWordA(sGroup, sDevice, true) );
- }
- /**
- * Switch a remote switch off (Type A with 10 pole DIP switches)
- *
- * @param sGroup Code of the switch group (refers to DIP switches 1..5 where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- * @param sDevice Code of the switch device (refers to DIP switches 6..10 (A..E) where "1" = on and "0" = off, if all DIP switches are on it's "11111")
- */
- void RCSwitch::switchOff(char* sGroup, char* sDevice) {
- this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
- }
- /**
- * Returns a char[13], representing the Code Word to be send.
- * A Code Word consists of 9 address bits, 3 data bits and one sync bit but in our case only the first 8 address bits and the last 2 data bits were used.
- * A Code Bit can have 4 different states: "F" (floating), "0" (low), "1" (high), "S" (synchronous bit)
- *
- * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
- * | 4 bits address (switch group) | 4 bits address (switch number) | 1 bit address (not used, so never mind) | 1 bit address (not used, so never mind) | 2 data bits (on|off) | 1 sync bit |
- * | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | F | F | on=FF off=F0 | S |
- * +-------------------------------+--------------------------------+-----------------------------------------+-----------------------------------------+----------------------+------------+
- *
- * @param nAddressCode Number of the switch group (1..4)
- * @param nChannelCode Number of the switch itself (1..4)
- * @param bStatus Wether to switch on (true) or off (false)
- *
- * @return char[13]
- */
- char* RCSwitch::getCodeWordB(int nAddressCode, int nChannelCode, boolean bStatus) {
- int nReturnPos = 0;
- static char sReturn[13];
- char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
- if (nAddressCode < 1 || nAddressCode > 4 || nChannelCode < 1 || nChannelCode > 4) {
- return '\0';
- }
- for (int i = 0; i<4; i++) {
- sReturn[nReturnPos++] = code[nAddressCode][i];
- }
- for (int i = 0; i<4; i++) {
- sReturn[nReturnPos++] = code[nChannelCode][i];
- }
- sReturn[nReturnPos++] = 'F';
- sReturn[nReturnPos++] = 'F';
- sReturn[nReturnPos++] = 'F';
- if (bStatus) {
- sReturn[nReturnPos++] = 'F';
- } else {
- sReturn[nReturnPos++] = '0';
- }
- sReturn[nReturnPos] = '\0';
- return sReturn;
- }
- /**
- * Returns a char[13], representing the Code Word to be send.
- *
- * getCodeWordA(char*, char*)
- *
- */
- char* RCSwitch::getCodeWordA(char* sGroup, char* sDevice, 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++) {
- if (sDevice[i] == '0') {
- sDipSwitches[j++] = 'F';
- } else {
- sDipSwitches[j++] = '0';
- }
- }
- if ( bOn ) {
- sDipSwitches[j++] = '0';
- sDipSwitches[j++] = 'F';
- } else {
- sDipSwitches[j++] = 'F';
- sDipSwitches[j++] = '0';
- }
- sDipSwitches[j] = '\0';
- return sDipSwitches;
- }
- /**
- * Like getCodeWord (Type C = Intertechno)
- */
- char* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, boolean bStatus) {
- static char sReturn[13];
- int nReturnPos = 0;
- if ( (byte)sFamily < 97 || (byte)sFamily > 112 || nGroup < 1 || nGroup > 4 || nDevice < 1 || nDevice > 4) {
- return '\0';
- }
- char* sDeviceGroupCode = dec2binWzerofill( (nDevice-1) + (nGroup-1)*4, 4 );
- char familycode[16][5] = { "0000", "F000", "0F00", "FF00", "00F0", "F0F0", "0FF0", "FFF0", "000F", "F00F", "0F0F", "FF0F", "00FF", "F0FF", "0FFF", "FFFF" };
- for (int i = 0; i<4; i++) {
- sReturn[nReturnPos++] = familycode[ (int)sFamily - 97 ][i];
- }
- for (int i = 0; i<4; i++) {
- sReturn[nReturnPos++] = (sDeviceGroupCode[3-i] == '1' ? 'F' : '0');
- }
- sReturn[nReturnPos++] = '0';
- sReturn[nReturnPos++] = 'F';
- sReturn[nReturnPos++] = 'F';
- if (bStatus) {
- sReturn[nReturnPos++] = 'F';
- } else {
- sReturn[nReturnPos++] = '0';
- }
- sReturn[nReturnPos] = '\0';
- return sReturn;
- }
- /**
- * Decoding for the REV Switch Type
- *
- * Returns a char[13], representing the Tristate to be send.
- * A Code Word consists of 7 address bits and 5 command data bits.
- * A Code Bit can have 3 different states: "F" (floating), "0" (low), "1" (high)
- *
- * +-------------------------------+--------------------------------+-----------------------+
- * | 4 bits address (switch group) | 3 bits address (device number) | 5 bits (command data) |
- * | A=1FFF B=F1FF C=FF1F D=FFF1 | 1=0FFF 2=F0FF 3=FF0F 4=FFF0 | on=00010 off=00001 |
- * +-------------------------------+--------------------------------+-----------------------+
- *
- * Source: http://www.the-intruder.net/funksteckdosen-von-rev-uber-arduino-ansteuern/
- *
- * @param sGroup Name of the switch group (A..D, resp. a..d)
- * @param nDevice Number of the switch itself (1..3)
- * @param bStatus Wether to switch on (true) or off (false)
- *
- * @return char[13]
- */
- char* RCSwitch::getCodeWordD(char sGroup, int nDevice, boolean bStatus){
- static char sReturn[13];
- int nReturnPos = 0;
- // Building 4 bits address
- // (Potential problem if dec2binWcharfill not returning correct string)
- char *sGroupCode;
- switch(sGroup){
- case 'a':
- case 'A':
- sGroupCode = dec2binWcharfill(8, 4, 'F'); break;
- case 'b':
- case 'B':
- sGroupCode = dec2binWcharfill(4, 4, 'F'); break;
- case 'c':
- case 'C':
- sGroupCode = dec2binWcharfill(2, 4, 'F'); break;
- case 'd':
- case 'D':
- sGroupCode = dec2binWcharfill(1, 4, 'F'); break;
- default:
- return '\0';
- }
- for (int i = 0; i<4; i++)
- {
- sReturn[nReturnPos++] = sGroupCode[i];
- }
- // Building 3 bits address
- // (Potential problem if dec2binWcharfill not returning correct string)
- char *sDevice;
- switch(nDevice) {
- case 1:
- sDevice = dec2binWcharfill(4, 3, 'F'); break;
- case 2:
- sDevice = dec2binWcharfill(2, 3, 'F'); break;
- case 3:
- sDevice = dec2binWcharfill(1, 3, 'F'); break;
- default:
- return '\0';
- }
- for (int i = 0; i<3; i++)
- sReturn[nReturnPos++] = sDevice[i];
- // fill up rest with zeros
- for (int i = 0; i<5; i++)
- sReturn[nReturnPos++] = '0';
- // encode on or off
- if (bStatus)
- sReturn[10] = '1';
- else
- sReturn[11] = '1';
- // last position terminate string
- sReturn[12] = '\0';
- return sReturn;
- }
- /**
- * @param sCodeWord /^[10FS]*$/ -> see getCodeWord
- */
- void RCSwitch::sendTriState(char* sCodeWord) {
- for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
- int i = 0;
- while (sCodeWord[i] != '\0') {
- switch(sCodeWord[i]) {
- case '0':
- this->sendT0();
- break;
- case 'F':
- this->sendTF();
- break;
- case '1':
- this->sendT1();
- break;
- }
- i++;
- }
- this->sendSync();
- }
- }
- void RCSwitch::send(unsigned long Code, unsigned int length) {
- this->send( this->dec2binWzerofill(Code, length) );
- }
- void RCSwitch::send(char* sCodeWord) {
- for (int nRepeat=0; nRepeat<nRepeatTransmit; nRepeat++) {
- int i = 0;
- while (sCodeWord[i] != '\0') {
- switch(sCodeWord[i]) {
- case '0':
- this->send0();
- break;
- case '1':
- this->send1();
- break;
- }
- i++;
- }
- this->sendSync();
- }
- }
- void RCSwitch::transmit(int nHighPulses, int nLowPulses) {
- #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) {
- this->disableReceive();
- disabled_Receive = true;
- }
- #endif
- digitalWrite(this->nTransmitterPin, HIGH);
- delayMicroseconds( this->nPulseLength * nHighPulses);
- digitalWrite(this->nTransmitterPin, LOW);
- delayMicroseconds( this->nPulseLength * nLowPulses);
- #if not defined( RCSwitchDisableReceiving )
- if(disabled_Receive){
- this->enableReceive(nReceiverInterrupt_backup);
- }
- #endif
- }
- }
- /**
- * Sends a "0" Bit
- * _
- * Waveform Protocol 1: | |___
- * _
- * Waveform Protocol 2: | |__
- */
- void RCSwitch::send0() {
- if (this->nProtocol == 1){
- this->transmit(1,3);
- }
- else if (this->nProtocol == 2) {
- this->transmit(1,2);
- }
- else if (this->nProtocol == 3) {
- this->transmit(4,11);
- }
- }
- /**
- * Sends a "1" Bit
- * ___
- * Waveform Protocol 1: | |_
- * __
- * Waveform Protocol 2: | |_
- */
- void RCSwitch::send1() {
- if (this->nProtocol == 1){
- this->transmit(3,1);
- }
- else if (this->nProtocol == 2) {
- this->transmit(2,1);
- }
- else if (this->nProtocol == 3) {
- this->transmit(9,6);
- }
- }
- /**
- * Sends a Tri-State "0" Bit
- * _ _
- * Waveform: | |___| |___
- */
- void RCSwitch::sendT0() {
- this->transmit(1,3);
- this->transmit(1,3);
- }
- /**
- * Sends a Tri-State "1" Bit
- * ___ ___
- * Waveform: | |_| |_
- */
- void RCSwitch::sendT1() {
- this->transmit(3,1);
- this->transmit(3,1);
- }
- /**
- * Sends a Tri-State "F" Bit
- * _ ___
- * Waveform: | |___| |_
- */
- void RCSwitch::sendTF() {
- this->transmit(1,3);
- this->transmit(3,1);
- }
- /**
- * Sends a "Sync" Bit
- * _
- * Waveform Protocol 1: | |_______________________________
- * _
- * Waveform Protocol 2: | |__________
- */
- void RCSwitch::sendSync() {
- if (this->nProtocol == 1){
- this->transmit(1,31);
- }
- else if (this->nProtocol == 2) {
- this->transmit(1,10);
- }
- else if (this->nProtocol == 3) {
- this->transmit(1,71);
- }
- }
- #if not defined( RCSwitchDisableReceiving )
- /**
- * Enable receiving data
- */
- void RCSwitch::enableReceive(int interrupt) {
- this->nReceiverInterrupt = interrupt;
- this->enableReceive();
- }
- void RCSwitch::enableReceive() {
- if (this->nReceiverInterrupt != -1) {
- RCSwitch::nReceivedValue = NULL;
- RCSwitch::nReceivedBitlength = NULL;
- attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
- }
- }
- /**
- * Disable receiving data
- */
- void RCSwitch::disableReceive() {
- detachInterrupt(this->nReceiverInterrupt);
- this->nReceiverInterrupt = -1;
- }
- bool RCSwitch::available() {
- return RCSwitch::nReceivedValue != NULL;
- }
- void RCSwitch::resetAvailable() {
- RCSwitch::nReceivedValue = NULL;
- }
- unsigned long RCSwitch::getReceivedValue() {
- return RCSwitch::nReceivedValue;
- }
- unsigned int RCSwitch::getReceivedBitlength() {
- return RCSwitch::nReceivedBitlength;
- }
- unsigned int RCSwitch::getReceivedDelay() {
- return RCSwitch::nReceivedDelay;
- }
- unsigned int RCSwitch::getReceivedProtocol() {
- return RCSwitch::nReceivedProtocol;
- }
- unsigned int* RCSwitch::getReceivedRawdata() {
- return RCSwitch::timings;
- }
- /**
- *
- */
- bool RCSwitch::receiveProtocol1(unsigned int changeCount){
- unsigned long code = 0;
- unsigned long delay = RCSwitch::timings[0] / 31;
- unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;
- for (int i = 1; i<changeCount ; i=i+2) {
- if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*3-delayTolerance && RCSwitch::timings[i+1] < delay*3+delayTolerance) {
- code = code << 1;
- } else if (RCSwitch::timings[i] > delay*3-delayTolerance && RCSwitch::timings[i] < delay*3+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
- code+=1;
- code = code << 1;
- } else {
- // Failed
- i = changeCount;
- code = 0;
- }
- }
- code = code >> 1;
- if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise
- RCSwitch::nReceivedValue = code;
- RCSwitch::nReceivedBitlength = changeCount / 2;
- RCSwitch::nReceivedDelay = delay;
- RCSwitch::nReceivedProtocol = 1;
- }
- if (code == 0){
- return false;
- }else if (code != 0){
- return true;
- }
- }
- bool RCSwitch::receiveProtocol2(unsigned int changeCount){
- unsigned long code = 0;
- unsigned long delay = RCSwitch::timings[0] / 10;
- unsigned long delayTolerance = delay * RCSwitch::nReceiveTolerance * 0.01;
- for (int i = 1; i<changeCount ; i=i+2) {
- if (RCSwitch::timings[i] > delay-delayTolerance && RCSwitch::timings[i] < delay+delayTolerance && RCSwitch::timings[i+1] > delay*2-delayTolerance && RCSwitch::timings[i+1] < delay*2+delayTolerance) {
- code = code << 1;
- } else if (RCSwitch::timings[i] > delay*2-delayTolerance && RCSwitch::timings[i] < delay*2+delayTolerance && RCSwitch::timings[i+1] > delay-delayTolerance && RCSwitch::timings[i+1] < delay+delayTolerance) {
- code+=1;
- code = code << 1;
- } else {
- // Failed
- i = changeCount;
- code = 0;
- }
- }
- code = code >> 1;
- if (changeCount > 6) { // ignore < 4bit values as there are no devices sending 4bit values => noise
- RCSwitch::nReceivedValue = code;
- RCSwitch::nReceivedBitlength = changeCount / 2;
- 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;
- }
- if (code == 0){
- return false;
- }else if (code != 0){
- return true;
- }
- }
- void RCSwitch::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 > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {
- repeatCount++;
- changeCount--;
- if (repeatCount == 2) {
- if (receiveProtocol1(changeCount) == false){
- if (receiveProtocol2(changeCount) == false){
- if (receiveProtocol3(changeCount) == false){
- //failed
- }
- }
- }
- repeatCount = 0;
- }
- changeCount = 0;
- } else if (duration > 5000) {
- changeCount = 0;
- }
- if (changeCount >= RCSWITCH_MAX_CHANGES) {
- changeCount = 0;
- repeatCount = 0;
- }
- RCSwitch::timings[changeCount++] = duration;
- lastTime = time;
- }
- /**
- * Turns a decimal value to its binary representation
- */
- char* RCSwitch::dec2binWzerofill(unsigned long Dec, unsigned int bitLength){
- return dec2binWcharfill(Dec, bitLength, '0');
- }
- char* RCSwitch::dec2binWcharfill(unsigned long Dec, unsigned int bitLength, char fill){
- static char bin[64];
- unsigned int i=0;
- while (Dec > 0) {
- bin[32+i++] = ((Dec & 1) > 0) ? '1' : fill;
- Dec = Dec >> 1;
- }
- for (unsigned int j = 0; j< bitLength; j++) {
- if (j >= bitLength - i) {
- bin[j] = bin[ 31 + i - (j - (bitLength - i)) ];
- }else {
- bin[j] = fill;
- }
- }
- bin[bitLength] = '\0';
- return bin;
- }
- #endif
- /* ======================== MAIN =========================== */
- /*
- Example for outlets which are configured with a 10 pole DIP switch.
- http://code.google.com/p/rc-switch/
- Need help? http://forum.ardumote.com
- */
- RCSwitch mySwitch = RCSwitch();
- void setup() {
- // Transmitter is connected to Arduino Pin #10
- mySwitch.enableTransmit(D7);
- // Optional set pulse length.
- // mySwitch.setPulseLength(320);
- }
- void loop() {
- // Switch on:
- // The first parameter represents the setting of the first 5 DIP switches.
- // In this example it's ON-ON-OFF-OFF-ON.
- //
- // The second parameter represents the setting of the last 5 DIP switches.
- // In this example the last 5 DIP switches are OFF-ON-OFF-ON-OFF.
- mySwitch.switchOn("11111", "00010");
- // Wait a second
- delay(1000);
- // Switch off
- mySwitch.switchOff("11111", "00010");
- // Wait another second
- delay(1000);
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement