From c6f7ac21355db559f6f971aa9494fa69e0e7b422 Mon Sep 17 00:00:00 2001 From: l33chy Date: Tue, 24 Mar 2026 15:51:16 +0100 Subject: [PATCH 1/3] Add Heltec Wireless Stick Lite V3 board support Add build environment for the HTIT-WSL_V3, which is hardware-identical to the Heltec WiFi LoRa 32 V3 but lacks an OLED display. Uses a NO_DISPLAY build flag to conditionally disable HAS_DISPLAY in the V3 board block. Also adds missing heltec32v3 provisioning case to extra_script.py. Co-Authored-By: Claude Opus 4.6 --- Boards.h | 4 +++- extra_script.py | 2 ++ platformio.ini | 26 ++++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 1 deletion(-) diff --git a/Boards.h b/Boards.h index c66a71bc..01d6787a 100644 --- a/Boards.h +++ b/Boards.h @@ -350,7 +350,9 @@ #elif BOARD_MODEL == BOARD_HELTEC32_V3 #define IS_ESP32S3 true - #define HAS_DISPLAY true + #ifndef NO_DISPLAY + #define HAS_DISPLAY true + #endif #define HAS_WIFI true #define HAS_BLUETOOTH false #define HAS_BLE true diff --git a/extra_script.py b/extra_script.py index 1904d069..8d3c5bc9 100644 --- a/extra_script.py +++ b/extra_script.py @@ -89,6 +89,8 @@ def device_provision(env): env.Execute("rnodeconf --product e0 --model e9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) case "lora32v21" | "lora32v21_local": env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) + case "heltec32v3" | "heltec32v3_local": + env.Execute("rnodeconf --product c1 --model ca --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) case "heltec32v4pa" | "heltec32v4pa_local": env.Execute("rnodeconf --product c3 --model c8 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) case "rak4631" | "rak4631_local": diff --git a/platformio.ini b/platformio.ini index ca9d1aad..11100522 100644 --- a/platformio.ini +++ b/platformio.ini @@ -539,6 +539,32 @@ lib_deps = https://github.com/attermann/microStore.git https://github.com/attermann/microReticulum.git +; Heltec Wireless Stick Lite V3 (HTIT-WSL_V3) +; Same as Heltec WiFi LoRa 32 V3 but without OLED display +; ESP32-S3FN8 + SX1262 +; SRAM: 512 KB +; Flash: 8 MB +; LoRa: Semtech SX1262 +[env:heltec_wireless_stick_lite_V3] +platform = espressif32 +board = heltec_wifi_lora_32_V3 +custom_variant = heltec32v3 +board_build.partitions = no_ota.csv +board_build.filesystem = littlefs +build_flags = + ${env.build_flags} + -DBOARD_MODEL=BOARD_HELTEC32_V3 + -DNO_DISPLAY + -DUSTORE_USE_POSIXFS=1 + -DURTN_PATH_TABLE_MAX_RECS=500 + -DUSTORE_SEGMENT_SIZE=24576 ; 24 KB + -DUSTORE_MAX_SEGMENTS=8 +lib_deps = + ${env.lib_deps} + XPowersLib@^0.2.1 + https://github.com/attermann/microStore.git + https://github.com/attermann/microReticulum.git + ; ESP32-S3 (ESP32-S3R2 Xtensa 32-bit LX7 dual-core, 240MHz) ; SRAM: 512 KB ; PSRAM: 2 MB From 4b8d6925992bebac08962a65cb1a21956d468535 Mon Sep 17 00:00:00 2001 From: slack-t Date: Tue, 21 Apr 2026 11:18:12 +0200 Subject: [PATCH 2/3] Add Heltec Wireless Stick Lite V3 as dedicated board (BOARD_HELTEC_WSL_V3 0x43) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware is identical to Heltec LoRa32 V3 (ESP32-S3 + SX1262 + TCXO) but without the OLED display. Defined as a proper separate board rather than using BOARD_HELTEC32_V3 + -DNO_DISPLAY, following the same pattern as all other boards in this firmware. Changes: - Boards.h: add BOARD_HELTEC_WSL_V3 constant (0x43) and full board config section with HAS_DISPLAY false and identical pin/modem/TCXO definitions - sx126x.cpp: add BOARD_HELTEC_WSL_V3 to TCXO 3.3V branch in enableTCXO() - Utilities.h: add BOARD_HELTEC_WSL_V3 to LED function definitions - platformio.ini: switch env to -DBOARD_MODEL=BOARD_HELTEC_WSL_V3, remove -DNO_DISPLAY, fix stale DUSTORE_* flags to RNS_PATH_TABLE_* - extra_script.py: add heltec32v3_wsl variant to provisioning (uses same rnodeconf product/model as V3: 0xC1/0xCA — identical hardware) Co-Authored-By: Claude Sonnet 4.6 --- Boards.h | 41 +++++++++++++++++++++++++++++++++++++++++ Utilities.h | 2 +- extra_script.py | 2 +- platformio.ini | 9 ++++----- sx126x.cpp | 2 +- 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/Boards.h b/Boards.h index 01d6787a..0ea31e5b 100644 --- a/Boards.h +++ b/Boards.h @@ -95,6 +95,8 @@ #define MODEL_C5 0xC5 // Heltec Lora32 v3, 433 MHz #define MODEL_CA 0xCA // Heltec Lora32 v3, 868 MHz + #define BOARD_HELTEC_WSL_V3 0x43 // Heltec Wireless Stick Lite V3 (same as V3, no display) + #define PRODUCT_H32_V4 0xC3 #define BOARD_HELTEC32_V4 0x3F #define MODEL_C8 0xC8 // Heltec Lora32 v3, 850-950 MHz, 28dBm @@ -390,6 +392,45 @@ const int pin_miso = 11; const int pin_sclk = 9; + #elif BOARD_MODEL == BOARD_HELTEC_WSL_V3 + #define IS_ESP32S3 true + #define HAS_DISPLAY false + #define HAS_WIFI true + #define HAS_BLUETOOTH false + #define HAS_BLE true + #define HAS_PMU true + #define HAS_CONSOLE true + #define HAS_EEPROM true + #define HAS_INPUT true + #define HAS_SLEEP true + #define PIN_WAKEUP GPIO_NUM_0 + #define WAKEUP_LEVEL 0 + #define OCP_TUNED 0x28 + + const int pin_btn_usr1 = 0; + + #if defined(EXTERNAL_LEDS) + const int pin_led_rx = 13; + const int pin_led_tx = 14; + #else + const int pin_led_rx = 35; + const int pin_led_tx = 35; + #endif + + #define MODEM SX1262 + #define HAS_TCXO true + const int pin_tcxo_enable = -1; + #define HAS_BUSY true + #define DIO2_AS_RF_SWITCH true + + const int pin_cs = 8; + const int pin_busy = 13; + const int pin_dio = 14; + const int pin_reset = 12; + const int pin_mosi = 10; + const int pin_miso = 11; + const int pin_sclk = 9; + #elif BOARD_MODEL == BOARD_HELTEC32_V4 #define IS_ESP32S3 true #define HAS_DISPLAY true diff --git a/Utilities.h b/Utilities.h index e5ede163..9d47bb84 100644 --- a/Utilities.h +++ b/Utilities.h @@ -303,7 +303,7 @@ extern RNS::Reticulum reticulum; void led_id_on() { } void led_id_off() { } #endif - #elif BOARD_MODEL == BOARD_HELTEC32_V3 + #elif BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 void led_rx_on() { digitalWrite(pin_led_rx, HIGH); } void led_rx_off() { digitalWrite(pin_led_rx, LOW); } void led_tx_on() { digitalWrite(pin_led_tx, HIGH); } diff --git a/extra_script.py b/extra_script.py index 8d3c5bc9..383eceaf 100644 --- a/extra_script.py +++ b/extra_script.py @@ -89,7 +89,7 @@ def device_provision(env): env.Execute("rnodeconf --product e0 --model e9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) case "lora32v21" | "lora32v21_local": env.Execute("rnodeconf --product b1 --model b9 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) - case "heltec32v3" | "heltec32v3_local": + case "heltec32v3" | "heltec32v3_local" | "heltec32v3_wsl": env.Execute("rnodeconf --product c1 --model ca --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) case "heltec32v4pa" | "heltec32v4pa_local": env.Execute("rnodeconf --product c3 --model c8 --hwrev 1 --rom " + env.subst("$UPLOAD_PORT")) diff --git a/platformio.ini b/platformio.ini index 11100522..903eabef 100644 --- a/platformio.ini +++ b/platformio.ini @@ -548,17 +548,16 @@ lib_deps = [env:heltec_wireless_stick_lite_V3] platform = espressif32 board = heltec_wifi_lora_32_V3 -custom_variant = heltec32v3 +custom_variant = heltec32v3_wsl board_build.partitions = no_ota.csv board_build.filesystem = littlefs build_flags = ${env.build_flags} - -DBOARD_MODEL=BOARD_HELTEC32_V3 - -DNO_DISPLAY + -DBOARD_MODEL=BOARD_HELTEC_WSL_V3 -DUSTORE_USE_POSIXFS=1 -DURTN_PATH_TABLE_MAX_RECS=500 - -DUSTORE_SEGMENT_SIZE=24576 ; 24 KB - -DUSTORE_MAX_SEGMENTS=8 + -DRNS_PATH_TABLE_SEGMENT_SIZE=24576 + -DRNS_PATH_TABLE_SEGMENT_COUNT=8 lib_deps = ${env.lib_deps} XPowersLib@^0.2.1 diff --git a/sx126x.cpp b/sx126x.cpp index 77e4dc3e..9bdf1987 100644 --- a/sx126x.cpp +++ b/sx126x.cpp @@ -696,7 +696,7 @@ void sx126x::sleep() { uint8_t byte = 0x00; executeOpcode(OP_SLEEP_6X, &byte, 1) void sx126x::enableTCXO() { #if HAS_TCXO - #if BOARD_MODEL == BOARD_RAK4631 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_XIAO_S3 + #if BOARD_MODEL == BOARD_RAK4631 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 || BOARD_MODEL == BOARD_XIAO_S3 uint8_t buf[4] = {MODE_TCXO_3_3V_6X, 0x00, 0x00, 0xFF}; #elif BOARD_MODEL == BOARD_TBEAM uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; From 79f92fab2b33755e3e7ac6d66a314c1a0350b339 Mon Sep 17 00:00:00 2001 From: slack-t Date: Tue, 21 Apr 2026 11:30:32 +0200 Subject: [PATCH 3/3] Fix BOARD_HELTEC_WSL_V3 radio offline: add missing board cases MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BOARD_HELTEC_WSL_V3 was missing from several per-board dispatch chains, causing the radio to stay offline: - sx126x.cpp preInit(): WSL V3 fell through to bare SPI.begin() without explicit pin arguments, so SX1262 SPI bus never initialised and the sync word check failed → modem_installed = false - Utilities.h eeprom_model_valid(): no case for WSL V3, so always returned false → "Invalid EEPROM configuration" printed at boot, hw_ready never set - Utilities.h eeprom_model_valid(): combined with BOARD_HELTEC32_V3 since both accept MODEL_C5 / MODEL_CA (identical provisioning bytes) Also add WSL V3 to Power.h battery/PMU init (same pins and ADC scaling as V3: pin_vbat=1, pin_ctrl=37, measurement factor 0.0041). Co-Authored-By: Claude Sonnet 4.6 --- Power.h | 10 +++++----- Utilities.h | 2 +- sx126x.cpp | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Power.h b/Power.h index 7ce6d8a7..419d510c 100644 --- a/Power.h +++ b/Power.h @@ -100,7 +100,7 @@ float pmu_temperature = PMU_TEMP_MIN-1; bool bat_voltage_dropping = false; float bat_delay_v = 0; float bat_state_change_v = 0; -#elif BOARD_MODEL == BOARD_HELTEC32_V3 +#elif BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 // Unless we implement some real voodoo // on these boards, we can't say with // any certainty whether we are actually @@ -202,15 +202,15 @@ void measure_temperature() { } void measure_battery() { - #if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TECHO + #if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TECHO battery_installed = true; - #if BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 + #if BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 battery_indeterminate = false; #else battery_indeterminate = true; #endif - #if BOARD_MODEL == BOARD_HELTEC32_V3 + #if BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 float battery_measurement = (float)(analogRead(pin_vbat)) * 0.0041; #elif BOARD_MODEL == BOARD_HELTEC32_V4 float battery_measurement = (float)(analogRead(pin_vbat)) * 0.00418; @@ -414,7 +414,7 @@ bool init_pmu() { #if BOARD_MODEL == BOARD_RNODE_NG_21 || BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_TECHO pinMode(pin_vbat, INPUT); return true; - #elif BOARD_MODEL == BOARD_HELTEC32_V3 + #elif BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 // there are three version of V3: V3, V3.1, and V3.2 // V3 and V3.1 have a pull up on pin_ctrl and are active low // V3.2 has a transistor and active high diff --git a/Utilities.h b/Utilities.h index 9d47bb84..29d6e278 100644 --- a/Utilities.h +++ b/Utilities.h @@ -1707,7 +1707,7 @@ bool eeprom_model_valid() { if (model == MODEL_B4 || model == MODEL_B9) { #elif BOARD_MODEL == BOARD_HELTEC32_V2 if (model == MODEL_C4 || model == MODEL_C9) { - #elif BOARD_MODEL == BOARD_HELTEC32_V3 + #elif BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 if (model == MODEL_C5 || model == MODEL_CA) { #elif BOARD_MODEL == BOARD_HELTEC32_V4 if (model == MODEL_C8) { diff --git a/sx126x.cpp b/sx126x.cpp index 9bdf1987..a2d2c3e2 100644 --- a/sx126x.cpp +++ b/sx126x.cpp @@ -134,7 +134,7 @@ bool sx126x::preInit() { pinMode(_ss, OUTPUT); digitalWrite(_ss, HIGH); - #if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_XIAO_S3 + #if BOARD_MODEL == BOARD_T3S3 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC_WSL_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_TDECK || BOARD_MODEL == BOARD_XIAO_S3 SPI.begin(pin_sclk, pin_miso, pin_mosi, pin_cs); #elif BOARD_MODEL == BOARD_TECHO SPI.setPins(pin_miso, pin_sclk, pin_mosi);