From 117b67090090fe86d93b522025e3bb8d5205bd6f Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Sat, 9 May 2020 22:12:39 +0430 Subject: [PATCH 1/7] Update library.properties already compatible with stm32duino --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 05dbffc..2fa4854 100644 --- a/library.properties +++ b/library.properties @@ -6,5 +6,5 @@ sentence=Operate 433/315Mhz devices. paragraph=Use your Arduino, ESP8266/ESP32 or Raspberry Pi to operate remote radio controlled devices. This will most likely work with all popular low cost power outlet sockets. category=Device Control url=https://github.com/sui77/rc-switch -architectures=avr,esp8266,esp32 +architectures=avr,esp8266,esp32,stm32 includes=RCSwitch.h From 1969dadc260b363f2b3f2d8aff299b3e0921580f Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Fri, 15 May 2020 01:06:01 +0430 Subject: [PATCH 2/7] Update RCSwitch.cpp move changeCount check to interrupt handler main routine in order to reduce overhead of calculations in the receiveProtocol() function. --- RCSwitch.cpp | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/RCSwitch.cpp b/RCSwitch.cpp index ac55acb..2ce750f 100644 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -651,16 +651,12 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun return false; } } - - if (changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise - RCSwitch::nReceivedValue = code; - RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; - RCSwitch::nReceivedDelay = delay; - RCSwitch::nReceivedProtocol = p; - return true; - } - - return false; + + RCSwitch::nReceivedValue = code; + RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; + RCSwitch::nReceivedDelay = delay; + RCSwitch::nReceivedProtocol = p; + return true; } void RECEIVE_ATTR RCSwitch::handleInterrupt() { @@ -682,7 +678,7 @@ void RECEIVE_ATTR RCSwitch::handleInterrupt() { // here that a sender will send the signal multiple times, // with roughly the same gap between them). repeatCount++; - if (repeatCount == 2) { + if (repeatCount == 2 && changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise for(unsigned int i = 1; i <= numProto; i++) { if (receiveProtocol(i, changeCount)) { // receive succeeded for protocol i From b52029bc5f8885e86740b802ffd29c4b0e74f38e Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Mon, 18 May 2020 23:10:32 +0430 Subject: [PATCH 3/7] Update RCSwitch.cpp enable multi instances of rc-switch support. --- RCSwitch.cpp | 90 ++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 48 deletions(-) diff --git a/RCSwitch.cpp b/RCSwitch.cpp index 2ce750f..592f599 100644 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -93,16 +93,10 @@ enum { }; #if not defined( RCSwitchDisableReceiving ) -volatile unsigned long RCSwitch::nReceivedValue = 0; -volatile unsigned int RCSwitch::nReceivedBitlength = 0; -volatile unsigned int RCSwitch::nReceivedDelay = 0; -volatile unsigned int RCSwitch::nReceivedProtocol = 0; -int RCSwitch::nReceiveTolerance = 60; const unsigned int RCSwitch::nSeparationLimit = 4300; // separationLimit: minimum microseconds between received codes, closer codes are ignored. // according to discussion on issue #14 it might be more suitable to set the separation // limit to the same time as the 'low' part of the sync signal for the current protocol. -unsigned int RCSwitch::timings[RCSWITCH_MAX_CHANGES]; #endif RCSwitch::RCSwitch() { @@ -112,7 +106,10 @@ RCSwitch::RCSwitch() { #if not defined( RCSwitchDisableReceiving ) this->nReceiverInterrupt = -1; this->setReceiveTolerance(60); - RCSwitch::nReceivedValue = 0; + this->nReceivedValue = 0; + this->nReceivedBitlength = 0; + this->nReceivedDelay = 0; + this->nReceivedProtocol = 0; #endif } @@ -165,7 +162,7 @@ void RCSwitch::setRepeatTransmit(int nRepeatTransmit) { */ #if not defined( RCSwitchDisableReceiving ) void RCSwitch::setReceiveTolerance(int nPercent) { - RCSwitch::nReceiveTolerance = nPercent; + this->nReceiveTolerance = nPercent; } #endif @@ -548,12 +545,12 @@ void RCSwitch::enableReceive(int interrupt) { void RCSwitch::enableReceive() { if (this->nReceiverInterrupt != -1) { - RCSwitch::nReceivedValue = 0; - RCSwitch::nReceivedBitlength = 0; + this->nReceivedValue = 0; + this->nReceivedBitlength = 0; #if defined(RaspberryPi) // Raspberry Pi wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); #else // Arduino - attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + attachInterrupt(this->nReceiverInterrupt, std::bind(&RCSwitch::handleInterrupt, this), CHANGE); #endif } } @@ -569,31 +566,31 @@ void RCSwitch::disableReceive() { } bool RCSwitch::available() { - return RCSwitch::nReceivedValue != 0; + return this->nReceivedValue != 0; } void RCSwitch::resetAvailable() { - RCSwitch::nReceivedValue = 0; + this->nReceivedValue = 0; } unsigned long RCSwitch::getReceivedValue() { - return RCSwitch::nReceivedValue; + return this->nReceivedValue; } unsigned int RCSwitch::getReceivedBitlength() { - return RCSwitch::nReceivedBitlength; + return this->nReceivedBitlength; } unsigned int RCSwitch::getReceivedDelay() { - return RCSwitch::nReceivedDelay; + return this->nReceivedDelay; } unsigned int RCSwitch::getReceivedProtocol() { - return RCSwitch::nReceivedProtocol; + return this->nReceivedProtocol; } unsigned int* RCSwitch::getReceivedRawdata() { - return RCSwitch::timings; + return this->timings; } /* helper function for the receiveProtocol method */ @@ -615,8 +612,8 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun unsigned long code = 0; //Assuming the longer pulse length is the pulse captured in timings[0] const unsigned int syncLengthInPulses = ((pro.syncFactor.low) > (pro.syncFactor.high)) ? (pro.syncFactor.low) : (pro.syncFactor.high); - const unsigned int delay = RCSwitch::timings[0] / syncLengthInPulses; - const unsigned int delayTolerance = delay * RCSwitch::nReceiveTolerance / 100; + const unsigned int delay = this->timings[0] / syncLengthInPulses; + const unsigned int delayTolerance = delay * this->nReceiveTolerance / 100; /* For protocols that start low, the sync period looks like * _________ @@ -639,11 +636,11 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun for (unsigned int i = firstDataTiming; i < changeCount - 1; i += 2) { code <<= 1; - if (diff(RCSwitch::timings[i], delay * pro.zero.high) < delayTolerance && - diff(RCSwitch::timings[i + 1], delay * pro.zero.low) < delayTolerance) { + if (diff(this->timings[i], delay * pro.zero.high) < delayTolerance && + diff(this->timings[i + 1], delay * pro.zero.low) < delayTolerance) { // zero - } else if (diff(RCSwitch::timings[i], delay * pro.one.high) < delayTolerance && - diff(RCSwitch::timings[i + 1], delay * pro.one.low) < delayTolerance) { + } else if (diff(this->timings[i], delay * pro.one.high) < delayTolerance && + diff(this->timings[i + 1], delay * pro.one.low) < delayTolerance) { // one code |= 1; } else { @@ -651,53 +648,50 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun return false; } } - - RCSwitch::nReceivedValue = code; - RCSwitch::nReceivedBitlength = (changeCount - 1) / 2; - RCSwitch::nReceivedDelay = delay; - RCSwitch::nReceivedProtocol = p; - return true; -} -void RECEIVE_ATTR RCSwitch::handleInterrupt() { - static unsigned int changeCount = 0; - static unsigned long lastTime = 0; - static unsigned int repeatCount = 0; + this->nReceivedValue = code; + this->nReceivedBitlength = (changeCount - 1) / 2; + this->nReceivedDelay = delay; + this->nReceivedProtocol = p; + return true; - const long time = micros(); - const unsigned int duration = time - lastTime; +} +void RECEIVE_ATTR RCSwitch::handleInterrupt() { + const long time = micros(); + const unsigned int duration = time - this->lastTime; + if (duration > RCSwitch::nSeparationLimit) { // A long stretch without signal level change occurred. This could // be the gap between two transmission. - if ((repeatCount==0) || (diff(duration, RCSwitch::timings[0]) < 200)) { + if ((this->repeatCount==0) || (diff(duration, this->timings[0]) < 200)) { // This long signal is close in length to the long signal which // started the previously recorded timings; this suggests that // it may indeed by a a gap between two transmissions (we assume // here that a sender will send the signal multiple times, // with roughly the same gap between them). - repeatCount++; - if (repeatCount == 2 && changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise + this->repeatCount++; + if (this->repeatCount == 2 && this->changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise) for(unsigned int i = 1; i <= numProto; i++) { - if (receiveProtocol(i, changeCount)) { + if (receiveProtocol(i, this->changeCount)) { // receive succeeded for protocol i break; } } - repeatCount = 0; + this->repeatCount = 0; } } - changeCount = 0; + this->changeCount = 0; } // detect overflow - if (changeCount >= RCSWITCH_MAX_CHANGES) { - changeCount = 0; - repeatCount = 0; + if (this->changeCount >= RCSWITCH_MAX_CHANGES) { + this->changeCount = 0; + this->repeatCount = 0; } - RCSwitch::timings[changeCount++] = duration; - lastTime = time; + this->timings[changeCount++] = duration; + this->lastTime = time; } #endif From ea422adec5422019576439ddc0f4ced88dcb4e22 Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Mon, 18 May 2020 23:10:57 +0430 Subject: [PATCH 4/7] Update RCSwitch.h enable multi instances of rc-switch support. --- RCSwitch.h | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/RCSwitch.h b/RCSwitch.h index b7755e0..8a27b22 100644 --- a/RCSwitch.h +++ b/RCSwitch.h @@ -156,8 +156,8 @@ class RCSwitch { void transmit(HighLow pulses); #if not defined( RCSwitchDisableReceiving ) - static void handleInterrupt(); - static bool receiveProtocol(const int p, unsigned int changeCount); + void handleInterrupt(); + bool receiveProtocol(const int p, unsigned int changeCount); int nReceiverInterrupt; #endif int nTransmitterPin; @@ -166,16 +166,22 @@ class RCSwitch { Protocol protocol; #if not defined( RCSwitchDisableReceiving ) - static int nReceiveTolerance; - volatile static unsigned long nReceivedValue; - volatile static unsigned int nReceivedBitlength; - volatile static unsigned int nReceivedDelay; - volatile static unsigned int nReceivedProtocol; + int nReceiveTolerance; + volatile unsigned long nReceivedValue; + volatile unsigned int nReceivedBitlength; + volatile unsigned int nReceivedDelay; + volatile unsigned int nReceivedProtocol; const static unsigned int nSeparationLimit; + /* + * Required values for interrupt handler + */ + unsigned int changeCount = 0; + unsigned long lastTime = 0; + unsigned int repeatCount = 0; /* * timings[0] contains sync timing, followed by a number of bits */ - static unsigned int timings[RCSWITCH_MAX_CHANGES]; + unsigned int timings[RCSWITCH_MAX_CHANGES]; #endif From 94c5d6ec4abdd3cb2b55611ed02130c80dfdb4d9 Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Mon, 13 Nov 2023 22:40:19 +0330 Subject: [PATCH 5/7] update for rp2040 and stm32 and remove AVR this update adds support for RP2040 cores and some minor fixes for stm32. for now I have to remove AVR support because of the attachInterupt function callback problem not being supported. --- RCSwitch.cpp | 80 +++++++++++++++++++++++++++++++++++++++++++--------- RCSwitch.h | 4 +++ 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/RCSwitch.cpp b/RCSwitch.cpp index b8f89cd..ba32378 100644 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -34,6 +34,10 @@ #include "RCSwitch.h" +#if (defined(ARDUINO_ARCH_RP2040) || defined(STM32_CORE_VERSION)) +#include +#endif + #ifdef RaspberryPi // PROGMEM and _P functions are for AVR based microprocessors, // so we must normalize these for the ARM processor: @@ -556,8 +560,13 @@ void RCSwitch::enableReceive() { this->nReceivedBitlength = 0; #if defined(RaspberryPi) // Raspberry Pi wiringPiISR(this->nReceiverInterrupt, INT_EDGE_BOTH, &handleInterrupt); -#else // Arduino - attachInterrupt(this->nReceiverInterrupt, std::bind(&RCSwitch::handleInterrupt, this), CHANGE); +#elif defined(ARDUINO_ARCH_RP2040) + attachInterruptParam(this->nReceiverInterrupt, &RCSwitch::handleInterrupt, CHANGE, this); +#elif defined(STM32_CORE_VERSION) + attachInterrupt(this->nReceiverInterrupt, std::bind(&RCSwitch::handleInterrupt, this), CHANGE); +#else // Arduino + //attachInterrupt(this->nReceiverInterrupt, [this](){ this->handleInterrupt(); }, CHANGE); + #error not supported #endif } } @@ -665,40 +674,83 @@ bool RECEIVE_ATTR RCSwitch::receiveProtocol(const int p, unsigned int changeCoun } +#if defined(ARDUINO_ARCH_RP2040) +void RCSwitch::handleInterrupt(void* obj) +{ + RCSwitch* thiz = static_cast(obj); + const long time = micros(); + const unsigned int duration = time - thiz->lastTime; + + if (duration > RCSwitch::nSeparationLimit) { + // A long stretch without signal level change occurred. This could + // be the gap between two transmission. + if ((thiz->repeatCount==0) || (diff(duration, thiz->timings[0]) < 200)) { + // This long signal is close in length to the long signal which + // started the previously recorded timings; this suggests that + // it may indeed by a a gap between two transmissions (we assume + // here that a sender will send the signal multiple times, + // with roughly the same gap between them). + thiz->repeatCount++; + if (thiz->repeatCount == 2 && thiz->changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise) + for(unsigned int i = 1; i <= numProto; i++) { + if (thiz->receiveProtocol(i, thiz->changeCount)) { + // receive succeeded for protocol i + break; + } + } + thiz->repeatCount = 0; + } + } + thiz->changeCount = 0; + } + + // detect overflow + if (thiz->changeCount >= RCSWITCH_MAX_CHANGES) { + thiz->changeCount = 0; + thiz->repeatCount = 0; + } + + thiz->timings[thiz->changeCount++] = duration; + thiz->lastTime = time; +} + +#else void RECEIVE_ATTR RCSwitch::handleInterrupt() { const long time = micros(); - const unsigned int duration = time - this->lastTime; + const unsigned int duration = time - lastTime; if (duration > RCSwitch::nSeparationLimit) { // A long stretch without signal level change occurred. This could // be the gap between two transmission. - if ((this->repeatCount==0) || (diff(duration, this->timings[0]) < 200)) { + if ((repeatCount==0) || (diff(duration, timings[0]) < 200)) { // This long signal is close in length to the long signal which // started the previously recorded timings; this suggests that // it may indeed by a a gap between two transmissions (we assume // here that a sender will send the signal multiple times, // with roughly the same gap between them). - this->repeatCount++; - if (this->repeatCount == 2 && this->changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise) + repeatCount++; + if (repeatCount == 2 && changeCount > 7) { // ignore very short transmissions: no device sends them, so this must be noise) for(unsigned int i = 1; i <= numProto; i++) { - if (receiveProtocol(i, this->changeCount)) { + if (receiveProtocol(i, changeCount)) { // receive succeeded for protocol i break; } } - this->repeatCount = 0; + repeatCount = 0; } } - this->changeCount = 0; + changeCount = 0; } // detect overflow - if (this->changeCount >= RCSWITCH_MAX_CHANGES) { - this->changeCount = 0; - this->repeatCount = 0; + if (changeCount >= RCSWITCH_MAX_CHANGES) { + changeCount = 0; + repeatCount = 0; } - this->timings[changeCount++] = duration; - this->lastTime = time; + timings[changeCount++] = duration; + lastTime = time; } #endif + +#endif diff --git a/RCSwitch.h b/RCSwitch.h index 8a27b22..9821488 100644 --- a/RCSwitch.h +++ b/RCSwitch.h @@ -156,7 +156,11 @@ class RCSwitch { void transmit(HighLow pulses); #if not defined( RCSwitchDisableReceiving ) + #if defined(ARDUINO_ARCH_RP2040) + static void handleInterrupt(void*); + #else void handleInterrupt(); + #endif bool receiveProtocol(const int p, unsigned int changeCount); int nReceiverInterrupt; #endif From b97f83a89f0f8dc59b153efa71288eeacc8875c6 Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Tue, 14 Nov 2023 13:48:21 +0330 Subject: [PATCH 6/7] Update README.md notes for future development --- README.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/README.md b/README.md index f6a679c..fd110f5 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,17 @@ +#This library compiles for STM32 and RP2040 but not Arduino AVR like Nano +to add support one has to figure out how to pass a non-static class member with `this` object to the attachInterupt +function. +other repos for future reference +https://github.com/maniacbug/StandardCplusplus +https://github.com/kekyo/BoostForArduino +https://github.com/vancegroup/arduino-boost +https://github.com/Stivius/callable-wrapper +https://github.com/fopeczek/function_objects +https://github.com/danyhm/functional +I could get std::bind to work on Arduino Nano however I can't convert it back to c style function pointer. +It seems it's possible to do it using boost library. however i couldn't get it to compile on Arduino. +another method is to change Arduino Core files to implement attachInterruptEx or attachInterruptParam + # rc-switch [![arduino-library-badge](https://www.ardu-badge.com/badge/rc-switch.svg?)](https://www.ardu-badge.com/rc-switch) [![Build Status](https://travis-ci.org/sui77/rc-switch.svg?branch=master)](https://travis-ci.org/sui77/rc-switch) From aaff22a5231e436fa3026101835a73382da5de9b Mon Sep 17 00:00:00 2001 From: danyhm <21024667+danyhm@users.noreply.github.com> Date: Tue, 23 Jan 2024 12:16:00 +0330 Subject: [PATCH 7/7] update --- RCSwitch.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RCSwitch.cpp b/RCSwitch.cpp index ba32378..dbf0fc3 100644 --- a/RCSwitch.cpp +++ b/RCSwitch.cpp @@ -565,8 +565,9 @@ void RCSwitch::enableReceive() { #elif defined(STM32_CORE_VERSION) attachInterrupt(this->nReceiverInterrupt, std::bind(&RCSwitch::handleInterrupt, this), CHANGE); #else // Arduino - //attachInterrupt(this->nReceiverInterrupt, [this](){ this->handleInterrupt(); }, CHANGE); - #error not supported + attachInterrupt(this->nReceiverInterrupt, &RCSwitch::handleInterrupt, CHANGE); + //attachInterrupt(this->nReceiverInterrupt, handleInterrupt, CHANGE); + //#error not supported #endif } }