From 2bfde05df4e0ce44d3181903013b425dae1f057e Mon Sep 17 00:00:00 2001 From: Brendan <2bndy5@gmail.com> Date: Sat, 27 Nov 2021 09:45:05 -0800 Subject: [PATCH] Reverse Engineering tricks (#804) * new toggleAllPipes() function * add toggleAllPipes() to python wrapper * trigger linux CI on changes to python wrapper * add new function setRadiation() * use uint8_t level like setPALevel() does * fix typo in docs reference * add new functions to sphinx docs * ran a hardware test; looks good --- .github/workflows/build_linux.yml | 2 + RF24.cpp | 106 +++++++++++++++++++----------- RF24.h | 37 +++++++++++ docs/sphinx/classRF24.rst | 2 + pyRF24/pyRF24.cpp | 2 + 5 files changed, 111 insertions(+), 38 deletions(-) diff --git a/.github/workflows/build_linux.yml b/.github/workflows/build_linux.yml index 670d59f98..174ff2fea 100644 --- a/.github/workflows/build_linux.yml +++ b/.github/workflows/build_linux.yml @@ -20,6 +20,7 @@ on: - "!examples_linux/*.py" - "!examples_linux/*.md" - "pyRF24/setup.py" + - "pyRF24/pyRF24.cpp" - ".github/workflows/build_linux.yml" push: paths: @@ -39,6 +40,7 @@ on: - "!examples_linux/*.py" - "!examples_linux/*.md" - "pyRF24/setup.py" + - "pyRF24/pyRF24.cpp" - ".github/workflows/build_linux.yml" release: types: [published, edited] diff --git a/RF24.cpp b/RF24.cpp index 454574b66..1fd63d82a 100644 --- a/RF24.cpp +++ b/RF24.cpp @@ -924,8 +924,9 @@ bool RF24::_init_radio() setRetries(5, 15); // Then set the data rate to the slowest (and most reliable) speed supported by all - // hardware. - setDataRate(RF24_1MBPS); + // hardware. Since this value occupies the same register as the PA level value, set + // the PA level to MAX + setRadiation(RF24_PA_MAX, RF24_1MBPS); // LNA enabled by default // detect if is a plus variant & use old toggle features command accordingly uint8_t before_toggle = read_register(FEATURE); @@ -1670,16 +1671,9 @@ bool RF24::testRPD(void) void RF24::setPALevel(uint8_t level, bool lnaEnable) { - - uint8_t setup = read_register(RF_SETUP) & 0xF8; - - if (level > 3) { // If invalid level, go to max PA - level = static_cast((RF24_PA_MAX << 1) + lnaEnable); // +1 to support the SI24R1 chip extra bit - } else { - level = static_cast((level << 1) + lnaEnable); // Else set level as requested - } - - write_register(RF_SETUP, setup |= level); // Write it to the chip + uint8_t setup = read_register(RF_SETUP) & static_cast(0xF8); + setup |= _pa_level_reg_value(level, lnaEnable); + write_register(RF_SETUP, setup); } /****************************************************************************/ @@ -1707,33 +1701,8 @@ bool RF24::setDataRate(rf24_datarate_e speed) // HIGH and LOW '00' is 1Mbs - our default setup = static_cast(setup & ~(_BV(RF_DR_LOW) | _BV(RF_DR_HIGH))); + setup |= _data_rate_reg_value(speed); - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay = 280; - #else //16Mhz Arduino - txDelay=85; - #endif - if (speed == RF24_250KBPS) { - // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 - // Making it '10'. - setup |= _BV(RF_DR_LOW); - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay = 505; - #else //16Mhz Arduino - txDelay = 155; - #endif - } else { - // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 - // Making it '01' - if (speed == RF24_2MBPS) { - setup |= _BV(RF_DR_HIGH); - #if !defined(F_CPU) || F_CPU > 20000000 - txDelay = 240; - #else // 16Mhz Arduino - txDelay = 65; - #endif - } - } write_register(RF_SETUP, setup); // Verify our result @@ -1851,6 +1820,7 @@ void RF24::startConstCarrier(rf24_pa_dbm_e level, uint8_t channel) } /****************************************************************************/ + void RF24::stopConstCarrier() { /* @@ -1863,3 +1833,63 @@ void RF24::stopConstCarrier() write_register(RF_SETUP, static_cast(read_register(RF_SETUP) & ~_BV(CONT_WAVE) & ~_BV(PLL_LOCK))); ce(LOW); } + +/****************************************************************************/ + +void RF24::toggleAllPipes(bool isEnabled) +{ + write_register(EN_RXADDR, static_cast(isEnabled ? 0x3F : 0)); +} + +/****************************************************************************/ + +uint8_t RF24::_data_rate_reg_value(rf24_datarate_e speed) +{ + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 280; + #else //16Mhz Arduino + txDelay=85; + #endif + if (speed == RF24_250KBPS) { + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 505; + #else //16Mhz Arduino + txDelay = 155; + #endif + // Must set the RF_DR_LOW to 1; RF_DR_HIGH (used to be RF_DR) is already 0 + // Making it '10'. + return static_cast(_BV(RF_DR_LOW)); + } + else if (speed == RF24_2MBPS) { + #if !defined(F_CPU) || F_CPU > 20000000 + txDelay = 240; + #else // 16Mhz Arduino + txDelay = 65; + #endif + // Set 2Mbs, RF_DR (RF_DR_HIGH) is set 1 + // Making it '01' + return static_cast(_BV(RF_DR_HIGH)); + } + // HIGH and LOW '00' is 1Mbs - our default + return static_cast(0); + +} + +/****************************************************************************/ + +uint8_t RF24::_pa_level_reg_value(uint8_t level, bool lnaEnable) +{ + // If invalid level, go to max PA + // Else set level as requested + // + lnaEnable (1 or 0) to support the SI24R1 chip extra bit + return static_cast(((level > RF24_PA_MAX ? static_cast(RF24_PA_MAX) : level) << 1) + lnaEnable); +} + +/****************************************************************************/ + +void RF24::setRadiation(uint8_t level, rf24_datarate_e speed, bool lnaEnable) +{ + uint8_t setup = _data_rate_reg_value(speed); + setup |= _pa_level_reg_value(level, lnaEnable); + write_register(RF_SETUP, setup); +} diff --git a/RF24.h b/RF24.h index ee7698041..59472461b 100644 --- a/RF24.h +++ b/RF24.h @@ -1642,6 +1642,26 @@ class RF24 { */ void stopConstCarrier(void); + /** + * @brief Open or close all data pipes. + * + * This function does not alter the addresses assigned to pipes. It is simply a + * convenience function that allows controling all pipes at once. + * @param isEnabled `true` opens all pipes; `false` closes all pipes. + */ + void toggleAllPipes(bool isEnabled); + + /** + * @brief configure the RF_SETUP register in 1 transaction + * @param level This parameter is the same input as setPALevel()'s `level` parameter. + * See @ref rf24_pa_dbm_e enum for accepted values. + * @param speed This parameter is the same input as setDataRate()'s `speed` parameter. + * See @ref rf24_datarate_e enum for accepted values. + * @param lnaEnable This optional parameter is the same as setPALevel()'s `lnaEnable` + * optional parameter. Defaults to `true` (meaning LNA feature is enabled) when not specified. + */ + void setRadiation(uint8_t level, rf24_datarate_e speed, bool lnaEnable = true); + /**@}*/ /** * @name Deprecated @@ -1864,6 +1884,23 @@ class RF24 { #endif + /** + * @brief Manipulate the @ref Datarate and txDelay + * + * This is a helper function to setRadiation() and setDataRate() + * @param speed The desired data rate. + */ + inline uint8_t _data_rate_reg_value(rf24_datarate_e speed); + + /** + * @brief Manipulate the @ref PALevel + * + * This is a helper function to setRadiation() and setPALevel() + * @param level The desired @ref PALevel. + * @param lnaEnable Toggle the LNA feature. + */ + inline uint8_t _pa_level_reg_value(uint8_t level, bool lnaEnable); + /**@}*/ }; diff --git a/docs/sphinx/classRF24.rst b/docs/sphinx/classRF24.rst index a29f490dc..42c16c883 100644 --- a/docs/sphinx/classRF24.rst +++ b/docs/sphinx/classRF24.rst @@ -84,6 +84,8 @@ Configuration API .. doxygenfunction:: RF24::maskIRQ .. doxygenfunction:: RF24::startConstCarrier .. doxygenfunction:: RF24::stopConstCarrier +.. doxygenfunction:: RF24::toggleAllPipes +.. doxygenfunction:: RF24::setRadiation Protected API ============== diff --git a/pyRF24/pyRF24.cpp b/pyRF24/pyRF24.cpp index a21bb8b9d..9e72c00b9 100644 --- a/pyRF24/pyRF24.cpp +++ b/pyRF24/pyRF24.cpp @@ -316,6 +316,8 @@ BOOST_PYTHON_MODULE(RF24) .def("stopListening", &RF24::stopListening) .def("testCarrier", &RF24::testCarrier) .def("testRPD", &RF24::testRPD) + .def("toggleAllPipes", &RF24::toggleAllPipes) + .def("setRadiation", &RF24::setRadiation) .def("txStandBy", (bool (::RF24::*)(::uint32_t, bool))(&RF24::txStandBy), txStandBy_wrap1(bp::args("timeout", "startTx"))) .def("whatHappened", &whatHappened_wrap) .def("startConstCarrier", &RF24::startConstCarrier, (bp::arg("level"), bp::arg("channel")))