Rewrote library to allow for multiple RX pins - #2
Open
Ernest314 wants to merge 3 commits into
Open
Conversation
WARNING: This breaks the current API (although a fix is simple enough). Rewrote example (`ReceiveDemo_Advanced.ino`) to use the new API. The number of RX pins must be defined at compile-time with #define RCSWITCH_MAX_RX_PINS.
Author
|
I can add functions which will fix the API if you would like. |
Owner
|
Hi Ernest! Sorry for very long response time! I will test it out tomorrow and let you know if everything works as expected! |
shamigulov
approved these changes
Apr 9, 2017
Mehdidadash
approved these changes
Mar 27, 2022
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WARNING: This breaks the current API (although a fix is simple enough).
Rewrote example (
ReceiveDemo_Advanced.ino) to use the new API.The number of RX pins must be defined at compile-time with
#define RCSWITCH_MAX_RX_PINS.Root cause
Previously, if multiple pins were enabled at once (with
enableReceive(int interrupt)), the interrupt handler for decoding signals was attached to both(/all) pins. But because interrupts must interface with the main program solely through global/static variables, and have no other information (e.g. callbacks), there is no way for the interrupt handler to know what pin actually triggered the interrupt. Therefore, when multiple pins were naïvely attached, noise from each pin--which would normally be filtered out--would be present, making it impossible to work with the data.There is the additional issue that the version of RCSwitch that Particle uses (repo here) is very out-of-date, which causes a few extra problems. The implementation of many functions is different from those in the official version, there is missing support for many protocols, and the API is slightly different. For the official RCSwitch library, there have been attempts in the past to implement multiple-pin RX (see here and here), but none have been successful. I have opened an issue detailing the changes needed to get multiple-pin RX actually working, but due to how behind the Particle library is, patching it into the official library is non-trivial (will either require porting or updating Particle's library to match the current official repo).
Solution
To address this issue, the simplest solution is to separate the global/static data used in the interrupt handler into different sets per RX pin (create an array), and size it based off a
#defined variable. (e.g.#define RCSWITCH_MAX_RX_PINS 2). This use of a macro#defineis acceptable because the number of RX pins needed is something that changes infrequently and is well-known to the developer, and also because this library is intended as performant embedded code (e.g. for MCUs like the ATtiny).I refactored all the data used in the interrupt handler into a struct (
RCSwitch::InterruptData). The static variables are then replaced with an array of these, one per RX pin (RCSwitch::receiverInterrupts[RCSWITCH_MAX_RX_PINS]). All of the code was simply extended to handle the array, and in most cases an additional parameter was added to specify which interrupt pin was intended. There is the issue of identifying each element of the array: I included aRCSwitch::InterruptData.interruptmember in the struct for this purpose. (std::mapwould be more straightforward but it is a lot of overhead.) There are also convenience functions which convert from array index to interrupt pin, and these functions should be inverses of the process since each pin can only be used for a single interrupt. (To actually perform the conversion, the array is simply searched for a matching interrupt pin. This is acceptable becauseRCSWITCH_MAX_RX_PINSshould be small, and this search should have a negligible performance impact.) Another thing to note: functions might take arguments dealing with array index or interrupt pin, and these different arguments are differentiated withint interrupt_iandint interrupt, respectively. (Most of the functions takingint interrupt_ishould beprivate.)I also added an additional member,
int nInterruptSourcePin, which is updated with the last RX pin to go high. This can be used to fetch which pin triggered the interrupt. In the interrupt handler itself, the data (in theRCSwitch::InterruptDataarray) is tracked separately for each pin, with a newisPinPrevHighmember in the data struct. This ensures that the correct member ofRCSwitch::receiverInterruptsis updated by the handler.