GithubHelp home page GithubHelp logo

rc-switch's Introduction

rc-switch

arduino-library-badge Build Status

Use your Arduino or Raspberry Pi to operate remote radio controlled devices

Download

https://github.com/sui77/rc-switch/releases/latest

rc-switch is also listed in the arduino library manager.

Wiki

https://github.com/sui77/rc-switch/wiki

Info

Send RC codes

Use your Arduino or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. If yours doesn't work, you might need to adjust the pulse length.

All you need is a Arduino or Raspberry Pi, a 315/433MHz AM transmitter and one or more devices with one of the supported chipsets:

  • SC5262 / SC5272
  • HX2262 / HX2272
  • PT2262 / PT2272
  • EV1527 / RT1527 / FP1527 / HS1527
  • Intertechno outlets
  • HT6P20X

Receive and decode RC codes

Find out what codes your remote is sending. Use your remote to control your Arduino.

All you need is an Arduino, a 315/433MHz AM receiver (altough there is no instruction yet, yes it is possible to hack an existing device) and a remote hand set.

For the Raspberry Pi, clone the https://github.com/ninjablocks/433Utils project to compile a sniffer tool and transmission commands.

rc-switch's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rc-switch's Issues

ENC28J60

Hello

I have a small project running on an arduino Uno, when receiving a 433Mz signal from a sensor, the arduino sends an email through ENC28J60 module. Everything almost works, once it's connected to the internet, the initialization of the module makes my arduino to reboot continuously. I discovered that the issue comes from the function mySwitch.enableReceive(0). For some reason, using this interrupt is the root cause. My question is, is there any other solution to use this function with pin 2 and no interruption ?

Thanks !
Mickael.

one question

I read on instructables.com that your library can stiff a code from a remote control and play that later? Is it true? can it sniff rolling code remotes? Thanks.

Why limited to certain transmitters?

When using the VirtualWire library, I can pick up any 433mhz transmitter (well, all of mine. Tested with 17 devices) However, when using this library it appears to be specifically designed to ignore all but the predefined transmitters, which only includes 2 of my own. Is this library specifically limited to ignore transmitters?

ReceiveDemo Simple and esp8266

Does anybody know if he enableReceive(0) is pin 2 on the ESP 8266, Will this work or is it not compatible. Are there maps interrupts to pins on the ESP? I get to load without any errors; just not receiving anything?

Problem with 32bit and different protocols

Hi there,

I have used the library together with an ESP8266, and try to put some codes into a clone remote keyfob.
I would like to use a 32bit value, but cannot get it to receive the learned value. Another thing, if I use standard 24 bit, and transmits a value as a protocol 2 - then the received value gets interpreted as protocol 1. How can that be?
Martin

projects built with rc-switch

wouldn't be cool to have a sections called "who use rc-switch? " which lists all the projects that make use of it?

Add more boards to Travis CI tests

Once #61 is resolved, the boards that have specific conditional code (#ifdefs) for support should be added to the Travis CI tests. Right now that looks to be an ESP8266 based board and the Raspberry Pi.

It wouldn't hurt to add more, but the two above are important to ensure the code compiles for all the platforms it aims to support.

Multiple receivers

I'm currently working on a project that requires multiple receivers (at 433MHz and 315MHz). I've read through past issues regarding this (#25 and #63), and I have a proposal for (sort of) resolving this issue.

What I'm planning on doing is to add the functionality to query which pin triggered the interrupt, which would at least allow two receivers to be used. This would also probably require changing variables such as nReceiverInterrupt to dynamically-allocated arrays, or better yet std::vector<int>s. (I'm working on a Particle Photon, so I can use STL libraries.) Would this be a satisfactory way to address this issue? I am currently working on a version that does use <vector>, but I assume with some effort that can be ported to malloc and such.

Please tell me if I've overlooked anything (or I'll find out in due time, I suppose).


Edit: The naive implementation would make the assumption that two pins would never be receiving simultaneously.


Edit 2: After working on this some more, it appears that it could substantially increase the size of the library (e.g. ideally there would be an enable_receive(std::vector<int>) etc.). Is this a problem? I suppose something could be done with #ifdefs and such.


Edit 3: I suppose multiple receivers operating at once might be possible if all of the static variables were turning into vectors/arrays? This depends on how the receiving protocol works, which I haven't figured out yet :P

Never reach mySwitch.available()

