This adds a build for the Nucleo WL55JC1 board, and ensures that
the STM32WLx examples are skipped on all other boards.
To slightly generalize the list of boards, this pushes the pnum option
for the black pill into the boards list, instead of setting it into the
options variable (even though it is technically a board option and not
the board itself, conceptually it is part of the selected board and
these values are just concatenated, so it can go in either place).
Co-Authored-By: jgromes <jan.gromes@gmail.com>
This checks for some system macros to be set, but also includes the
doxygen build to generate documentation.
This reuses the RADIOLIB_EXCLUDE_STM32WLX that the code already checks
for to prevent having to duplicate this macro check in four places.
To detect running inside doxygen, this configures doxygen to predefine
a DOXYGEN macro (it seems no such macros are defined by default by
doxygen).
Because this interrupt is not connected to a GPIO or even the EXTI unit,
but directly to the MCU NVIC, the regular attachInterrupt flow cannot be
used.
Instead, this lets STM32WLx override the setDio1Action() and
clearDio1Action() methods to register the radio IRQ directly. Note that
it would have been nicer to implement this by overriding attachInterrupt
in STM32WLx_Module, but that is never called for virtual pins (because
the STM32Duino digitalPinToInterrupt() macro does not work for virtual
pins).
In addition, because the NVIC is level-sensitive and the code expects
edge-sensitive interrupts (for GPIO, the EXTI module in front of the
NVIC makes the interrupts edge-sensitive), this adds some additional
handling around the user-registered interrupt callback. To prevent the
ISR from triggering over and over again (and also to not require SPI
transactions in the ISR to clear the IRQ flags inside the radio), the
interrupt is disabled in the NVIC whenever it is trigered. Then,
whenever the IRQ flags *are* cleared in the radio, the IRQ is enabled in
the NVIC again. This requires making the SX126x::clearIrqStatus() method
virtual so STM32WLx can override it.
This is a nearly complete implementation, except that the Dio1 interrupt
is not yet supported (this will be added in a subsequent commit to
simplify review).
This fixes#588.
This removes the compatibility wrapper and applies the following
replacements:
sed -i 's/setRfSwitchState(LOW, LOW)/setRfSwitchState(Module::MODE_IDLE)/' src/modules/*/*.cpp
sed -i 's/setRfSwitchState(HIGH, LOW)/setRfSwitchState(Module::MODE_RX)/' src/modules/*/*.cpp
sed -i 's/setRfSwitchState(LOW, HIGH)/setRfSwitchState(Module::MODE_TX)/' src/modules/*/*.cpp
This gives all radios that use an rfswitch (i.e. have
a setRfSwitchPins() wrapper already) a wrapper method for
setRfSwitchTable() too. This wrapper just calls the same method on
Module, to make it easier for sketches to use it.
This defines operation modes (IDLE, RX and TX) and allows defining up to
to three pins to be controlled. For each mode a value can be specified
for each pin a table.
Compared to the previous handling, this:
- Allows up to three pins instead of only two.
- Gives more control over output pin values (e.g. to simply change
polarity or support more complex control logic).
In addition, the modes are treated as opaque by the Module code,
allowing radio classes to define their own modes if needed.
Some notes regarding the implementation:
- The number of pins is limited at three, since most boards seem to need
only two pins and only the Nucleo STM32WL55 board needs three. If
more pins are needed in the future, the setRfSwitchTable()
can be overloaded to accept either a 3-element or e.g. 4-element pins
array, to allow new and old code to work as-is.
Note that there is a RFSWITCH_MAX_PINS constant defined, but it is
not recommended for sketches to use this constant when defining
a rfswitch pins array, to prevent issues when this value is ever
increased and such an array gets extra zero elements (that will be
interpreted as pin 0).
Note that this is not a problem for the RfSwitchMode_t values array,
since any extra values in there will only be used if a valid pin was
set in the pins array.
- The pins array is passed by reference, so the compiler complains if
the array passed is not the expected size. Since a reference to an
array without a length is not supported (at least not by the gcc
7 used by the AVR core - gcc 10 for STM32 seems to accept it), the
table array is passed as a pointer instead (but because arrays and
pointers are reasonably interchangeable, the caller does not see the
difference).
- The existing setRfSwitchPins() method is still supported as before.
Internally it creates a table with the right values and pins and
passes those to setRfSwitchTable.
- For easier review, this commit does not modify all calls to
setRfSwitchState() in all radio modules yet, but has a compatibility
wrapper to delay this change until the next commit. Similarly, the
setRfSwitchTable() method is now defined on Module only, a wrapper
for it will be defined in all radios that already have the
setRfSwitchPins() wrapper in another commit.
- To allow future radios to define any number of modes, the modes table
does not have a fixed length, but instead is terminated by a special
value. This is a bit fragile (if the terminator is omitted, the code
will read past the end of the array), but rather flexible. One
alternative to this approach would be to make setRfSwitchTable
a template that deduces the array size from a template argument and
then stores the size explicitly, but using templates probably reduces
code clarity.
All radios that support RfSwitch define this method that simply forwards
to the `Module::setRfSwitchPins()` method. Previously, all these methods
duplicated the documentation as well, but this uses the doxygen \copydoc
to remove this duplication.