Breaking backward compatibility changes
- **NEW** `available()` 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()`.
- **RENAMED** `recv()` 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.
- **RENAMED** `what_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.
- **REMOVED** `FakeBLE.to_android` attribute because it was marked for deprecation.
- **REMOVED** `RF24.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 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.
- **NEW** `set_*()` & `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.
- **NEW** `allow_ask_no_ack` attribute for unofficial support of the Si24R1 (a flaw from cloning a typo in the nRF24L01 datasheet)
- **NEW** `last_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.
- **NEW** `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*
- **NEW** *scanner_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()`
- **NEW** *manual_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)
- **REMOVED** *nrf24l01_2arduino_handling_data.py* in favor of the **NEW** *nrf24l01_manual_ack_test.py* example (they're practically identical).
- Compatibility with TMRh20's library now only requires;
1. `dynamic_payloads` has to be disabled
2. `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
![image](https://user-images.githubusercontent.com/14963867/103445442-010e0c00-4c29-11eb-84e5-9f7cfbfec048.png)
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.
- changed docs theme to use [sphinx-material theme](https://github.com/bashtage/sphinx-material) (better display on mobile screens)
- 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.