Files
wadamesh/variants/heltec_v4/target.cpp
T
Kaj SchittecatandClaude Opus 4.8 687eb3865c touch: add Heltec WiFi LoRa 32 V4-R8 board (8 MB octal PSRAM + Expansion Kit V2 SD)
The V4-R8 uses an ESP32-S3R8 (8 MB OCTAL PSRAM) which claims GPIO33-37, so
Heltec moved every control signal off them and the Expansion Kit V2 rebuilt the
display/touch/SD block onto a hardware-SPI bus:
  Vext 36->40 (active-LOW) . GPS_EN 34->42 . LED 35->46 . ADC_Ctrl removed
  TFT (LovyanGFX HW-SPI): MOSI=15 SCK=16 MISO=45 CS=47 DC=48 RST=21 BL=44
  touch (CHSC6x, shares board I2C 17/18) . micro-SD (shared TFT SPI, CS=3)

The build defines HELTEC_LORA_V4_TFT too, so it reuses all the V4 touch-UI code;
HELTEC_LORA_V4_R8 gates only the deltas. 8 MB enables the on-device web browser
(CAP_WEB_BROWSER) and the SD card (CAP_SD). Also wires the board into the release
+ web-flasher pipeline (release.sh, gen-flasher-meta.py, the flasher picker).

UNTESTED — no V4-R8 hardware yet. Pin sources: Meshtastic heltec_v4_r8 variant,
Heltec V4-R8 pinmap, and the Expansion_board_V2.03 schematic. All three touch
envs build clean; V4/T-Deck unregressed. On-device TODO: CHSC6x shared-Wire on
17/18, SD_CS=3, and the V2 PAM8904 buzzer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-14 11:27:40 +02:00

81 lines
2.3 KiB
C++

#include <Arduino.h>
#include "target.h"
// Set phase 1 when target.cpp globals start (no Serial - can crash before setup). Read g_boot_phase in setup().
namespace {
struct BootTrace {
BootTrace() { set_boot_phase(1); }
} _boot_trace;
}
HeltecV4Board board;
#if defined(P_LORA_SCLK)
#if defined(HELTEC_LORA_V4_R8)
static SPIClass spi(HSPI); // R8: LoRa on HSPI; the TFT + micro-SD own FSPI (SPI2)
#else
static SPIClass spi;
#endif
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi);
#else
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY);
#endif
WRAPPER_CLASS radio_driver(radio, board);
ESP32RTCClock fallback_clock;
ClockFloorRTC rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
#ifdef DISPLAY_CLASS
#if defined(HELTEC_LORA_V4_R8)
DISPLAY_CLASS display(&board.periph_power); // LGFXDisplay claims Vext(40) on turnOn
#else
DISPLAY_CLASS display(NULL);
#endif
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
fallback_clock.begin();
rtc_clock.begin(Wire);
#if defined(HELTEC_LORA_V4_R8)
// V4-R8 + Expansion Kit V2: bring up the shared TFT/SD bus on FSPI (SPI2) so
// LovyanGFX (bus_shared=true) finds an already-begun bus and skips a double
// spi_bus_initialize, and so the micro-SD mount (main.cpp, CS=3) can share it.
// MISO=45 is needed for SD reads even though the ST7789 panel is write-only.
#if PIN_TFT_LEDA_CTL >= 0
pinMode(PIN_TFT_LEDA_CTL, OUTPUT);
digitalWrite(PIN_TFT_LEDA_CTL, HIGH);
delay(50);
#endif
SPI.begin(PIN_TFT_SCL, PIN_TFT_MISO, PIN_TFT_SDA, PIN_TFT_CS);
#endif
#if defined(P_LORA_SCLK)
return radio.std_init(&spi);
#else
return radio.std_init();
#endif
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity
}
#if defined(HELTEC_LORA_V4_R8)
SPIClass* heltecV4R8SharedSPI() {
return &SPI; // FSPI (SPI2), begun in radio_init() for the TFT + micro-SD
}
#endif