Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ Console/build
build/*
.pio/*
.vscode/*
.gitnexus
77 changes: 73 additions & 4 deletions Boards.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,15 @@
#define BOARD_HELTEC32_V4 0x3F
#define MODEL_C8 0xC8 // Heltec Lora32 v3, 850-950 MHz, 28dBm

#define PRODUCT_HELTEC_T114 0xC2 // Heltec Mesh Node T114
#define BOARD_HELTEC_T114 0x3C
#define MODEL_C6 0xC6 // Heltec Mesh Node T114, 470-510 MHz
#define MODEL_C7 0xC7 // Heltec Mesh Node T114, 863-928 MHz
#define PRODUCT_HELTEC_T114 0xC2 // Heltec Mesh Node T114
#define BOARD_HELTEC_T114 0x3C
#define MODEL_C6 0xC6 // Heltec Mesh Node T114, 470-510 MHz
#define MODEL_C7 0xC7 // Heltec Mesh Node T114, 863-928 MHz

#define PRODUCT_HELTEC_TRACKER 0xC4 // Heltec Wireless Tracker v1.1
#define BOARD_HELTEC_TRACKER 0x43
#define MODEL_CB 0xCB // Heltec Wireless Tracker, 433/470 MHz
#define MODEL_CC 0xCC // Heltec Wireless Tracker, 868/915 MHz

#define PRODUCT_TECHO 0x15 // LilyGO T-Echo devices
#define BOARD_TECHO 0x44
Expand Down Expand Up @@ -167,6 +172,7 @@
#define HAS_SLEEP false
#define HAS_LORA_PA false
#define HAS_LORA_LNA false
#define HAS_GNSS false
#define PIN_DISP_SLEEP -1
#define VALIDATE_FIRMWARE true

Expand Down Expand Up @@ -467,6 +473,69 @@
const int pin_miso = 11;
const int pin_sclk = 9;

#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
#define IS_ESP32S3 true
#define HAS_DISPLAY true
#define HAS_BLUETOOTH false
#ifdef BOUNDARY_MODE
#define HAS_BLE false
#else
#define HAS_BLE true
#endif
#define HAS_WIFI true
#define HAS_PMU true
#define HAS_CONSOLE true
#define HAS_EEPROM true
#define HAS_INPUT true
#define HAS_SLEEP true
#define HAS_GNSS true
#define PIN_WAKEUP GPIO_NUM_0
#define WAKEUP_LEVEL 0
// VEXT (GPIO3, active LOW) powers TFT and GNSS module
#define Vext GPIO_NUM_3

const int pin_btn_usr1 = 0;
const int pin_led_rx = 18;
const int pin_led_tx = 18;

#define MODEM SX1262
#define HAS_TCXO true
const int pin_tcxo_enable = -1;
#define HAS_BUSY true
#define DIO2_AS_RF_SWITCH true

#define PA_MAX_OUTPUT 22

// SX1262 LoRa (same pins as V3/V4)
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;

// ST7735S 0.96" 80×160 TFT (software SPI on dedicated pins)
#define TRACKER_TFT_BL 21
#define TRACKER_TFT_DC 40
#define TRACKER_TFT_CS 38
#define TRACKER_TFT_RST 39
#define TRACKER_TFT_MOSI 42
#define TRACKER_TFT_SCK 41

const int DISPLAY_BL_PIN = TRACKER_TFT_BL;
const int DISPLAY_DC = TRACKER_TFT_DC;
const int DISPLAY_CS = TRACKER_TFT_CS;
const int DISPLAY_RST = TRACKER_TFT_RST;
const int DISPLAY_MOSI = TRACKER_TFT_MOSI;
const int DISPLAY_CLK = TRACKER_TFT_SCK;

// UC6580 GNSS (UART2)
#define TRACKER_GNSS_TX 33
#define TRACKER_GNSS_RX 34
#define TRACKER_GNSS_RST 35
#define TRACKER_GNSS_PPS 36

#elif BOARD_MODEL == BOARD_RNODE_NG_20
#define HAS_DISPLAY true
#define HAS_BLUETOOTH true
Expand Down
7 changes: 6 additions & 1 deletion BoundaryConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ static const int BW_OPTIONS_COUNT = sizeof(BW_OPTIONS_HZ) / sizeof(BW_OPTIONS_HZ
static uint8_t config_default_display_rotation() {
#if BOARD_MODEL == BOARD_LORA32_V2_1 || BOARD_MODEL == BOARD_TBEAM || BOARD_MODEL == BOARD_RAK4631
return 0;
#elif BOARD_MODEL == BOARD_HELTEC32_V2 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TBEAM_S_V1
#elif BOARD_MODEL == BOARD_HELTEC32_V2 || BOARD_MODEL == BOARD_HELTEC32_V3 || BOARD_MODEL == BOARD_HELTEC32_V4 || BOARD_MODEL == BOARD_HELTEC_TRACKER || BOARD_MODEL == BOARD_HELTEC_T114 || BOARD_MODEL == BOARD_TBEAM_S_V1
return 1;
#else
return 3;
Expand Down Expand Up @@ -779,9 +779,14 @@ void config_portal_start() {
stat_area.println("");
stat_area.println("Open browser");
stat_area.println("http://10.0.0.1");
#if BOARD_MODEL == BOARD_HELTEC_TRACKER
display.fillScreen(SSD1306_BLACK);
display.drawBitmap(8, 0, stat_area.getBuffer(), stat_area.width(), stat_area.height(), SSD1306_WHITE, SSD1306_BLACK);
#else
display.clearDisplay();
display.drawBitmap(0, 0, stat_area.getBuffer(), stat_area.width(), stat_area.height(), SSD1306_WHITE, SSD1306_BLACK);
display.display();
#endif
}
#endif
// Headless: LED ramp will be driven from the WCC portal loop
Expand Down
63 changes: 61 additions & 2 deletions Display.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
#elif BOARD_MODEL == BOARD_HELTEC_T114
#include "ST7789.h"
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
#include <Adafruit_ST7735.h>
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
#include <Adafruit_SH110X.h>
#else
Expand Down Expand Up @@ -153,6 +155,11 @@ extern BoundaryState boundary_state;
ST7789Spi display(&SPI1, DISPLAY_RST, DISPLAY_DC, DISPLAY_CS);
#define SSD1306_WHITE ST77XX_WHITE
#define SSD1306_BLACK ST77XX_BLACK
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
// Software SPI on dedicated GPIO-matrix pins, separate from LoRa SPI bus
Adafruit_ST7735 display = Adafruit_ST7735(DISPLAY_CS, DISPLAY_DC, DISPLAY_MOSI, DISPLAY_CLK, DISPLAY_RST);
#define SSD1306_WHITE ST77XX_WHITE
#define SSD1306_BLACK ST77XX_BLACK
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
Adafruit_SH1106G display = Adafruit_SH1106G(128, 64, &Wire, -1);
#define SSD1306_WHITE SH110X_WHITE
Expand Down Expand Up @@ -238,6 +245,14 @@ void update_area_positions() {
p_as_x = 126;
p_as_y = p_ad_y;
}
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
// 160×80 landscape: two 64×64 canvases side by side, vertically centered (8px top margin)
if (disp_mode == DISP_MODE_LANDSCAPE) {
p_ad_x = 16; // disp area: left half (80px) → center 64px → offset 8px, +8px left margin
p_ad_y = 8; // (80-64)/2
p_as_x = 80; // stat area: right half starts at x=80
p_as_y = 8;
}
#elif BOARD_MODEL == BOARD_TECHO
if (disp_mode == DISP_MODE_PORTRAIT) {
p_ad_x = 61;
Expand Down Expand Up @@ -271,6 +286,11 @@ uint8_t display_contrast = 0x00;
}
#elif BOARD_MODEL == BOARD_HELTEC_T114
void set_contrast(ST7789Spi *display, uint8_t value) { }
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
void set_contrast(Adafruit_ST7735 *display, uint8_t value) {
// BL is active HIGH: higher PWM duty = brighter.
analogWrite(DISPLAY_BL_PIN, value == 0 ? 0 : map(value, 1, 255, 40, 255));
}
#elif BOARD_MODEL == BOARD_TECHO
void set_contrast(void *display, uint8_t value) {
if (value == 0) { analogWrite(pin_backlight, 0); }
Expand Down Expand Up @@ -352,6 +372,14 @@ bool display_init() {
#elif BOARD_MODEL == BOARD_HELTEC_T114
pinMode(PIN_T114_TFT_EN, OUTPUT);
digitalWrite(PIN_T114_TFT_EN, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
// VEXT is active HIGH (GPIO3 HIGH = peripheral power on)
pinMode(Vext, OUTPUT);
digitalWrite(Vext, HIGH);
// BL is active HIGH — claim LEDC channel at a visible duty before any
// set_contrast() call can fire and override it.
analogWrite(DISPLAY_BL_PIN, 200);
delay(50);
#elif BOARD_MODEL == BOARD_TECHO
display.init(0, true, 10, false, displaySPI, SPISettings(4000000, MSBFIRST, SPI_MODE0));
display.setPartialWindow(0, 0, DISP_W, DISP_H);
Expand Down Expand Up @@ -418,14 +446,28 @@ bool display_init() {
// set white as default pixel colour for Heltec T114
display.setRGB(COLOR565(0xFF, 0xFF, 0xFF));
if (false) {
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
display.initR(INITR_MINI160x80_PLUGIN); // heltec_tracker uses PLUGIN variant
display.fillScreen(SSD1306_BLACK);
if (false) {
#elif BOARD_MODEL == BOARD_TBEAM_S_V1
if (!display.begin(display_address, true)) {
#else
if (!display.begin(SSD1306_SWITCHCAPVCC, display_address)) {
#endif
return false;
} else {
set_contrast(&display, display_contrast);
// Tracker backlight was already set in the VEXT block above;
// calling set_contrast(display_contrast=0) here would reset LEDC to 0%.
#if BOARD_MODEL != BOARD_HELTEC_TRACKER
set_contrast(&display, display_contrast);
#endif
// Tracker rotation is fixed by hardware; never load a stale NVS value.
#if BOARD_MODEL == BOARD_HELTEC_TRACKER
disp_mode = DISP_MODE_LANDSCAPE;
display.setRotation(3);
if (false) { // structural dummy — balances the closing } of the else block below
#else
if (display_rotation != 0xFF) {
if (display_rotation == 0 || display_rotation == 2) {
disp_mode = DISP_MODE_LANDSCAPE;
Expand All @@ -434,6 +476,7 @@ bool display_init() {
}
display.setRotation(display_rotation);
} else {
#endif
#if BOARD_MODEL == BOARD_RNODE_NG_20
disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(3);
Expand Down Expand Up @@ -464,6 +507,9 @@ bool display_init() {
#elif BOARD_MODEL == BOARD_HELTEC32_V4
disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(1);
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
disp_mode = DISP_MODE_LANDSCAPE;
display.setRotation(3); // INITR_MINI160x80_PLUGIN: rot3 = 160w × 80h landscape, correct origin
#elif BOARD_MODEL == BOARD_HELTEC_T114
disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(1);
Expand Down Expand Up @@ -519,6 +565,15 @@ bool display_init() {
fillRect(p_as_x, p_as_y, 128, 128, SSD1306_BLACK);
pinMode(PIN_T114_TFT_BLGT, OUTPUT);
digitalWrite(PIN_T114_TFT_BLGT, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
// Fresh EEPROM (erased flash) returns 0 from the NVS layer, which would
// call set_contrast(0) and turn the backlight off. Treat 0 as "not yet
// configured" and fall back to full brightness so first boot is visible.
if (display_intensity == 0) {
display_intensity = 0xFF;
display_unblank_intensity = 0xFF;
}
set_contrast(&display, display_intensity);
#endif

return true;
Expand Down Expand Up @@ -1257,6 +1312,8 @@ void update_display(bool blank = false) {
#if BOARD_MODEL == BOARD_HELTEC_T114
display.clear();
display.display();
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
display.fillScreen(SSD1306_BLACK);
#elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO
display.clearDisplay();
display.display();
Expand All @@ -1277,6 +1334,8 @@ void update_display(bool blank = false) {

#if BOARD_MODEL == BOARD_HELTEC_T114
display.clear();
#elif BOARD_MODEL == BOARD_HELTEC_TRACKER
// drawBitmap is fully opaque; no fill needed — avoids slow full-screen SPI writes
#elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO
display.clearDisplay();
#endif
Expand All @@ -1302,7 +1361,7 @@ void update_display(bool blank = false) {
last_epd_refresh = millis();
epd_blanked = false;
}
#elif BOARD_MODEL != BOARD_TDECK
#elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_HELTEC_TRACKER
display.display();
#endif

Expand Down
Loading