feat: Add NiceRF LoRa2021 (LR2021 Gen 4) variant support#2739
Conversation
Adds MeshCore support for the NiceRF LoRa2021 module (Semtech LR2021 Gen 4) on ESP32-C3_Mini_V1 development board. RadioLib LR2021 class (extends LRxxxx -> PhysicalLayer). This is a separate class from LR1121 (extends LR11x0). Key differences from SX1262: - IRQ on DIO9 (not DIO1): irqDioNum=9 + setDioFunction(9) - setRxBoostedGainMode(uint8_t 0-7) vs bool - No DIO2-as-RF-switch (NiceRF handles internally) - Crystal oscillator (XTAL): tcxoVoltage=0 - getPacketLength() override handles header errors Uses ESP-IDF SPI HAL (EspIdfHal) because Arduino SPIClass returns all-zero responses on the ESP32-C3_Mini_V1 with non-default SPI pins. Direct spi_bus_initialize() works correctly. See EspIdfHal.h for details. Build targets: companion_usb/ble/wifi, repeater, room_server, secure_chat, kiss_modem. All verified building. Hardware tested: radio init OK, noise floor -102 dBm, companion connects via meshcore-cli v1.5.7, advert TX verified.
|
Community mesh test (Berlin): Prior to opening this PR, I tested the LR2021 + ESP32-C3 against the live Berlin MeshCore community mesh:
|
|
Looks good. Just a small suggestion: I'd probably move the IDF Hal to /src/helpers/radiolib, as it's related only to RadioLib and could potentially be re-used by other variants |
|
|
||
| NiceRFLR2021Board board; | ||
|
|
||
| static EspIdfHal hal(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); |
There was a problem hiding this comment.
Did you try using static SPIClass spi(0) or one of the other SPI peripherals like FSPI or HSPI? Some of the ESP32 boards like C6 for example don't have the same SPI peripherals and it can cause SPI to fail silently and return 0s.
|
|
||
| size_t getPacketLength(bool update) override { | ||
| size_t len = LR2021::getPacketLength(update); | ||
| if (len == 0 && getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR) { |
There was a problem hiding this comment.
Likely not required unless it's confirmed that this workaround is necessary on the LR2021?
|
|
||
| bool isReceiving() { | ||
| uint32_t irq = getIrqStatus(); | ||
| bool detected = (irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || |
There was a problem hiding this comment.
Should these be RADIOLIB_LR2021_IRQ_PREAMBLE_DETECTED and RADIOLIB_LR2021_IRQ_LORA_HEADER_VALID?
|
|
||
| public: | ||
| CustomLR2021(Module *mod) : LR2021(mod) { | ||
| irqDioNum = 9; |
There was a problem hiding this comment.
irqDioNum will need to be configured via platformio define instead of hardcoded, since the LR2021 allows connecting the interrupt do any of the DIO pins.
Probably -D LR2021_IRQ_DIO and change this to irqDioNum = LR2021_IRQ_DIO or something?
Summary
Adds MeshCore support for the NiceRF LoRa2021 module (Semtech LR2021 Gen 4) on ESP32-C3_Mini_V1 development board.
Hardware
RadioLib Class
Uses the
LR2021class (extendsLRxxxx→PhysicalLayer). This is a separate RadioLib class fromLR1121(which extendsLR11x0). RadioLib v7.6.0 (already in MeshCore deps) includes LR2021 support.Key differences from SX1262:
irqDioNum = 9+setDioFunction(9)setRxBoostedGainMode(uint8_t level)takes 0-7, notbooltcxoVoltage = 0getPacketLength()override handles header errors (same as LR1110 pattern)Known Issue: Arduino SPI
The Arduino
SPIClasson ESP32-C3_Mini_V1 returns all-zero SPI responses, causingRADIOLIB_ERR_SPI_CMD_FAILED(-707). The same hardware works with ESP-IDF'sspi_bus_initialize().This variant includes
EspIdfHal.h— a custom RadioLib HAL that bypasses ArduinoSPIClassand uses ESP-IDF'sspi_bus_initialize()/spi_device_polling_transmit()directly. This is the same approach used in our ESP-IDF tracker firmware.Root cause hypothesis: The ESP32-C3 has one SPI peripheral (FSPI/SPI2_HOST). The Arduino SPIClass may not properly reconfigure FSPI when the SPI pins differ from the default boot-time configuration (our board uses GPIO2/6/7 instead of default SPI pins).
If anyone has insight into why Arduino SPI fails on this board, I would love to fix this properly and remove the custom HAL.
Build Targets
All verified building against
devbranch:LR2021_companion_radio_usbLR2021_repeaterLR2021_room_serverLR2021_secure_chatLR2021_kiss_modemAll fit within ESP32-C3 4MB flash. Reference build (
Heltec_v3_companion_radio_ble) passes — no regressions.Files Added
Radio Helpers (in
src/helpers/radiolib/)CustomLR2021.h— ExtendsLR2021, addsstd_init(),isReceiving(),getPacketLength()overrideCustomLR2021Wrapper.h— ExtendsRadioLibWrapper, implementssetParams(),doResetAGC(),getSpreadingFactor()Board Variant (in
variants/nicerf_lr2021/)platformio.ini— 5 build environments with LR2021 pin mappingtarget.h/target.cpp— Radio init via EspIdfHalNiceRFLR2021Board.h— Board class (deep sleep, battery ADC)EspIdfHal.h— ESP-IDF SPI HAL (documented workaround)Board Definition (shared)
boards/esp32c3_supermini.json— ESP32-C3 SuperMini V1 board definitionvariants/esp32c3_supermini/pins_arduino.h— Pin mapping (D0-D10 = GPIO0-GPIO10)Testing
devbranchRelated
Pin Mapping