Merge pull request #2520 from Quency-D/heltec-mesh-node-t1

add heltec-mesh-node-t1
This commit is contained in:
Liam Cottle
2026-05-12 00:38:14 +12:00
committed by GitHub
10 changed files with 597 additions and 1 deletions
+61
View File
@@ -0,0 +1,61 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A","0x8029"],
["0x239A","0x0029"],
["0x239A","0x002A"],
["0x239A","0x802A"]
],
"usb_product": "HT-n5262T1",
"mcu": "nrf52840",
"variant": "heltec_t1",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": [
"bluetooth"
],
"debug": {
"jlink_device": "nRF52840_xxAA",
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52.cfg"
},
"frameworks": [
"arduino"
],
"name": "Heltec Mesh Node T1 Board",
"upload": {
"maximum_ram_size": 235520,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://heltec.org/",
"vendor": "Heltec"
}
+4 -1
View File
@@ -28,7 +28,10 @@ bool ST7735Display::begin() {
#endif
digitalWrite(PIN_TFT_RST, HIGH);
#if defined(HELTEC_TRACKER_V2) || defined(HELTEC_T096)
#if defined(HELTEC_T1)
display.initR(INITR_MINI160x80);
display.setRotation(DISPLAY_ROTATION);
#elif defined(HELTEC_TRACKER_V2) || defined(HELTEC_T096)
display.initR(INITR_MINI160x80);
display.setRotation(DISPLAY_ROTATION);
uint8_t madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV |ST7735_MADCTL_BGR;//Adjust color to BGR
+1
View File
@@ -1,3 +1,4 @@
#include "Arduino.h"
#ifdef PIN_BUZZER
#include "buzzer.h"
+135
View File
@@ -0,0 +1,135 @@
#include "T1Board.h"
#include <Arduino.h>
#include <Wire.h>
#ifdef NRF52_POWER_MANAGEMENT
const PowerMgtConfig power_config = {
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
};
void T1Board::initiateShutdown(uint8_t reason) {
variant_shutdown();
bool enable_lpcomp = (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
reason == SHUTDOWN_REASON_BOOT_PROTECT);
pinMode(PIN_BAT_CTL, OUTPUT);
digitalWrite(PIN_BAT_CTL, enable_lpcomp ? ADC_CTRL_ENABLED : !ADC_CTRL_ENABLED);
if (enable_lpcomp) {
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
}
enterSystemOff(reason);
}
#endif
void T1Board::begin() {
NRF52Board::begin();
#ifdef NRF52_POWER_MANAGEMENT
checkBootVoltage(&power_config);
#endif
#if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
#endif
Wire.begin();
pinMode(P_LORA_TX_LED, OUTPUT);
digitalWrite(P_LORA_TX_LED, !LED_STATE_ON);
pinMode(PIN_GPS_EN, OUTPUT);
digitalWrite(PIN_GPS_EN, !PIN_GPS_EN_ACTIVE);
pinMode(PIN_SENSOR_EN, OUTPUT);
digitalWrite(PIN_SENSOR_EN, PIN_SENSOR_EN_ACTIVE);
pinMode(PIN_BUZZER, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
pinMode(PIN_BUZZER_VOLTAGE_MULTIPLIER_1, OUTPUT);
pinMode(PIN_BUZZER_VOLTAGE_MULTIPLIER_2, OUTPUT);
digitalWrite(PIN_BUZZER_VOLTAGE_MULTIPLIER_1, HIGH);
digitalWrite(PIN_BUZZER_VOLTAGE_MULTIPLIER_2, HIGH);
periph_power.begin();
delay(1);
}
void T1Board::onBeforeTransmit() {
digitalWrite(P_LORA_TX_LED, LED_STATE_ON);
}
void T1Board::onAfterTransmit() {
digitalWrite(P_LORA_TX_LED, !LED_STATE_ON);
}
uint16_t T1Board::getBattMilliVolts() {
analogReadResolution(12);
analogReference(VBAT_AR_INTERNAL);
pinMode(PIN_VBAT_READ, INPUT);
pinMode(PIN_BAT_CTL, OUTPUT);
digitalWrite(PIN_BAT_CTL, ADC_CTRL_ENABLED);
delay(10);
int adcvalue = analogRead(PIN_VBAT_READ);
digitalWrite(PIN_BAT_CTL, !ADC_CTRL_ENABLED);
return (uint16_t)((float)adcvalue * MV_LSB * ADC_MULTIPLIER);
}
void T1Board::variant_shutdown() {
nrf_gpio_cfg_default(PIN_TFT_CS);
nrf_gpio_cfg_default(PIN_TFT_DC);
nrf_gpio_cfg_default(PIN_TFT_SDA);
nrf_gpio_cfg_default(PIN_TFT_SCL);
nrf_gpio_cfg_default(PIN_TFT_RST);
nrf_gpio_cfg_default(PIN_TFT_LEDA_CTL);
nrf_gpio_cfg_default(PIN_TFT_VDD_CTL);
nrf_gpio_cfg_default(PIN_WIRE_SDA);
nrf_gpio_cfg_default(PIN_WIRE_SCL);
nrf_gpio_cfg_default(LORA_CS);
nrf_gpio_cfg_default(SX126X_DIO1);
nrf_gpio_cfg_default(SX126X_BUSY);
nrf_gpio_cfg_default(SX126X_RESET);
nrf_gpio_cfg_default(PIN_SPI_MISO);
nrf_gpio_cfg_default(PIN_SPI_MOSI);
nrf_gpio_cfg_default(PIN_SPI_SCK);
nrf_gpio_cfg_default(PIN_SPI1_MOSI);
nrf_gpio_cfg_default(PIN_SPI1_SCK);
nrf_gpio_cfg_default(PIN_GPS_RESET);
nrf_gpio_cfg_default(PIN_GPS_EN);
nrf_gpio_cfg_default(PIN_GPS_PPS);
nrf_gpio_cfg_default(PIN_GPS_RX);
nrf_gpio_cfg_default(PIN_GPS_TX);
nrf_gpio_cfg_default(PIN_BUZZER_VOLTAGE_MULTIPLIER_1);
nrf_gpio_cfg_default(PIN_BUZZER_VOLTAGE_MULTIPLIER_2);
pinMode(PIN_BUZZER, OUTPUT);
digitalWrite(PIN_BUZZER, LOW);
pinMode(PIN_SENSOR_EN, OUTPUT);
digitalWrite(PIN_SENSOR_EN, !PIN_SENSOR_EN_ACTIVE);
pinMode(PIN_LED1, OUTPUT);
digitalWrite(PIN_LED1, !LED_STATE_ON);
pinMode(PIN_BAT_CTL, OUTPUT);
digitalWrite(PIN_BAT_CTL, !ADC_CTRL_ENABLED);
}
void T1Board::powerOff() {
variant_shutdown();
sd_power_system_off();
}
const char* T1Board::getManufacturerName() const {
return "Heltec T1";
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <Arduino.h>
#include <MeshCore.h>
#include <helpers/NRF52Board.h>
#include <helpers/RefCountedDigitalPin.h>
class T1Board : public NRF52BoardDCDC {
protected:
#ifdef NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif
void variant_shutdown();
public:
RefCountedDigitalPin periph_power;
T1Board() : periph_power(PIN_TFT_VDD_CTL, PIN_TFT_VDD_CTL_ACTIVE), NRF52Board("T1_OTA") {}
void begin();
void onBeforeTransmit() override;
void onAfterTransmit() override;
uint16_t getBattMilliVolts() override;
const char* getManufacturerName() const override;
void powerOff() override;
};
+108
View File
@@ -0,0 +1,108 @@
[Heltec_t1]
extends = nrf52_base
board = heltec_t1
board_build.ldscript = boards/nrf52840_s140_v6.ld
build_flags = ${nrf52_base.build_flags}
${sensor_base.build_flags}
-I lib/nrf52/s140_nrf52_6.1.1_API/include
-I lib/nrf52/s140_nrf52_6.1.1_API/include/nrf52
-I variants/heltec_t1
-I src/helpers/ui
-D HELTEC_T1
-D NRF52_POWER_MANAGEMENT
-D RADIO_CLASS=CustomSX1262
-D WRAPPER_CLASS=CustomSX1262Wrapper
-D LORA_TX_POWER=22
-D DISPLAY_CLASS=ST7735Display
build_src_filter = ${nrf52_base.build_src_filter}
+<helpers/*.cpp>
+<helpers/sensors>
+<../variants/heltec_t1>
+<helpers/ui/ST7735Display.cpp>
+<helpers/ui/MomentaryButton.cpp>
lib_deps =
${nrf52_base.lib_deps}
${sensor_base.lib_deps}
adafruit/Adafruit ST7735 and ST7789 Library @ ^1.11.0
debug_tool = jlink
upload_protocol = nrfutil
[env:Heltec_t1_repeater]
extends = Heltec_t1
build_src_filter = ${Heltec_t1.build_src_filter}
+<../examples/simple_repeater>
build_flags =
${Heltec_t1.build_flags}
-D ADVERT_NAME='"Heltec_t1 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
[env:Heltec_t1_room_server]
extends = Heltec_t1
build_src_filter = ${Heltec_t1.build_src_filter}
+<../examples/simple_room_server>
build_flags =
${Heltec_t1.build_flags}
-D ADVERT_NAME='"Heltec_t1 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
[env:Heltec_t1_companion_radio_ble]
extends = Heltec_t1
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${Heltec_t1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
-D BLE_PIN_CODE=123456
-D ENV_INCLUDE_GPS=1
; -D BLE_DEBUG_LOGGING=1
-D OFFLINE_QUEUE_SIZE=256
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t1.build_src_filter}
+<helpers/nrf52/SerialBLEInterface.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t1.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:Heltec_t1_companion_radio_usb]
extends = Heltec_t1
board_build.ldscript = boards/nrf52840_s140_v6_extrafs.ld
board_upload.maximum_size = 712704
build_flags =
${Heltec_t1.build_flags}
-I examples/companion_radio/ui-new
-D MAX_CONTACTS=350
-D MAX_GROUP_CHANNELS=40
; -D MESH_PACKET_LOGGING=1
; -D MESH_DEBUG=1
build_src_filter = ${Heltec_t1.build_src_filter}
+<helpers/nrf52/*.cpp>
+<helpers/ui/buzzer.cpp>
+<../examples/companion_radio/*.cpp>
+<../examples/companion_radio/ui-new/*.cpp>
lib_deps =
${Heltec_t1.lib_deps}
densaugeo/base64 @ ~1.4.0
end2endzone/NonBlockingRTTTL@^1.3.0
[env:Heltec_t1_kiss_modem]
extends = Heltec_t1
build_src_filter = ${Heltec_t1.build_src_filter}
+<../examples/kiss_modem/>
+48
View File
@@ -0,0 +1,48 @@
#include "target.h"
#include <Arduino.h>
#include <helpers/ArduinoHelpers.h>
#ifdef ENV_INCLUDE_GPS
#include <helpers/sensors/MicroNMEALocationProvider.h>
#endif
T1Board board;
#if defined(P_LORA_SCLK)
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);
VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, GPS_RESET, GPS_EN, &board.periph_power);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
EnvironmentSensorManager sensors;
#endif
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display(&board.periph_power);
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
#endif
bool radio_init() {
rtc_clock.begin(Wire);
#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);
}
+30
View File
@@ -0,0 +1,30 @@
#pragma once
#define RADIOLIB_STATIC_ONLY 1
#include <RadioLib.h>
#include <T1Board.h>
#include <helpers/AutoDiscoverRTCClock.h>
#include <helpers/radiolib/CustomSX1262Wrapper.h>
#include <helpers/radiolib/RadioLibWrappers.h>
#include <helpers/sensors/EnvironmentSensorManager.h>
#include <helpers/sensors/LocationProvider.h>
#ifdef DISPLAY_CLASS
#include <helpers/ui/MomentaryButton.h>
#include <helpers/ui/ST7735Display.h>
#else
#include "helpers/ui/NullDisplayDriver.h"
#endif
extern T1Board board;
extern WRAPPER_CLASS radio_driver;
extern AutoDiscoverRTCClock rtc_clock;
extern EnvironmentSensorManager sensors;
#ifdef DISPLAY_CLASS
extern DISPLAY_CLASS display;
extern MomentaryButton user_btn;
#endif
bool radio_init();
mesh::LocalIdentity radio_new_identity();
+15
View File
@@ -0,0 +1,15 @@
#include "variant.h"
#include "wiring_constants.h"
#include "wiring_digital.h"
const uint32_t g_ADigitalPinMap[] = {
0xff, 0xff, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
40, 41, 42, 43, 44, 45, 46, 47
};
void initVariant()
{
pinMode(PIN_USER_BTN, INPUT);
}
+169
View File
@@ -0,0 +1,169 @@
/*
* Heltec Mesh Node T1 nRF52840 variant.
*/
#pragma once
#include "WVariant.h"
#define USE_LFXO
#define VARIANT_MCK (64000000ul)
////////////////////////////////////////////////////////////////////////////////
// Number of pins
#define PINS_COUNT (48)
#define NUM_DIGITAL_PINS (48)
#define NUM_ANALOG_INPUTS (1)
#define NUM_ANALOG_OUTPUTS (0)
////////////////////////////////////////////////////////////////////////////////
// Display
#define ST7735_CS (0 + 12)
#define ST7735_RS (0 + 22)
#define ST7735_SDA (0 + 24)
#define ST7735_SCK (32 + 0)
#define ST7735_RESET (0 + 20)
#define ST7735_MISO (-1)
#define ST7735_BUSY (-1)
#define ST7735_BL (0 + 15)
#define VTFT_CTRL (0 + 13)
#define PIN_TFT_CS ST7735_CS
#define PIN_TFT_DC ST7735_RS
#define PIN_TFT_SDA ST7735_SDA
#define PIN_TFT_SCL ST7735_SCK
#define PIN_TFT_RST ST7735_RESET
#define PIN_TFT_LEDA_CTL ST7735_BL
#define PIN_TFT_LEDA_CTL_ACTIVE LOW
#define PIN_TFT_VDD_CTL VTFT_CTRL
#define PIN_TFT_VDD_CTL_ACTIVE LOW
#define DISPLAY_ROTATION 3
////////////////////////////////////////////////////////////////////////////////
// Builtin LEDs
#define PIN_LED1 (0 + 16)
#define LED_BUILTIN PIN_LED1
#define PIN_LED LED_BUILTIN
#define LED_RED (-1)
#define LED_BLUE (-1)
#define LED_GREEN (-1)
#define LED_PIN LED_BUILTIN
#define LED_STATE_ON LOW
////////////////////////////////////////////////////////////////////////////////
// Builtin buttons
#define PIN_BUTTON1 (32 + 10)
#define PIN_BUTTON2 (0 + 14)
#define BUTTON_PIN PIN_BUTTON1
#define BUTTON_PIN2 PIN_BUTTON2
#define PIN_USER_BTN BUTTON_PIN
////////////////////////////////////////////////////////////////////////////////
// UART
// No longer populated on PCB.
#define PIN_SERIAL2_RX (-1)
#define PIN_SERIAL2_TX (-1)
////////////////////////////////////////////////////////////////////////////////
// I2C
#define WIRE_INTERFACES_COUNT (1)
#define PIN_WIRE_SDA (32 + 3)
#define PIN_WIRE_SCL (0 + 10)
#define PIN_SENSOR_EN (32 + 6)
#define PIN_SENSOR_EN_ACTIVE LOW
////////////////////////////////////////////////////////////////////////////////
// LoRa
#define USE_SX1262
#define SX126X_CS (32 + 11)
#define LORA_CS SX126X_CS
#define SX126X_DIO1 (0 + 31)
#define SX126X_BUSY (0 + 29)
#define SX126X_RESET (0 + 2)
#define SX126X_DIO2_AS_RF_SWITCH true
#define SX126X_DIO3_TCXO_VOLTAGE 1.8
#define SX126X_CURRENT_LIMIT 140
#define SX126X_RX_BOOSTED_GAIN 1
#define P_LORA_DIO_1 SX126X_DIO1
#define P_LORA_NSS LORA_CS
#define P_LORA_RESET SX126X_RESET
#define P_LORA_BUSY SX126X_BUSY
#define P_LORA_TX_LED PIN_LED1
////////////////////////////////////////////////////////////////////////////////
// SPI
#define SPI_INTERFACES_COUNT (2)
#define PIN_SPI_MISO (0 + 3)
#define PIN_SPI_MOSI (32 + 14)
#define PIN_SPI_SCK (32 + 13)
#define PIN_SPI_NSS LORA_CS
#define PIN_SPI1_MISO ST7735_MISO
#define PIN_SPI1_MOSI ST7735_SDA
#define PIN_SPI1_SCK ST7735_SCK
#define P_LORA_SCLK PIN_SPI_SCK
#define P_LORA_MISO PIN_SPI_MISO
#define P_LORA_MOSI PIN_SPI_MOSI
////////////////////////////////////////////////////////////////////////////////
// GPS
#define GPS_UC6580
#define GPS_BAUD_RATE 115200
#define PIN_GPS_RESET (0 + 26)
#define GPS_RESET PIN_GPS_RESET
#define GPS_RESET_MODE LOW
#define PIN_GPS_RESET_ACTIVE LOW
#define PIN_GPS_EN (0 + 4)
#define GPS_EN PIN_GPS_EN
#define GPS_EN_ACTIVE LOW
#define PIN_GPS_EN_ACTIVE LOW
#define PIN_GPS_PPS (32 + 9)
#define GPS_TX_PIN (0 + 8)
#define GPS_RX_PIN (0 + 7)
#define PIN_GPS_TX GPS_TX_PIN
#define PIN_GPS_RX GPS_RX_PIN
#define PIN_SERIAL1_RX GPS_RX_PIN
#define PIN_SERIAL1_TX GPS_TX_PIN
////////////////////////////////////////////////////////////////////////////////
// Buzzer
#define PIN_BUZZER (0 + 9)
#define PIN_BUZZER_VOLTAGE_MULTIPLIER_1 (32 + 2)
#define PIN_BUZZER_VOLTAGE_MULTIPLIER_2 (32 + 5)
////////////////////////////////////////////////////////////////////////////////
// Battery
#define ADC_CTRL (0 + 11)
#define PIN_BAT_CTL ADC_CTRL
#define ADC_CTRL_ENABLED HIGH
#define BATTERY_PIN (0 + 5)
#define PIN_VBAT_READ BATTERY_PIN
#define ADC_RESOLUTION (14)
#define AREF_VOLTAGE (3.0)
#define VBAT_AR_INTERNAL AR_INTERNAL_3_0
#define ADC_MULTIPLIER (4.916F)
#define MV_LSB (3000.0F / 4096.0F)
#define PWRMGT_VOLTAGE_BOOTLOCK 3100
#define PWRMGT_LPCOMP_AIN 3
#define PWRMGT_LPCOMP_REFSEL 1
#define HAS_RTC 0