I don't know whats going wrong, it's an Arduino Uno, Pin 2. But nothing over the Serial interface. I "debugged" that it never comes into the „mySwitch.available()“ Part. I use Arduino IDE 1.6.5
If i turn Warnings in the Arduino IDE on i get several Warnings:

Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:33:42: warning: converting to non-pointer type 'long unsigned int' from NULL [-Wconversion-null]
 unsigned long RCSwitch::nReceivedValue = NULL;
                                          ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In constructor 'RCSwitch::RCSwitch()':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:49:28: warning: converting to non-pointer type 'long unsigned int' from NULL [-Wconversion-null]
   RCSwitch::nReceivedValue = NULL;
                            ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'void RCSwitch::switchOn(char*, int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
   char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
                                                                          ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:189:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'void RCSwitch::switchOff(char*, int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
   char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
                                                                          ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:201:74: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'char* RCSwitch::getCodeWordB(int, int, boolean)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:245:61: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
    char* code[5] = { "FFFF", "0FFF", "F0FF", "FF0F", "FFF0" };
                                                             ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:245:61: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:245:61: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:245:61: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:245:61: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'void RCSwitch::enableReceive()':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:597:30: warning: converting to non-pointer type 'long unsigned int' from NULL [-Wconversion-null]
     RCSwitch::nReceivedValue = NULL;
                              ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:598:34: warning: converting to non-pointer type 'unsigned int' from NULL [-Wconversion-null]
     RCSwitch::nReceivedBitlength = NULL;
                                  ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'bool RCSwitch::available()':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:612:38: warning: NULL used in arithmetic [-Wpointer-arith]
   return RCSwitch::nReceivedValue != NULL;
                                      ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In member function 'void RCSwitch::resetAvailable()':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:616:28: warning: converting to non-pointer type 'long unsigned int' from NULL [-Wconversion-null]
   RCSwitch::nReceivedValue = NULL;
                            ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol1(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:648:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       for (int i = 1; i<changeCount ; i=i+2) {
                         ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol2(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:684:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       for (int i = 1; i<changeCount ; i=i+2) {
                         ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol3(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:722:25: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
       for (int i = 1; i<changeCount ; i=i+2) {
                         ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol1(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:676:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol2(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:711:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp: In static member function 'static bool RCSwitch::receiveProtocol3(unsigned int)':
Arduino/libraries/rc-switch-2.52/RCSwitch.cpp:754:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

ReceiveDemo_Advance - Compiler error IDE 1.6.6

Hello Board,

after compiling the Advance Demo i got the following compiler error

exit status 1
'char* dec2binWzerofill(long unsigned int, unsigned int)' was declared 'extern' and later 'static' [-fpermissive]

I have tried the actual IDE version 1.6.11 and the older version 1.6.2.

Thanks for helping

PT2260 support - sniffing unsupported devices?

I have a remote controller looking exactly like this one on eBay: 361529945280 and a XY-MK-5V receiver. The controller is said to have the PT2260 chip, which is not on the list of chips supported by this library.

My problem/question is that I can't get any readings using RCSwitch, although I can see that some data is coming from the receiver. I also tried some other remote controllers I found at home (car openers) but also didn't get any readings from RCSwitch.

Is that the expected behaviour? I just wonder if it's because the chips in my remotes aren't supported or is it because the protocols may use rolling codes. I thought RCSwitch should be able to show/sniff the transmission anyway? Is that right or it won't sniff such transmission and I must find a simpler remote to see the transmitted codes?

Out of index assign of value

Hi there,

I think there might be an out of index assignment here :

diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) {

Perhaps this can be solved by adding:
if (changeCount < RCSWITCH_MAX_CHANGES)
{

Where's the wiki?

How do we know which remotes are supported?

Brennenstuhl RCS 1000 N are supported?

Record the first half of the sync signal, too

Right now, our received timings omit half of the sync signal. While this is not a problem for normal decoding, it is quite annoying when one wants to analyze a new protocol, for it makes it difficult to determine the length of the first half of the sync signal; and that is important for sending signals. (See also issue #53.)

Implementing this shouldn't be hard, but I don't want to try it without access to my hardware, so that I can conduct tests :-).

Problem with SCT 2260 chip

Hello,

I have bought a set of remote power sockets from ebay
http://www.ebay.com/itm/311482637595

I succeeded to read the code (decimal protocol 1 24 bit) with the received demo of the remote controller but when trying to send it with the Arduino it dose not work!

I opened the remote and noticed that the chip is SCT 2260 that is not listed here.
Is this the problem I have?
How can I solve it?

Thanks!

Problem with make on Raspberry Pi

Current master version download appears to have RCSwitch.o missing? Make on Raspberry PI fails with:

pi@raspberrypi ~/lloytron/433Utils/RPi_utils $ make
make: *** No rule to make target '../rc-switch/RCSwitch.o', needed by 'send'. Stop.
pi@raspberrypi ~/lloytron/433Utils/RPi_utils $

Promax support

Hi,

I bought a new Promax switch from our local Action store in The Netherlands. They are "self learning", but don't appear to listen to the normal protocols. When using the ReceiveDemo it looks normal, except after the Tri-State decoding there are some extra symbols (see attached file).

The receiverdemo works fine when listening to controls sent by the Remote Control, except when you transmit the same decimal number (or binary) the sockets just won't respond.
Is there any way I can make this working? I'm not the only one, it looks like a lot of people are having issues with the new sockets from the Action.

knipsel

SRX882 + STX882 Modules issue

Hello:

I bought SRX882 & STX882 modules and I was able to make the transmitter work with RCSwitch easily. It was just plug&play. Both in Raspberry PI and Arduino.

However I can't make the receiver work. I tested it and it seems that the receiver is working fine. If I use a simple program to attach the interrupt I see the changes when I press a button on my remote. However using the RCSwitch library with the "sniffer" example will not show a thing.

Is there anything I'm doing wrong? or somehow this device is not compatible with RCSwitch? if you could point me in the right direction I will be grateful.

Generate random RF code is possible?

Hi,
First of all thanks very much for your project, I got it working so far so good on 433mhz.
I would like to know if is it possible to generate a 315mhz signal (randomly).

Let me explain, I have another project that I would like to transmit 315mhz signal to not get interference in the 433mhz signal, though I don't have any remote control in 315mhz. The board that I want to use to receive this "generate" signal is a self learning relay board that accepts almost all IC (2262 2264 2260 2240 1527).

Is it possible or do I have to get a remote control in 315mhz to get the codes? Sorry, for the basic questions, I don't understand much about rf transmissions.

Thanks in advance

Sending to GT-FSI-07 not possible

Hello

is it possible to switch Globaltronics GT-FSI-07 (Sender: GT-9000)?
I tried everything to archive that but it won't work.

Capturing raw data is possible by the receiveDemo_advanced. I received packages like (e.g.):

Decimal: 15114215 (24Bit) Binary: 111001101001111111100111 Tri-State: not applicable PulseLength: 101 microseconds Protocol: 3
Raw data: 7200,968,564,968,568,964,564,1196,1088,440,1092,436,328,1200,1084,440,328,1200,324,1196,332,1092,432,336,1192,1092,436,1088,444,1084,436,328,1200,328,332,1196,332,1192,332,1196,328,1196,1092,432,1092,440,564,964,572,

I tried to send data with protocol 3, 4 & 5 and pulse lengths of 101 and 213...

Thanks for an information if using this piece of hardware is generally possible.
Please let me know if you need further information.
David

Can't compile latest?

Just me?

~/utils/433Utils/RPi_utils $ make
g++ -DRPI -c -o ../rc-switch/RCSwitch.o ../rc-switch/RCSwitch.cpp
../rc-switch/RCSwitch.cpp: In member function ‘void RCSwitch::send(long unsigned int, unsigned int)’:
../rc-switch/RCSwitch.cpp:493:26: error: ‘bitRead’ was not declared in this scope
: recipe for target '../rc-switch/RCSwitch.o' failed
make: *** [../rc-switch/RCSwitch.o] Error 1

ESP8266 crashes with receiver enabled

Hi,
I am building a 433 MHz receiver around a Adafruit HUZZAH ESP8266.
The receiver is going to switch two different light channels. It should receive "toggle" commands from some wall switches (using battery powered Attiny85 and 443 MHz sender) and it is connected via WIFI to a MQTT bus to send and receive commands for home automation (currently openHAB).
This way not only the two light channels can be switch via MQTT but any 433Mhz receiver in my house using openHAB.

Though the standalone receive demo from RCSwitch works flawlessly, I do get crashes, as soon as I integrate the RCSwitch library into my Sketch. The sketch is mainly connecting via WiFI to a MQTT bus to send and receive messages or commands.
The crashes always happen in the Interrupt service routine (ISR) or any function called by the ISR in the receive code of RCSwitch.

After reading a lot I found that it is absolutely necessary to have all ISR functions and all functions called from the ISR in RAM on the ESP8266, not in PROGMEM.
Currently the following modifications to RCSwitch.cpp helped in getting the crashes go away.
Please consider the changes to be integrated into the release.
Anybody also trying to do this on a busy ESP8266 (WiFi) should also note that you need the ESP8266 core >= 2.2.0. Starting with this release the micro() function is also in RAM. If it is not, you will get crashes in that function.

Changes I did:
Have the protocols in RAM
#ifdef ESP8266
// because of timing reasons we keep that in memory on esp8266
static const RCSwitch::Protocol proto[] = {
#else
static const RCSwitch::Protocol PROGMEM proto[] = {
#endif

Changes to receiveProtocol (called by ISR)
#ifdef ESP8266
bool ICACHE_RAM_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
#else
bool RCSwitch::receiveProtocol(const int p, unsigned int changeCount) {
#endif

Protocol pro;
 #ifdef ESP8266
pro = proto[p-1];
#else
    memcpy_P(&pro, &proto[p-1], sizeof(Protocol));
#endif

Changes to ISR:

ifdef ESP8266

void ICACHE_RAM_ATTR RCSwitch::handleInterrupt() {

else

void RCSwitch::handleInterrupt() {

endif

Please let me know if someone has a better idea.

Thanks

Ralf

Comments

The code is rather well documented, but i still have some troubles understanding the signification of the changeCount, repeatCount and the Timings array. Would be glad if you could comment them.

In addition, but it perhaps due to my weak experience, i didn't get the Protocols signification in terme of each member of the structure and How to use them. As I have some 433Mhz sensors that RCSwitch doesn't get i thought i could add in some new protocols.

Thanks

Problem detecting a single frame, sync start condition.

Hi I have used the transmit function to learn a copy remote some values. It seems the receive part only works if multiple values are sent (long press on my remote makes it retransmit ) . Could there be something with an issue getting in sync.

Doesn't work with the dooya dc90

I recently started with connecting my rf devices to the internet using an arduino to copy the rf (decimal)singals and using a raspberry pi to send the singals. My rf light switches work great! but when I trie to copy the singal of my sun screen which uses the dooya dc90 remote(fcc) I get nothing I don't know why because the RF report says it uses 433.92MHz as frequency and ASK as modulation which my receiver supports. Do you guys have any ideas on why I can't receive the singals?

Can connect RCSwitch to native AVR??

Hi,first tank you.
Can use this program for connect rcswitc 433 to native AVR ??if yes I use codevision for programmer,I want to do this: if push upkey do something if downkey do something else and....I cant print and see the return value of getReceivedValue() function , I used this [(https://github.com/ninjablocks/433Utils/blob/master/RPi_utils/RFSniffer.cpp)] before and I connect RCSwitch to raspberry my return getReceivedValue() function for upkey and downkey is 5592332 and 5592512 is it the same in this source code??If not can you give me return value of getReceivedValue() function of all 4 keys??
picture of my switch:img_0243

slow in detecting signal

Hi,

I have tried using both arduino uno and esp8266 to receive 433Mhz signals from those power socket transmitters, but they are not as responsive as the power sockets. Meaning, I need to hold down my transmitter button a little longer for uno or esp8266 to receive and echo on screen.

Is there any possible room for improvement? Thank you.

Are protocol 3 and 5 the same?

PR #11 added protocol 5. In the pull request, it is explained that the signals from the remote were already "incorrectly" recognized as protocol 3, but that sending did not work using protocol 3.

Well, the same was the case for me, until I tweaked protocol 3 in PR #33. After that tweak, we have this:

    { 100, { 30, 71 }, {  4, 11 }, {  9,  6 } },    // protocol 3
...
    { 500, {  6, 14 }, {  1,  2 }, {  2,  1 } },    // protocol 5

If one changes things to a uniform base unit of 100us, we get:

    { 100, { 30, 71 }, {  4, 11 }, {  9,  6 } },    // protocol 3
    { 100, { 30, 70 }, {  5, 10 }, { 10,  5 } },    // protocol 5

Note how close the values are. Indeed, close enough that the fuzzy matching implemented in rc-switch may ignores the difference.

As a result, my remote, which definitely sends using protocol 3 (based on analyzing raw timings), regularly is detected as protocol 5 instead.

So, I now wonder whether perhaps protocol 5 is really the same as protocl 3, and the numbers in it were simply fuzzed up as "looking nice and working", as opposed to being based on raw timings?

Connecting the two receivers

The problem is when you connect the two receivers(315MHz and 433MHz). In consequence of using a variable of type static, it overwrites data in a single memory controller.

Code review request

Branch name: raspberry-quigg

Purpose of code changes on this branch:
- Send Commands to Quigg Devices
- A "little" code rearrangement
- Compile Option for RaspberryPi (use -DRASPBERRY)

When reviewing my code changes, please focus on:
- is everything working?
  - Commands to all other devices
  - Does it still work on Arduino et al?
  - Do the receiver methods still work? (Couldn't test this at all)

- Are these changes fully backward compatible?

Not for RPi reviewers:
Minimum example for an executable:
#include "RCSwitch.h"
int main(int argc, char*argv[])
{
  if(wiringPiSetup() == -1)
    return 1;
  piHiPri(20);
  RCSwitch mySwitch;
  mySwitch.enableTransmit(0); // PIN 0;
  mySwitch.toggleTypeD("111100001111", 3, 1); // Quigg's system code is 12-bit, unit code can be 0 (=all) or 1-4.
  return 0;
}

After the review, I'll merge this branch into:
/trunk

Malte

Original issue reported on code.google.com by [email protected] on 17 Feb 2014 at 9:39

Arduino Due PIN

Hi I am using a Due but I don´t know if this library is compatible with this and if is compatible what pins use?.

code bits are sent in the wrong order

See #51 for background.

The for-loop at RCSwitch.cpp:494 sends the bits in the wrong order, it should send MSB first.

void RCSwitch::send(unsigned long code, unsigned int length) {
    for (int nRepeat = 0; nRepeat < nRepeatTransmit; nRepeat++) {
        //for (unsigned int i = 0; i < length; i++) { // incorrect order
        for (int i = length-1; i >= 0; i--) { // correct order
            if (code & (1L << i))
                this->transmit(protocol.one);
            else
                this->transmit(protocol.zero);
            }
            this->transmit(protocol.syncFactor);
        }
}

Guide for Raspberry Pi

In the code, I see support for the Raspberry Pi.
But how do I implement rc-switch for Raspberry Pi?
I failed to do so.

TE89TP16N

Could you please add a support for TE89TP16N?
Protocol has been described in details here:
http://tech.jolowe.se/home-automation-rf-protocol-update/

I tried to add it by myself but adding proper values to proto[] like that:
{ 250, { 1, 11 }, { 1, 6 }, { 1, 1 } }, // protocol 6
is clearly not enough to receive. Could you at least advise what else needs to be done to properly recognize a protocol and receive?

Any help will be appreciated.

Adjust timings for RCO-14-b / fht 7901

screen shot 2015-12-10 at 17 47 20

As You can see, the gap between transmitted chunks is about 4690 microseconds. RCSwitch::handleInterrupt() expects this gap to be at least 5000 microseconds which prevents any readout.
Accordingly - changing following lines in RCSwitch::handleInterrupt() allowed me to read the transmission from the RC:

if (duration > 5000 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {

to

if (duration > 4600 && duration > RCSwitch::timings[0] - 200 && duration < RCSwitch::timings[0] + 200) {

and

  } else if (duration > 5000) {

to

  } else if (duration > 4600) {

Two receivers + why static definitions?

@bilogic The class uses static definitions because Arduino interrupt handler callbacks sadly only can access static / global data; and interrupt handlers cannot easily be shared for different users. In particular, they have no void *refCon parameter, which many other callback based APIs offer.

So I am really curious to learn how you bypassed that problem. But please let's not put it onto this old, closed issue; instead, submit a pull request, and/or a new issue where you explain your changes.

@fingolfin

  1. Sorry, but i have no idea how to do a pull request without forking, so I'm just going to attach my code here
  2. The code is a proof of concept, not too dirty, but can be much cleaner
  3. I'm experienced in C/C++ but very new to Arduino
  4. Initially I wanted to go the way of non static, but after reviewing the code, it was much easier to just add another buffer and interrupt handler
  5. No offence, but I wasn't convinced about the "access static" data and did a test, you can find it as non_static in my code. Interrupt handler is able to read + write to it, is my test correct?
  6. Assuming my test is correct (aka interrupt handlers can access non static variables), I think the best way is to have 2 instances of rc-switch, 1 for each receiver, keeping as much code and variables static while the buffers non static
  7. My earlier encounter with static definitions on Arduino was to prevent memory fragmentation, this was certainly a valid consideration
  8. I'm not sure if 2 or more instances will lead to any memory fragmentation or other issues

Finally, thanks for this library, I having a fantastic time turning on/off electricity :)

/*
  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
  - Max Horn / max(at)quendi(dot)de
  - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com
  - Johann Richard / <first name>.<last name>(at)gmail(dot)com
  - Vlad Gheorghe / <first name>.<last name>(at)gmail(dot)com https://github.com/vgheo

  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
  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"

/* Format for protocol definitions:
 * {pulselength, Sync bit, "0" bit, "1" bit}
 *
 * pulselength: pulse length in microseconds, e.g. 350
 * Sync bit: {1, 31} means 1 high pulse and 31 low pulses
 *     (perceived as a 31*pulselength long pulse, total length of sync bit is
 *     32*pulselength microseconds), i.e:
 *      _
 *     | |_______________________________ (don't count the vertical bars)
 * "0" bit: waveform for a data bit of value "0", {1, 3} means 1 high pulse
 *     and 3 low pulses, total length (1+3)*pulselength, i.e:
 *      _
 *     | |___
 * "1" bit: waveform for a data bit of value "1", e.g. {3,1}:
 *      ___
 *     |   |_
 *
 * These are combined to form Tri-State bits when sending or receiving codes.
 */
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, { 30, 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]);

int non_static = 1184;

#if not defined( RCSwitchDisableReceiving )
unsigned long RCSwitch::nReceivedValue = 0;
unsigned int RCSwitch::nReceivedBitlength = 0;
unsigned int RCSwitch::nReceivedDelay = 0;
unsigned int RCSwitch::nReceivedProtocol = 0;
int RCSwitch::nReceiveTolerance = 60;
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::timings0[RCSWITCH_MAX_CHANGES];
unsigned int RCSwitch::timings1[RCSWITCH_MAX_CHANGES];
#endif

RCSwitch::RCSwitch() {
  this->nTransmitterPin = -1;
  this->setRepeatTransmit(10);
  this->setProtocol(1);
  #if not defined( RCSwitchDisableReceiving )
  this->nReceiverInterrupt = -1;
  this->setReceiveTolerance(60);
  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) {
  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) {
  setProtocol(nProtocol);
  this->setPulseLength(nPulseLength);
}


/**
  * Sets pulse length in microseconds
  */
void RCSwitch::setPulseLength(int nPulseLength) {
  this->protocol.pulseLength = 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(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(const char* sGroup, int nChannel) {
  const char* code[6] = { "00000", "10000", "01000", "00100", "00010", "00001" };
  this->switchOn(sGroup, code[nChannel]);
}

/**
 * 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(const char* sGroup, int nChannel) {
  const 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(const char* sGroup, const 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(const char* sGroup, const char* sDevice) {
    this->sendTriState( this->getCodeWordA(sGroup, sDevice, false) );
}

/**
 * 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              | 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       Whether 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];

   const 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.
 *
 */
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++) {
        sDipSwitches[j++] = (sGroup[i] == '0') ? 'F' : '0';
    }

    for (i = 0; i < 5; i++) {
        sDipSwitches[j++] = (sDevice[i] == '0') ? 'F' : '0';
    }

    if (bOn) {
        sDipSwitches[j++] = '0';
        sDipSwitches[j++] = 'F';
    } else {
        sDipSwitches[j++] = 'F';
        sDipSwitches[j++] = '0';
    }

    sDipSwitches[j] = '\0';

    return sDipSwitches;
}

/**
 * Like getCodeWord (Type C = Intertechno)
 */
char* 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';
  }

  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];
  }
  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       Whether 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(const 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->dec2binWcharfill(code, length, '0') );
}

void RCSwitch::send(const 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 (this->nTransmitterPin != -1) {
        #if not defined( RCSwitchDisableReceiving )
        int nReceiverInterrupt_backup = nReceiverInterrupt;
        if (nReceiverInterrupt_backup != -1) {
            this->disableReceive();
        }
        #endif
        digitalWrite(this->nTransmitterPin, HIGH);
        delayMicroseconds( this->protocol.pulseLength * nHighPulses);
        digitalWrite(this->nTransmitterPin, LOW);
        delayMicroseconds( this->protocol.pulseLength * nLowPulses);

        #if not defined( RCSwitchDisableReceiving )
        if (nReceiverInterrupt_backup != -1) {
            this->enableReceive(nReceiverInterrupt_backup);
        }
        #endif
    }
}

void RCSwitch::transmit(HighLow pulses) {
    transmit(pulses.high, pulses.low);
}

/**
 * Sends a "0" Bit
 *                       _
 * Waveform Protocol 1: | |___
 *                       _
 * Waveform Protocol 2: | |__
 */
void RCSwitch::send0() {
    this->transmit(protocol.zero);
}

/**
 * Sends a "1" Bit
 *                       ___
 * Waveform Protocol 1: |   |_
 *                       __
 * Waveform Protocol 2: |  |_
 */
void RCSwitch::send1() {
    this->transmit(protocol.one);
}


/**
 * Sends a Tri-State "0" Bit
 *            _     _
 * Waveform: | |___| |___
 */
void RCSwitch::sendT0() {
  this->send0();
  this->send0();
}

/**
 * Sends a Tri-State "1" Bit
 *            ___   ___
 * Waveform: |   |_|   |_
 */
void RCSwitch::sendT1() {
  this->send1();
  this->send1();
}

/**
 * Sends a Tri-State "F" Bit
 *            _     ___
 * Waveform: | |___|   |_
 */
void RCSwitch::sendTF() {
  this->send0();
  this->send1();
}

/**
 * Sends a "Sync" Bit
 *                       _
 * Waveform Protocol 1: | |_______________________________
 *                       _
 * Waveform Protocol 2: | |__________
 */
void RCSwitch::sendSync() {
    this->transmit(protocol.syncFactor);
}

#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 = 0;
    RCSwitch::nReceivedBitlength = 0;
#if defined(RaspberryPi) // Raspberry Pi
    wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt1);
#else // Arduino
    // attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE);
    attachInterrupt(0, handleInterrupt0, CHANGE);
    attachInterrupt(1, handleInterrupt1, CHANGE);
#endif
  }
}

/**
 * Disable receiving data
 */
void RCSwitch::disableReceive() {
#if not defined(RaspberryPi) // Arduino
  // detachInterrupt(this->nReceiverInterrupt);
  detachInterrupt(0);
  detachInterrupt(1);
#endif // For Raspberry Pi (wiringPi) you can't unregister the ISR
  this->nReceiverInterrupt = -1;
}

bool RCSwitch::available() {
  return RCSwitch::nReceivedValue != 0;
}

void RCSwitch::resetAvailable() {
  RCSwitch::nReceivedValue = 0;
}

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

/* helper function for the various receiveProtocol methods */
static inline unsigned int diff(int A, int B) {
    return abs(A - B);
}

/**
 *
 */
bool RCSwitch::receiveProtocol(const int p, unsigned int changeCount, unsigned int interrupt) {

    Protocol pro;
    memcpy_P(&pro, &proto[p-1], sizeof(Protocol));

    unsigned int *timings;

    switch (interrupt)
    {
        case 0: timings = RCSwitch::timings0; break;
        case 1: timings = RCSwitch::timings1; break;
    }

    unsigned long code = 0;
    const unsigned int delay = 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(timings[i], delay * pro.zero.high) < delayTolerance &&
            diff(timings[i + 1], delay * pro.zero.low) < delayTolerance) {
            // zero
        } else if (diff(timings[i], delay * pro.one.high) < delayTolerance &&
                   diff(timings[i + 1], delay * pro.one.low) < delayTolerance) {
            // one
            code |= 1;
        } else {
            // Failed
            return false;
        }
    }

    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 = p;
    }

    return true;
}

void RCSwitch::handleInterrupt0() {

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

  Serial.print("non_static: ");
  Serial.println(non_static);

  non_static = 1234;

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

  if (duration > RCSwitch::nSeparationLimit && diff(duration, RCSwitch::timings0[0]) < 200) {
    repeatCount++;
    changeCount--;
    if (repeatCount == 2) {
    for(unsigned int i = 1; i <= numProto; i++ ) {
        if (receiveProtocol(i, changeCount, 0)) {
            // receive succeeded for protocol i
            break;
        }
    }
      repeatCount = 0;
    }
    changeCount = 0;
  } else if (duration > RCSwitch::nSeparationLimit) {
    changeCount = 0;
  }

  if (changeCount >= RCSWITCH_MAX_CHANGES) {
    changeCount = 0;
    repeatCount = 0;
  }
  RCSwitch::timings0[changeCount++] = duration;
  lastTime = time;
}

void RCSwitch::handleInterrupt1() {

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

  // Serial.println("interrupting 1");

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

  if (duration > RCSwitch::nSeparationLimit && diff(duration, RCSwitch::timings1[0]) < 200) {
    repeatCount++;
    changeCount--;
    if (repeatCount == 2) {
    for(unsigned int i = 1; i <= numProto; i++ ) {
        if (receiveProtocol(i, changeCount, 1)) {
            // receive succeeded for protocol i
            break;
        }
    }
      repeatCount = 0;
    }
    changeCount = 0;
  } else if (duration > RCSwitch::nSeparationLimit) {
    changeCount = 0;
  }

  if (changeCount >= RCSWITCH_MAX_CHANGES) {
    changeCount = 0;
    repeatCount = 0;
  }
  RCSwitch::timings1[changeCount++] = duration;
  lastTime = time;
}
#endif

/**
  * Turns a decimal value to its binary representation
  */
char* RCSwitch::dec2binWcharfill(unsigned long dec, unsigned int bitLength, char fill) {
  static char bin[32];

  bin[bitLength] = '\0';
  while (bitLength > 0) {
    bitLength--;
    bin[bitLength] = (dec & 1) ? '1' : fill;
    dec >>= 1;
  }

  return bin;
}
/*
  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
  - Max Horn / max(at)quendi(dot)de
  - Robert ter Vehn / <first name>.<last name>(at)gmail(dot)com

  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
  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

#if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
#elif defined(ENERGIA) // LaunchPad, FraunchPad and StellarPad specific
    #include "Energia.h"
#elif defined(RPI) // Raspberry Pi
    #define RaspberryPi
    // PROGMEM och _P functions are for AVR based microprocessors,
    // so we must normalize these for the ARM processor:
    #define PROGMEM
    #define memcpy_P(dest, src, num) memcpy((dest), (src), (num))
    // Include libraries for RPi:
    #include <string.h> /* memcpy */
    #include <stdlib.h> /* abs */
    #include <stddef.h> /* NULL */
    #include <wiringPi.h>
    #include <stdint.h>
    #define CHANGE 1
    // The following typedefs are needed to be able to compile RCSwitch.cpp
    // with the RPi C++ compiler (g++)
    #ifdef __cplusplus
        extern "C"{
    #endif
        typedef uint8_t boolean;
        typedef uint8_t byte;
    #ifdef __cplusplus
    }
    #endif
    // Last line within Raspberry Pi block
#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

class RCSwitch {

  public:
    RCSwitch();

    void switchOn(int nGroupNumber, int nSwitchNumber);
    void switchOff(int nGroupNumber, 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(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(const char* Code);
    void send(unsigned long Code, unsigned int length);
    void send(const 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

    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(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();
    void sendT1();
    void sendTF();
    void send0();
    void send1();
    void sendSync();
    void transmit(int nHighPulses, int nLowPulses);
    void transmit(HighLow pulses);

    static char* dec2binWcharfill(unsigned long dec, unsigned int length, char fill);

    #if not defined( RCSwitchDisableReceiving )
    static void handleInterrupt0();
    static void handleInterrupt1();
    static bool receiveProtocol(const int p, unsigned int changeCount, unsigned int interrupt);
    int nReceiverInterrupt;
    #endif
    int nTransmitterPin;
    int nRepeatTransmit;

    Protocol protocol;

    #if not defined( RCSwitchDisableReceiving )
    static int nReceiveTolerance;
    static unsigned long nReceivedValue;
    static unsigned int nReceivedBitlength;
    static unsigned int nReceivedDelay;
    static unsigned int nReceivedProtocol;
    const static unsigned int nSeparationLimit;
    /*
     * timings[0] contains sync timing, followed by a number of bits
     */
    static unsigned int timings0[RCSWITCH_MAX_CHANGES];
    static unsigned int timings1[RCSWITCH_MAX_CHANGES];
    #endif


};

#endif

Implement a learning mode

I think it wouldn't be hard to implement a "learning" mode, where rc-switch detects signals it does not know before, and then replays them later.

One part of this is a modified receive function, which simply records an input, and a "replay" function which retransmits the prior signal.

This could also be helpful while debugging new protocols: Record a signal, then print it to serial.

Then, the next step is some code which takes a recorded signal, and performs a simple statistcal analysis, to determine the base pulse length, and the high/low patterns for sync, zero, one -- of course that would only work for protocols similar to the existing ones, but I believe that would cover a lot of the systems out there.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.