diff --git a/boards/heltec_v4_r8.json b/boards/heltec_v4_r8.json
new file mode 100644
index 000000000..6dd97c84b
--- /dev/null
+++ b/boards/heltec_v4_r8.json
@@ -0,0 +1,43 @@
+{
+ "build": {
+ "arduino": {
+ "ldscript": "esp32s3_out.ld",
+ "partitions": "default_16MB.csv",
+ "memory_type": "qio_opi"
+ },
+ "core": "esp32",
+ "extra_flags": [
+ "-DBOARD_HAS_PSRAM",
+ "-DARDUINO_USB_CDC_ON_BOOT=1",
+ "-DARDUINO_USB_MODE=1",
+ "-DARDUINO_RUNNING_CORE=1",
+ "-DARDUINO_EVENT_RUNNING_CORE=1"
+ ],
+ "f_cpu": "240000000L",
+ "f_flash": "80000000L",
+ "flash_mode": "qio",
+ "psram_type": "opi",
+ "hwids": [["0x303A", "0x1001"]],
+ "mcu": "esp32s3",
+ "variant": "heltec_v4_r8"
+ },
+ "connectivity": ["wifi", "bluetooth", "lora"],
+ "debug": {
+ "default_tool": "esp-builtin",
+ "onboard_tools": ["esp-builtin"],
+ "openocd_target": "esp32s3.cfg"
+ },
+ "frameworks": ["arduino", "espidf"],
+ "name": "heltec_wifi_lora_32 v4 r8 (16 MB FLASH, 8 MB PSRAM)",
+ "upload": {
+ "flash_size": "16MB",
+ "maximum_ram_size": 327680,
+ "maximum_size": 16777216,
+ "use_1200bps_touch": true,
+ "wait_for_upload_port": true,
+ "require_upload_port": true,
+ "speed": 921600
+ },
+ "url": "https://heltec.org/",
+ "vendor": "heltec"
+}
diff --git a/src/configuration.h b/src/configuration.h
index efd9ddcf7..e0284e6c9 100644
--- a/src/configuration.h
+++ b/src/configuration.h
@@ -162,6 +162,9 @@ along with this program. If not, see .
#elif defined(HELTEC_MESH_NODE_T096)
#define NUM_PA_POINTS 22
#define TX_GAIN_LORA 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 12, 11, 10, 9, 8, 7
+#elif defined(HELTEC_V4_R8)
+#define NUM_PA_POINTS 22
+#define TX_GAIN_LORA 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 9, 8, 7
#else
// If a board enables USE_KCT8103L_PA but does not match a known variant and has
// not already provided a PA curve, fail at compile time to avoid unsafe defaults.
diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp
index 7df0c57cc..a28924ba6 100644
--- a/src/graphics/TFTDisplay.cpp
+++ b/src/graphics/TFTDisplay.cpp
@@ -422,7 +422,7 @@ static LGFX *tft = nullptr;
#elif defined(ST7789_CS)
#include // Graphics and font library for ST7735 driver chip
-#ifdef HELTEC_V4_TFT
+#if defined(HELTEC_V4_TFT) || defined(HELTEC_V4_R8_TFT)
#include "chsc6x.h"
#include "lgfx/v1/Touch.hpp"
namespace lgfx
@@ -444,7 +444,11 @@ class TOUCH_CHSC6X : public ITouch
bool init(void) override
{
if (chsc6xTouch == nullptr) {
+#if (TOUCH_I2C_PORT == 1)
chsc6xTouch = new chsc6x(&Wire1, TOUCH_SDA_PIN, TOUCH_SCL_PIN, TOUCH_INT_PIN, TOUCH_RST_PIN);
+#else
+ chsc6xTouch = new chsc6x(&Wire, TOUCH_SDA_PIN, TOUCH_SCL_PIN, TOUCH_INT_PIN, TOUCH_RST_PIN);
+#endif
}
chsc6xTouch->chsc6x_init();
return true;
@@ -481,7 +485,7 @@ class LGFX : public lgfx::LGFX_Device
#if HAS_TOUCHSCREEN
#if defined(T_WATCH_S3) || defined(ELECROW)
lgfx::Touch_FT5x06 _touch_instance;
-#elif defined(HELTEC_V4_TFT)
+#elif defined(HELTEC_V4_TFT) || defined(HELTEC_V4_R8_TFT)
lgfx::TOUCH_CHSC6X _touch_instance;
#else
lgfx::Touch_GT911 _touch_instance;
@@ -500,7 +504,11 @@ class LGFX : public lgfx::LGFX_Device
cfg.freq_write = SPI_FREQUENCY; // SPI clock for transmission (up to 80MHz, rounded to the value obtained by dividing
// 80MHz by an integer)
cfg.freq_read = SPI_READ_FREQUENCY; // SPI clock when receiving
- cfg.spi_3wire = false;
+#ifdef SPI_3_WIRE
+ cfg.spi_3wire = SPI_3_WIRE;
+#else
+ cfg.spi_3wire = true; // Set to true if reception is done on the MOSI pin
+#endif
cfg.use_lock = true; // Set to true to use transaction locking
cfg.dma_channel = SPI_DMA_CH_AUTO; // SPI_DMA_CH_AUTO; // Set DMA channel to use (0=not use DMA / 1=1ch / 2=ch /
// SPI_DMA_CH_AUTO=auto setting)
@@ -550,8 +558,11 @@ class LGFX : public lgfx::LGFX_Device
cfg.rgb_order = false; // Set to true if the panel's red and blue are swapped
cfg.dlen_16bit =
false; // Set to true for panels that transmit data length in 16-bit units with 16-bit parallel or SPI
+#if defined(HAS_SDCARD)
cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.)
-
+#else
+ cfg.bus_shared = false;
+#endif
// Set the following only when the display is shifted with a driver with a variable number of pixels, such as the
// ST7735 or ILI9163.
// cfg.memory_width = TFT_WIDTH; // Maximum width supported by the driver IC
diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp
index 6e57e89f6..0193585e2 100644
--- a/src/mesh/NodeDB.cpp
+++ b/src/mesh/NodeDB.cpp
@@ -688,7 +688,7 @@ void NodeDB::installDefaultConfig(bool preserveKey = false)
strncpy(config.network.ntp_server, "meshtastic.pool.ntp.org", 32);
#if (defined(T_DECK) || defined(T_WATCH_S3) || defined(UNPHONE) || defined(PICOMPUTER_S3) || defined(SENSECAP_INDICATOR) || \
- defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT)) && \
+ defined(ELECROW_PANEL) || defined(HELTEC_V4_TFT) || defined(HELTEC_V4_R8_TFT)) && \
HAS_TFT
// switch BT off by default; use TFT programming mode or hotkey to enable
config.bluetooth.enabled = false;
diff --git a/variants/esp32s3/heltec_v4/platformio.ini b/variants/esp32s3/heltec_v4/platformio.ini
index d6634aa74..ca81ab435 100644
--- a/variants/esp32s3/heltec_v4/platformio.ini
+++ b/variants/esp32s3/heltec_v4/platformio.ini
@@ -89,8 +89,10 @@ build_flags =
-D VIEW_240x320
-D DISPLAY_SET_RESOLUTION
-D DISPLAY_SIZE=240x320 ; portrait mode
+ -D LGFX_SPI_3WIRE=true
-D LGFX_PIN_SCK=17
-D LGFX_PIN_MOSI=33
+ -D LGFX_PIN_MISO=-1
-D LGFX_PIN_DC=16
-D LGFX_PIN_CS=15
-D LGFX_PIN_BL=21
@@ -123,7 +125,7 @@ build_flags =
-D SCREEN_TRANSITION_FRAMERATE=30
-D BRIGHTNESS_DEFAULT=130 ; Medium Low Brightness
-D HAS_TOUCHSCREEN=1
- -D TOUCH_I2C_PORT=0
+ -D TOUCH_I2C_PORT=1
-D TOUCH_SLAVE_ADDRESS=0x2E
-D SCREEN_TOUCH_INT=TOUCH_INT_PIN
-D SCREEN_TOUCH_RST=TOUCH_RST_PIN
diff --git a/variants/esp32s3/heltec_v4_r8/pins_arduino.h b/variants/esp32s3/heltec_v4_r8/pins_arduino.h
new file mode 100644
index 000000000..631f07513
--- /dev/null
+++ b/variants/esp32s3/heltec_v4_r8/pins_arduino.h
@@ -0,0 +1,56 @@
+#ifndef Pins_Arduino_h
+#define Pins_Arduino_h
+
+#include
+
+#define USB_VID 0x303a
+#define USB_PID 0x1001
+
+static const uint8_t TX = 43;
+static const uint8_t RX = 44;
+
+static const uint8_t SDA = 17;
+static const uint8_t SCL = 18;
+
+static const uint8_t SS = 8;
+static const uint8_t MOSI = 10;
+static const uint8_t MISO = 11;
+static const uint8_t SCK = 9;
+
+static const uint8_t A0 = 1;
+static const uint8_t A1 = 2;
+static const uint8_t A2 = 3;
+static const uint8_t A3 = 4;
+static const uint8_t A4 = 5;
+static const uint8_t A5 = 6;
+static const uint8_t A6 = 7;
+static const uint8_t A7 = 8;
+static const uint8_t A8 = 9;
+static const uint8_t A9 = 10;
+static const uint8_t A10 = 11;
+static const uint8_t A11 = 12;
+static const uint8_t A12 = 13;
+static const uint8_t A13 = 14;
+static const uint8_t A14 = 15;
+static const uint8_t A15 = 16;
+static const uint8_t A16 = 17;
+static const uint8_t A17 = 18;
+static const uint8_t A18 = 19;
+static const uint8_t A19 = 20;
+
+static const uint8_t T1 = 1;
+static const uint8_t T2 = 2;
+static const uint8_t T3 = 3;
+static const uint8_t T4 = 4;
+static const uint8_t T5 = 5;
+static const uint8_t T6 = 6;
+static const uint8_t T7 = 7;
+static const uint8_t T8 = 8;
+static const uint8_t T9 = 9;
+static const uint8_t T10 = 10;
+static const uint8_t T11 = 11;
+static const uint8_t T12 = 12;
+static const uint8_t T13 = 13;
+static const uint8_t T14 = 14;
+
+#endif /* Pins_Arduino_h */
\ No newline at end of file
diff --git a/variants/esp32s3/heltec_v4_r8/platformio.ini b/variants/esp32s3/heltec_v4_r8/platformio.ini
new file mode 100644
index 000000000..747cc8c49
--- /dev/null
+++ b/variants/esp32s3/heltec_v4_r8/platformio.ini
@@ -0,0 +1,145 @@
+[heltec_v4_r8_base]
+extends = esp32s3_base
+board = heltec_v4_r8
+board_check = true
+board_build.partitions = default_16MB.csv
+build_flags =
+ ${esp32s3_base.build_flags}
+ -D HELTEC_V4_R8
+ -D HAS_LORA_FEM=1
+ -D BOARD_HAS_PSRAM
+ -I variants/esp32s3/heltec_v4_r8
+ -ULED_BUILTIN
+
+[env:heltec-v4-r8-oled]
+custom_meshtastic_hw_model = 132
+custom_meshtastic_hw_model_slug = HELTEC_V4_R8
+custom_meshtastic_architecture = esp32-s3
+custom_meshtastic_actively_supported = true
+custom_meshtastic_support_level = 1
+custom_meshtastic_display_name = Heltec V4 R8
+custom_meshtastic_images = heltec_v4_r8.svg
+custom_meshtastic_tags = Heltec
+custom_meshtastic_requires_dfu = true
+custom_meshtastic_partition_scheme = 16MB
+
+extends = heltec_v4_r8_base
+build_flags =
+ ${heltec_v4_r8_base.build_flags}
+ -D HELTEC_V4_R8_OLED
+ -D USE_SSD1306 ; Heltec_v4_R8 has an SSD1315 display (compatible with SSD1306 driver)
+ -D LED_POWER=46
+ -D RESET_OLED=21
+ -D I2C_SDA=17
+ -D I2C_SCL=18
+
+[env:heltec-v4-r8-tft]
+custom_meshtastic_hw_model = 132
+custom_meshtastic_hw_model_slug = HELTEC_V4_R8
+custom_meshtastic_architecture = esp32-s3
+custom_meshtastic_actively_supported = true
+custom_meshtastic_support_level = 1
+custom_meshtastic_display_name = Heltec V4 R8 TFT
+custom_meshtastic_images = heltec_v4_r8_tft.svg
+custom_meshtastic_tags = Heltec
+custom_meshtastic_requires_dfu = true
+custom_meshtastic_partition_scheme = 16MB
+
+extends = heltec_v4_r8_base
+build_flags =
+ ${heltec_v4_r8_base.build_flags} ;-Os
+ -D HELTEC_V4_R8_TFT
+ -D I2C_SDA=17
+ -D I2C_SCL=18
+ -D PIN_BUTTON2=46
+ -D ALT_BUTTON_PIN=PIN_BUTTON2
+ -D ALT_BUTTON_ACTIVE_LOW=false
+ -D PIN_BUZZER=4
+ -D USE_PIN_BUZZER=PIN_BUZZER
+ -D CONFIG_ARDUHAL_LOG_COLORS
+ -D RADIOLIB_DEBUG_SPI=0
+ -D RADIOLIB_DEBUG_PROTOCOL=0
+ -D RADIOLIB_DEBUG_BASIC=0
+ -D RADIOLIB_VERBOSE_ASSERT=0
+ -D RADIOLIB_SPI_PARANOID=0
+ -D CONFIG_DISABLE_HAL_LOCKS=1
+ -D INPUTDRIVER_BUTTON_TYPE=0
+ -D HAS_SCREEN=1
+ -D HAS_TFT=1
+ -D RAM_SIZE=5120
+ -D LV_LVGL_H_INCLUDE_SIMPLE
+ -D LV_CONF_INCLUDE_SIMPLE
+ -D LV_COMP_CONF_INCLUDE_SIMPLE
+ -D LV_USE_SYSMON=0
+ -D LV_USE_PROFILER=0
+ -D LV_USE_PERF_MONITOR=0
+ -D LV_USE_MEM_MONITOR=0
+ -D LV_USE_LOG=0
+ -D LV_BUILD_TEST=0
+ -D USE_LOG_DEBUG
+ -D LOG_DEBUG_INC=\"DebugConfiguration.h\"
+ -D USE_PACKET_API
+ -D LGFX_DRIVER=LGFX_HELTEC_V4_TFT
+ -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_HELTEC_V4_TFT.h\"
+ -D VIEW_240x320
+ -D DISPLAY_SET_RESOLUTION
+ -D DISPLAY_SIZE=240x320 ; portrait mode
+ -D LGFX_SPI_3WIRE=false
+ -D LGFX_PIN_SCK=16
+ -D LGFX_PIN_MOSI=15
+ -D LGFX_PIN_MISO=45
+ -D LGFX_PIN_DC=48
+ -D LGFX_PIN_CS=47
+ -D LGFX_PIN_BL=44
+ -D LGFX_PIN_RST=21
+ -D CUSTOM_TOUCH_DRIVER
+ -D TOUCH_SDA_PIN=I2C_SDA
+ -D TOUCH_SCL_PIN=I2C_SCL
+ -D TOUCH_INT_PIN=-1
+ -D TOUCH_RST_PIN=-1
+;base UI
+ -D TFT_CS=LGFX_PIN_CS
+ -D ST7789_CS=TFT_CS
+ -D ST7789_RS=LGFX_PIN_DC
+ -D ST7789_SDA=LGFX_PIN_MOSI
+ -D ST7789_SCK=LGFX_PIN_SCK
+ -D ST7789_RESET=LGFX_PIN_RST
+ -D ST7789_MISO=LGFX_PIN_MISO
+ -D ST7789_BUSY=-1
+ -D ST7789_BL=LGFX_PIN_BL
+ -D ST7789_SPI_HOST=SPI3_HOST
+ -D TFT_BL=ST7789_BL
+ -D SPI_FREQUENCY=75000000
+ -D SPI_READ_FREQUENCY=SPI_FREQUENCY
+ -D SPI_3_WIRE=false
+ -D TFT_HEIGHT=320
+ -D TFT_WIDTH=240
+ -D TFT_OFFSET_X=0
+ -D TFT_OFFSET_Y=0
+ -D TFT_OFFSET_ROTATION=0
+ -D SCREEN_ROTATE
+ -D SCREEN_TRANSITION_FRAMERATE=5
+ -D BRIGHTNESS_DEFAULT=130 ; Medium Low Brightness
+ -D HAS_TOUCHSCREEN=1
+ -D TOUCH_I2C_PORT=0
+ -D TOUCH_SLAVE_ADDRESS=0x2E
+ -D SCREEN_TOUCH_INT=TOUCH_INT_PIN
+ -D SCREEN_TOUCH_RST=TOUCH_RST_PIN
+
+; Have SPI interface SD card slot
+ -D HAS_SDCARD
+ -D SDCARD_USE_SPI1
+ -D SDCARD_USER_SPI_BEGIN
+ -D SPI_MOSI=LGFX_PIN_MOSI
+ -D SPI_SCK=LGFX_PIN_SCK
+ -D SPI_MISO=LGFX_PIN_MISO
+ -D SPI_CS=3
+ -D SDCARD_CS=SPI_CS
+ -D SD_SPI_FREQUENCY=SPI_FREQUENCY
+
+lib_deps = ${heltec_v4_r8_base.lib_deps}
+ ${device-ui_base.lib_deps}
+ # renovate: datasource=custom.pio depName=LovyanGFX packageName=lovyan03/library/LovyanGFX
+ lovyan03/LovyanGFX@1.2.19
+ # renovate: datasource=git-refs depName=Quency-D_chsc6x packageName=https://github.com/Quency-D/chsc6x gitBranch=master
+ https://github.com/Quency-D/chsc6x/archive/3b2b6cebf3177b3e2c33d06e07909b0b10159516.zip
\ No newline at end of file
diff --git a/variants/esp32s3/heltec_v4_r8/variant.h b/variants/esp32s3/heltec_v4_r8/variant.h
new file mode 100644
index 000000000..1f638f24c
--- /dev/null
+++ b/variants/esp32s3/heltec_v4_r8/variant.h
@@ -0,0 +1,72 @@
+#define VEXT_ENABLE 40 // active low, powers the oled display and the lora antenna boost
+#define VEXT_ON_VALUE LOW
+#define BUTTON_PIN 0
+
+#define BATTERY_PIN 1 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage
+#define ADC_CHANNEL ADC1_GPIO1_CHANNEL
+#define ADC_ATTENUATION ADC_ATTEN_DB_2_5 // lower dB for high resistance voltage divider
+#define ADC_MULTIPLIER 4.9 * 1.035
+
+#define USE_SX1262
+#define LORA_DIO0 -1 // a No connect on the SX1262 module
+#define LORA_RESET 12
+#define LORA_DIO1 14 // SX1262 IRQ
+#define LORA_DIO2 13 // SX1262 BUSY
+#define LORA_DIO3 // Not connected on PCB, but internally on the TTGO SX1262, if DIO3 is high the TCXO is enabled
+
+#define LORA_SCK 9
+#define LORA_MISO 11
+#define LORA_MOSI 10
+#define LORA_CS 8
+
+#define SX126X_CS LORA_CS
+#define SX126X_DIO1 LORA_DIO1
+#define SX126X_BUSY LORA_DIO2
+#define SX126X_RESET LORA_RESET
+
+#define SX126X_DIO2_AS_RF_SWITCH
+#define SX126X_DIO3_TCXO_VOLTAGE 1.8
+
+// Enable Traffic Management Module for Heltec V4
+#ifndef HAS_TRAFFIC_MANAGEMENT
+#define HAS_TRAFFIC_MANAGEMENT 1
+#endif
+#ifndef TRAFFIC_MANAGEMENT_CACHE_SIZE
+#define TRAFFIC_MANAGEMENT_CACHE_SIZE 2048
+#endif
+
+// ---- KCT8103L RF FRONT END CONFIGURATION ----
+// The Heltec V4.3 uses a KCT8103L FEM chip with integrated PA and LNA
+// RF path: SX1262 -> Pi attenuator -> KCT8103L PA -> Antenna
+// Control logic (from KCT8103L datasheet):
+// Transmit PA: CSD=1, CTX=1, CPS=1
+// Receive LNA: CSD=1, CTX=0, CPS=X (21dB gain, 1.9dB NF)
+// Receive bypass: CSD=1, CTX=1, CPS=0
+// Shutdown: CSD=0, CTX=X, CPS=X
+// Pin mapping:
+// CPS (pin 5) -> SX1262 DIO2: TX/RX path select (automatic via SX126X_DIO2_AS_RF_SWITCH)
+// CSD (pin 4) -> GPIO2: Chip enable (HIGH=on, LOW=shutdown)
+// CTX (pin 6) -> GPIO5: Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA)
+// VCC0/VCC1 -> Vfem via U3 LDO, controlled by GPIO7
+// KCT8103L FEM: TX/RX path switching is handled by DIO2 -> CPS pin (via SX126X_DIO2_AS_RF_SWITCH)
+
+#define USE_KCT8103L_PA
+#define LORA_PA_POWER 7 // VFEM_Ctrl - KCT8103L LDO power enable
+#define LORA_KCT8103L_PA_CSD 2 // CSD - KCT8103L chip enable (HIGH=on)
+#define LORA_KCT8103L_PA_CTX 5 // CTX - Switch between Receive LNA Mode and Receive Bypass Mode. (HIGH=RX bypass, LOW=RX LNA)
+
+#if HAS_TFT
+#define USE_TFTDISPLAY 1
+#endif
+/*
+ * GPS pins
+ */
+#define GPS_L76K
+#define PIN_GPS_EN (42)
+#define GPS_EN_ACTIVE LOW
+#define PERIPHERAL_WARMUP_MS 1000 // Make sure I2C QuickLink has stable power before continuing
+#define PIN_GPS_PPS (41)
+// Seems to be missing on this new board
+#define GPS_TX_PIN (38) // This is for bits going TOWARDS the CPU
+#define GPS_RX_PIN (39) // This is for bits going TOWARDS the GPS
+#define GPS_THREAD_INTERVAL 50