From 3984b872ca4a0b4c7bddb48e089e52e608f1dc3b Mon Sep 17 00:00:00 2001 From: Frieder Schrempf Date: Wed, 22 Apr 2026 19:56:21 +0200 Subject: [PATCH 01/14] Disable NRF52 undervoltage bootlock feature The NRF52 undervoltage bootlock feature implemented behind NRF52_POWER_MANAGEMENT was introduced in v1.12. It configures a fixed voltage level of 3.3V and prevents the software from booting if the battery voltage is below that level. This is problematic for various reasons. The most important one being that it breaks devices that use cell chemistries other than Li-Ion, such as LFP, LTO or SIB which have much lower minimum voltages. As a quick fix to prevent devices from failing, disable the feature until it has been decided how to handle this in the future and a proper implementation has been provided. Signed-off-by: Frieder Schrempf --- variants/gat562_30s_mesh_kit/platformio.ini | 1 - variants/gat562_mesh_evb_pro/platformio.ini | 1 - variants/gat562_mesh_tracker_pro/platformio.ini | 1 - variants/gat562_mesh_watch13/platformio.ini | 1 - variants/heltec_t096/platformio.ini | 1 - variants/heltec_t114/platformio.ini | 1 - variants/muziworks_r1_neo/platformio.ini | 1 - variants/rak3401/platformio.ini | 1 - variants/rak4631/platformio.ini | 1 - variants/sensecap_solar/platformio.ini | 1 - variants/xiao_nrf52/platformio.ini | 1 - 11 files changed, 11 deletions(-) diff --git a/variants/gat562_30s_mesh_kit/platformio.ini b/variants/gat562_30s_mesh_kit/platformio.ini index 1467f0fa3..efc87e377 100644 --- a/variants/gat562_30s_mesh_kit/platformio.ini +++ b/variants/gat562_30s_mesh_kit/platformio.ini @@ -7,7 +7,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/gat562_30s_mesh_kit -D RAK_4631 -D RAK_BOARD - -D NRF52_POWER_MANAGEMENT -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 diff --git a/variants/gat562_mesh_evb_pro/platformio.ini b/variants/gat562_mesh_evb_pro/platformio.ini index cede9c97c..b14e89af5 100644 --- a/variants/gat562_mesh_evb_pro/platformio.ini +++ b/variants/gat562_mesh_evb_pro/platformio.ini @@ -5,7 +5,6 @@ board_check = true build_flags = ${nrf52_base.build_flags} ${sensor_base.build_flags} -I variants/gat562_mesh_evb_pro - -D NRF52_POWER_MANAGEMENT -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D RADIO_CLASS=CustomSX1262 diff --git a/variants/gat562_mesh_tracker_pro/platformio.ini b/variants/gat562_mesh_tracker_pro/platformio.ini index 8a947bce7..1f7502d66 100644 --- a/variants/gat562_mesh_tracker_pro/platformio.ini +++ b/variants/gat562_mesh_tracker_pro/platformio.ini @@ -5,7 +5,6 @@ board_check = true build_flags = ${nrf52_base.build_flags} ${sensor_base.build_flags} -I variants/gat562_mesh_tracker_pro - -D NRF52_POWER_MANAGEMENT -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 diff --git a/variants/gat562_mesh_watch13/platformio.ini b/variants/gat562_mesh_watch13/platformio.ini index ef30829d5..92bfe54ce 100644 --- a/variants/gat562_mesh_watch13/platformio.ini +++ b/variants/gat562_mesh_watch13/platformio.ini @@ -8,7 +8,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/gat562_mesh_watch13 -D RAK_4631 -D RAK_BOARD - -D NRF52_POWER_MANAGEMENT -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_OLED_RESET=-1 diff --git a/variants/heltec_t096/platformio.ini b/variants/heltec_t096/platformio.ini index 19b05f3ce..3d72c96b5 100644 --- a/variants/heltec_t096/platformio.ini +++ b/variants/heltec_t096/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/heltec_t096 -I src/helpers/ui -D HELTEC_T096 - -D NRF52_POWER_MANAGEMENT -D P_LORA_DIO_1=21 -D P_LORA_NSS=5 -D P_LORA_RESET=16 diff --git a/variants/heltec_t114/platformio.ini b/variants/heltec_t114/platformio.ini index b985030f7..a6ad2a38b 100644 --- a/variants/heltec_t114/platformio.ini +++ b/variants/heltec_t114/platformio.ini @@ -12,7 +12,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/heltec_t114 -I src/helpers/ui -D HELTEC_T114 - -D NRF52_POWER_MANAGEMENT -D P_LORA_DIO_1=20 -D P_LORA_NSS=24 -D P_LORA_RESET=25 diff --git a/variants/muziworks_r1_neo/platformio.ini b/variants/muziworks_r1_neo/platformio.ini index 39ef8728f..645961cef 100644 --- a/variants/muziworks_r1_neo/platformio.ini +++ b/variants/muziworks_r1_neo/platformio.ini @@ -7,7 +7,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/muziworks_r1_neo -I src/helpers/ui -D R1Neo - -D NRF52_POWER_MANAGEMENT -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 diff --git a/variants/rak3401/platformio.ini b/variants/rak3401/platformio.ini index 3d2d4a3ec..949bf2c4a 100644 --- a/variants/rak3401/platformio.ini +++ b/variants/rak3401/platformio.ini @@ -6,7 +6,6 @@ build_flags = ${nrf52_base.build_flags} ${sensor_base.build_flags} -I variants/rak3401 -D RAK_3401 - -D NRF52_POWER_MANAGEMENT -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D LORA_TX_POWER=22 diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index ea7e49c35..373653549 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -7,7 +7,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/rak4631 -D RAK_4631 -D RAK_BOARD - -D NRF52_POWER_MANAGEMENT -D PIN_BOARD_SCL=14 -D PIN_BOARD_SDA=13 -D PIN_GPS_TX=PIN_SERIAL1_RX diff --git a/variants/sensecap_solar/platformio.ini b/variants/sensecap_solar/platformio.ini index aabbcf000..24407180a 100644 --- a/variants/sensecap_solar/platformio.ini +++ b/variants/sensecap_solar/platformio.ini @@ -10,7 +10,6 @@ build_flags = ${nrf52_base.build_flags} -I src/helpers/nrf52 -D NRF52_PLATFORM=1 -D USE_SX1262 - -D NRF52_POWER_MANAGEMENT -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper -D P_LORA_TX_LED=11 diff --git a/variants/xiao_nrf52/platformio.ini b/variants/xiao_nrf52/platformio.ini index a08543368..931629c79 100644 --- a/variants/xiao_nrf52/platformio.ini +++ b/variants/xiao_nrf52/platformio.ini @@ -9,7 +9,6 @@ build_flags = ${nrf52_base.build_flags} -I variants/xiao_nrf52 -UENV_INCLUDE_GPS -D NRF52_PLATFORM - -D NRF52_POWER_MANAGEMENT -D XIAO_NRF52 -D USE_SX1262 -D RADIO_CLASS=CustomSX1262 From 4c2af58d3e5e25eed9534ff012cd125134234b79 Mon Sep 17 00:00:00 2001 From: Sebastian Muszynski Date: Tue, 6 Oct 2026 18:50:15 +0200 Subject: [PATCH 02/14] Use consistent `_OTA` suffix for nRF52 OTA BLE names --- variants/lilygo_t_impulse_plus/TImpulsePlusBoard.h | 2 +- variants/meshtiny/MeshtinyBoard.h | 2 +- variants/wio-tracker-l1-1w/WioTrackerL1Board.h | 2 +- variants/wio-tracker-l1/WioTrackerL1Board.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.h b/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.h index 30bbc3a5c..f7ef536ba 100644 --- a/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.h +++ b/variants/lilygo_t_impulse_plus/TImpulsePlusBoard.h @@ -9,7 +9,7 @@ protected: uint8_t btn_prev_state; public: - TImpulsePlusBoard() : NRF52Board("T-Impulse-Plus OTA") {} + TImpulsePlusBoard() : NRF52Board("T-Impulse-Plus_OTA") {} void begin(); #if defined(P_LORA_TX_LED) diff --git a/variants/meshtiny/MeshtinyBoard.h b/variants/meshtiny/MeshtinyBoard.h index 67a521fe9..21673d0aa 100644 --- a/variants/meshtiny/MeshtinyBoard.h +++ b/variants/meshtiny/MeshtinyBoard.h @@ -9,7 +9,7 @@ protected: uint8_t btn_prev_state; public: - MeshtinyBoard() : NRF52Board("Meshtiny OTA") {} + MeshtinyBoard() : NRF52Board("Meshtiny_OTA") {} void begin(); #if defined(P_LORA_TX_LED) diff --git a/variants/wio-tracker-l1-1w/WioTrackerL1Board.h b/variants/wio-tracker-l1-1w/WioTrackerL1Board.h index 798145db0..f6164e47a 100644 --- a/variants/wio-tracker-l1-1w/WioTrackerL1Board.h +++ b/variants/wio-tracker-l1-1w/WioTrackerL1Board.h @@ -14,7 +14,7 @@ protected: bool isLoRaFemPaGainEnabled() const { return _is_pa_enabled; } public: - WioTrackerL1Board() : NRF52Board("WioTrackerL1 OTA") {} + WioTrackerL1Board() : NRF52Board("WioTrackerL1_OTA") {} void begin(); void attachDynamicPrefs(KeyValueStore* prefs); bool handleCommand(const char* command, uint32_t sender_timestamp, char* reply) override; diff --git a/variants/wio-tracker-l1/WioTrackerL1Board.h b/variants/wio-tracker-l1/WioTrackerL1Board.h index e376e0666..99e852bb7 100644 --- a/variants/wio-tracker-l1/WioTrackerL1Board.h +++ b/variants/wio-tracker-l1/WioTrackerL1Board.h @@ -9,7 +9,7 @@ protected: uint8_t btn_prev_state; public: - WioTrackerL1Board() : NRF52Board("WioTrackerL1 OTA") {} + WioTrackerL1Board() : NRF52Board("WioTrackerL1_OTA") {} void begin(); #if defined(P_LORA_TX_LED) From 47c3005b08624f55d1ef6848d9af5e458d702143 Mon Sep 17 00:00:00 2001 From: quyenlt298 <61147413+quyenlt298@users.noreply.github.com> Date: Wed, 7 Oct 2026 13:09:36 +0700 Subject: [PATCH 03/14] Add Nelos allocation for GroupData --- docs/number_allocations.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/number_allocations.md b/docs/number_allocations.md index b8cc22a21..79cc90b84 100644 --- a/docs/number_allocations.md +++ b/docs/number_allocations.md @@ -19,6 +19,7 @@ Once you have a working app/project, you need to be able to demonstrate it exist | 0110 - 011F | Ripple | ripple_biz@protonmail.com — https://buymeacoffee.com/ripplebiz | | 0120 | MCO Advanced | most.original.address@gmail.com — https://hdden.ru/MCOa/ | | 0130 - 013F | StreamSensor | william@housedillon.com - https://housedillon.com/blog/lora-e5-with-seeed-fusion | +| 0140 | Nelos | support@nelos.app — https://nelos.app | | FF00 - FFFF | -reserved for testing/dev- | | (add rows, inside the range 0100 - FEFF for custom apps) From 01f9293be073937791cdb6594c08d7bcc7f7f3ed Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Thu, 8 Oct 2026 19:56:45 +1100 Subject: [PATCH 04/14] * treat transport code 0 the same as un-scoped. --- src/helpers/RegionMap.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/helpers/RegionMap.cpp b/src/helpers/RegionMap.cpp index 4667e0038..d8d773803 100644 --- a/src/helpers/RegionMap.cpp +++ b/src/helpers/RegionMap.cpp @@ -188,6 +188,7 @@ int RegionMap::getTransportKeysFor(const RegionEntry& src, TransportKey dest[], } RegionEntry* RegionMap::findMatch(mesh::Packet* packet, uint8_t mask) { + if (packet->transport_codes[0] == 0) return &wildcard; for (int i = 0; i < num_regions; i++) { auto region = ®ions[i]; if ((region->flags & mask) == 0) { // does region allow this? (per 'mask' param) From 6df5aaed4335d41e092f9f9c2516903dc9f451ff Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Mon, 12 Oct 2026 10:44:42 +1100 Subject: [PATCH 05/14] * ACK forwarding (in direct mode) had zero delay --- src/Mesh.cpp | 12 ++++++------ src/Mesh.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index c11f37cac..9dc42f0b0 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -87,13 +87,14 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { } if (self_id.isHashMatch(pkt->path, pkt->getPathHashSize()) && allowPacketForward(pkt)) { + uint32_t d = getDirectRetransmitDelay(pkt); if (pkt->getPayloadType() == PAYLOAD_TYPE_MULTIPART) { - return forwardMultipartDirect(pkt); + return forwardMultipartDirect(pkt, d); } else if (pkt->getPayloadType() == PAYLOAD_TYPE_ACK) { if (!_tables->wasSeen(pkt)) { // don't retransmit! _tables->markSeen(pkt); removeSelfFromPath(pkt); - routeDirectRecvAcks(pkt, 0); + routeDirectRecvAcks(pkt, d); } return ACTION_RELEASE; } @@ -102,7 +103,6 @@ DispatcherAction Mesh::onRecvPacket(Packet* pkt) { _tables->markSeen(pkt); removeSelfFromPath(pkt); - uint32_t d = getDirectRetransmitDelay(pkt); return ACTION_RETRANSMIT_DELAYED(0, d); // Routed traffic is HIGHEST priority } } @@ -356,7 +356,7 @@ DispatcherAction Mesh::routeRecvPacket(Packet* packet) { return ACTION_RELEASE; } -DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) { +DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt, uint32_t delay_millis) { uint8_t remaining = pkt->payload[0] >> 4; // num of packets in this multipart sequence still to be sent uint8_t type = pkt->payload[0] & 0x0F; @@ -370,7 +370,7 @@ DispatcherAction Mesh::forwardMultipartDirect(Packet* pkt) { if (!_tables->wasSeen(&tmp)) { // don't retransmit! _tables->markSeen(&tmp); removeSelfFromPath(&tmp); - routeDirectRecvAcks(&tmp, ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2) + routeDirectRecvAcks(&tmp, delay_millis + ((uint32_t)remaining + 1) * 300); // expect multipart ACKs 300ms apart (x2) } } return ACTION_RELEASE; @@ -380,13 +380,13 @@ void Mesh::routeDirectRecvAcks(Packet* packet, uint32_t delay_millis) { if (!packet->isMarkedDoNotRetransmit()) { uint8_t extra = getExtraAckTransmitCount(); while (extra > 0) { - delay_millis += getDirectRetransmitDelay(packet) + 300; auto a1 = createMultiAck(packet->payload, packet->payload_len, extra); if (a1) { a1->path_len = Packet::copyPath(a1->path, packet->path, packet->path_len); a1->header &= ~PH_ROUTE_MASK; a1->header |= ROUTE_TYPE_DIRECT; sendPacket(a1, 0, delay_millis); + delay_millis += 300; } extra--; } diff --git a/src/Mesh.h b/src/Mesh.h index 49a299a6a..22bb5c6d5 100644 --- a/src/Mesh.h +++ b/src/Mesh.h @@ -32,7 +32,7 @@ class Mesh : public Dispatcher { void removeSelfFromPath(Packet* packet); void routeDirectRecvAcks(Packet* packet, uint32_t delay_millis); //void routeRecvAcks(Packet* packet, uint32_t delay_millis); - DispatcherAction forwardMultipartDirect(Packet* pkt); + DispatcherAction forwardMultipartDirect(Packet* pkt, uint32_t delay_millis); protected: DispatcherAction onRecvPacket(Packet* pkt) override; From 3d1a5d4c64eec2e3310593fe7112f2ca02a05772 Mon Sep 17 00:00:00 2001 From: agessaman Date: Sun, 11 Oct 2026 20:51:18 -0700 Subject: [PATCH 06/14] feat(variants): add Waveshare ESP32-S3-LR1121 ESP32-S3FH4R2 (4MB flash, 2MB PSRAM, native USB-CDC) with an LR1121. Pins, the DIO5/DIO6 RF switch table and the 1.8 V TCXO follow the HF schematic and Waveshare's examples. Envs: repeater, room server, companion USB/BLE and KISS modem, all on min_spiffs so roles share one partition layout. Only RFO_HP_LF is wired (R4 on RFO_LP_LF is not fitted), so the new opt-in LR1121_FORCE_HP_PA flag keeps RadioLib on the HP PA at <= 14 dBm, where it would otherwise select the unconnected LP PA. --- src/helpers/radiolib/CustomLR1121.h | 7 ++ .../WaveshareS3LR1121Board.h | 11 ++ .../waveshare_esp32s3_lr1121/platformio.ini | 102 ++++++++++++++++++ variants/waveshare_esp32s3_lr1121/target.cpp | 63 +++++++++++ variants/waveshare_esp32s3_lr1121/target.h | 17 +++ 5 files changed, 200 insertions(+) create mode 100644 variants/waveshare_esp32s3_lr1121/WaveshareS3LR1121Board.h create mode 100644 variants/waveshare_esp32s3_lr1121/platformio.ini create mode 100644 variants/waveshare_esp32s3_lr1121/target.cpp create mode 100644 variants/waveshare_esp32s3_lr1121/target.h diff --git a/src/helpers/radiolib/CustomLR1121.h b/src/helpers/radiolib/CustomLR1121.h index 67e3b52a9..e8c6c431d 100644 --- a/src/helpers/radiolib/CustomLR1121.h +++ b/src/helpers/radiolib/CustomLR1121.h @@ -36,6 +36,13 @@ class CustomLR1121 : public LR1121 { return len; } +#ifdef LR1121_FORCE_HP_PA + // boards with only RFO_HP_LF wired: stop RadioLib switching to the LP PA at <= 14 dBm (2.4 GHz still uses the HF PA) + int16_t setOutputPower(int8_t power) override { + return LR1121::setOutputPower(power, true); + } +#endif + float getFreqMHz() const { return freqMHz; } int16_t setRxBoostedGainMode(bool en) { diff --git a/variants/waveshare_esp32s3_lr1121/WaveshareS3LR1121Board.h b/variants/waveshare_esp32s3_lr1121/WaveshareS3LR1121Board.h new file mode 100644 index 000000000..8307ba505 --- /dev/null +++ b/variants/waveshare_esp32s3_lr1121/WaveshareS3LR1121Board.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +class WaveshareS3LR1121Board : public ESP32Board { +public: + const char* getManufacturerName() const override { + return "Waveshare ESP32-S3-LR1121"; + } +}; diff --git a/variants/waveshare_esp32s3_lr1121/platformio.ini b/variants/waveshare_esp32s3_lr1121/platformio.ini new file mode 100644 index 000000000..8e7b52d4f --- /dev/null +++ b/variants/waveshare_esp32s3_lr1121/platformio.ini @@ -0,0 +1,102 @@ +; Waveshare ESP32-S3-LR1121 (HF: 850-930 MHz + 2.4 GHz) +; ESP32-S3FH4R2 (4MB flash, 2MB PSRAM), native USB-CDC via the Tiny-Adapter FPC. +; No user LED, battery sense or user button (BOOT is GPIO0). +[Waveshare_S3_LR1121] +extends = esp32_base +board = esp32-s3-zero +; min_spiffs: 1.9MB OTA app slots; one layout for every role so switching roles keeps the filesystem +board_build.partitions = min_spiffs.csv +build_flags = ${esp32_base.build_flags} + -I variants/waveshare_esp32s3_lr1121 + -D BOARD_HAS_PSRAM + -D P_LORA_DIO_1=38 + -D P_LORA_NSS=42 + -D P_LORA_RESET=39 + -D P_LORA_BUSY=41 + -D P_LORA_SCLK=40 + -D P_LORA_MISO=46 + -D P_LORA_MOSI=45 + -D RADIO_CLASS=CustomLR1121 + -D WRAPPER_CLASS=CustomLR1121Wrapper + -D LR11X0_DIO3_TCXO_VOLTAGE=1.8 + -D LR1121_FORCE_HP_PA ; RFO_LP_LF is not fitted (R4 NC) + -D RX_BOOSTED_GAIN=true + -D LORA_TX_POWER=22 +build_src_filter = ${esp32_base.build_src_filter} + +<../variants/waveshare_esp32s3_lr1121> +lib_deps = + ${esp32_base.lib_deps} + +[env:Waveshare_S3_LR1121_repeater] +extends = Waveshare_S3_LR1121 +build_flags = + ${Waveshare_S3_LR1121.build_flags} + -D ADVERT_NAME='"Waveshare LR1121 Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=50 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Waveshare_S3_LR1121.build_src_filter} + +<../examples/simple_repeater/*.cpp> +lib_deps = + ${Waveshare_S3_LR1121.lib_deps} + ${esp32_ota.lib_deps} + +[env:Waveshare_S3_LR1121_room_server] +extends = Waveshare_S3_LR1121 +build_flags = + ${Waveshare_S3_LR1121.build_flags} + -D ADVERT_NAME='"Waveshare LR1121 Room"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D ROOM_PASSWORD='"hello"' +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Waveshare_S3_LR1121.build_src_filter} + +<../examples/simple_room_server> +lib_deps = + ${Waveshare_S3_LR1121.lib_deps} + ${esp32_ota.lib_deps} + +[env:Waveshare_S3_LR1121_companion_radio_usb] +extends = Waveshare_S3_LR1121 +build_flags = + ${Waveshare_S3_LR1121.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_USB_INTERFACE +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Waveshare_S3_LR1121.build_src_filter} + + + +<../examples/companion_radio/*.cpp> +lib_deps = + ${Waveshare_S3_LR1121.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Waveshare_S3_LR1121_companion_radio_ble] +extends = Waveshare_S3_LR1121 +build_flags = + ${Waveshare_S3_LR1121.build_flags} + -D MAX_CONTACTS=350 + -D MAX_GROUP_CHANNELS=40 + -D OFFLINE_QUEUE_SIZE=256 + -D BLE_PIN_CODE=123456 +; -D BLE_DEBUG_LOGGING=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${Waveshare_S3_LR1121.build_src_filter} + + + +<../examples/companion_radio/*.cpp> +lib_deps = + ${Waveshare_S3_LR1121.lib_deps} + densaugeo/base64 @ ~1.4.0 + +[env:Waveshare_S3_LR1121_kiss_modem] +extends = Waveshare_S3_LR1121 +build_src_filter = ${Waveshare_S3_LR1121.build_src_filter} + +<../examples/kiss_modem/> diff --git a/variants/waveshare_esp32s3_lr1121/target.cpp b/variants/waveshare_esp32s3_lr1121/target.cpp new file mode 100644 index 000000000..56775c4ce --- /dev/null +++ b/variants/waveshare_esp32s3_lr1121/target.cpp @@ -0,0 +1,63 @@ +#include +#include "target.h" + +WaveshareS3LR1121Board board; + +static SPIClass spi; +RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); +SensorManager sensors; + +#ifndef LORA_CR + #define LORA_CR 5 +#endif + +// DIO5/DIO6 drive the RTC6603SP sub-GHz T/R switch; the 2.4 GHz port (RFIO_HF) is unswitched +static const uint32_t rfswitch_dios[Module::RFSWITCH_MAX_PINS] = { + RADIOLIB_LR11X0_DIO5, + RADIOLIB_LR11X0_DIO6, + RADIOLIB_NC +}; + +static const Module::RfSwitchMode_t rfswitch_table[] = { + // mode DIO5 DIO6 + { LR11x0::MODE_STBY, {LOW, LOW}}, + { LR11x0::MODE_RX, {HIGH, LOW}}, + { LR11x0::MODE_TX, {LOW, HIGH}}, + { LR11x0::MODE_TX_HP, {LOW, HIGH}}, + { LR11x0::MODE_TX_HF, {LOW, LOW}}, + { LR11x0::MODE_GNSS, {LOW, LOW}}, + { LR11x0::MODE_WIFI, {LOW, LOW}}, + END_OF_MODE_TABLE, +}; + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + + spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_LR11X0_LORA_SYNC_WORD_PRIVATE, + LORA_TX_POWER, 16, LR11X0_DIO3_TCXO_VOLTAGE); + if (status != RADIOLIB_ERR_NONE) { + Serial.print("ERROR: radio init failed: "); + Serial.println(status); + return false; + } + + radio.setCRC(2); + radio.explicitHeader(); + radio.setRfSwitchTable(rfswitch_dios, rfswitch_table); +#ifdef RX_BOOSTED_GAIN + radio.setRxBoostedGainMode(RX_BOOSTED_GAIN); +#endif + + return true; +} + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); +} diff --git a/variants/waveshare_esp32s3_lr1121/target.h b/variants/waveshare_esp32s3_lr1121/target.h new file mode 100644 index 000000000..461509e51 --- /dev/null +++ b/variants/waveshare_esp32s3_lr1121/target.h @@ -0,0 +1,17 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include "WaveshareS3LR1121Board.h" + +extern WaveshareS3LR1121Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern SensorManager sensors; + +bool radio_init(); +mesh::LocalIdentity radio_new_identity(); From eac6e66b1bf423e68bdc26cbf1180096c33340ef Mon Sep 17 00:00:00 2001 From: agessaman Date: Sun, 11 Oct 2026 20:53:23 -0700 Subject: [PATCH 07/14] fix(radiolib): keep LR1121 tx power valid across sub-GHz and 2.4 GHz - Clip requested power to the active PA's range instead of failing. A stored 22 dBm was rejected at 2.4 GHz (HF PA max 13 dBm), and since setTxPower ignores errors the sub-GHz PA stayed configured. - Re-apply the requested power after every successful retune: PA choice depends on the band, and set radio / tempradio only call setParams. --- src/helpers/radiolib/CustomLR1121.h | 30 +++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/src/helpers/radiolib/CustomLR1121.h b/src/helpers/radiolib/CustomLR1121.h index e8c6c431d..7182d1d5c 100644 --- a/src/helpers/radiolib/CustomLR1121.h +++ b/src/helpers/radiolib/CustomLR1121.h @@ -9,6 +9,8 @@ class CustomLR1121 : public LR1121 { uint32_t _activityAt = 0; bool _headerSeen = false; bool _rx_boosted = false; + int8_t _txPower = 0; + bool _txPowerSet = false; public: CustomLR1121(Module *mod) : LR1121(mod) { } @@ -36,12 +38,32 @@ class CustomLR1121 : public LR1121 { return len; } -#ifdef LR1121_FORCE_HP_PA - // boards with only RFO_HP_LF wired: stop RadioLib switching to the LP PA at <= 14 dBm (2.4 GHz still uses the HF PA) + using LR1121::setOutputPower; + using LR1121::setFrequency; + int16_t setOutputPower(int8_t power) override { - return LR1121::setOutputPower(power, true); - } +#ifdef LR1121_FORCE_HP_PA + const bool force_hp = true; // boards with only RFO_HP_LF wired: never select the LP PA +#else + const bool force_hp = false; #endif + // clip to the active PA's range (HF PA tops out at 13 dBm) rather than fail and keep the other band's PA + int8_t clipped = power; + checkOutputPower(power, &clipped, force_hp); + int16_t state = LR1121::setOutputPower(clipped, force_hp); + if (state == RADIOLIB_ERR_NONE) { + _txPower = power; + _txPowerSet = true; + } + return state; + } + + int16_t setFrequency(float freq) override { + int16_t state = LR1121::setFrequency(freq); + // PA selection depends on the band, and set radio / tempradio don't call setTxPower + if (state == RADIOLIB_ERR_NONE && _txPowerSet) state = setOutputPower(_txPower); + return state; + } float getFreqMHz() const { return freqMHz; } From 8579c667472d95d7873ea91a8ff5b219ff48cb85 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 14 Oct 2026 11:48:58 +1100 Subject: [PATCH 08/14] * Room: "set repeat" CLI now deprecated --- examples/simple_room_server/MyMesh.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 71b8d32a3..458537e62 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -983,6 +983,8 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply addSystemPost(msg); snprintf(reply, MAX_POST_TEXT_LEN, "OK"); } + } else if (memcmp(command, "set repeat ", 11) == 0) { + strcpy(reply, "ERR - repeat now deprecated"); } else{ _cli.handleCommand(sender_timestamp, command, reply); // common CLI commands } From 481f72cae7bf9bee43c3e47cfb21138a1cb34cc0 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 14 Oct 2026 12:21:38 +1100 Subject: [PATCH 09/14] * only 'repeat on' now intercepted --- examples/simple_room_server/MyMesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/simple_room_server/MyMesh.cpp b/examples/simple_room_server/MyMesh.cpp index 458537e62..da4c776c0 100644 --- a/examples/simple_room_server/MyMesh.cpp +++ b/examples/simple_room_server/MyMesh.cpp @@ -983,7 +983,7 @@ void MyMesh::handleCommand(uint32_t sender_timestamp, char *command, char *reply addSystemPost(msg); snprintf(reply, MAX_POST_TEXT_LEN, "OK"); } - } else if (memcmp(command, "set repeat ", 11) == 0) { + } else if (memcmp(command, "set repeat on", 13) == 0) { strcpy(reply, "ERR - repeat now deprecated"); } else{ _cli.handleCommand(sender_timestamp, command, reply); // common CLI commands From 590bc23ab9bd32be5366be4ae90c8a91677ffffe Mon Sep 17 00:00:00 2001 From: liamcottle Date: Wed, 14 Oct 2026 15:05:00 +1300 Subject: [PATCH 10/14] enable wifi interface for heltec v3 ble variant --- variants/heltec_v3/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index a2b159ecc..e60e35e01 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -168,12 +168,14 @@ build_flags = -D AUTO_SHUTDOWN_MILLIVOLTS=3400 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> lib_deps = From c0d00a060a794bbd4a3acfba8db3b7b91efe95b7 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Wed, 14 Oct 2026 15:16:55 +1300 Subject: [PATCH 11/14] enable wifi interface for heltec v4 ble variant --- variants/heltec_v4/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/variants/heltec_v4/platformio.ini b/variants/heltec_v4/platformio.ini index 96b3eec04..76e8e714e 100644 --- a/variants/heltec_v4/platformio.ini +++ b/variants/heltec_v4/platformio.ini @@ -211,12 +211,14 @@ build_flags = -D AUTO_SHUTDOWN_MILLIVOLTS=3400 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${heltec_v4_oled.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> lib_deps = From a0fc769660642c6f3a8371b11e90064f6591b7ba Mon Sep 17 00:00:00 2001 From: liamcottle Date: Wed, 14 Oct 2026 16:29:41 +1300 Subject: [PATCH 12/14] rework companion ui for ip address so it fits in multi interface variants --- examples/companion_radio/ui-new/UITask.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/examples/companion_radio/ui-new/UITask.cpp b/examples/companion_radio/ui-new/UITask.cpp index 181bc8328..bc25de79c 100644 --- a/examples/companion_radio/ui-new/UITask.cpp +++ b/examples/companion_radio/ui-new/UITask.cpp @@ -281,10 +281,17 @@ public: if (_page == HomePage::FIRST) { display.setColor(UIColor::primary_txt); + #ifdef ENABLE_WIFI_INTERFACE + // smaller unread message ui for wifi variants + display.setTextSize(1); + sprintf(tmp, "Unread Msg: %d", _task->getMsgCount()); + display.drawTextCentered(display.width() / 2, 22, tmp); + #else + // larger unread message ui for non wifi variants display.setTextSize(2); sprintf(tmp, "MSG: %d", _task->getMsgCount()); display.drawTextCentered(display.width() / 2, 22, tmp); - + #endif #ifdef UI_SHOW_CLOCK display.setTextSize(3); uint32_t now = _rtc->getCurrentTime(); @@ -300,7 +307,7 @@ public: IPAddress ip = WiFi.localIP(); snprintf(tmp, sizeof(tmp), "IP: %d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); display.setTextSize(1); - display.drawTextCentered(display.width() / 2, 54, tmp); + display.drawTextCentered(display.width() / 2, 32, tmp); #endif if (_task->hasConnection()) { display.setColor(UIColor::warning_txt); From 97c0aec8d6e2671ba2c64467b408ee2fd79c808f Mon Sep 17 00:00:00 2001 From: Rastislav Vysoky Date: Thu, 15 Oct 2026 09:57:31 +0200 Subject: [PATCH 13/14] added dynamic wifi to: heltec wsl3, v4r8, wireless paper; rak 3112; xiao s3 (wio) --- variants/heltec_v3/platformio.ini | 4 +++- variants/heltec_v4_r8/platformio.ini | 2 ++ variants/heltec_wireless_paper/platformio.ini | 4 +++- variants/rak3112/platformio.ini | 4 +++- variants/xiao_s3/platformio.ini | 2 ++ variants/xiao_s3_wio/platformio.ini | 2 ++ 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index e60e35e01..06c028569 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -314,12 +314,14 @@ build_flags = -D MAX_CONTACTS=350 -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 - -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE +; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Heltec_lora32_v3.build_src_filter} + + + +<../examples/companion_radio/*.cpp> lib_deps = ${Heltec_lora32_v3.lib_deps} diff --git a/variants/heltec_v4_r8/platformio.ini b/variants/heltec_v4_r8/platformio.ini index 7611cc1cb..e22ca8f54 100644 --- a/variants/heltec_v4_r8/platformio.ini +++ b/variants/heltec_v4_r8/platformio.ini @@ -160,10 +160,12 @@ build_flags = -D AUTO_SHUTDOWN_MILLIVOLTS=3400 -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE build_src_filter = ${heltec_v4_r8_oled.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> lib_deps = diff --git a/variants/heltec_wireless_paper/platformio.ini b/variants/heltec_wireless_paper/platformio.ini index 55ed62b34..56f95b2f9 100644 --- a/variants/heltec_wireless_paper/platformio.ini +++ b/variants/heltec_wireless_paper/platformio.ini @@ -52,11 +52,13 @@ build_flags = -D MAX_GROUP_CHANNELS=40 -D DISPLAY_CLASS=E213Display -D BLE_PIN_CODE=123456 ; dynamic, random PIN - -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE +; -D BLE_DEBUG_LOGGING=1 build_src_filter = ${Heltec_Wireless_Paper_base.build_src_filter} + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> lib_deps = diff --git a/variants/rak3112/platformio.ini b/variants/rak3112/platformio.ini index 5f3b905bd..d181388b0 100644 --- a/variants/rak3112/platformio.ini +++ b/variants/rak3112/platformio.ini @@ -155,12 +155,14 @@ build_flags = -D MAX_GROUP_CHANNELS=40 -D BLE_PIN_CODE=123456 ; dynamic, random PIN -D AUTO_SHUTDOWN_MILLIVOLTS=3400 - -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE +; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${rak3112.build_src_filter} + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-orig/*.cpp> lib_deps = diff --git a/variants/xiao_s3/platformio.ini b/variants/xiao_s3/platformio.ini index 1632d1120..b8ae79733 100644 --- a/variants/xiao_s3/platformio.ini +++ b/variants/xiao_s3/platformio.ini @@ -100,12 +100,14 @@ build_flags = -D BLE_PIN_CODE=123456 -D DISPLAY_CLASS=SSD1306Display -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_S3.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> diff --git a/variants/xiao_s3_wio/platformio.ini b/variants/xiao_s3_wio/platformio.ini index 3bb956070..5a2ef1061 100644 --- a/variants/xiao_s3_wio/platformio.ini +++ b/variants/xiao_s3_wio/platformio.ini @@ -160,12 +160,14 @@ build_flags = -D BLE_PIN_CODE=123456 -D DISPLAY_CLASS=SSD1306Display -D OFFLINE_QUEUE_SIZE=256 + -D ENABLE_WIFI_INTERFACE ; -D BLE_DEBUG_LOGGING=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${Xiao_S3_WIO.build_src_filter} + + + + + +<../examples/companion_radio/*.cpp> +<../examples/companion_radio/ui-new/*.cpp> From 07a833bbbe7c0431f652e32a835db1205ca412ed Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Thu, 15 Oct 2026 19:42:01 +1100 Subject: [PATCH 14/14] * version 1.18.0 --- examples/companion_radio/MyMesh.h | 4 ++-- examples/simple_repeater/MyMesh.h | 4 ++-- examples/simple_room_server/MyMesh.h | 4 ++-- examples/simple_sensor/SensorMesh.h | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index 52a22cb41..944790df9 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -7,11 +7,11 @@ #define FIRMWARE_VER_CODE 14 #ifndef FIRMWARE_BUILD_DATE -#define FIRMWARE_BUILD_DATE "14 Aug 2026" +#define FIRMWARE_BUILD_DATE "15 Oct 2026" #endif #ifndef FIRMWARE_VERSION -#define FIRMWARE_VERSION "v1.17.1" +#define FIRMWARE_VERSION "v1.18.0" #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) diff --git a/examples/simple_repeater/MyMesh.h b/examples/simple_repeater/MyMesh.h index a9ac453a0..dc8932586 100644 --- a/examples/simple_repeater/MyMesh.h +++ b/examples/simple_repeater/MyMesh.h @@ -67,11 +67,11 @@ struct NeighbourInfo { }; #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "14 Aug 2026" + #define FIRMWARE_BUILD_DATE "15 Oct 2026" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.17.1" + #define FIRMWARE_VERSION "v1.18.0" #endif #define FIRMWARE_ROLE "repeater" diff --git a/examples/simple_room_server/MyMesh.h b/examples/simple_room_server/MyMesh.h index 5cf949c6b..4dee8bdbf 100644 --- a/examples/simple_room_server/MyMesh.h +++ b/examples/simple_room_server/MyMesh.h @@ -28,11 +28,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "14 Aug 2026" + #define FIRMWARE_BUILD_DATE "15 Oct 2026" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.17.1" + #define FIRMWARE_VERSION "v1.18.0" #endif #ifndef LORA_FREQ diff --git a/examples/simple_sensor/SensorMesh.h b/examples/simple_sensor/SensorMesh.h index 8b421081b..590ca0c76 100644 --- a/examples/simple_sensor/SensorMesh.h +++ b/examples/simple_sensor/SensorMesh.h @@ -34,11 +34,11 @@ #define PERM_RECV_ALERTS_HI (1 << 7) // high priority alerts #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "14 Aug 2026" + #define FIRMWARE_BUILD_DATE "15 Oct 2026" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.17.1" + #define FIRMWARE_VERSION "v1.18.0" #endif #define FIRMWARE_ROLE "sensor"