Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:6f4be1a7962c, committed 2014-10-12
- Comitter:
- TheChrisyd
- Date:
- Sun Oct 12 09:57:12 2014 +0000
- Commit message:
- Initial commit
Changed in this revision
| RCSwitch.cpp | Show annotated file Show diff for this revision Revisions of this file |
| RCSwitch.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RCSwitch.cpp Sun Oct 12 09:57:12 2014 +0000
@@ -0,0 +1,858 @@
+/*
+ RCSwitch - Ported from the 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
+ - Chris Dick / Porting to mbed
+
+ 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"
+
+ unsigned long RCSwitch::nReceivedValue = NULL;
+ unsigned int RCSwitch::nReceivedBitlength = 0;
+ unsigned int RCSwitch::nReceivedDelay = 0;
+ unsigned int RCSwitch::nReceivedProtocol = 0;
+ int RCSwitch::nReceiveTolerance = 60;
+ unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES];
+ bool RCSwitch::TransmitEnablePin = false;
+ bool RCSwitch::ReceiveEnabled = true;
+ bool RCSwitch::TransmitEnable = true;
+
+/** Class constructor.
+ * The constructor assigns the specified pinout, attatches
+ * an Interrupt to the receive pin. for the LPC1768 this must not
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx Transmitter pin of the RF module.
+ * @param rx Receiver pin of the RF module.
+ */
+RCSwitch::RCSwitch(PinName tx, PinName rx)
+:
+ _tx(DigitalOut(tx)),
+ _rx(InterruptIn(rx)),
+ _tx_en(NC)
+{
+ nReceivedDelay = 0;
+ RCSwitch::nReceivedValue = NULL;
+ nReceivedBitlength = 0;
+ ReceiveEnabled = true;
+ TransmitEnable = true;
+ TransmitEnablePin = false;
+ setRepeatTransmit(15);
+ setProtocol(1);
+ setReceiveTolerance(60);
+ _rx.rise(this, &RCSwitch::RCSwitchRxPinChange);
+ _rx.fall(this, &RCSwitch::RCSwitchRxPinChange);
+ timer.start();
+}
+
+ /** Class constructor.
+ * The constructor assigns the specified pinout, attatches
+ * an Interrupt to the receive pin. for the LPC1768 this must not
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx Transmitter pin of the RF module.
+ * @param rx Receiver pin of the RF module.
+ * @param tx_en Enable pin of the transmitter
+ */
+RCSwitch::RCSwitch(PinName tx, PinName rx, PinName tx_en)
+:
+ _tx(DigitalOut(tx)),
+ _rx(InterruptIn(rx)),
+ _tx_en(DigitalOut(tx_en))
+{
+ nReceivedDelay = 0;
+ RCSwitch::nReceivedValue = NULL;
+ nReceivedBitlength = 0;
+ ReceiveEnabled = true;
+ TransmitEnable = false;
+ TransmitEnablePin = true;
+ setRepeatTransmit(15);
+ setProtocol(1);
+ setReceiveTolerance(60);
+ _rx.rise(this, &RCSwitch::RCSwitchRxPinChange);
+ _rx.fall(this, &RCSwitch::RCSwitchRxPinChange);
+ timer.start();
+
+}
+
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ */
+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);
+ }
+}
+
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ * @param nPulseLength Length of each pulse
+ */
+void RCSwitch::setProtocol(int nProtocol, int nPulseLength) {
+ this->nProtocol = nProtocol;
+ this->setPulseLength(nPulseLength);
+}
+
+
+/**
+ * Set pulse length in micro seconds
+ * @param nPulseLength the Length of the pulse
+ */
+void RCSwitch::setPulseLength(int nPulseLength) {
+ this->nPulseLength = nPulseLength;
+}
+
+/**
+ * Set number of times to repeat transmission
+ * @param nRepeat Number of repeats
+ */
+void RCSwitch::setRepeatTransmit(int nRepeatTransmit) {
+ this->nRepeatTransmit = nRepeatTransmit;
+}
+
+/**
+ * Set receive tolerance
+ * @param nPercent Percentage tolerance of the receiver
+ */
+void RCSwitch::setReceiveTolerance(int nPercent) {
+ RCSwitch::nReceiveTolerance = nPercent;
+}
+
+
+/**
+ * Enable the transmitter
+ */
+void RCSwitch::enableTransmit() {
+ if (TransmitEnablePin == true)
+ {
+ _tx_en = true;
+ }
+ TransmitEnable = true;
+}
+
+/**
+ * Disable the transmitter
+ */
+void RCSwitch::disableTransmit() {
+ if (TransmitEnablePin == true)
+ {
+ _tx_en = false;
+ }
+ TransmitEnable = false;
+}
+
+/**
+ * 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, bool 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, 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* RCSwitch::getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus) {
+ static char sReturn[13];
+ int nReturnPos = 0;
+
+ if ( (char)sFamily < 97 || (char)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, bool 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;
+
+}
+
+/**
+ * Sends a codeword
+ * @param sCodeWord Codeword to be sent
+ */
+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) {
+ bool disabled_Receive = false;
+
+ if (TransmitEnable) {
+ if (ReceiveEnabled) {
+ this->disableReceive();
+ disabled_Receive = true;
+ }
+ _tx = 1;
+ wait_us(this->nPulseLength * nHighPulses);
+ _tx = 0;
+ wait_us(this->nPulseLength *nLowPulses);
+ if(disabled_Receive){
+ this->enableReceive();
+ }
+ }
+}
+/**
+ * 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);
+ }
+}
+
+/**
+ * Enable receiving data
+ */
+void RCSwitch::enableReceive() {
+ RCSwitch::nReceivedValue = NULL;
+ RCSwitch::nReceivedBitlength = NULL;
+ _rx.enable_irq();
+ ReceiveEnabled = true;
+}
+
+/**
+ * Disable receiving data This disables the interrupt
+ * which may disable the port
+ */
+void RCSwitch::disableReceive() {
+ _rx.disable_irq();
+ ReceiveEnabled = false;
+}
+
+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 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;
+ nReceivedDelay = delay;
+ RCSwitch::nReceivedProtocol = 1;
+ }
+
+ if (code == 0){
+ return false;
+ }
+ 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;
+ nReceivedDelay = delay;
+ RCSwitch::nReceivedProtocol = 2;
+ }
+
+ if (code == 0){
+ return false;
+ }
+ 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;
+ nReceivedDelay = delay;
+ RCSwitch::nReceivedProtocol = 3;
+ }
+
+ if (code == 0){
+ return false;
+ }
+ return true;
+}
+
+void RCSwitch::RCSwitchRxPinChange() {
+
+ static unsigned int duration;
+ static unsigned int changeCount;
+ static unsigned int repeatCount;
+ timer.stop();
+ duration = timer.read_us();
+ timer.reset();
+ timer.start();
+
+
+ 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;
+}
+
+/**
+ * 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;
+}
+
+
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/RCSwitch.h Sun Oct 12 09:57:12 2014 +0000
@@ -0,0 +1,364 @@
+/**
+ *@section DESCRIPTION
+ * RCSwitch - Ported from the Arduino libary for remote control outlet switches
+ * 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
+ * - Chris Dick / Porting to mbed
+ *
+ * Project home: http://code.google.com/p/rc-switch/
+ * @section LICENSE
+ * Copyright (c) 2011 Suat Özgür. All right reserved.
+ *
+ * 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
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * @file "RCSwitch.h"
+ */
+#ifndef _RCSwitch_h
+#define _RCSwitch_h
+#include "mbed.h"
+
+// might need to change this...
+// We can handle up to (unsigned long) => 32 bit * 2 H/L changes per bit + 2 for sync
+#define RCSWITCH_MAX_CHANGES 67 /**< Number of maximum High/Low changes per packet. */
+
+#define PROTOCOL3_SYNC_FACTOR 71 /**< Protocol 3 Sync Factor */
+#define PROTOCOL3_0_HIGH_CYCLES 4 /**< Protocol 3 number of high cycles in a 0 */
+#define PROTOCOL3_0_LOW_CYCLES 11 /**< Protocol 3 number of low cycles in a 0*/
+#define PROTOCOL3_1_HIGH_CYCLES 9 /**< Protocol 3 number of high cycles in a 1*/
+#define PROTOCOL3_1_LOW_CYCLES 6 /**< Protocol 3 number of low cycles in a 1*/
+/** RCSwitch Class
+ *
+ * Example:
+ * @code
+ * #include "mbed.h"
+ * #include "RCSwitch.h"
+ *
+ * // This Example should only do one of either transmit or receive
+ * //#define TRANSMIT
+ * #define RECEIVE
+ *
+ * Serial pc(USBTX, USBRX); // tx, rx
+ * RCSwitch mySwitch = RCSwitch( p11, p21 ); //tx, rx
+ *
+ * int main()
+ * {
+ * pc.printf("Setup");
+ * while(1) {
+ * #ifdef RECEIVE
+ * if (mySwitch.available()) {
+ *
+ * int value = mySwitch.getReceivedValue();
+ *
+ * if (value == 0) {
+ * pc.printf("Unknown encoding");
+ * } else {
+ * pc.printf("Received %d \n\r", mySwitch.getReceivedValue());
+ * pc.printf(" bit %d \n\r", mySwitch.getReceivedBitlength());
+ * pc.printf(" Protocol: %d \n\r", mySwitch.getReceivedProtocol());
+ * }
+ * mySwitch.resetAvailable();
+ * }
+ * #endif
+ * #ifdef TRANSMIT
+ * // Example: TypeA_WithDIPSwitches
+ * mySwitch.switchOn("11111", "00010");
+ * wait(1);
+ * mySwitch.switchOn("11111", "00010");
+ * wait(1);
+ *
+ * // Same switch as above, but using decimal code
+ * mySwitch.send(5393, 24);
+ * wait(1);
+ * mySwitch.send(5396, 24);
+ * wait(1);
+ *
+ * // Same switch as above, but using binary code
+ * mySwitch.send("000000000001010100010001");
+ * wait(1);
+ * mySwitch.send("000000000001010100010100");
+ * wait(1);
+ *
+ * // Same switch as above, but tri-state code
+ * mySwitch.sendTriState("00000FFF0F0F");
+ * wait(1);
+ * mySwitch.sendTriState("00000FFF0FF0");
+ * wait(1);
+ * #endif
+ * }
+ * }
+ *
+ * @endcode
+ */
+
+ /**
+ *
+ *
+ */
+class RCSwitch {
+
+ public:
+ /** Class constructor.
+ * The constructor assigns the specified pinout, attatches
+ * an Interrupt to the receive pin. for the LPC1768 this must not
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx Transmitter pin of the RF module.
+ * @param rx Receiver pin of the RF module.
+ */
+ RCSwitch(PinName tx, PinName rx);
+ /** Class constructor.
+ * The constructor assigns the specified pinout, attatches
+ * an Interrupt to the receive pin. for the LPC1768 this must not
+ * be pins 19 and 20. For the KL25Z, the pin must be on ports A or C
+ * @param tx Transmitter pin of the RF module.
+ * @param rx Receiver pin of the RF module.
+ * @param tx_en Enable pin of the transmitter
+ */
+ RCSwitch(PinName tx, PinName rx, PinName rx_en);
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ */
+ void setProtocol(int nProtocol);
+/**
+ * Set protocol to be used in transmission
+ * @param nProtocol Protocol type ot transmit
+ * @param nPulseLength Length of each pulse
+ */
+ void setProtocol(int nProtocol, int nPulseLength);
+/**
+ * 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 switchOn(char* sGroup, char* sDevice);
+/**
+ * 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 switchOff(char* sGroup, char* sDevice);
+/**
+ * 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 switchOn(char* sGroup, int nChannelCode);
+/**
+ * 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 switchOff(char* sGroup, int nChannelCode);
+/**
+ * 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);
+/**
+ * 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);
+/**
+ * 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 switchOn(char sFamily, int nGroup, int nDevice);
+/**
+ * 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 switchOff(char sFamily, int nGroup, int nDevice);
+
+/**
+ * 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 switchOn(char sGroup, int nDevice);
+/**
+ * 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 switchOff(char sGroup, int nDevice);
+/**
+ * Sends a codeword
+ * @param sCodeWord Codeword to be sent
+ */
+ void sendTriState(char* Code);
+/**
+ * Converts a CodeWord to a set Length and sends it
+ * @param Code CodeWord to be sent
+ * @param length Length of CodeWord to send
+ */
+ void send(unsigned long Code, unsigned int length);
+/**
+ * Sends a CodeWord
+ * @param Code CodeWord to send
+ */
+ void send(char* Code);
+/**
+ * Enable receiving data This clear message storage
+ * and enables the interrupt, which may enable the port
+ */
+ void enableReceive();
+/**
+ * Disable receiving data This disables the interrupt
+ * which may disable the port
+ */
+ void disableReceive();
+/**
+ * Message availiable
+ * @return bool Message availiability
+ */
+ bool available();
+/**
+ * Clear Messages
+ */
+ void resetAvailable();
+/**
+ * Get Message Value
+ * @return unsigned long The value of the message received
+ */
+ unsigned long getReceivedValue();
+/**
+ * Get bit length
+ * @return unsigned int Number of bits received
+ */
+ unsigned int getReceivedBitlength();
+/**
+ * Get the delay
+ * @Return unsigned int The delay
+ */
+ unsigned int getReceivedDelay();
+/**
+ * Get Protocol
+ * @return unsigned int The protocol used in the message
+ */
+ unsigned int getReceivedProtocol();
+/**
+ * Get Raw data
+ * @return unsinged int The raw data of the message recieved
+ */
+ unsigned int* getReceivedRawdata();
+/**
+ * Enable the transmitter
+ */
+ void enableTransmit();
+/**
+ * Disable the transmitter
+ */
+ void disableTransmit();
+/**
+ * Set pulse length in micro seconds
+ * @param nPulseLength the Length of the pulse
+ */
+ void setPulseLength(int nPulseLength);
+/**
+ * Set number of times to repeat transmission
+ * @param nRepeat Number of repeats
+ */
+ void setRepeatTransmit(int nRepeatTransmit);
+/**
+ * Set receive tolerance
+ * @param nPercent Percentage tolerance of the receiver
+ */
+ void setReceiveTolerance(int nPercent);
+
+ static int nReceiveTolerance; /**< Tolerance of the receiver */
+ static unsigned long nReceivedValue; /**< Value Recieved */
+ static unsigned int nReceivedBitlength; /**< Length in bits of value reveived */
+ static unsigned int nReceivedDelay; /**< Delay in receive */
+ static unsigned int nReceivedProtocol; /**< Protocol of message recieved */
+ static bool ReceiveEnabled; /**< Receive enabled */
+ static bool TransmitEnable; /**< Transmit enabled */
+ static bool TransmitEnablePin; /**< Pin of transmitter enable pin */
+ static unsigned int timings[RCSWITCH_MAX_CHANGES]; /**< timings[0] contains sync timing, followed by a number of bits */
+
+ private:
+ DigitalOut _tx;
+ InterruptIn _rx;
+ DigitalOut _tx_en;
+
+ char* getCodeWordB(int nGroupNumber, int nSwitchNumber, bool bStatus);
+
+ char* getCodeWordA(char* sGroup, int nSwitchNumber, bool bStatus);
+
+ char* getCodeWordA(char* sGroup, char* sDevice, bool bStatus);
+
+ char* getCodeWordC(char sFamily, int nGroup, int nDevice, bool bStatus);
+
+ char* getCodeWordD(char group, int nDevice, bool bStatus);
+
+ void sendT0();
+
+ void sendT1();
+
+ void sendTF();
+
+ void send0();
+
+ void send1();
+
+ void sendSync();
+
+ void transmit(int nHighPulses, int nLowPulses);
+
+ void RCSwitchRxPinChange();
+
+ static char* dec2binWzerofill(unsigned long dec, unsigned int length);
+
+ static char* dec2binWcharfill(unsigned long dec, unsigned int length, char fill);
+
+ static void handleInterrupt();
+
+ static bool receiveProtocol1(unsigned int changeCount);
+
+ static bool receiveProtocol2(unsigned int changeCount);
+
+ static bool receiveProtocol3(unsigned int changeCount);
+
+ int nReceiverInterrupt;
+ int nTransmitterPin;
+ int nPulseLength;
+ int nRepeatTransmit;
+ char nProtocol;
+ Timer timer;
+};
+
+#endif
RCSwitch