diff --git a/boards/t-deck.json b/boards/t-deck.json new file mode 100644 index 000000000..9d74834e9 --- /dev/null +++ b/boards/t-deck.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "dio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "t-deck" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": ["esp-builtin"], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "Espressif Systems LilyGO T-Deck (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://www.lilygo.cc/en-pl/products/t-deck", + "vendor": "LilyGO" +} diff --git a/src/FSCommon.cpp b/src/FSCommon.cpp index 150391237..a458a9fcf 100644 --- a/src/FSCommon.cpp +++ b/src/FSCommon.cpp @@ -8,6 +8,8 @@ #ifdef SDCARD_USE_SPI1 SPIClass SPI1(HSPI); #define SDHandler SPI1 +#else +#define SDHandler SPI #endif #endif // HAS_SDCARD diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 689c0315c..049382c19 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -102,7 +102,7 @@ static uint16_t displayWidth, displayHeight; #define SCREEN_WIDTH displayWidth #define SCREEN_HEIGHT displayHeight -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) // The screen is bigger so use bigger fonts #define FONT_SMALL ArialMT_Plain_16 // Height: 19 #define FONT_MEDIUM ArialMT_Plain_24 // Height: 28 @@ -492,7 +492,7 @@ static void drawNodes(OLEDDisplay *display, int16_t x, int16_t y, NodeStatus *no { char usersString[20]; snprintf(usersString, sizeof(usersString), "%d/%d", nodeStatus->getNumOnline(), nodeStatus->getNumTotal()); -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) display->drawFastImage(x, y + 3, 8, 8, imgUser); #else display->drawFastImage(x, y, 8, 8, imgUser); @@ -1482,7 +1482,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 #ifdef ARCH_ESP32 if (millis() - storeForwardModule->lastHeartbeat > (storeForwardModule->heartbeatInterval * 1200)) { // no heartbeat, overlap a bit -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1); display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, @@ -1492,7 +1492,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 imgQuestion); #endif } else { -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1); display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 16, 8, @@ -1504,7 +1504,7 @@ void DebugInfo::drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16 } #endif } else { -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1); display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(ourId), y + 11 + FONT_HEIGHT_SMALL, 12, 8, diff --git a/src/graphics/Screen.h b/src/graphics/Screen.h index 992a73285..debc6ac0b 100644 --- a/src/graphics/Screen.h +++ b/src/graphics/Screen.h @@ -380,7 +380,7 @@ class Screen : public concurrency::OSThread SH1106Wire dispdev; #elif defined(USE_SSD1306) SSD1306Wire dispdev; -#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) +#elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ST7789_CS) TFTDisplay dispdev; #elif defined(USE_EINK) EInkDisplay dispdev; diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index b54ac75cf..6f58d421d 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -96,6 +96,118 @@ class LGFX : public lgfx::LGFX_Device static LGFX tft; +#elif defined(ST7789_CS) +#include // Graphics and font library for ST7735 driver chip + +#if defined(ST7789_BACKLIGHT_EN) && !defined(TFT_BL) +#define TFT_BL ST7789_BACKLIGHT_EN +#endif + +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_ST7789 _panel_instance; + lgfx::Bus_SPI _bus_instance; + lgfx::Light_PWM _light_instance; + lgfx::Touch_GT911 _touch_instance; + + public: + LGFX(void) + { + { + auto cfg = _bus_instance.config(); + + // SPI + cfg.spi_host = ST7789_SPI_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 / + cfg.pin_sclk = ST7789_SCK; // Set SPI SCLK pin number + cfg.pin_mosi = ST7789_SDA; // Set SPI MOSI pin number + cfg.pin_miso = ST7789_MISO; // Set SPI MISO pin number (-1 = disable) + cfg.pin_dc = ST7789_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 = ST7789_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = -1; // Pin number where RST is connected (-1 = disable) + cfg.pin_busy = -1; // 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 mirrored) + cfg.dummy_read_pixel = 9; // 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. (delete if not necessary) + { + auto cfg = _light_instance.config(); // Gets a structure for backlight settings. + + cfg.pin_bl = ST7789_BL; // Pin number to which the backlight is connected + cfg.invert = true; // true to invert the brightness of the backlight + // cfg.pwm_channel = 0; + + _light_instance.config(cfg); + _panel_instance.setLight(&_light_instance); // Set the backlight on the panel. + } + + // Configure settings for touch screen control. + { + auto cfg = _touch_instance.config(); + + cfg.pin_cs = -1; + cfg.x_min = 0; + cfg.x_max = TFT_HEIGHT - 1; + cfg.y_min = 0; + cfg.y_max = TFT_WIDTH - 1; + cfg.pin_int = SCREEN_TOUCH_INT; + cfg.bus_shared = true; + cfg.offset_rotation = 0; + // cfg.freq = 2500000; + + // I2C + cfg.i2c_port = 1; + cfg.i2c_addr = TOUCH_SLAVE_ADDRESS; + cfg.pin_sda = I2C_SDA; + cfg.pin_scl = I2C_SCL; + cfg.freq = 400000; + + _touch_instance.config(cfg); + _panel_instance.setTouch(&_touch_instance); + } + + setPanel(&_panel_instance); // Sets the panel to use. + } +}; + +static LGFX tft; + #elif defined(ST7735_CS) || defined(ILI9341_DRIVER) #include // Graphics and font library for ILI9341 driver chip @@ -103,7 +215,7 @@ static TFT_eSPI tft = TFT_eSPI(); // Invoke library, pins defined in User_Setup. #endif -#if defined(ST7735_CS) || defined(ILI9341_DRIVER) +#if defined(ST7735_CS) || defined(ST7789_CS) || defined(ILI9341_DRIVER) #include "SPILock.h" #include "TFTDisplay.h" #include @@ -190,8 +302,8 @@ bool TFTDisplay::connect() #endif tft.init(); -#ifdef M5STACK - tft.setRotation(1); // M5Stack has the TFT in landscape +#if defined(M5STACK) || defined(T_DECK) + tft.setRotation(1); // M5Stack/T-Deck have the TFT in landscape #else tft.setRotation(3); // Orient horizontal and wide underneath the silkscreen name label #endif diff --git a/src/graphics/images.h b/src/graphics/images.h index b1818e32c..46c9118b1 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -14,7 +14,7 @@ const uint8_t imgUser[] PROGMEM = {0x3C, 0x42, 0x99, 0xA5, 0xA5, 0x99, 0x42, 0x3 const uint8_t imgPositionEmpty[] PROGMEM = {0x20, 0x30, 0x28, 0x24, 0x42, 0xFF}; const uint8_t imgPositionSolid[] PROGMEM = {0x20, 0x30, 0x38, 0x3C, 0x7E, 0xFF}; -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) const uint8_t imgQuestionL1[] PROGMEM = {0xff, 0x01, 0x01, 0x32, 0x7b, 0x49, 0x49, 0x6f, 0x26, 0x01, 0x01, 0xff}; const uint8_t imgQuestionL2[] PROGMEM = {0x0f, 0x08, 0x08, 0x08, 0x06, 0x0f, 0x0f, 0x06, 0x08, 0x08, 0x08, 0x0f}; const uint8_t imgInfoL1[] PROGMEM = {0xff, 0x01, 0x01, 0x01, 0x1e, 0x7f, 0x1e, 0x01, 0x01, 0x01, 0x01, 0xff}; diff --git a/src/main.cpp b/src/main.cpp index e503aadcf..949dbcf1f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -528,7 +528,7 @@ void setup() // Don't call screen setup until after nodedb is setup (because we need // the current region name) -#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) +#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) screen->setup(); #else if (screen_found.port != ScanI2C::I2CPort::NO_I2C) diff --git a/src/mesh/NodeDB.cpp b/src/mesh/NodeDB.cpp index 0192544fb..6d71a750c 100644 --- a/src/mesh/NodeDB.cpp +++ b/src/mesh/NodeDB.cpp @@ -184,7 +184,7 @@ void NodeDB::installDefaultConfig() // FIXME: Default to bluetooth capability of platform as default config.bluetooth.enabled = true; config.bluetooth.fixed_pin = defaultBLEPin; -#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) +#if defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7789_CS) bool hasScreen = true; #else bool hasScreen = screen_found.port != ScanI2C::I2CPort::NO_I2C; diff --git a/src/modules/CannedMessageModule.cpp b/src/modules/CannedMessageModule.cpp index 5e8cdcbf5..d3a450371 100644 --- a/src/modules/CannedMessageModule.cpp +++ b/src/modules/CannedMessageModule.cpp @@ -18,7 +18,7 @@ #include "graphics/fonts/OLEDDisplayFontsUA.h" #endif -#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) +#if defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ST7735_CS) || defined(ST7789_CS) // The screen is bigger so use bigger fonts #define FONT_SMALL ArialMT_Plain_16 #define FONT_MEDIUM ArialMT_Plain_24 diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 23346d493..c6842eee9 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -81,6 +81,8 @@ #define HW_VENDOR meshtastic_HardwareModel_TLORA_V2_1_1P6 #elif defined(TLORA_V2_1_18) #define HW_VENDOR meshtastic_HardwareModel_TLORA_V2_1_1P8 +#elif defined(T_DECK) +#define HW_VENDOR meshtastic_HardwareModel_T_DECK #elif defined(GENIEBLOCKS) #define HW_VENDOR meshtastic_HardwareModel_GENIEBLOCKS #elif defined(PRIVATE_HW) diff --git a/variants/t-deck/pins_arduino.h b/variants/t-deck/pins_arduino.h new file mode 100644 index 000000000..0150935ed --- /dev/null +++ b/variants/t-deck/pins_arduino.h @@ -0,0 +1,69 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#define EXTERNAL_NUM_INTERRUPTS 46 +#define NUM_DIGITAL_PINS 48 +#define NUM_ANALOG_INPUTS 20 + +#define analogInputToDigitalPin(p) (((p) < NUM_ANALOG_INPUTS) ? (analogChannelToDigitalPin(p)) : -1) +#define digitalPinToInterrupt(p) (((p) < NUM_DIGITAL_PINS) ? (p) : -1) +#define digitalPinHasPWM(p) (p < EXTERNAL_NUM_INTERRUPTS) + +// static const uint8_t LED_BUILTIN = -1; + +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +static const uint8_t SDA = 18; +static const uint8_t SCL = 8; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 9; +static const uint8_t MOSI = 41; +static const uint8_t MISO = 38; +static const uint8_t SCK = 40; + +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; + +static const uint8_t BAT_ADC_PIN = 4; + +#endif /* Pins_Arduino_h */ diff --git a/variants/t-deck/platformio.ini b/variants/t-deck/platformio.ini new file mode 100644 index 000000000..8344fb990 --- /dev/null +++ b/variants/t-deck/platformio.ini @@ -0,0 +1,14 @@ +; LilyGo T-Deck +[env:t-deck] +extends = esp32s3_base +board = t-deck +upload_protocol = esp-builtin +debug_tool = esp-builtin + +build_flags = ${esp32_base.build_flags} + -DT_DECK + -DBOARD_HAS_PSRAM + -Ivariants/t-deck + +lib_deps = ${esp32s3_base.lib_deps} + lovyan03/LovyanGFX@^1.1.7 \ No newline at end of file diff --git a/variants/t-deck/variant.h b/variants/t-deck/variant.h new file mode 100644 index 000000000..e434cd35d --- /dev/null +++ b/variants/t-deck/variant.h @@ -0,0 +1,74 @@ +// ST7789 TFT LCD +#define ST7789_CS 12 +#define ST7789_RS 11 // DC +#define ST7789_SDA 41 // MOSI +#define ST7789_SCK 40 +#define ST7789_RESET -1 +#define ST7789_MISO 38 +#define ST7789_BUSY -1 +#define ST7789_BL 42 +#define ST7789_SPI_HOST SPI2_HOST +#define ST7789_BACKLIGHT_EN 42 +#define SPI_FREQUENCY 40000000 +#define SPI_READ_FREQUENCY 16000000 +#define TFT_HEIGHT 320 +#define TFT_WIDTH 240 +#define TFT_OFFSET_X 0 +#define TFT_OFFSET_Y 0 +#define SCREEN_ROTATE +#define SCREEN_TRANSITION_FRAMERATE 1 // fps +#define SCREEN_TOUCH_INT 16 +#define TOUCH_SLAVE_ADDRESS 0x5D // GT911 + +#define BUTTON_PIN 0 +// #define BUTTON_NEED_PULLUP + +#define HAS_GPS 0 +#undef GPS_RX_PIN +#undef GPS_TX_PIN + +// Have SPI interface SD card slot +#define HAS_SDCARD 1 +#define SPI_MOSI (41) +#define SPI_SCK (40) +#define SPI_MISO (38) +#define SPI_CS (39) +#define SDCARD_CS SPI_CS + +#define BATTERY_PIN 4 // A battery voltage measurement pin, voltage divider connected here to measure battery voltage +// ratio of voltage divider = 2.0 (RD2=100k, RD3=100k) +#define ADC_MULTIPLIER 2.11 // 2.0 + 10% for correction of display undervoltage. +#define ADC_CHANNEL ADC1_GPIO1_CHANNEL + +// keyboard +#define I2C_SDA 18 // I2C pins for this board +#define I2C_SCL 8 +#define BOARD_POWERON 10 // must be set to HIGH +#define KB_SLAVE_ADDRESS 0x55 +#define KB_BL_PIN 46 // INT, set to INPUT +#define KB_UP 2 +#define KB_DOWN 3 +#define KB_LEFT 1 +#define KB_RIGHT 15 + +#define USE_SX1262 +#define USE_SX1268 + +#define RF95_SCK 40 +#define RF95_MISO 38 +#define RF95_MOSI 41 +#define RF95_NSS 9 + +#define LORA_DIO0 -1 // a No connect on the SX1262 module +#define LORA_RESET 17 +#define LORA_DIO1 45 // 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 TXCO is enabled + +#define SX126X_CS RF95_NSS // FIXME - we really should define LORA_CS instead +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_E22 // Not really an E22 but TTGO seems to be trying to clone that +// Internally the TTGO module hooks the SX1262-DIO2 in to control the TX/RX switch (which is the default for the sx1262interface +// code)