diff --git a/boards/t5-epaper-s3.json b/boards/t5-epaper-s3.json new file mode 100644 index 000000000..8d47b1866 --- /dev/null +++ b/boards/t5-epaper-s3.json @@ -0,0 +1,38 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM", + "-DARDUINO_RUNNING_CORE=0", + "-DARDUINO_EVENT_RUNNING_CORE=0", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino", "espidf"], + "name": "LilyGo T5-ePaper-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://lilygo.cc/products/t5-e-paper-s3-pro", + "vendor": "LILYGO" +} diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index e1cc0ccad..96ae87545 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -637,7 +637,7 @@ void Screen::setup() touchScreenImpl1->init(); } } -#elif HAS_TOUCHSCREEN && !defined(USE_EINK) +#elif HAS_TOUCHSCREEN && !defined(USE_EINK) && !defined(USE_EPD) touchScreenImpl1 = new TouchScreenImpl1(dispdev->getWidth(), dispdev->getHeight(), static_cast(dispdev)->getTouch); touchScreenImpl1->init(); diff --git a/src/graphics/niche/InkHUD/Applet.h b/src/graphics/niche/InkHUD/Applet.h index 802186e6e..798cc88cb 100644 --- a/src/graphics/niche/InkHUD/Applet.h +++ b/src/graphics/niche/InkHUD/Applet.h @@ -15,6 +15,7 @@ #include // GFXRoot drawing lib +#include "mesh/MeshModule.h" #include "mesh/MeshTypes.h" #include "./AppletFont.h" diff --git a/src/main.cpp b/src/main.cpp index 689e80e35..26e2ca40f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -394,6 +394,19 @@ void setup() io.pinMode(EXPANDS_GPIO_EN, OUTPUT); io.digitalWrite(EXPANDS_GPIO_EN, HIGH); io.pinMode(EXPANDS_SD_PULLEN, INPUT); +#elif defined(T5_S3_EPAPER_PRO) + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + pinMode(SDCARD_CS, OUTPUT); + digitalWrite(SDCARD_CS, HIGH); + pinMode(BOARD_BL_EN, OUTPUT); +#if !defined(T5_S3_EPAPER_PRO_V1) + io.begin(Wire, PCA9535_ADDR, SDA, SCL); + io.configPort(ExtensionIOXL9555::PORT0, 0x00); + io.configPort(ExtensionIOXL9555::PORT1, 0xFF); + io.digitalWrite(PCA9535_IO00_LORA_EN, HIGH); + delay(100); +#endif #endif concurrency::hasBeenSetup = true; #if ARCH_PORTDUINO diff --git a/src/platform/extra_variants/t5_s3_epaper_pro/variant.cpp b/src/platform/extra_variants/t5_s3_epaper_pro/variant.cpp new file mode 100644 index 000000000..943b8510d --- /dev/null +++ b/src/platform/extra_variants/t5_s3_epaper_pro/variant.cpp @@ -0,0 +1,33 @@ +#include "configuration.h" + +#ifdef T5_S3_EPAPER_PRO + +#include "input/TouchScreenImpl1.h" +#include +#include + +BBCapTouch bbct; + +bool readTouch(int16_t *x, int16_t *y) +{ + TOUCHINFO ti; + if (!digitalRead(GT911_PIN_INT)) { + if (bbct.getSamples(&ti)) { + *x = ti.x[0]; + *y = ti.y[0]; + return true; + } + } + return false; +} + +// T5-S3-ePaper Pro specific (late-) init +void lateInitVariant() +{ + bbct.init(GT911_PIN_SDA, GT911_PIN_SCL, GT911_PIN_RST, GT911_PIN_INT); + bbct.setOrientation(90, EPD_WIDTH, EPD_HEIGHT); + // FIXME: crashes! + // touchScreenImpl1 = new TouchScreenImpl1(EPD_WIDTH, EPD_HEIGHT, readTouch); + // touchScreenImpl1->init(); +} +#endif \ No newline at end of file diff --git a/variants/esp32s3/t5s3_epaper/nicheGraphics.h b/variants/esp32s3/t5s3_epaper/nicheGraphics.h new file mode 100644 index 000000000..699a82de0 --- /dev/null +++ b/variants/esp32s3/t5s3_epaper/nicheGraphics.h @@ -0,0 +1,123 @@ +/* + +Most of the Meshtastic firmware uses preprocessor macros throughout the code to support different hardware variants. +NicheGraphics attempts a different approach: + +Per-device config takes place in this setupNicheGraphics() method +(And a small amount in platformio.ini) + +This file sets up InkHUD for Heltec VM-E290. +Different NicheGraphics UIs and different hardware variants will each have their own setup procedure. + +*/ + +#pragma once + +#include "configuration.h" +#include "mesh/MeshModule.h" + +#ifdef MESHTASTIC_INCLUDE_NICHE_GRAPHICS + +// InkHUD-specific components +// --------------------------- +// #include "graphics/niche/InkHUD/InkHUD.h" +#include "graphics/niche/InkHUD/WindowManager.h" + +// Applets +#include "graphics/niche/InkHUD/Applets/User/AllMessage/AllMessageApplet.h" +#include "graphics/niche/InkHUD/Applets/User/DM/DMApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Heard/HeardApplet.h" +#include "graphics/niche/InkHUD/Applets/User/Positions/PositionsApplet.h" +#include "graphics/niche/InkHUD/Applets/User/RecentsList/RecentsListApplet.h" +#include "graphics/niche/InkHUD/Applets/User/ThreadedMessage/ThreadedMessageApplet.h" + +// Shared NicheGraphics components +// -------------------------------- +#include "graphics/niche/Drivers/Backlight/LatchingBacklight.h" +#include "graphics/niche/Drivers/EInk/DEPG0290BNS800.h" +#include "graphics/niche/Inputs/TwoButton.h" + +void setupNicheGraphics() +{ + using namespace NicheGraphics; + + // SPI + // ----------------------------- + + // Display is connected to HSPI + SPIClass *hspi = new SPIClass(HSPI); + hspi->begin(PIN_EINK_SCLK, -1, PIN_EINK_MOSI, PIN_EINK_CS); + + // E-Ink Driver + // ----------------------------- + + // Use E-Ink driver + Drivers::EInk *driver = new Drivers::DEPG0290BNS800; + driver->begin(hspi, PIN_EINK_DC, PIN_EINK_CS, PIN_EINK_BUSY); + + // InkHUD + // ---------------------------- + + InkHUD::InkHUD *inkhud = InkHUD::InkHUD::getInstance(); + + // Set the driver + inkhud->setDriver(driver); + + // Set how many FAST updates per FULL update + // Set how unhealthy additional FAST updates beyond this number are + inkhud->setDisplayResilience(7, 1.5); + + // Prepare fonts + InkHUD::Applet::fontLarge = FREESANS_9PT_WIN1252; + InkHUD::Applet::fontSmall = FREESANS_6PT_WIN1252; + + // Init settings, and customize defaults + inkhud->persistence->settings.userTiles.maxCount = 2; // How many tiles can the display handle? + inkhud->persistence->settings.rotation = 1; // 90 degrees clockwise + inkhud->persistence->settings.userTiles.count = 1; // One tile only by default, keep things simple for new users + inkhud->persistence->settings.optionalMenuItems.nextTile = false; // Behavior handled by aux button instead + inkhud->persistence->settings.optionalFeatures.batteryIcon = true; // Device definitely has a battery + + // Setup backlight + // Note: AUX button behavior configured further down + Drivers::LatchingBacklight *backlight = Drivers::LatchingBacklight::getInstance(); + backlight->setPin(PIN_EINK_EN); + + // Pick applets + // Note: order of applets determines priority of "auto-show" feature + // Optional arguments for defaults: + // - is activated? + // - is autoshown? + // - is foreground on a specific tile (index)? + inkhud->addApplet("All Messages", new InkHUD::AllMessageApplet, true, true); // Activated, autoshown + inkhud->addApplet("DMs", new InkHUD::DMApplet); + inkhud->addApplet("Channel 0", new InkHUD::ThreadedMessageApplet(0)); + inkhud->addApplet("Channel 1", new InkHUD::ThreadedMessageApplet(1)); + inkhud->addApplet("Positions", new InkHUD::PositionsApplet, true); // Activated + inkhud->addApplet("Recents List", new InkHUD::RecentsListApplet); + inkhud->addApplet("Heard", new InkHUD::HeardApplet, true, false, 0); // Activated, not autoshown, default on tile 0 + // inkhud->addApplet("Basic", new InkHUD::BasicExampleApplet); + // inkhud->addApplet("NewMsg", new InkHUD::NewMsgExampleApplet); + + // Start running InkHUD + inkhud->begin(); + + // Buttons + // -------------------------- + + Inputs::TwoButton *buttons = Inputs::TwoButton::getInstance(); // A shared NicheGraphics component + + // Setup the main user button (0) + buttons->setWiring(0, BUTTON_PIN); + buttons->setHandlerShortPress(0, []() { InkHUD::InkHUD::getInstance()->shortpress(); }); + buttons->setHandlerLongPress(0, []() { InkHUD::InkHUD::getInstance()->longpress(); }); + + // Setup the aux button (1) + // Bonus feature of VME290 + buttons->setWiring(1, BUTTON_PIN_SECONDARY); + buttons->setHandlerShortPress(1, []() { InkHUD::InkHUD::getInstance()->nextTile(); }); + + buttons->start(); +} + +#endif \ No newline at end of file diff --git a/variants/esp32s3/t5s3_epaper/pins_arduino.h b/variants/esp32s3/t5s3_epaper/pins_arduino.h new file mode 100644 index 000000000..4978cff2a --- /dev/null +++ b/variants/esp32s3/t5s3_epaper/pins_arduino.h @@ -0,0 +1,43 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +#define USB_VID 0x303a +#define USB_PID 0x1001 + +#if defined(T5_S3_EPAPER_PRO_V1) +// The default Wire will be mapped to RTC, Touch, BQ25896, and BQ27220 +static const uint8_t SDA = 6; +static const uint8_t SCL = 5; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 46; +static const uint8_t MOSI = 17; +static const uint8_t MISO = 8; +static const uint8_t SCK = 18; + +#define SPI_MOSI (17) +#define SPI_SCK (18) +#define SPI_MISO (8) +#define SPI_CS (16) + +#else // T5_S3_EPAPER_PRO_V2 +// The default Wire will be mapped to RTC, Touch, PCA9535, BQ25896, and BQ27220 +static const uint8_t SDA = 39; +static const uint8_t SCL = 40; + +// Default SPI will be mapped to Radio +static const uint8_t SS = 46; +static const uint8_t MOSI = 13; +static const uint8_t MISO = 21; +static const uint8_t SCK = 14; + +#define SPI_MOSI (13) +#define SPI_SCK (14) +#define SPI_MISO (21) +#define SPI_CS (12) + +#endif + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32s3/t5s3_epaper/platformio.ini b/variants/esp32s3/t5s3_epaper/platformio.ini new file mode 100644 index 000000000..c4187a807 --- /dev/null +++ b/variants/esp32s3/t5s3_epaper/platformio.ini @@ -0,0 +1,51 @@ +[t5s3_epaper_base] +extends = esp32s3_base +board = t5-epaper-s3 +board_build.partition = default_16MB.csv +board_check = false +upload_protocol = esptool +build_flags = + ${esp32_base.build_flags} + -I variants/esp32s3/t5s3_epaper + -D T5_S3_EPAPER_PRO + -D PRIVATE_HW + -D GPS_POWER_TOGGLE +build_src_filter = + ${esp32s3_base.build_src_filter} +lib_deps = + ${esp32s3_base.lib_deps} + https://github.com/Xinyuan-LilyGO/LilyGo-EPD47 + ;https://github.com/vroland/epdiy/archive/c61e9e923ce2418150d54f88cea5d196cdc40c54.zip + https://github.com/mverch67/BQ27220/archive/07d92be846abd8a0258a50c23198dac0858b22ed.zip + https://github.com/bitbank2/bb_captouch/archive/refs/tags/1.3.1.zip + lewisxhe/XPowersLib@0.3.1 + lewisxhe/SensorLib@0.3.1 + + +[env:t5s3_epaper_inkhud] +extends = t5s3_epaper_base, inkhud +build_flags = + ${t5s3_epaper_base.build_flags} + ${inkhud.build_flags} +build_src_filter = + ${t5s3_epaper_base.build_src_filter} + ${inkhud.build_src_filter} + -D SDCARD_USE_SPI1 +lib_deps = + ${inkhud.lib_deps} ; InkHUD libs first, so we get GFXRoot instead of AdafruitGFX + ${t5s3_epaper_base.lib_deps} + + +[env:t5s3-epaper-v1] ; H752 +extends = t5s3_epaper_base +build_flags = + ${t5s3_epaper_base.build_flags} + -D T5_S3_EPAPER_PRO_V1 + -D GPS_DEFAULT_NOT_PRESENT=1 + +[env:t5s3-epaper-v2] ; H752-01 +extends = t5s3_epaper_base +build_flags = + ${t5s3_epaper_base.build_flags} + -D T5_S3_EPAPER_PRO_V2 + -D SDCARD_USE_SPI1 diff --git a/variants/esp32s3/t5s3_epaper/variant.h b/variants/esp32s3/t5s3_epaper/variant.h new file mode 100644 index 000000000..134e79d4a --- /dev/null +++ b/variants/esp32s3/t5s3_epaper/variant.h @@ -0,0 +1,104 @@ + +// Display (E-Ink) ED047TC1 - 8bit parallel +#define USE_EPD +#define EPD_WIDTH 960 +#define EPD_HEIGHT 540 + +#if defined(T5_S3_EPAPER_PRO_V1) +#define BOARD_BL_EN 40 +#else +#define BOARD_BL_EN 11 +#endif + +#define I2C_SDA SDA +#define I2C_SCL SCL + +#define HAS_TOUCHSCREEN 1 +#define GT911_PIN_SDA SDA +#define GT911_PIN_SCL SCL +#if defined(T5_S3_EPAPER_PRO_V1) +#define GT911_PIN_INT 15 +#define GT911_PIN_RST 41 +#else +#define GT911_PIN_INT 3 +#define GT911_PIN_RST 9 +#endif + +#define PCF85063_RTC 0x51 +#define HAS_RTC 1 +#define PCF85063_INT 2 + +#define USE_POWERSAVE +#define SLEEP_TIME 120 + +// GPS +#if !defined(T5_S3_EPAPER_PRO_V1) +#define GPS_RX_PIN 44 +#define GPS_TX_PIN 43 +#endif + +#define BUTTON_PIN 0 +#define PIN_BUTTON2 48 +#define ALT_BUTTON_PIN PIN_BUTTON2 + +// SD card +#define HAS_SDCARD +#define SDCARD_CS SPI_CS +#define SD_SPI_FREQUENCY 75000000U + +// battery charger BQ25896 +#define HAS_PPM 1 +#define XPOWERS_CHIP_BQ25896 + +// battery quality management BQ27220 +#define HAS_BQ27220 1 +#define BQ27220_I2C_SDA SDA +#define BQ27220_I2C_SCL SCL +#define BQ27220_DESIGN_CAPACITY 1500 + +#if !defined(T5_S3_EPAPER_PRO_V1) +// TPS651851 + +// PCA9535 IO extender +#define USE_XL9555 +#define PCA9535_ADDR 0x20 +#define PCA9535_INT 38 +#define PCA9535_IO00_LORA_EN 00 +#define PCA9535_IO10_EP_OE 10 // EP Output enable source driver +#define PCA9535_IO11_EP_MODE 11 // EP Output mode selection gate driver +#define PCA9535_IO12_BUTTON 12 +#define PCA9535_IO13_TPS_PWRUP 13 +#define PCA9535_IO14_VCOM_CTRL 14 +#define PCA9535_IO15_TPS_WAKEUP 15 +#define PCA9535_IO16_TPS_PWR_GOOD 16 +#define PCA9535_IO17_TPS_INT 17 +#endif + +// LoRa +#define USE_SX1262 +#define USE_SX1268 + +#define LORA_SCK SCK +#define LORA_MISO MISO +#define LORA_MOSI MOSI +#define LORA_CS 46 + +#define LORA_DIO0 -1 +#if defined(T5_S3_EPAPER_PRO_V1) +#define LORA_RESET 43 +#define LORA_DIO1 3 // SX1262 IRQ +#define LORA_DIO2 44 // SX1262 BUSY +#define LORA_DIO3 +#else +#define LORA_RESET 1 +#define LORA_DIO1 10 // SX1262 IRQ +#define LORA_DIO2 47 // SX1262 BUSY +#define LORA_DIO3 +#endif + +#define SX126X_CS LORA_CS +#define SX126X_DIO1 LORA_DIO1 +#define SX126X_BUSY LORA_DIO2 +#define SX126X_RESET LORA_RESET +#define SX126X_DIO2_AS_RF_SWITCH +#define SX126X_DIO3_TCXO_VOLTAGE 2.4