-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
enhancing radio datatype for non-nRF24 HW #204
Comments
If we go with an abstracted API class, then we could eventually incorporate support for Texas Instruments' chips that can replicate the ESB protocol. That's not a priority though. This might be the beginning of v2.x for the RF24 stack... |
In theory modern C++ provides plenty of functionality to implement different back-ends to provide the same "interface" so to say. This would also in theory allow clone/semi-clone support. |
Do you have alternate suggestions? I'm looking for something that is the most backward compatible, but I keep landing on polymorphism.
Absolutely! It would be better to have a separate implementation lib for the RFM7x chips because the setup operations are so much different from the nRF24L01. |
I hesitate to say this because I haven't researched it. An abstracted API (+ pipe count config) might even allow porting the network layers to HW radios that use a different spectrum entirely (ie RFM69). |
Though I'm not entirely sure about Arduino IDE and its latest C++ version, but the InfiniTime project is probably a good example how hardware abstraction can be done with newer C++: InfiniTimeOrg/InfiniTime#1387 (comment) |
Interesting. I think you'll find that different Arduino cores use (or are pinned to) specific versions of compilers. I'm not sure we can guarantee C++20 compatibility in Arduino. There doesn't seem to be a way for an Arduino lib to specify compiler args like
This has worked well for us in the past for a SPI bus. This doesn't seem geared to building with more than 1 type of HW radio driver. What if you wanted to broadcast 1 network only on channel 90 with 1 radio, and another network only on channel 97 with a different radio? |
Fully optional really, you can utilize There are lower C++ version concepts that could be used as well, like |
No |
So I've been playing around with templates, trying to find a solution to this, and it looks kind of ugly. I'm starting to thing that a bit of
I don't pretend to fully know what I'm doing here, I'm just learning about templates, but it seems like it creates more problems than its worth. See the templateSupport branches of RF24Network and RF24Mesh for some incomplete but functional template code with Arduino Pro Mini and NRF52 devices. |
To be fair, C++ concepts are a kind of template that shouldn't require much change in higher layer abstractions. I've never played with these because I learned C++ before the C++20 std was introduced. Inheritance might be "cleaner" as for code clutter. My main concern is increasing compile size. It has been a while since I tried polymorphism in C++... My initial idea was something like this// in RF24_ABS_API.h (located in RF24 repo)
class RF24_API
{
virtual bool begin() = 0;
}; // in RF24.h
#include "RF24_ABS_API.h"
class RF24 : public RF24_API
{
override bool begin();
}; // in nrf_to_nrf.h
#include "RF24_ABS_API.h"
class nrf_to_nrf : public RF24_API
{
override bool begin();
}; // in RF24Network.h
#include "RF24_ABS_API.h"
class RF24Network
{
RF24Network(RF24_API* radio, ...);
}; |
I'm still seeing some of the same issues with that approach, things largely still need to be defined, and when switching from RF24 to nrf_to_nrf on the NRF52, I still need to manually add a I've got the overrides working for |
You might have to type cast the RF24Network network((RF24_API*)&radio); But this might have consequences. Typically, you'd type cast a derivative (AKA "downcast") to access the base class' API. I'm hoping that the pure virtual methods defined in No matter what we do here, it would require a breaking change throughout the RF24 stack in terms of instantiating the objects that use the radio HW. |
Err, that just gives a different variation of the same error.
Not if we just use I'm starting to think that either way it will be a compromise on how we would ideally like it to work. |
If use defines then it limits the type of radio HW used in a single application, right? I was hoping there was a way to allow various/multiple radio HW types in the same app (eg 1 nRF52 network on channel X and another nRF24 network on channel Y). I don't really have a problem with the |
Yeah, but same with templates as far as I can figure. One thing I found, even with templates, if you have two objects RF24& radio and nrf_to_nrf& radio, you need to initialize them both in a single constructor. This negates the ability to have separate calls to I've struggled over a day of coding trying to make it work with templates and think I've given up. Learned a lot about templates though lol. |
I don't really follow. You should be able to have separate instantiated objects based on the template param. I just starting to look at what you did in the template-support branch, and I think it could be improved... In what you pushed, you're not really using the template param: Lines 74 to 75 in aeb12d7
Lines 60 to 61 in aeb12d7
Typically it would be more like: template<typename RF24_like>
RF24Network<RF24_like>::RF24Network(RF24_like& _radio) : radio(_radio), next_frame(frame_queue) Where the c'tor would be declared in the header file like so: template<typename RF24_like>
class RF24Network
{
RF24Network(RF24_like& radio);
// ...
RF24_like& radio;
}; And, I think each function definition for the RF24Network class would also need the added template<typename RF24_like>
RF24Network<RF24_like>::begin() { /* ... */ } |
Should also be able to set the default value for the template<typename RF24_like = RF24>
class RF24Network
{
RF24Network(RF24_like& radio);
// ...
RF24_like& radio;
}; But, depending on the C++ std used (specifically C++17), a user could instantiate with a blank set of template args: RF24 radio(7, 8);
RF24Network<> network(radio);
// with C++17 or later
RF24Network network(radio);
// using non-default template param value
nrf_to_nrf radio1;
RF24Network<nrf_to_nrf> network(radio1); |
Hahaha, you think? I'll have to take some time and think about this, maybe try again. |
I'm playing with it now (locally). To avoid merge conflicts, I'll post a fair warning if I end up pushing changes to that branch -- or maybe I'll start my own branch. |
Ok, I got it to compile with proper use of template args, but the Adafruit nRF52 Arduino core doesn't use C++17 or newer, so users will have to specify a blank set of template args. I haven't actually got the HW setup to test this, but the modified helloworld_tx example compiles fine (disregarding warnings about nrf_to_nrf src code). #include <SPI.h>
#include <RF24.h>
#include <nrf_to_nrf.h>
#include <RF24Network.h>
RF24 radio(7, 8); // nRF24L01(+) radio attached using Getting Started board
nrf_to_nrf radio1; // nRF24L01(+) radio attached using Getting Started board
RF24Network<> network(radio); // Network uses that radio
RF24Network<nrf_to_nrf> network1(radio1); // Network uses that radio I also hit a snag in which the compiler wasn't aware of the possible template arg values (even with a default value set), but this SO answer helped satisfy the "undefined reference" errors. Basically, I had to add the following to the end of the RF24Network.cpp file: // ensure the compiler is aware of the possible datatype for the template class
template class RF24Network<RF24>;
#ifdef ARDUINO_ARCH_NRF52
template class RF24Network<nrf_to_nrf>;
#endif |
My attempt is on I'm not sure if it is worth it since this templating tactic could be used to support other external radio HW on Linux. But, I think we can typedef (& macro sub) the template stuff out class RF24;
#if defined RF24_LINUX
typedef ESB_RADIO RF24;
#define ESB_RADIO_TEMPLATE_SPEC
#else
#define ESB_RADIO_TEMPLATE_SPEC template<class ESB_RADIO>
#endif And just use the macro |
Hmm, this ain't so different from what I was trying to do, except that it works! The only problem I ran into so far is that it gives linker errors when I try to use nrf_to_nrf on my XIAO BLE Sense 52840 with the MBED core The other core works fine as does the Feather 52840. Tried changing the defines to accommodate and no luck. This is a big step towards getting this issue sorted out! |
The Seeduino MBed core uses a slightly more specific
Nonetheless, it is fixed by adding to the -#ifdef ARDUINO_ARCH_NRF52
+#if defined(ARDUINO_ARCH_NRF52) || defined(ARDUINO_ARCH_NRF52840) BTW, the nrf_to_nrf lib is flagged as incompatible with the mbed core because of the arch specified in the library.properties:
But, I don't see a adequate solution unless |
Could have sworn I tried that, but must have typed it wrong or something :/ |
I still don't know what to do about Linux. It would seem an ideal candidate for non-RF24L01 HW support, but exposing a specialized template class in boost.python is not a trivial change. So far, my efforts to update the individual wrapper have failed to compile. |
FYI, the cmake-based auto-installer has the ability to select a branch for each layer. But this functionality was never exposed to the CLI; it was actually used for testing/developing. I'm guessing it would be a good idea to ask the user for a branch name (defaulting to master) before it installs the lib. Instead of a branch name, I think it could also use a git tag, but I think the installer has to do a The cmake-based installer will only work for versions that have CMake support. If we try to fix that the install script would have to become a lot longer, so it could fallback to the old build/install system (if no root CMakeLists.txt file is present). |
Lets not get too complicated here, I don't think we need to worry too much about older versions, as long as the newer versions have CMake support, we should be OK. Also I just checked Platform IO registry and RF24 was still at v1.4.5 for some reason so I pushed the current code as 1.4.6. The other libs are up-to-date. Just something we need to check on after our next releases. |
That's odd. It is supposed to get deployed to PIO registry in the PIO CI when a release is published. I'll have to investigate... I'm reviewing the cmake installer script, and it was written well enough to not have a significant re-write for the old build system. I'm currently playing around with this idea now. I'm not sure how we could have the old installer forward to the new one though. |
The installer script mods are at the .github repo's |
The logs for that CI run are too old (github removes logs older than 90 days). So, I can't see if it tried deploy to PIO. Given that the CI published the pkg to v1.4.6 release's assets, I think the problem may have been in the CI step's conditional trigger/skip. Since I updated all the CI to be re-usable workflows (post v1.4.6), I think I still need to add the validate_lib_json:
uses: nRF24/.github/.github/workflows/validate_deploy_platformio.yaml@main
secrets: inherit
with:
deploy-release: ${{ github.event_name == 'release' }} |
in accordance with discussion at nRF24/RF24Network#204 uses type definition for RF24Mesh and renames class to ESB_Mesh for backwards compatibility. updates CI to check RF24Network changes specifically for the template-attempt2 branch
CI updated org-wide. 🤞🏼 I also rebased the relevant template-* branches to avoid merge conflicts. |
Still having trouble getting RF24Mesh's PIO CI to install the right branch of RF24Network
But that is the wrong SHA for RF24Network's template-attempt2 branch... It should be |
So are we ready to do this thing? You want me to do the 1.x releases? |
Sorry I've been dragging my feet no real reason here. Yeah, we're ready for release crusade. I didn't see anything noteable in the in the net work layer histories since our last crusade. RF24 lib got some significant updates in the PicoSDK support, but that has been in master for a while and I suspect that people are using master instead of a tagged commit with the PicoSDK because our PicoSDK instructions don't explicitly say to use tags. |
@TMRh20 If you want to do the releases (should be easy with that auto-generate summary button), then I'll open the PRs and start the v1.x branches. I almost forgot about the version bump in the lib.properties/json files. |
Is it ok to remove the initial NRF52Support and templateSupport branches that you started? |
I can do the version bump with the releases, you should be able to remove except for RF24Ethernet branch |
RF24Gateway has only had CI changes since last release. It might be a good idea to make sure the CI deploys to PIO for RF24 v1.4.7 before continuing to publish releases for other layers because they'll all be using the same PIO validate/deploy workflow. |
It deployed to PIO! I verified with the CI logs, then I got the email. 🎉 UPDATE: The network, mesh, and ethernet libs have also been accurately deployed to PIO. |
v1.x branches createdI created a branch rule for each of the new v1.x branches on the network, mesh, and gateway layer. This way the git history should be respected the same as it is for the master branches. v2.0 PRs openI left some open as drafts to indicate that they aren't ready to merge unless the dependency layer has been merged. This is done to remind me to clean up the CI changes I used for testing. |
I know this isn't a goal, but if there are any breaking API changes you want make (like renaming functions with underscores to not have underscores), then this is the chance to do so. I mention this because semantically, it makes sense to remove deprecated functions (or rename functions) in a major version bump. On the topic of deprecated functions: |
So sorry. I'm going to have to step away again... life and whatnot. The PRs look good at a glance, I found some areas where the docstring mods should more explicitly reference the nrf_to_nrf lib. And the usual CI reverts before merging... |
No rush, the 1.x release is in successfully, so whenever you get a chance for 2.0 its all good. |
* apply template to RF24Mesh lib in accordance with discussion at nRF24/RF24Network#204 uses type definition for RF24Mesh and renames class to ESB_Mesh for backwards compatibility. updates CI to check RF24Network changes specifically for the template-attempt2 branch * Update docs for v2.0 * bump major version --------- Co-authored-by: TMRh20 <tmrh20@gmail.com>
* Update for recent template changes to RF24Network and RF24Mesh see nRF24/RF24Network#204 * convert RF24Gateway class into a template uses a typedef for backward compatibility * Update docs for v2.0 --------- Co-authored-by: TMRh20 <tmrh20@gmail.com>
Ok. Its all merged. We can do a v2.0 release crusade whenever you want. I also re-released RF24Mesh to make sure installing v1.1.10 or newer doesn't install RF24Network v2.x in PlatformIO. Older versions of RF24Mesh v1 will likely cause an error when used with RF24Network v2.x because there was nothing in RF24Mesh v1.1.9 or previous stopping PIO from using the latest release of RF24Network. I don't really know if Arduino IDE has version checking for lib deps (see lib specs), but v2 is backward compatible enough for users to migrate. The PIO dependencies were a real pain in the a$$. |
Done! |
This is related to using nRF5x HW under the guise of RF24 API. Currently, the approach to use TMRh20's
nrf_to_nrf
lib is to modify the network layers c'tor. But, this leaves users no option to use the internal nRF5x radio for BLE and an external nRF24 for ESB.My first impression was to overload the network layers' c'tors for nRF5x boards. This way the original behavior still exists, and the new behavior (to support nRF5x radios) is optionally available on the right HW. However, the problem is that the
radio
datatype (RF24
) does not properly describe annrf_to_nrf
object. Remember, RF24 class is the base class for the API. If one inherits from the RF24 class, then they get otherwise unnecessary functionality (private/protected methods like SPI transactions).How do we properly expand HW radio support?
My first guess is to have RF24 class inherit from a base class that declares the abstract public API, namely the functionality required to port the RF24 API to new HW radios. But this might be a breaking change as changing the network/mesh c'tor to use a abstracted datatype for the radio will break older installed versions of RF24* network layers. I almost opened this on RF24 repo because the abstracted API class would likely live in the RF24 lib. This approach feels similar to what the RadioHead lib had done.
I also had a thought about declaring
typedef
s for compatible RF24-API objects, but my expertise in C is lacking. So, I'm not sure if this idea is plausible at all.The text was updated successfully, but these errors were encountered: