Skip to content

feat: Add NiceRF LoRa2021 (LR2021 Gen 4) variant support#2739

Draft
c03rad0r wants to merge 2 commits into
meshcore-dev:devfrom
c03rad0r:feature/nicerf-lr2021-variant
Draft

feat: Add NiceRF LoRa2021 (LR2021 Gen 4) variant support#2739
c03rad0r wants to merge 2 commits into
meshcore-dev:devfrom
c03rad0r:feature/nicerf-lr2021-variant

Conversation

@c03rad0r

Copy link
Copy Markdown

Summary

Adds MeshCore support for the NiceRF LoRa2021 module (Semtech LR2021 Gen 4) on ESP32-C3_Mini_V1 development board.

Hardware

Component Details
MCU ESP32-C3_Mini_V1 (Maker go, 22.52x18mm, USB-C, 4MB flash)
Radio NiceRF LoRa2021 (Semtech LR2021 Gen 4, 19.72x15mm, 18-pin)
Antenna Wire dipole (~8.2cm for 868 MHz Sub-GHz)
Cost ~$8 total (MCU + radio module)
Frequency Sub-GHz: 150-960 MHz + 2.4 GHz (dual-band)

RadioLib Class

Uses the LR2021 class (extends LRxxxxPhysicalLayer). This is a separate RadioLib class from LR1121 (which extends LR11x0). RadioLib v7.6.0 (already in MeshCore deps) includes LR2021 support.

Key differences from SX1262:

  • IRQ on DIO9 (not DIO1) — set via irqDioNum = 9 + setDioFunction(9)
  • setRxBoostedGainMode(uint8_t level) takes 0-7, not bool
  • No DIO2-as-RF-switch (NiceRF handles internally)
  • Crystal oscillator (XTAL), not TCXO — tcxoVoltage = 0
  • getPacketLength() override handles header errors (same as LR1110 pattern)

Known Issue: Arduino SPI

The Arduino SPIClass on ESP32-C3_Mini_V1 returns all-zero SPI responses, causing RADIOLIB_ERR_SPI_CMD_FAILED (-707). The same hardware works with ESP-IDF's spi_bus_initialize().

This variant includes EspIdfHal.h — a custom RadioLib HAL that bypasses Arduino SPIClass and uses ESP-IDF's spi_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 dev branch:

Target Flash RAM Status
LR2021_companion_radio_usb 542 KB (41%) 140 KB (43%)
LR2021_repeater
LR2021_room_server
LR2021_secure_chat
LR2021_kiss_modem

All 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 — Extends LR2021, adds std_init(), isReceiving(), getPacketLength() override
  • CustomLR2021Wrapper.h — Extends RadioLibWrapper, implements setParams(), doResetAGC(), getSpreadingFactor()

Board Variant (in variants/nicerf_lr2021/)

  • platformio.ini — 5 build environments with LR2021 pin mapping
  • target.h / target.cpp — Radio init via EspIdfHal
  • NiceRFLR2021Board.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 definition
  • variants/esp32c3_supermini/pins_arduino.h — Pin mapping (D0-D10 = GPIO0-GPIO10)

Testing

  • All build targets compile on dev branch
  • No regressions on reference builds
  • Flash to ESP32-C3_Mini_V1 + NiceRF LoRa2021 hardware
  • Radio init succeeds
  • Noise floor calibration: -102 dBm stable
  • Companion connects via meshcore-cli v1.5.7
  • Advert TX verified
  • Two-device encrypted chat (second board in progress)
  • Community node reception test (Berlin, no nearby nodes found indoors)

Related

Pin Mapping

ESP32-C3_Mini_V1  →  NiceRF LoRa2021
3V3               →  Pin 1 (VCC)
GND               →  Pin 2,8,11,12,18
D2 (GPIO2)        →  Pin 3 (MISO)
D7 (GPIO7)        →  Pin 4 (MOSI)
D6 (GPIO6)        →  Pin 5 (SCK)
D10 (GPIO10)      →  Pin 6 (NSS/CS)
D4 (GPIO4)        →  Pin 7 (BUSY)
D3 (GPIO3)        →  Pin 14 (RST)
D5 (GPIO5)        →  Pin 15 (DIO9/IRQ)

Your Name added 2 commits June 10, 2026 05:13
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant