Files
MeshCore-Solo/variants/heltec_v3/platformio.ini
T
JakubandClaude Opus 5 6d667d8bca fix(release): publish ESP32 solo binaries, add screenshot to Heltec envs
The solo release job only attached *.uf2 and *.zip, which covered every solo
board back when they were all nRF52. The Heltec V3/V4 .bin images were built
and then silently dropped, so tagging a release produced nothing downloadable
for those two boards.

Releases now carry a single -merged.bin per ESP32 board (bootloader +
partition table + app at 0x0). build.sh also writes an app-only .bin, but
that one needs offset 0x10000 and a bootloader already on the chip, so it's
deleted before upload rather than shipped next to the merged image — flashing
it at 0x0 looks exactly like a bricked device.

Also adds -D ENABLE_SCREENSHOT to both Heltec solo envs. Every other solo env
already had it, so Solo Tools couldn't capture these two boards' displays and
the README's "no special build flags required" was untrue for them. Both envs
rebuilt clean (V3: RAM 58.8%, Flash 43.2%).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 19:21:12 +02:00

454 lines
14 KiB
INI

[Heltec_lora32_v3]
extends = esp32_base
board = esp32-s3-devkitc-1
build_flags =
${esp32_base.build_flags}
${sensor_base.build_flags}
-I variants/heltec_v3
-D HELTEC_LORA_V3
-D ESP32_CPU_FREQ=80
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=RADIOLIB_NC
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D USE_SX1262
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D P_LORA_TX_LED=35
-D PIN_BOARD_SDA=17
-D PIN_BOARD_SCL=18
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=36
-D SX126X_DIO2_AS_RF_SWITCH=true
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1
-D PIN_GPS_RX=47
-D PIN_GPS_TX=48
-D PIN_GPS_EN=26
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_v3>
+<helpers/sensors>
lib_deps =
${esp32_base.lib_deps}
${sensor_base.lib_deps}
[env:Heltec_v3_repeater]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"Heltec 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 = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_v3_repeater_bridge_rs232]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"RS232 Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=5
-D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/bridges/RS232Bridge.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_v3_repeater_bridge_espnow]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"ESPNow Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_v3_room_server]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D DISPLAY_CLASS=SSD1306Display
-D ADVERT_NAME='"Heltec 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 = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_v3_terminal_chat]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_v3_companion_radio_usb]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_v3_companion_radio_ble]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
-D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
; Solo build: the full standalone on-device UI (message history, contacts, map,
; tools) rather than a screen that only mirrors the phone app. Dual transport --
; the companion app can attach over BLE or USB serial, whichever it finds, and
; BLE wins while both are live.
;
; This firmware needs a real input device: the solo UI cannot be driven from the
; PRG button alone. Both supported ones are wired up in target.cpp and enabled
; below, so either is enough on its own and having both is fine. The pins are
; defaults picked from what this board leaves free -- change them to match how
; the device is actually built. Pins with nothing attached read as not-pressed,
; so the unused half costs nothing.
;
; * CardKB (M5Stack I2C keyboard, addr 0x5F) on a second I2C bus. Any two free
; GPIOs -- NOT 17/18, the OLED already owns those on Wire. It's probed at
; boot, so a build with these set still runs fine with nothing plugged in.
; Pair it with Settings > Keyboard > Ext. KB = Compact, which is designed to
; need no joystick at all. The same bus is scanned for environment sensors.
;
; * Wired joystick: four direction pins plus a separate Back button -- the UI
; uses Back unconditionally once UI_HAS_JOYSTICK is set, so it isn't optional.
; PIN_USER_BTN (PRG) stays the centre/Enter press. Each contact just shorts
; its pin to GND; target.cpp enables the internal pull-ups. Drop
; UI_HAS_JOYSTICK_UPDOWN for a left/right-only stick. JOYSTICK_ROTATION (0-3)
; rotates the mapping if the stick is mounted sideways -- it's also a runtime
; setting, so leave it out unless you want a different default.
; Comment the whole block out for a CardKB-only build. UI_HAS_JOYSTICK
; replaces the single-button handling rather than adding to it (UITask.cpp
; dispatches on '#if UI_HAS_JOYSTICK ... #elif defined(PIN_USER_BTN)'), which
; costs nothing here -- that fallback only feeds KEY_NEXT/KEY_PREV, which the
; solo screens don't act on.
;
; V3 and V4 are pin-compatible per Heltec's own docs, so the defaults below are
; carried over from the heltec_v4_companion_solo_dual env, where this exact
; CardKB + joystick combination is confirmed working on real hardware -- still
; worth checking against your own V3 module before soldering, but not a blind
; guess like the earlier SDA 41/SCL 42 default was. PIN_GPS_RX=47/TX=48/EN=26
; above are dead defines on V3 (ENV_INCLUDE_GPS is never set to 1 in this file),
; so they don't conflict with reusing 47/48 here despite the name.
[env:Heltec_v3_companion_solo_dual]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D BLE_PIN_CODE=123456 ; dynamic, random PIN
-D DUAL_SERIAL=1 ; companion app over BLE *or* USB serial
-D AUTO_SHUTDOWN_MILLIVOLTS=3400
-D OFFLINE_QUEUE_SIZE=256
-D FIRMWARE_SOLO_BUILD=1
-D UI_SENSORS_PAGE=1
-D OLED_MISC_FIXED_FONT=1 ; full Latin/Greek/Cyrillic 6x9 font, ~14 KB flash
-D ENABLE_SCREENSHOT ; same as the other solo builds — Solo Tools reads the framebuffer over USB
; CardKB on the second I2C bus. Harmless with nothing plugged in.
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
; Wired joystick — comment the block out for a CardKB-only build.
-D UI_HAS_JOYSTICK=1
-D UI_HAS_JOYSTICK_UPDOWN=1
-D JOYSTICK_UP=23
-D JOYSTICK_DOWN=6
-D JOYSTICK_LEFT=47
-D JOYSTICK_RIGHT=48
-D PIN_BACK_BTN=33
; -D PIN_BUZZER=<gpio>
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/ui/buzzer.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:Heltec_v3_companion_radio_wifi]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=SSD1306Display
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_v3_sensor]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"Heltec v3 Sensor"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ENV_PIN_SDA=33
-D ENV_PIN_SCL=34
-D DISPLAY_CLASS=SSD1306Display
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_sensor>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_WSL3_repeater]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"Heltec 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 = ${Heltec_lora32_v3.build_src_filter}
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_WSL3_repeater_bridge_rs232]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"RS232 Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D WITH_RS232_BRIDGE=Serial2
-D WITH_RS232_BRIDGE_RX=5
-D WITH_RS232_BRIDGE_TX=6
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/bridges/RS232Bridge.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_WSL3_repeater_bridge_espnow]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"ESPNow Bridge"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D MAX_NEIGHBOURS=50
-D WITH_ESPNOW_BRIDGE=1
; -D BRIDGE_DEBUG=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<../examples/simple_repeater>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:Heltec_WSL3_room_server]
extends = Heltec_lora32_v3
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"Heltec 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
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_WSL3_companion_radio_ble]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.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 MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_WSL3_companion_radio_usb]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<../examples/companion_radio/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_WSL3_companion_radio_wifi]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
lib_deps =
${Heltec_lora32_v3.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:Heltec_WSL3_sensor]
extends = Heltec_lora32_v3
build_flags =
${Heltec_lora32_v3.build_flags}
-D ADVERT_NAME='"Heltec Sensor"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<../examples/simple_sensor>
lib_deps =
${Heltec_lora32_v3.lib_deps}
${esp32_ota.lib_deps}
[env:Heltec_v3_kiss_modem]
extends = Heltec_lora32_v3
build_src_filter = ${Heltec_lora32_v3.build_src_filter}
+<../examples/kiss_modem/>