Files
MeshCore-Solo/variants/heltec_v4/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

522 lines
16 KiB
INI

[Heltec_lora32_v4]
extends = esp32_base
board = heltec_v4
build_flags =
${esp32_base.build_flags}
${sensor_base.build_flags}
-I variants/heltec_v4
-D HELTEC_LORA_V4
-D USE_SX1262
-D ESP32_CPU_FREQ=80
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D P_LORA_TX_LED=35
-D P_LORA_DIO_1=14
-D P_LORA_NSS=8
-D P_LORA_RESET=12
-D P_LORA_BUSY=13
-D P_LORA_SCLK=9
-D P_LORA_MISO=11
-D P_LORA_MOSI=10
-D P_LORA_PA_POWER=7 ; // VFEM_Ctrl -LDO power enable
-D P_LORA_GC1109_PA_EN=2 ; // CSD - GC1109 chip enable (HIGH=on)
-D P_LORA_GC1109_PA_TX_EN=46 ;// CPS - GC1109 PA mode (HIGH=full PA, LOW=bypass)
-D P_LORA_KCT8103L_PA_CSD=2
-D P_LORA_KCT8103L_PA_CTX=5
-D PIN_USER_BTN=0
-D PIN_VEXT_EN=36
-D PIN_VEXT_EN_ACTIVE=HIGH
-D LORA_TX_POWER=10 ;If it is configured as 10 here, the final output will be 22 dbm.
-D MAX_LORA_TX_POWER=22 ; Max SX1262 output
-D SX126X_REGISTER_PATCH=1 ; Patch register 0x8B5 for improved RX
-D SX126X_DIO2_AS_RF_SWITCH=true ; GC1109 CTX is controlled by SX1262 DIO2
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
-D SX126X_CURRENT_LIMIT=140
-D SX126X_RX_BOOSTED_GAIN=1 ; In some cases, commenting this out will improve RX
-D PIN_GPS_RX=38
-D PIN_GPS_TX=39
-D PIN_GPS_RESET=42
-D PIN_GPS_RESET_ACTIVE=LOW
-D PIN_GPS_EN=34
-D PIN_GPS_EN_ACTIVE=LOW
-D ENV_INCLUDE_GPS=1
-D PIN_ADC_CTRL=37
-D PIN_VBAT_READ=1
build_src_filter = ${esp32_base.build_src_filter}
+<../variants/heltec_v4>
+<helpers/sensors>
lib_deps =
${esp32_base.lib_deps}
${sensor_base.lib_deps}
[heltec_v4_oled]
extends = Heltec_lora32_v4
build_flags =
${Heltec_lora32_v4.build_flags}
-D HELTEC_LORA_V4_OLED
-D PIN_BOARD_SDA=17
-D PIN_BOARD_SCL=18
-D PIN_OLED_RESET=21
build_src_filter= ${Heltec_lora32_v4.build_src_filter}
lib_deps = ${Heltec_lora32_v4.lib_deps}
[heltec_v4_tft]
extends = Heltec_lora32_v4
build_flags =
${Heltec_lora32_v4.build_flags}
-D HELTEC_LORA_V4_TFT
-D PIN_BOARD_SDA=4
-D PIN_BOARD_SCL=3
-D DISPLAY_SCALE_X=2.5
-D DISPLAY_SCALE_Y=3.75
-D PIN_TFT_RST=18
-D PIN_TFT_VDD_CTL=-1
-D PIN_TFT_LEDA_CTL=21
-D PIN_TFT_LEDA_CTL_ACTIVE=HIGH
-D PIN_TFT_CS=15
-D PIN_TFT_DC=16
-D PIN_TFT_SCL=17
-D PIN_TFT_SDA=33
build_src_filter= ${Heltec_lora32_v4.build_src_filter}
lib_deps =
${Heltec_lora32_v4.lib_deps}
adafruit/Adafruit ST7735 and ST7789 Library @ ^1.11.0
[env:heltec_v4_repeater]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${heltec_v4_oled.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:heltec_v4_expansionkit_repeater]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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
-D ENV_PIN_SDA=4
-D ENV_PIN_SCL=3
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${heltec_v4_oled.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:heltec_v4_repeater_bridge_espnow]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_repeater>
lib_deps =
${heltec_v4_oled.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_room_server]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_room_server>
lib_deps =
${heltec_v4_oled.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_terminal_chat]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps =
${heltec_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_companion_radio_usb]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_companion_radio_ble]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.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_v4_oled.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. OLED board only -- the TFT variant would need
; its own DISPLAY_CLASS.
;
; 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.
; Defaults below: SDA 3, SCL 4 -- the pins heltec_v4_sensor and
; heltec_v4_expansionkit_repeater already use for their second I2C bus, i.e.
; the expansion kit's. (Those envs disagree on the order: two say SDA 3 /
; SCL 4, one says the reverse. 3/4 is the pair either way; swap them if the
; keyboard doesn't answer.)
;
; * 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.
;
; Free on this board, per its pinout: 3, 4, 6, 23, 33, 43, 44, 45, 46, 47, 48.
; Two of those can't take an I2C pull-up: 45 selects VDD_SPI at boot, so held
; high the chip comes up expecting 1.8V flash and won't boot at all, and 46 is
; the boot-mode strap. 3 is a strapping pin too, but it only picks the JTAG
; source -- and it's what this board's own expansion kit uses for I2C anyway.
; 43/44 are UART0: unused by this build, since ARDUINO_USB_CDC_ON_BOOT (set in
; boards/heltec_v4.json) makes Serial the native USB port, but a USB-UART bridge
; may still be wired to them, so they're left alone.
[env:heltec_v4_companion_solo_dual]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.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_v4_oled.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_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:heltec_v4_companion_radio_wifi]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=SSD1306Display
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_oled.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_v4_oled.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_sensor]
extends = heltec_v4_oled
build_flags =
${heltec_v4_oled.build_flags}
-D ADVERT_NAME='"Heltec v4 Sensor"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
-D DISPLAY_CLASS=SSD1306Display
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_oled.build_src_filter}
+<helpers/ui/SSD1306Display.cpp>
+<../examples/simple_sensor>
lib_deps =
${heltec_v4_oled.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_tft_repeater]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-D DISPLAY_CLASS=ST7789LCDDisplay
-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_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<../examples/simple_repeater>
lib_deps =
${heltec_v4_tft.lib_deps}
${esp32_ota.lib_deps}
bakercp/CRC32 @ ^2.0.0
[env:heltec_v4_tft_repeater_bridge_espnow]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-D DISPLAY_CLASS=ST7789LCDDisplay
-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_v4_tft.build_src_filter}
+<helpers/bridges/ESPNowBridge.cpp>
+<helpers/ui/ST7789LCDDisplay.cpp>
+<../examples/simple_repeater>
lib_deps =
${heltec_v4_tft.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_tft_room_server]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-D DISPLAY_CLASS=ST7789LCDDisplay
-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_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<../examples/simple_room_server>
lib_deps =
${heltec_v4_tft.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_tft_terminal_chat]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=1
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_tft.build_src_filter}
+<../examples/simple_secure_chat/main.cpp>
lib_deps =
${heltec_v4_tft.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_tft_companion_radio_usb]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D DISPLAY_CLASS=ST7789LCDDisplay
; NOTE: DO NOT ENABLE --> -D MESH_PACKET_LOGGING=1
; NOTE: DO NOT ENABLE --> -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_tft.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_tft_companion_radio_ble]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-I examples/companion_radio/ui-new
-D DISPLAY_CLASS=ST7789LCDDisplay
-D MAX_CONTACTS=350
-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 MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_tft.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_tft_companion_radio_wifi]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D OFFLINE_QUEUE_SIZE=256
-D DISPLAY_CLASS=ST7789LCDDisplay
-D WIFI_DEBUG_LOGGING=1
-D WIFI_SSID='"myssid"'
-D WIFI_PWD='"mypwd"'
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<helpers/ui/MomentaryButton.cpp>
+<helpers/esp32/*.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${heltec_v4_tft.lib_deps}
densaugeo/base64 @ ~1.4.0
[env:heltec_v4_tft_sensor]
extends = heltec_v4_tft
build_flags =
${heltec_v4_tft.build_flags}
-D ADVERT_NAME='"Heltec v4 Sensor"'
-D ADVERT_LAT=0.0
-D ADVERT_LON=0.0
-D ADMIN_PASSWORD='"password"'
-D ENV_PIN_SDA=3
-D ENV_PIN_SCL=4
-D DISPLAY_CLASS=ST7789LCDDisplay
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${heltec_v4_tft.build_src_filter}
+<helpers/ui/ST7789LCDDisplay.cpp>
+<../examples/simple_sensor>
lib_deps =
${heltec_v4_tft.lib_deps}
${esp32_ota.lib_deps}
[env:heltec_v4_kiss_modem]
extends = Heltec_lora32_v4
build_src_filter = ${Heltec_lora32_v4.build_src_filter}
+<../examples/kiss_modem/>