From c75965480f9da9f067cf0d4722c06bf31ca7f959 Mon Sep 17 00:00:00 2001 From: Manuel <71137295+mverch67@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:53:26 +0200 Subject: [PATCH] Heltec-Tracker: TFT LCD support (#2612) * Heltec-Tracker: TFT LCD support * trunk fmt * backwards compatibility with ST7735 devices * trunk fmt --- platformio.ini | 3 +- src/graphics/TFTDisplay.cpp | 148 ++++++++++++++++-- src/graphics/TFTDisplay.h | 1 - .../heltec_wireless_tracker/platformio.ini | 21 +-- variants/heltec_wireless_tracker/variant.h | 31 ++-- 5 files changed, 156 insertions(+), 48 deletions(-) diff --git a/platformio.ini b/platformio.ini index b580d7160..e19175af7 100644 --- a/platformio.ini +++ b/platformio.ini @@ -9,6 +9,7 @@ ;default_envs = heltec-v1 ;default_envs = heltec-v2_0 ;default_envs = heltec-v2_1 +;default_envs = heltec-wireless-tracker ;default_envs = tlora-v1 ;default_envs = tlora_v1_3 ;default_envs = tlora-v2 @@ -119,4 +120,4 @@ lib_deps = adafruit/Adafruit SHT31 Library@^2.2.0 adafruit/Adafruit PM25 AQI Sensor@^1.0.6 adafruit/Adafruit MPU6050@^2.2.4 - adafruit/Adafruit LIS3DH@^1.2.4 \ No newline at end of file + adafruit/Adafruit LIS3DH@^1.2.4 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index a7d33174a..b54ac75cf 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -1,12 +1,112 @@ #include "configuration.h" +#ifndef TFT_BACKLIGHT_ON +#define TFT_BACKLIGHT_ON HIGH +#endif + +// convert 24-bit color to 16-bit (56K) +#define COLOR565(r, g, b) (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3)) +#define TFT_MESH COLOR565(0x67, 0xEA, 0x94) + +#if defined(ST7735S) +#include // Graphics and font library for ST7735 driver chip + +#if defined(ST7735_BACKLIGHT_EN) && !defined(TFT_BL) +#define TFT_BL ST7735_BACKLIGHT_EN +#endif + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_ST7735S _panel_instance; + lgfx::Bus_SPI _bus_instance; + lgfx::Light_PWM _light_instance; + + public: + LGFX(void) + { + { + auto cfg = _bus_instance.config(); + + // configure SPI + cfg.spi_host = ST7735_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST + cfg.spi_mode = 0; + 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; // Set to true if reception is done on the MOSI pin + 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) + cfg.pin_sclk = ST7735_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = ST7735_SDA; // Set SPI MOSI pin number + cfg.pin_miso = ST7735_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = ST7735_RS; // Set SPI DC pin number (-1 = disable) + + _bus_instance.config(cfg); // applies the set value to the bus. + _panel_instance.setBus(&_bus_instance); // set the bus on the panel. + } + + { // Set the display panel control. + auto cfg = _panel_instance.config(); // Gets a structure for display panel settings. + + cfg.pin_cs = ST7735_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = ST7735_RESET; // Pin number where RST is connected (-1 = disable) + cfg.pin_busy = ST7735_BUSY; // Pin number where BUSY is connected (-1 = disable) + + // The following setting values ​​are general initial values ​​for each panel, so please comment out any + // unknown items and try them. + + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_x = TFT_OFFSET_X; // Panel offset amount in X direction + cfg.offset_y = TFT_OFFSET_Y; // Panel offset amount in Y direction + cfg.offset_rotation = 0; // Rotation direction value offset 0~7 (4~7 is upside down) + cfg.dummy_read_pixel = 8; // Number of bits for dummy read before pixel readout + cfg.dummy_read_bits = 1; // Number of bits for dummy read before non-pixel data read + cfg.readable = true; // Set to true if data can be read + cfg.invert = true; // Set to true if the light/darkness of the panel is reversed + 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 + cfg.bus_shared = true; // If the bus is shared with the SD card, set to true (bus control with drawJpgFile etc.) + + // 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 + cfg.memory_height = TFT_HEIGHT; // Maximum height supported by the driver IC + _panel_instance.config(cfg); + } + + // Set the backlight control + { + auto cfg = _light_instance.config(); // Gets a structure for backlight settings. + + cfg.pin_bl = ST7735_BL; // Pin number to which the backlight is connected + cfg.invert = true; // true to invert the brightness of the backlight + // cfg.freq = 44100; // PWM frequency of backlight + // cfg.pwm_channel = 1; // PWM channel number to use + + _light_instance.config(cfg); + _panel_instance.setLight(&_light_instance); // Set the backlight on the panel. + } + + setPanel(&_panel_instance); + } +}; + +static LGFX tft; + +#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) +#include // Graphics and font library for ILI9341 driver chip + +static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h + +#endif + #if defined(ST7735_CS) || defined(ILI9341_DRIVER) #include "SPILock.h" #include "TFTDisplay.h" #include -#include // Graphics and font library for ST7735 driver chip - -static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup.h TFTDisplay::TFTDisplay(uint8_t address, int sda, int scl, OLEDDISPLAY_GEOMETRY geometry, HW_I2C i2cBus) { @@ -26,11 +126,11 @@ void TFTDisplay::display(void) for (y = 0; y < displayHeight; y++) { for (x = 0; x < displayWidth; x++) { - // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficient + // get src pixel in the page based ordering the OLED lib uses FIXME, super inefficent auto isset = buffer[x + (y / 8) * displayWidth] & (1 << (y & 7)); auto dblbuf_isset = buffer_back[x + (y / 8) * displayWidth] & (1 << (y & 7)); if (isset != dblbuf_isset) { - tft.drawPixel(x, y, isset ? TFT_WHITE : TFT_BLACK); + tft.drawPixel(x, y, isset ? TFT_MESH : TFT_BLACK); } } } @@ -46,8 +146,31 @@ void TFTDisplay::display(void) // Send a command to the display (low level function) void TFTDisplay::sendCommand(uint8_t com) { - (void)com; - // Drop all commands to device (we just update the buffer) + // handle display on/off directly + switch (com) { + case DISPLAYON: { +#ifdef TFT_BL + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); +#endif +#ifdef VTFT_CTRL + digitalWrite(VTFT_CTRL, LOW); +#endif + break; + } + case DISPLAYOFF: { +#ifdef TFT_BL + digitalWrite(TFT_BL, !TFT_BACKLIGHT_ON); +#endif +#ifdef VTFT_CTRL + digitalWrite(VTFT_CTRL, HIGH); +#endif + break; + } + default: + break; + } + + // Drop all other commands to device (we just update the buffer) } void TFTDisplay::setDetected(uint8_t detected) @@ -62,18 +185,10 @@ bool TFTDisplay::connect() LOG_INFO("Doing TFT init\n"); #ifdef TFT_BL - digitalWrite(TFT_BL, HIGH); + digitalWrite(TFT_BL, TFT_BACKLIGHT_ON); pinMode(TFT_BL, OUTPUT); #endif -#ifdef TFT_POWER_EN - digitalWrite(TFT_POWER_EN, HIGH); - pinMode(TFT_POWER_EN, OUTPUT); -#endif -#ifdef ST7735_BACKLIGHT_EN - digitalWrite(ST7735_BACKLIGHT_EN, HIGH); - pinMode(ST7735_BACKLIGHT_EN, OUTPUT); -#endif tft.init(); #ifdef M5STACK tft.setRotation(1); // M5Stack has the TFT in landscape @@ -81,7 +196,6 @@ bool TFTDisplay::connect() tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label #endif tft.fillScreen(TFT_BLACK); - // tft.drawRect(0, 0, 40, 10, TFT_PURPLE); // wide rectangle in upper left return true; } diff --git a/src/graphics/TFTDisplay.h b/src/graphics/TFTDisplay.h index 013f4961e..46cfe85e7 100644 --- a/src/graphics/TFTDisplay.h +++ b/src/graphics/TFTDisplay.h @@ -7,7 +7,6 @@ * * Remaining TODO: * optimize display() to only draw changed pixels (see other OLED subclasses for examples) - * implement displayOn/displayOff to turn off the TFT device (and backlight) * Use the fast NRF52 SPI API rather than the slow standard arduino version * * turn radio back on - currently with both on spi bus is fucked? or are we leaving chip select asserted? diff --git a/variants/heltec_wireless_tracker/platformio.ini b/variants/heltec_wireless_tracker/platformio.ini index ec28fe6ca..43f80687d 100644 --- a/variants/heltec_wireless_tracker/platformio.ini +++ b/variants/heltec_wireless_tracker/platformio.ini @@ -1,23 +1,12 @@ [env:heltec-wireless-tracker] extends = esp32s3_base board = heltec_wifi_lora_32_V3 +upload_protocol = esp-builtin + build_flags = ${esp32s3_base.build_flags} -D HELTEC_WIRELESS_TRACKER -I variants/heltec_wireless_tracker - -DUSER_SETUP_LOADED - -DTFT_WIDTH=80 - -DTFT_HEIGHT=160 - -DST7735_GREENTAB160x80 - -DST7735_DRIVER - ;-TFT_RGB_ORDER=TFT_BGR - -DTFT_CS=38 - -DTFT_DC=40 - -DTFT_RST=39 - -DTFT_WR=42 - -DTFT_SCLK=41 - ;-DSPI_FREQUENCY=40000000 - ;-DSPI_FREQUENCY=27000000 - ;-DSPI_READ_FREQUENCY=16000000 - ;-DDISABLE_ALL_LIBRARY_WARNINGS + -DARDUINO_USB_CDC_ON_BOOT=1 + lib_deps = ${esp32s3_base.lib_deps} - bodmer/TFT_eSPI@^2.4.76 \ No newline at end of file + lovyan03/LovyanGFX@^1.1.7 \ No newline at end of file diff --git a/variants/heltec_wireless_tracker/variant.h b/variants/heltec_wireless_tracker/variant.h index f1bb071ef..7930a18a8 100644 --- a/variants/heltec_wireless_tracker/variant.h +++ b/variants/heltec_wireless_tracker/variant.h @@ -1,18 +1,25 @@ #define LED_PIN 18 -#define TFT_POWER_EN 46 - -#define ST7735_RESET 39 // Output +// ST7735S TFT LCD +#define ST7735S 1 // there are different (sub-)versions of ST7735 #define ST7735_CS 38 -#define ST7735_BACKLIGHT_EN 45 -#define ST7735_RS 40 -#define ST7735_SDA 42 +#define ST7735_RS 40 // DC +#define ST7735_SDA 42 // MOSI #define ST7735_SCK 41 - -// #define RESET_OLED 21 -// #define I2C_SDA 17 // I2C pins for this board -// #define I2C_SCL 18 - +#define ST7735_RESET 39 +#define ST7735_MISO -1 +#define ST7735_BUSY -1 +#define ST7735_BL 45 +#define ST7735_SPI_HOST SPI3_HOST +#define ST7735_BACKLIGHT_EN 45 +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define SCREEN_ROTATE +#define TFT_HEIGHT 160 +#define TFT_WIDTH 80 +#define TFT_OFFSET_X 26 +#define TFT_OFFSET_Y 0 +#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT #define SCREEN_TRANSITION_FRAMERATE 1 // fps #define VEXT_ENABLE Vext // active low, powers the oled display and the lora antenna boost @@ -31,8 +38,6 @@ #define PIN_GPS_PPS 36 #define VGNSS_CTRL 37 // Heltec Tracker needs this pulled low for GPS -#define VTFT_CTRL 46 // Heltec Tracker needs this pulled low for TFT - #define USE_SX1262 #define LORA_DIO0 -1 // a No connect on the SX1262 module