Breaking backward compatibility changes -- next Release will be 2.0
NEWavailable() function provided as a convenience instead of using nrf.update() and nrf.pipe is not None (a technique introduced in the last release). To expose this new available() function in the FakeBLE API, I had to rename the current available() function to len_available().
RENAMEDrecv() is now read(). The descriptive name read() makes more sense because this function isn't actually doing the receiving, rather it is simply reading payload data that was already received and stored in the radio's RX FIFO.
RENAMEDwhat_happened() to print_details(). The name "what_happened" came from my misunderstanding of the TMRh20 library's RF24::whatHappened() (& partly I just liked the name). Now, using "print_details" makes more sense because it is an apt description of what the function actually does.
REMOVEDFakeBLE.to_android attribute because it was marked for deprecation.
REMOVEDRF24.read_ack() function because it was marked for deprecation.
All examples now use time.monotonic_ns() to measure transmission times. This change requires Python v3.7 in Linux, thus setup.py stipulates this requirement via python_requires option. Recommend using latest release of the Raspberry Pi OS which ships with Python v3.7.2 (as of this writing).
auto_ack returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.
dynamic_payloads returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.
payload_length returns the current setting of pipe 0 instead of a list for all pipes. This actually fixes a bug that allowed a flood of other subsequent bugs.
In v1.2.0 - v1.2.3, if a user called payload_length[0] = 0, there was nothing in the code to prevent this mis-configuration (payload length cannot be 0). Furthermore this mis-configuration was not written to the corresponding nRF24L01 registers which would cause errors in every other function that handled payloads and/or payload lengths (namely any(), send(), write(), recv(), & what_happened(True))
Code Changes Include
TRANSMISSIONS THAT PREVIOUSLY TOOK 32 MILLISECONDS NOW TAKE ABOUT 2 OR 3 MILLISECONDS!!! (~10x Speed-up!) I've achieved this huge speed-up on this branch by removing the time.sleep(0.005) calls in the SPI access functions. To compensate for the inherent CSN pin bouncing instability, I've implemented the extra_clocks=8 parameter to Circuitpython's SPIDevice c'tor. Essentially this means that after the CSN pin is set inactive HIGH, the SPIDevice object writes another dummy byte to let the CSN pin settle. This technique is faster than trying to do a time-based delay using time.sleep() (& also turns the disadvantage of Python's slow execution time into more of a strength). I'm aware that this technique is meant for SD cards and is dependent on the SPI bus' frequency, but if we encounter problems... I'll cross that bridge if we come to it.
Removed any other time.sleep() call that waited for less than 100 microseconds. Also, I took an idea from TMRh20's RF24::write() and moved the ce_pin.value = 0 call to after the resulting status flags are asserted.
REMOVED the CSN_DELAY constant since altering its value had no real-time affect on the SPI access functions. Additionally, it isn't needed anymore due to the first point about implementing the huge speed-up.
listen no longer flushes RX FIFO when entering RX mode.
listen now flushes TX FIFO when entering TX mode and ack payloads are enabled.
listen closes pipe 0 if it hasn't been designated for RX when entering RX mode.
open_tx_pipe() does not actually open pipe 0 when auto_ack is enabled. Rather, listen now opens pipe 0 when entering TX mode and auto_ack is enabled for pipe 0.
send() & resend() doesn't clear the Status flags when finished anymore. This change will likely have little impact on applications since the status flags are still cleared when entering write() and resend(). This was done to speed up execution.
auto_ack now force-enables the automatic acknowledgement feature for pipe 0 when any other RX pipe has auto_ack enabled.
NEWset_*() & get_*() publicly exposed functions for auto_ack, dynamic_payloads, payload_length, & ard/arc attributes. These should allow faster, easier, & less error-prone interaction when setting or getting the configuration for said attributes on any individual pipe or all pipes at once. I haven't deprecated the attribute's older setter-decorated functions for backward compatibility (the new set_*() functions still utilize the attribute's setter-decorated functions as helpers).
ard, arc, & crc attributes now clamp invalid input values instead throwing a ValueError exception.
NEWallow_ask_no_ack attribute for unofficial support of the Si24R1 (a flaw from cloning a typo in the nRF24L01 datasheet)
NEWlast_tx_arc attribute for getting the number of retry attempts made in previous transmission. This data was previously only available in what_happened(), I found it useful when helping people troubleshhoot TMRh20's RF24 library.
FakeBLE now inherits from RF24. Some attributes/functions are overridden to raise a NotImplementedError exception, so some vital ingredients to the BLE operation isn't compromised via the FakeBLE API.
close_rx_pipe() now properly prevents the listen attribute from overriding the pipe 0 reading address
print_details() now prints a more accurate representation of the addresses used on the pipes. Like the TMRh20 RF24 library's printDetails(), the address now prints a "hexlified" string in big endian form.
NEWaddress_repr() function (belonging to the rf24.py module not the RF24 class) is the helper function that returns the address specified as a "hexlified" string in big endian form.
Revised examples + new nrf24l01_manual_ack_test.py & nrf24l01_scanner_test.py
NEWscanner_test example that prints a vertical graph of potential RF interference for all applicable frequencies (vertically labeled by channel number).
In making a similar contribution to TMRh20's RF24 library, @TMRh20 kindly emphasized the importance of demonstrating "proper addressing" related to pipe usage. To show my appreciation for the discussion (& lessons learned), the examples have all (except the multiceiver example) been revised to use pipe 0 for TX & pipe 1 for RX. This revision adds a preliminary prompt that asks "Which radio is this?" Whereby:
entering 0 uses b"1Node" on pipe 0 and b"2Node" on pipe 1
entering 1 uses b"2Node" on pipe 0 and b"1Node" on pipe 1
some examples' payloads have also been altered. This has been done to match the new examples I've submitted to TMRh20's RF24 library.
simple_test uses a incrementing float that persists between calling master() & slave()
ack_payload_test shows data structure usage and C-string's NULL terminating char with a counter that increments on successful transmissions and persists between calling master() & slave()
NEWmanual_ack_test mimics the ack_payload_test, but it doesn't use ACK payloads. Rather it uses manually switch between RX/TX modes.
multiceiver_test uses an 8 byte payload that is properly packed using Python's struct library (instead of directly encoding the UTF-8 data into the bytearray)
REMOVEDnrf24l01_2arduino_handling_data.py in favor of the NEWnrf24l01_manual_ack_test.py example (they're practically identical).
Compatibility with TMRh20's library now only requires;
dynamic_payloads has to be disabled
payload_length has to be set accordingly to match TMRh20's RF24 new examples' configuration
I've left these 2 lines commented out for easy modification (instead of typing it in the python REPL). Because most examples are compatible with TMRh20's new examples, the docs now have a table and hints about making this library compatible with TMRh20's RF24 library (instead of using 1 dedicated example).
multiceiver_test doesn't use ACK payloads for node(1) anymore. This demonstration was a bit over zealous anyway, and removing it better matches the multiceiverDemo.ino example I submitted to TMRh20's RF24 library.
all examples can be executed from CLI. This change is really helpful in that it requires less typing and less prone to typos (using terminal's auto-complete mechanism). This really only applies to the Linux platform, and there is no support for CLI args because CircuitPython firmware doesn't use them.
Other changes
Behold the new project Logo for usage on rtfd.io and social media links
Also changed the favicon to a miniature version of this logo. This should fall under the repo's MIT license, and I'm pretty sure its not as original as I think it is.
Of course, there are corresponding doc changes to suit all code changes.
Docs now contain retroactive changes related to different versions of the library using Sphinx's admonitions .. versionadded:: and .. versionchanged::.
I've added a feature to the Github action build.yml workflow: Archiving built assets (namely the mpy files for Circuitpython firmware) as workflow artifacts that can be downloaded (for up to a maximum of 90 days).
The PyPi upload process now uses an API key because my PyPi account has 2FA enabled.
Breaking backward compatibility changes -- next Release will be 2.0
available()
function provided as a convenience instead of usingnrf.update() and nrf.pipe is not None
(a technique introduced in the last release). To expose this newavailable()
function in theFakeBLE
API, I had to rename the currentavailable()
function tolen_available()
.recv()
is nowread()
. The descriptive nameread()
makes more sense because this function isn't actually doing the receiving, rather it is simply reading payload data that was already received and stored in the radio's RX FIFO.what_happened()
toprint_details()
. The name "what_happened" came from my misunderstanding of the TMRh20 library'sRF24::whatHappened()
(& partly I just liked the name). Now, using "print_details" makes more sense because it is an apt description of what the function actually does.FakeBLE.to_android
attribute because it was marked for deprecation.RF24.read_ack()
function because it was marked for deprecation.time.monotonic_ns()
to measure transmission times. This change requires Python v3.7 in Linux, thus setup.py stipulates this requirement viapython_requires
option. Recommend using latest release of the Raspberry Pi OS which ships with Python v3.7.2 (as of this writing).auto_ack
returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.dynamic_payloads
returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.payload_length
returns the current setting of pipe 0 instead of a list for all pipes. This actually fixes a bug that allowed a flood of other subsequent bugs.payload_length[0] = 0
, there was nothing in the code to prevent this mis-configuration (payload length cannot be 0). Furthermore this mis-configuration was not written to the corresponding nRF24L01 registers which would cause errors in every other function that handled payloads and/or payload lengths (namelyany()
,send()
,write()
,recv()
, &what_happened(True)
)Code Changes Include
time.sleep(0.005)
calls in the SPI access functions. To compensate for the inherent CSN pin bouncing instability, I've implemented theextra_clocks=8
parameter to Circuitpython'sSPIDevice
c'tor. Essentially this means that after the CSN pin is set inactive HIGH, theSPIDevice
object writes another dummy byte to let the CSN pin settle. This technique is faster than trying to do a time-based delay usingtime.sleep()
(& also turns the disadvantage of Python's slow execution time into more of a strength). I'm aware that this technique is meant for SD cards and is dependent on the SPI bus' frequency, but if we encounter problems... I'll cross that bridge if we come to it.time.sleep()
call that waited for less than 100 microseconds. Also, I took an idea from TMRh20'sRF24::write()
and moved thece_pin.value = 0
call to after the resulting status flags are asserted.CSN_DELAY
constant since altering its value had no real-time affect on the SPI access functions. Additionally, it isn't needed anymore due to the first point about implementing the huge speed-up.listen
no longer flushes RX FIFO when entering RX mode.listen
now flushes TX FIFO when entering TX mode andack
payloads are enabled.listen
closes pipe 0 if it hasn't been designated for RX when entering RX mode.open_tx_pipe()
does not actually open pipe 0 whenauto_ack
is enabled. Rather,listen
now opens pipe 0 when entering TX mode andauto_ack
is enabled for pipe 0.send()
&resend()
doesn't clear the Status flags when finished anymore. This change will likely have little impact on applications since the status flags are still cleared when enteringwrite()
andresend()
. This was done to speed up execution.auto_ack
now force-enables the automatic acknowledgement feature for pipe 0 when any other RX pipe hasauto_ack
enabled.set_*()
&get_*()
publicly exposed functions forauto_ack
,dynamic_payloads
,payload_length
, &ard
/arc
attributes. These should allow faster, easier, & less error-prone interaction when setting or getting the configuration for said attributes on any individual pipe or all pipes at once. I haven't deprecated the attribute's older setter-decorated functions for backward compatibility (the newset_*()
functions still utilize the attribute's setter-decorated functions as helpers).ard
,arc
, &crc
attributes now clamp invalid input values instead throwing aValueError
exception.allow_ask_no_ack
attribute for unofficial support of the Si24R1 (a flaw from cloning a typo in the nRF24L01 datasheet)last_tx_arc
attribute for getting the number of retry attempts made in previous transmission. This data was previously only available inwhat_happened()
, I found it useful when helping people troubleshhoot TMRh20's RF24 library.FakeBLE
now inherits fromRF24
. Some attributes/functions are overridden to raise aNotImplementedError
exception, so some vital ingredients to the BLE operation isn't compromised via theFakeBLE
API.close_rx_pipe()
now properly prevents thelisten
attribute from overriding the pipe 0 reading addressprint_details()
now prints a more accurate representation of the addresses used on the pipes. Like the TMRh20 RF24 library'sprintDetails()
, the address now prints a "hexlified" string in big endian form.address_repr()
function (belonging to the rf24.py module not the RF24 class) is the helper function that returns the address specified as a "hexlified" string in big endian form.Revised examples + new nrf24l01_manual_ack_test.py & nrf24l01_scanner_test.py
b"1Node"
on pipe 0 andb"2Node"
on pipe 1b"2Node"
on pipe 0 andb"1Node"
on pipe 1master()
&slave()
master()
&slave()
struct
library (instead of directly encoding the UTF-8 data into the bytearray)Compatibility with TMRh20's library now only requires;
dynamic_payloads
has to be disabledpayload_length
has to be set accordingly to match TMRh20's RF24 new examples' configurationI've left these 2 lines commented out for easy modification (instead of typing it in the python REPL). Because most examples are compatible with TMRh20's new examples, the docs now have a table and hints about making this library compatible with TMRh20's RF24 library (instead of using 1 dedicated example).
node(1)
anymore. This demonstration was a bit over zealous anyway, and removing it better matches the multiceiverDemo.ino example I submitted to TMRh20's RF24 library.Other changes
.. versionadded::
and.. versionchanged::
.