Added Heltec T096 support

This commit is contained in:
2026-05-11 13:24:03 +03:00
parent fb8d01a394
commit ed5f68f3fa
5 changed files with 169 additions and 7 deletions
+90
View File
@@ -1209,6 +1209,96 @@
const int DISPLAY_BL_PIN = PIN_T114_TFT_BLGT; const int DISPLAY_BL_PIN = PIN_T114_TFT_BLGT;
const int DISPLAY_RST = PIN_T114_TFT_RST; const int DISPLAY_RST = PIN_T114_TFT_RST;
#elif BOARD_MODEL == BOARD_HELTEC_T096
#define MODEM SX1262
#define HAS_EEPROM false
#define HAS_DISPLAY true
#define HAS_BLUETOOTH false
#define HAS_BLE true
#define HAS_CONSOLE false
#define HAS_PMU false
#define HAS_NP false
#define HAS_SD false
#define HAS_TCXO true
#define HAS_BUSY true
#define HAS_INPUT true
#define HAS_SLEEP false
#define DIO2_AS_RF_SWITCH true
#define CONFIG_UART_BUFFER_SIZE 6144
#define CONFIG_QUEUE_SIZE 6144
#define CONFIG_QUEUE_MAX_LENGTH 200
#define EEPROM_SIZE 296
#define EEPROM_OFFSET EEPROM_SIZE-EEPROM_RESERVED
#define BLE_MANUFACTURER "Heltec"
#define BLE_MODEL "T096"
#define HAS_LORA_PA true
#define HAS_LORA_LNA true
#define OCP_TUNED 0x28
#define LORA_PA_MODEL LORA_PA_KCT8103L
#define LNA_GD_THRSHLD (-109)
#define LNA_GD_LIMIT (-89)
#define LORA_LNA_GAIN 17
#define LORA_LNA_GVT 12
#define LORA_PA_PWR_EN 7
#define LORA_PA_CPS -1
#define LORA_PA_CSD 12
#define LORA_PA_CTX 9
#define PA_MAX_OUTPUT 28
#define PA_GAIN_POINTS 22
#define LORA_LNA_KCT8103L_GAIN 21
const int PA_KCT8103L_VALUES[PA_GAIN_POINTS] = {13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 12, 12, 11, 11, 10, 9, 8, 7};
// LED
#define PIN_T096_LED 28
// SPI
#define PIN_T096_MOSI 11
#define PIN_T096_MISO 14
#define PIN_T096_SCK 40
#define PIN_T096_SS 5
// SX1262
#define PIN_T096_RST 16
#define PIN_T096_DIO1 21
#define PIN_T096_BUSY 19
// TFT
#define DISPLAY_SCALE 1
#define PIN_T096_TFT_MOSI 17
#define PIN_T096_TFT_SCK 20
#define PIN_T096_TFT_SS 22
#define PIN_T096_TFT_DC 15
#define PIN_T096_TFT_RST 13
#define PIN_T096_TFT_EN 26
#define PIN_T096_TFT_BLGT 44
// pins for buttons on Heltec T096
const int pin_btn_usr1 = 42;
// pins for sx1262 on Heltec T096
const int pin_reset = PIN_T096_RST;
const int pin_cs = PIN_T096_SS;
const int pin_sclk = PIN_T096_SCK;
const int pin_mosi = PIN_T096_MOSI;
const int pin_miso = PIN_T096_MISO;
const int pin_busy = PIN_T096_BUSY;
const int pin_dio = PIN_T096_DIO1;
const int pin_led_rx = 28;
const int pin_led_tx = 28;
const int pin_tcxo_enable = -1;
// pins for ST7735 display on Heltec T096
const int DISPLAY_DC = PIN_T096_TFT_DC;
const int DISPLAY_CS = PIN_T096_TFT_SS;
const int DISPLAY_MOSI = PIN_T096_TFT_MOSI;
const int DISPLAY_CLK = PIN_T096_TFT_SCK;
const int DISPLAY_BL_PIN = PIN_T096_TFT_BLGT;
const int DISPLAY_RST = PIN_T096_TFT_RST;
#elif BOARD_MODEL == BOARD_PROMICRO #elif BOARD_MODEL == BOARD_PROMICRO
//TODO: //TODO:
// - Fix low output power // - Fix low output power
+59 -2
View File
@@ -22,6 +22,9 @@
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
#include "ST7789.h" #include "ST7789.h"
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)) #define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
#elif BOARD_MODEL == BOARD_HELTEC_T096
#include <Adafruit_ST7735.h>
#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3))
#elif BOARD_MODEL == BOARD_TBEAM_S_V1 || BOARD_MODEL == BOARD_TBEAM_S_V3 #elif BOARD_MODEL == BOARD_TBEAM_S_V1 || BOARD_MODEL == BOARD_TBEAM_S_V3
#include <Adafruit_SH110X.h> #include <Adafruit_SH110X.h>
#else #else
@@ -154,6 +157,10 @@
Adafruit_ST7789 display = Adafruit_ST7789(DISPLAY_CS, DISPLAY_DC, -1); Adafruit_ST7789 display = Adafruit_ST7789(DISPLAY_CS, DISPLAY_DC, -1);
#define SSD1306_WHITE ST77XX_WHITE #define SSD1306_WHITE ST77XX_WHITE
#define SSD1306_BLACK ST77XX_BLACK #define SSD1306_BLACK ST77XX_BLACK
#elif BOARD_MODEL == BOARD_HELTEC_T096
Adafruit_ST7735 display = Adafruit_ST7735(&SPI1, DISPLAY_CS, DISPLAY_DC, DISPLAY_RST);
#define SSD1306_WHITE ST77XX_WHITE
#define SSD1306_BLACK ST77XX_BLACK
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
ST7789Spi display(&SPI1, DISPLAY_RST, DISPLAY_DC, DISPLAY_CS); ST7789Spi display(&SPI1, DISPLAY_RST, DISPLAY_DC, DISPLAY_CS);
#define SSD1306_WHITE ST77XX_WHITE #define SSD1306_WHITE ST77XX_WHITE
@@ -243,6 +250,18 @@ void update_area_positions() {
p_as_x = 126; p_as_x = 126;
p_as_y = p_ad_y; p_as_y = p_ad_y;
} }
#elif BOARD_MODEL == BOARD_HELTEC_T096
if (disp_mode == DISP_MODE_LANDSCAPE) {
p_ad_x = 16;
p_ad_y = 8;
p_as_x = 82;
p_as_y = 8;
} else if (disp_mode == DISP_MODE_PORTRAIT) {
p_ad_x = 8;
p_ad_y = 0;
p_as_x = 8;
p_as_y = 64;
}
#elif BOARD_MODEL == BOARD_TECHO #elif BOARD_MODEL == BOARD_TECHO
if (disp_mode == DISP_MODE_PORTRAIT) { if (disp_mode == DISP_MODE_PORTRAIT) {
p_ad_x = 61; p_ad_x = 61;
@@ -276,6 +295,11 @@ uint8_t display_contrast = 0x00;
} }
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
void set_contrast(ST7789Spi *display, uint8_t value) { } void set_contrast(ST7789Spi *display, uint8_t value) { }
#elif BOARD_MODEL == BOARD_HELTEC_T096
void set_contrast(Adafruit_ST7735 *display, uint8_t value) {
if (value == 0) { digitalWrite(PIN_T096_TFT_BLGT, HIGH); }
else { digitalWrite(PIN_T096_TFT_BLGT, LOW); }
}
#elif BOARD_MODEL == BOARD_TECHO #elif BOARD_MODEL == BOARD_TECHO
void set_contrast(void *display, uint8_t value) { void set_contrast(void *display, uint8_t value) {
if (value == 0) { analogWrite(pin_backlight, 0); } if (value == 0) { analogWrite(pin_backlight, 0); }
@@ -357,6 +381,9 @@ bool display_init() {
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
pinMode(PIN_T114_TFT_EN, OUTPUT); pinMode(PIN_T114_TFT_EN, OUTPUT);
digitalWrite(PIN_T114_TFT_EN, LOW); digitalWrite(PIN_T114_TFT_EN, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_T096
pinMode(PIN_T096_TFT_EN, OUTPUT);
digitalWrite(PIN_T096_TFT_EN, HIGH);
#elif BOARD_MODEL == BOARD_MESHADVENTURER_S3 || BOARD_MODEL == BOARD_MESHPOE_S3 #elif BOARD_MODEL == BOARD_MESHADVENTURER_S3 || BOARD_MODEL == BOARD_MESHPOE_S3
Wire.setPins(SDA_OLED, SCL_OLED); Wire.setPins(SDA_OLED, SCL_OLED);
Wire.begin(); Wire.begin();
@@ -431,6 +458,9 @@ bool display_init() {
// set white as default pixel colour for Heltec T114 // set white as default pixel colour for Heltec T114
display.setRGB(COLOR565(0xFF, 0xFF, 0xFF)); display.setRGB(COLOR565(0xFF, 0xFF, 0xFF));
if (false) { if (false) {
#elif BOARD_MODEL == BOARD_HELTEC_T096
display.initR(INITR_MINI160x80);
if (false) {
#elif BOARD_MODEL == BOARD_TBEAM_S_V1 || BOARD_MODEL == BOARD_TBEAM_S_V3 #elif BOARD_MODEL == BOARD_TBEAM_S_V1 || BOARD_MODEL == BOARD_TBEAM_S_V3
if (!display.begin(display_address, true)) { if (!display.begin(display_address, true)) {
#else #else
@@ -480,6 +510,9 @@ bool display_init() {
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
disp_mode = DISP_MODE_PORTRAIT; disp_mode = DISP_MODE_PORTRAIT;
display.setRotation(1); display.setRotation(1);
#elif BOARD_MODEL == BOARD_HELTEC_T096
disp_mode = DISP_MODE_LANDSCAPE;
display.setRotation(1);
#elif BOARD_MODEL == BOARD_RAK4631 #elif BOARD_MODEL == BOARD_RAK4631
disp_mode = DISP_MODE_LANDSCAPE; disp_mode = DISP_MODE_LANDSCAPE;
display.setRotation(0); display.setRotation(0);
@@ -547,6 +580,10 @@ bool display_init() {
fillRect(p_as_x, p_as_y, 128, 128, SSD1306_BLACK); fillRect(p_as_x, p_as_y, 128, 128, SSD1306_BLACK);
pinMode(PIN_T114_TFT_BLGT, OUTPUT); pinMode(PIN_T114_TFT_BLGT, OUTPUT);
digitalWrite(PIN_T114_TFT_BLGT, LOW); digitalWrite(PIN_T114_TFT_BLGT, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_T096
display.fillScreen(SSD1306_BLACK);
pinMode(PIN_T096_TFT_BLGT, OUTPUT);
digitalWrite(PIN_T096_TFT_BLGT, LOW);
#endif #endif
return true; return true;
@@ -586,7 +623,21 @@ void fillRect(int16_t x, int16_t y, int16_t width, int16_t height, uint16_t colo
// Draws a bitmap to the display and auto scales it based on the boards configured DISPLAY_SCALE // Draws a bitmap to the display and auto scales it based on the boards configured DISPLAY_SCALE
void drawBitmap(int16_t startX, int16_t startY, const uint8_t* bitmap, int16_t bitmapWidth, int16_t bitmapHeight, uint16_t foregroundColour, uint16_t backgroundColour) { void drawBitmap(int16_t startX, int16_t startY, const uint8_t* bitmap, int16_t bitmapWidth, int16_t bitmapHeight, uint16_t foregroundColour, uint16_t backgroundColour) {
#if DISPLAY_SCALE == 1 #if BOARD_MODEL == BOARD_HELTEC_T096
{
static uint16_t rowbuf[64];
int16_t byteWidth = (bitmapWidth + 7) / 8;
display.startWrite();
display.setAddrWindow(startX, startY, bitmapWidth, bitmapHeight);
for (int16_t row = 0; row < bitmapHeight; row++) {
for (int16_t col = 0; col < bitmapWidth; col++) {
rowbuf[col] = (bitmap[row * byteWidth + col / 8] & (0x80 >> (col % 8))) ? foregroundColour : backgroundColour;
}
display.writePixels(rowbuf, bitmapWidth);
}
display.endWrite();
}
#elif DISPLAY_SCALE == 1
display.drawBitmap(startX, startY, bitmap, bitmapWidth, bitmapHeight, foregroundColour, backgroundColour); display.drawBitmap(startX, startY, bitmap, bitmapWidth, bitmapHeight, foregroundColour, backgroundColour);
#else #else
for(int16_t row = 0; row < bitmapHeight; row++){ for(int16_t row = 0; row < bitmapHeight; row++){
@@ -1142,6 +1193,8 @@ void update_display(bool blank = false) {
display.clear(); display.clear();
display.display(); display.display();
digitalWrite(PIN_T114_TFT_BLGT, HIGH); digitalWrite(PIN_T114_TFT_BLGT, HIGH);
#elif BOARD_MODEL == BOARD_HELTEC_T096
digitalWrite(PIN_T096_TFT_BLGT, HIGH);
#elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO #elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO
display.clearDisplay(); display.clearDisplay();
display.display(); display.display();
@@ -1163,6 +1216,8 @@ void update_display(bool blank = false) {
#if BOARD_MODEL == BOARD_HELTEC_T114 #if BOARD_MODEL == BOARD_HELTEC_T114
display.clear(); display.clear();
digitalWrite(PIN_T114_TFT_BLGT, LOW); digitalWrite(PIN_T114_TFT_BLGT, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_T096
digitalWrite(PIN_T096_TFT_BLGT, LOW);
#elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO #elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_TECHO
display.clearDisplay(); display.clearDisplay();
#endif #endif
@@ -1188,7 +1243,7 @@ void update_display(bool blank = false) {
last_epd_refresh = millis(); last_epd_refresh = millis();
epd_blanked = false; epd_blanked = false;
} }
#elif BOARD_MODEL != BOARD_TDECK #elif BOARD_MODEL != BOARD_TDECK && BOARD_MODEL != BOARD_HELTEC_T096
display.display(); display.display();
#endif #endif
@@ -1202,6 +1257,8 @@ void display_unblank() {
last_unblank_event = millis(); last_unblank_event = millis();
#if BOARD_MODEL == BOARD_HELTEC_T114 #if BOARD_MODEL == BOARD_HELTEC_T114
digitalWrite(PIN_T114_TFT_BLGT, LOW); digitalWrite(PIN_T114_TFT_BLGT, LOW);
#elif BOARD_MODEL == BOARD_HELTEC_T096
digitalWrite(PIN_T096_TFT_BLGT, LOW);
#endif #endif
} }
+1 -1
View File
@@ -135,7 +135,7 @@ void setup() {
boot_seq(); boot_seq();
#endif #endif
#if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_MESHPOE_S3 && BOARD_MODEL != BOARD_MESHADVENTURER_S3 && BOARD_MODEL != BOARD_PROMICRO && BOARD_MODEL != BOARD_AETHERNODE_S3 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_TBEAM_S_V3 && BOARD_MODEL != BOARD_HELTEC32_V4 #if BOARD_MODEL != BOARD_RAK4631 && BOARD_MODEL != BOARD_HELTEC_T114 && BOARD_MODEL != BOARD_HELTEC_T096 && BOARD_MODEL != BOARD_MESHPOE_S3 && BOARD_MODEL != BOARD_MESHADVENTURER_S3 && BOARD_MODEL != BOARD_PROMICRO && BOARD_MODEL != BOARD_AETHERNODE_S3 && BOARD_MODEL != BOARD_TECHO && BOARD_MODEL != BOARD_T3S3 && BOARD_MODEL != BOARD_TBEAM_S_V1 && BOARD_MODEL != BOARD_TBEAM_S_V3 && BOARD_MODEL != BOARD_HELTEC32_V4
// Some boards need to wait until the hardware UART is set up before booting // Some boards need to wait until the hardware UART is set up before booting
// the full firmware. In the case of the RAK4631 and Heltec T114, the line below will wait // the full firmware. In the case of the RAK4631 and Heltec T114, the line below will wait
// until a serial connection is actually established with a master. Thus, it // until a serial connection is actually established with a master. Thus, it
+14 -1
View File
@@ -424,6 +424,14 @@ uint8_t boot_vector = 0x00;
void led_tx_off() { digitalWrite(pin_led_tx, HIGH); } void led_tx_off() { digitalWrite(pin_led_tx, HIGH); }
void led_id_on() { } void led_id_on() { }
void led_id_off() { } void led_id_off() { }
#elif BOARD_MODEL == BOARD_HELTEC_T096
// Heltec T096 pulls pins HIGH to turn on
void led_rx_on() { digitalWrite(pin_led_rx, HIGH); }
void led_rx_off() { digitalWrite(pin_led_rx, LOW); }
void led_tx_on() { digitalWrite(pin_led_tx, HIGH); }
void led_tx_off() { digitalWrite(pin_led_tx, LOW); }
void led_id_on() { }
void led_id_off() { }
#elif BOARD_MODEL == BOARD_TECHO #elif BOARD_MODEL == BOARD_TECHO
void led_rx_on() { digitalWrite(pin_led_rx, LED_ON); } void led_rx_on() { digitalWrite(pin_led_rx, LED_ON); }
void led_rx_off() { digitalWrite(pin_led_rx, LED_OFF); } void led_rx_off() { digitalWrite(pin_led_rx, LED_OFF); }
@@ -1353,6 +1361,9 @@ int getTxPower() {
#if BOARD_MODEL == BOARD_HELTEC32_V4 #if BOARD_MODEL == BOARD_HELTEC32_V4
bool pa_values_determined = false; bool pa_values_determined = false;
int tx_gain[PA_GAIN_POINTS] = {100}; int tx_gain[PA_GAIN_POINTS] = {100};
#elif BOARD_MODEL == BOARD_HELTEC_T096
bool pa_values_determined = false;
int tx_gain[PA_GAIN_POINTS] = {100};
#else #else
bool pa_values_determined = true; bool pa_values_determined = true;
const int tx_gain[PA_GAIN_POINTS] = {PA_GAIN_VALUES}; const int tx_gain[PA_GAIN_POINTS] = {PA_GAIN_VALUES};
@@ -1687,7 +1698,7 @@ bool eeprom_product_valid() {
#elif PLATFORM == PLATFORM_ESP32 #elif PLATFORM == PLATFORM_ESP32
if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_H32_V4 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1 || rval == PRODUCT_TBEAM_S_V3 || rval == PRODUCT_XIAO_S3) { if (rval == PRODUCT_RNODE || rval == BOARD_RNODE_NG_20 || rval == BOARD_RNODE_NG_21 || rval == PRODUCT_HMBRW || rval == PRODUCT_TBEAM || rval == PRODUCT_T32_10 || rval == PRODUCT_T32_20 || rval == PRODUCT_T32_21 || rval == PRODUCT_H32_V2 || rval == PRODUCT_H32_V3 || rval == PRODUCT_H32_V4 || rval == PRODUCT_TDECK_V1 || rval == PRODUCT_TBEAM_S_V1 || rval == PRODUCT_TBEAM_S_V3 || rval == PRODUCT_XIAO_S3) {
#elif PLATFORM == PLATFORM_NRF52 #elif PLATFORM == PLATFORM_NRF52
if (rval == PRODUCT_RAK4631 || rval == PRODUCT_HELTEC_T114 || rval == PRODUCT_TECHO || rval == PRODUCT_HMBRW) { if (rval == PRODUCT_RAK4631 || rval == PRODUCT_HELTEC_T114 || rval == PRODUCT_HELTEC_T096 || rval == PRODUCT_TECHO || rval == PRODUCT_HMBRW) {
#else #else
if (false) { if (false) {
#endif #endif
@@ -1737,6 +1748,8 @@ bool eeprom_model_valid() {
if (model == MODEL_C8) { if (model == MODEL_C8) {
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
if (model == MODEL_C6 || model == MODEL_C7) { if (model == MODEL_C6 || model == MODEL_C7) {
#elif BOARD_MODEL == BOARD_HELTEC_T096
if (model == MODEL_D3 || model == MODEL_D5) {
#elif BOARD_MODEL == BOARD_RAK4631 #elif BOARD_MODEL == BOARD_RAK4631
if (model == MODEL_11 || model == MODEL_12) { if (model == MODEL_11 || model == MODEL_12) {
#elif BOARD_MODEL == BOARD_HUZZAH32 #elif BOARD_MODEL == BOARD_HUZZAH32
+2
View File
@@ -736,6 +736,8 @@ void sx126x::enableTCXO() {
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_HELTEC_T114 #elif BOARD_MODEL == BOARD_HELTEC_T114
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_HELTEC_T096
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_TECHO #elif BOARD_MODEL == BOARD_TECHO
uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF}; uint8_t buf[4] = {MODE_TCXO_1_8V_6X, 0x00, 0x00, 0xFF};
#elif BOARD_MODEL == BOARD_HELTEC32_V4 #elif BOARD_MODEL == BOARD_HELTEC32_V4