diff --git a/boards/t-watch-ultra.json b/boards/t-watch-ultra.json new file mode 100644 index 0000000000..9aa102a4c4 --- /dev/null +++ b/boards/t-watch-ultra.json @@ -0,0 +1,40 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "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=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "qio", + "hwids": [["0x303A", "0x1001"]], + "mcu": "esp32s3", + "variant": "t-watch-ultra" + }, + "connectivity": ["wifi", "bluetooth", "lora"], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": ["arduino"], + "name": "LilyGo T-Watch Ultra", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "speed": 921600 + }, + "url": "https://www.lilygo.cc/en-pl/products/t-watch-ultra", + "vendor": "LilyGo" +} diff --git a/platformio.ini b/platformio.ini index 2e101a8a2a..345e2e832d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -120,7 +120,7 @@ lib_deps = [device-ui_base] lib_deps = # renovate: datasource=git-refs depName=meshtastic/device-ui packageName=https://github.com/meshtastic/device-ui gitBranch=master - https://github.com/meshtastic/device-ui/archive/e564d78ae1a7e9a225aaf4a73b1cb84c549f510f.zip + https://github.com/meshtastic/device-ui/archive/d8929cd2bd2825da0e706660b5465bec12f6998f.zip ; Common libs for environmental measurements in telemetry module [environmental_base] diff --git a/src/Power.cpp b/src/Power.cpp index 7de82b8d6b..9c556fa78b 100644 --- a/src/Power.cpp +++ b/src/Power.cpp @@ -1138,8 +1138,52 @@ bool Power::axpChipInit() PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist PMU->disablePowerOutput(XPOWERS_VBACKUP); - } + } else if (HW_VENDOR == meshtastic_HardwareModel_T_WATCH_ULTRA) { + PMU->clearIrqStatus(); + + // Turn off the PMU charging indicator light, no physical connection + PMU->setChargingLedMode(XPOWERS_CHG_LED_OFF); // NO LED + + PMU->setPowerChannelVoltage(XPOWERS_ALDO1, 3300); // SD Card + PMU->enablePowerOutput(XPOWERS_ALDO1); + + PMU->setPowerChannelVoltage(XPOWERS_ALDO2, 3300); // Display + PMU->enablePowerOutput(XPOWERS_ALDO2); + + PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); // LoRa + PMU->enablePowerOutput(XPOWERS_ALDO3); + + PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 1800); // Sensor + PMU->enablePowerOutput(XPOWERS_ALDO4); + + PMU->setPowerChannelVoltage(XPOWERS_BLDO1, 3300); // GPS + PMU->enablePowerOutput(XPOWERS_BLDO1); + PMU->setPowerChannelVoltage(XPOWERS_BLDO2, 3300); // Speaker + PMU->enablePowerOutput(XPOWERS_BLDO2); + + PMU->setPowerChannelVoltage(XPOWERS_VBACKUP, 3300); // RTC Button battery + PMU->enablePowerOutput(XPOWERS_VBACKUP); + + // PMU->enablePowerOutput(XPOWERS_DLDO1); // NFC + + // UNUSED POWER CHANNEL + PMU->disablePowerOutput(XPOWERS_DCDC2); + PMU->disablePowerOutput(XPOWERS_DCDC3); + PMU->disablePowerOutput(XPOWERS_DCDC4); + PMU->disablePowerOutput(XPOWERS_DCDC5); + PMU->disablePowerOutput(XPOWERS_CPULDO); + + // Enable Measure + PMU->enableBattDetection(); + PMU->enableVbusVoltageMeasure(); + PMU->enableBattVoltageMeasure(); + PMU->enableSystemVoltageMeasure(); + PMU->enableTemperatureMeasure(); + + // Clear all PMU interrupts + PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); + } // disable all axp chip interrupt PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); diff --git a/src/detect/ScanI2CTwoWire.cpp b/src/detect/ScanI2CTwoWire.cpp index 89a0610b45..ffef698b07 100644 --- a/src/detect/ScanI2CTwoWire.cpp +++ b/src/detect/ScanI2CTwoWire.cpp @@ -483,7 +483,7 @@ void ScanI2CTwoWire::scanPort(I2CPort port, uint8_t *address, uint8_t asize) SCAN_SIMPLE_CASE(DFROBOT_RAIN_ADDR, DFROBOT_RAIN, "DFRobot Rain Gauge", (uint8_t)addr.address); SCAN_SIMPLE_CASE(LTR390UV_ADDR, LTR390UV, "LTR390UV", (uint8_t)addr.address); SCAN_SIMPLE_CASE(PCT2075_ADDR, PCT2075, "PCT2075", (uint8_t)addr.address); - SCAN_SIMPLE_CASE(CST328_ADDR, CST328, "CST328", (uint8_t)addr.address); + SCAN_SIMPLE_CASE(CST328_ADDR, CST328, "Touch controller CSTxxxx", (uint8_t)addr.address); SCAN_SIMPLE_CASE(LTR553ALS_ADDR, LTR553ALS, "LTR553ALS", (uint8_t)addr.address); SCAN_SIMPLE_CASE(BHI260AP_ADDR, BHI260AP, "BHI260AP", (uint8_t)addr.address); SCAN_SIMPLE_CASE(SCD4X_ADDR, SCD4X, "SCD4X", (uint8_t)addr.address); diff --git a/src/gps/GPS.cpp b/src/gps/GPS.cpp index 2cfa558edb..95a9bae9c1 100644 --- a/src/gps/GPS.cpp +++ b/src/gps/GPS.cpp @@ -945,6 +945,9 @@ void GPS::setPowerPMU(bool on) } else if (HW_VENDOR == meshtastic_HardwareModel_LILYGO_TBEAM_S3_CORE) { // t-beam-s3-core GNSS power channel on ? PMU->enablePowerOutput(XPOWERS_ALDO4) : PMU->disablePowerOutput(XPOWERS_ALDO4); + } else if (HW_VENDOR == meshtastic_HardwareModel_T_WATCH_ULTRA) { + // t-watch-ultra GNSS power channel + on ? PMU->enablePowerOutput(XPOWERS_BLDO1) : PMU->disablePowerOutput(XPOWERS_BLDO1); } } else if (model == XPOWERS_AXP192) { // t-beam v1.1 GNSS power channel diff --git a/src/graphics/Screen.cpp b/src/graphics/Screen.cpp index 4485ca7a35..a3f4038b01 100644 --- a/src/graphics/Screen.cpp +++ b/src/graphics/Screen.cpp @@ -369,7 +369,7 @@ Screen::Screen(ScanI2C::DeviceAddress address, meshtastic_Config_DisplayConfig_O LOG_INFO("SSD1306 init success"); } #elif defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(CO5300_CS) dispdev = new TFTDisplay(address.address, -1, -1, geometry, (address.port == ScanI2C::I2CPort::WIRE1) ? HW_I2C::I2C_TWO : HW_I2C::I2C_ONE); #elif defined(USE_EINK) && !defined(USE_EINK_DYNAMICDISPLAY) @@ -431,7 +431,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) if (on) { LOG_INFO("Turn on screen"); powerMon->setState(meshtastic_PowerMon_State_Screen_On); -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(T_WATCH_ULTRA) PMU->enablePowerOutput(XPOWERS_ALDO2); #endif @@ -501,7 +501,7 @@ void Screen::handleSetOn(bool on, FrameCallback einkScreensaver) #endif #endif -#ifdef T_WATCH_S3 +#if defined(T_WATCH_S3) || defined(T_WATCH_ULTRA) PMU->disablePowerOutput(XPOWERS_ALDO2); #endif enabled = false; @@ -601,7 +601,7 @@ void Screen::setup() #else if (!config.display.flip_screen) { #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7789_CS) || \ - defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) + defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || defined(CO5300_CS) static_cast(dispdev)->flipScreenVertically(); #elif defined(USE_ST7789) static_cast(dispdev)->flipScreenVertically(); diff --git a/src/graphics/ScreenFonts.h b/src/graphics/ScreenFonts.h index c497a27b24..1b002cf196 100644 --- a/src/graphics/ScreenFonts.h +++ b/src/graphics/ScreenFonts.h @@ -73,7 +73,8 @@ #endif #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \ + defined(CO5300_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) // The screen is bigger so use bigger fonts #define FONT_SMALL FONT_MEDIUM_LOCAL // Height: 19 diff --git a/src/graphics/TFTDisplay.cpp b/src/graphics/TFTDisplay.cpp index 0663602d99..08a8f83051 100644 --- a/src/graphics/TFTDisplay.cpp +++ b/src/graphics/TFTDisplay.cpp @@ -21,6 +21,109 @@ uint16_t TFT_MESH = TFT_MESH_OVERRIDE; uint16_t TFT_MESH = COLOR565(0x67, 0xEA, 0x94); #endif +#if defined(CO5300_CS) +#include // Graphics and font library for AMOLED driver chip +class LGFX : public lgfx::LGFX_Device +{ + lgfx::Panel_CO5300 _panel_instance; + lgfx::Bus_SPI _bus_instance; + + public: + LGFX(void) + { + { + auto cfg = _bus_instance.config(); + + // configure SPI + cfg.spi_host = CO5300_SPI_HOST; // ESP32-S2,S3,C3 : SPI2_HOST or SPI3_HOST / ESP32 : VSPI_HOST or HSPI_HOST + cfg.spi_mode = SPI_MODE0; + 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 = CO5300_SCK; // Set SPI SCLK pin number + cfg.pin_io0 = CO5300_IO0; + cfg.pin_io1 = CO5300_IO1; + cfg.pin_io2 = CO5300_IO2; + cfg.pin_io3 = CO5300_IO3; + + _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 = CO5300_CS; // Pin number where CS is connected (-1 = disable) + cfg.pin_rst = CO5300_RESET; // Pin number where RST is connected (-1 = disable) + cfg.panel_width = TFT_WIDTH; // actual displayable width + cfg.panel_height = TFT_HEIGHT; // actual displayable height + cfg.offset_rotation = TFT_OFFSET_ROTATION; // Rotation direction value offset 0~7 (4~7 is upside down) + cfg.offset_x = TFT_OFFSET_X; + cfg.offset_y = TFT_OFFSET_Y; + 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 = false; // 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 + 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 + 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); + } + + setPanel(&_panel_instance); + } + + bool enableFrameBuffer(bool auto_display = false) + { + if (_panel_instance.initPanelFb()) { + auto fbPanel = _panel_instance.getPanelFb(); + if (fbPanel) { + fbPanel->setBus(&_bus_instance); + fbPanel->setAutoDisplay(auto_display); + setPanel(fbPanel); + return true; + } + } + return false; + } + + void disableFrameBuffer() + { + auto fbPanel = _panel_instance.getPanelFb(); + if (fbPanel) { + _panel_instance.deinitPanelFb(); + setPanel(&_panel_instance); + } + } + + bool init() + { +#ifdef CO5300_RESET + LOG_DEBUG("LGFX_Panel_CO5300::init()"); + lgfx::pinMode(CO5300_RESET, lgfx::pin_mode_t::output); + lgfx::gpio_hi(CO5300_RESET); + delay(200); + lgfx::gpio_lo(CO5300_RESET); + delay(300); + lgfx::gpio_hi(CO5300_RESET); + delay(200); +#endif + return lgfx::LGFX_Device::init() && enableFrameBuffer(false); + } +}; + +static LGFX *tft = nullptr; + +#endif + #if defined(ST7735S) #include // Graphics and font library for ST7735 driver chip @@ -1083,7 +1186,7 @@ static LGFX *tft = nullptr; #if defined(ST7701_CS) || defined(ST7735_CS) || defined(ST7789_CS) || defined(ST7796_CS) || defined(ILI9341_DRIVER) || \ defined(ILI9342_DRIVER) || defined(RAK14014) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST72xx_DE) || \ - (ARCH_PORTDUINO && HAS_SCREEN != 0) + defined(CO5300_CS) || (ARCH_PORTDUINO && HAS_SCREEN != 0) #include "SPILock.h" #include "TFTDisplay.h" #include @@ -1222,8 +1325,8 @@ void TFTDisplay::display(bool fromBlank) // Step 4: Send the changed pixels on this line to the screen as a single block transfer. // This function accepts pixel data MSB first so it can dump the memory straight out the SPI port. - tft->pushRect(x_FirstPixelUpdate, y, (x_LastPixelUpdate - x_FirstPixelUpdate + 1), 1, - &linePixelBuffer[x_FirstPixelUpdate]); + tft->pushImage(x_FirstPixelUpdate, y, (x_LastPixelUpdate - x_FirstPixelUpdate + 1), 1, + &linePixelBuffer[x_FirstPixelUpdate]); somethingChanged = true; } @@ -1282,7 +1385,7 @@ void TFTDisplay::sendCommand(uint8_t com) // handle display on/off directly switch (com) { case DISPLAYON: { - // LOG_DEBUG("Display on"); + LOG_DEBUG("Display on"); backlightEnable->set(true); #if ARCH_PORTDUINO display(true); @@ -1301,12 +1404,13 @@ void TFTDisplay::sendCommand(uint8_t com) #endif #ifdef RAK14014 #elif !defined(M5STACK) && !defined(ST7789_CS) // T-Deck gets brightness set in Screen.cpp in the handleSetOn function + LOG_DEBUG("tft->setBrightness(172)"); tft->setBrightness(172); #endif break; } case DISPLAYOFF: { - // LOG_DEBUG("Display off"); + LOG_DEBUG("Display off"); backlightEnable->set(false); #if ARCH_PORTDUINO tft->clear(); @@ -1325,6 +1429,7 @@ void TFTDisplay::sendCommand(uint8_t com) #endif #ifdef RAK14014 #elif !defined(M5STACK) + LOG_DEBUG("tft->setBrightness(0)"); tft->setBrightness(0); #endif break; @@ -1400,8 +1505,8 @@ bool TFTDisplay::connect() tft = new LGFX; #endif - backlightEnable->set(true); LOG_INFO("Power to TFT Backlight"); + backlightEnable->set(true); #ifdef UNPHONE unphone.backlight(true); // using unPhone library @@ -1422,7 +1527,7 @@ bool TFTDisplay::connect() tft->setRotation(1); // T-Deck has the TFT in landscape #elif defined(T_WATCH_S3) tft->setRotation(2); // T-Watch S3 left-handed orientation -#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR) || defined(T_LORA_PAGER) +#elif ARCH_PORTDUINO || defined(SENSECAP_INDICATOR) || defined(T_LORA_PAGER) || defined(T_WATCH_ULTRA) tft->setRotation(0); // use config.yaml to set rotation #else tft->setRotation(3); // Orient horizontal and wide underneath the silkscreen name label diff --git a/src/graphics/draw/DebugRenderer.cpp b/src/graphics/draw/DebugRenderer.cpp index 60abd661e6..32b362d3c8 100644 --- a/src/graphics/draw/DebugRenderer.cpp +++ b/src/graphics/draw/DebugRenderer.cpp @@ -95,7 +95,7 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 (storeForwardModule->heartbeatInterval * 1200))) { // no heartbeat, overlap a bit #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ - ARCH_PORTDUINO) && \ + defined(CO5300_CS) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgQuestionL1); @@ -107,7 +107,8 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 #endif } else { #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ + defined(CO5300_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 18 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 16, 8, imgSFL1); @@ -123,7 +124,7 @@ void drawFrame(OLEDDisplay *display, OLEDDisplayUiState *state, int16_t x, int16 // TODO: Raspberry Pi supports more than just the one screen size #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ - ARCH_PORTDUINO) && \ + defined(CO5300_CS) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) display->drawFastImage(x + SCREEN_WIDTH - 14 - display->getStringWidth(screen->ourId), y + 3 + FONT_HEIGHT_SMALL, 12, 8, imgInfoL1); diff --git a/src/graphics/draw/UIRenderer.cpp b/src/graphics/draw/UIRenderer.cpp index ff8cd20c5d..9b90e96a0c 100644 --- a/src/graphics/draw/UIRenderer.cpp +++ b/src/graphics/draw/UIRenderer.cpp @@ -256,7 +256,8 @@ void UIRenderer::drawNodes(OLEDDisplay *display, int16_t x, int16_t y, const mes } #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ - defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS)) && \ + defined(ST7789_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(HX8357_CS) || defined(ST7796_CS) || \ + defined(CO5300_CS)) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) if (isHighResolution) { diff --git a/src/graphics/images.h b/src/graphics/images.h index b5010b1162..44b5a9927c 100644 --- a/src/graphics/images.h +++ b/src/graphics/images.h @@ -28,7 +28,7 @@ const uint8_t bluetoothConnectedIcon[36] PROGMEM = {0xfe, 0x01, 0xff, 0x03, 0x03 #if (defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || defined(ST7701_CS) || defined(ST7735_CS) || \ defined(ST7789_CS) || defined(USE_ST7789) || defined(HX8357_CS) || defined(ILI9488_CS) || defined(ST7796_CS) || \ - ARCH_PORTDUINO) && \ + defined(CO5300_CS) || ARCH_PORTDUINO) && \ !defined(DISPLAY_FORCE_SMALL_FONTS) 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}; diff --git a/src/main.cpp b/src/main.cpp index 029b8d7087..d14c768ec7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -204,7 +204,7 @@ ScanI2C::FoundDevice rgb_found = ScanI2C::FoundDevice(ScanI2C::DeviceType::NONE, /// The I2C address of our Air Quality Indicator (if found) ScanI2C::DeviceAddress aqi_found = ScanI2C::ADDRESS_NONE; -#if defined(T_WATCH_S3) || defined(T_LORA_PAGER) +#ifdef HAS_DRV2605 Adafruit_DRV2605 drv; #endif @@ -393,6 +393,27 @@ void setup() io.pinMode(EXPANDS_GPIO_EN, OUTPUT); io.digitalWrite(EXPANDS_GPIO_EN, HIGH); io.pinMode(EXPANDS_SD_PULLEN, INPUT); +#elif defined(T_WATCH_ULTRA) + pinMode(LORA_CS, OUTPUT); + digitalWrite(LORA_CS, HIGH); + pinMode(DISP_CS, OUTPUT); + digitalWrite(DISP_CS, HIGH); + pinMode(SDCARD_CS, OUTPUT); + digitalWrite(SDCARD_CS, HIGH); + + if (io.begin(Wire, XL9555_SLAVE_ADDRESS0)) { + io.pinMode(EXPANDS_DRV_EN, OUTPUT); + io.digitalWrite(EXPANDS_DRV_EN, HIGH); + delay(1); + io.pinMode(EXPANDS_DISP_EN, OUTPUT); + io.digitalWrite(EXPANDS_DISP_EN, HIGH); + delay(1); + io.pinMode(EXPANDS_TOUCH_RST, OUTPUT); + io.digitalWrite(EXPANDS_TOUCH_RST, HIGH); + delay(1); + } else { + LOG_ERROR("io expander initialisation failed!"); + } #endif concurrency::hasBeenSetup = true; #if ARCH_PORTDUINO @@ -838,7 +859,7 @@ void setup() #endif #endif -#if defined(T_WATCH_S3) || defined(T_LORA_PAGER) +#ifdef HAS_DRV2605 drv.begin(); drv.selectLibrary(1); // I2C trigger by sending 'go' command @@ -885,7 +906,7 @@ void setup() #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ - defined(USE_SPISSD1306) + defined(CO5300_CS) || defined(USE_SPISSD1306) screen = new graphics::Screen(screen_found, screen_model, screen_geometry); #elif defined(ARCH_PORTDUINO) if ((screen_found.port != ScanI2C::I2CPort::NO_I2C || portduino_config.displayPanel) && @@ -1154,7 +1175,7 @@ void setup() // the current region name) #if defined(ST7701_CS) || defined(ST7735_CS) || defined(USE_EINK) || defined(ILI9341_DRIVER) || defined(ILI9342_DRIVER) || \ defined(ST7789_CS) || defined(HX8357_CS) || defined(USE_ST7789) || defined(ILI9488_CS) || defined(ST7796_CS) || \ - defined(USE_SPISSD1306) + defined(CO5300_CS) || defined(USE_SPISSD1306) if (screen) screen->setup(); #elif defined(ARCH_PORTDUINO) diff --git a/src/main.h b/src/main.h index 414752b5c6..7ca14d825d 100644 --- a/src/main.h +++ b/src/main.h @@ -42,7 +42,7 @@ extern bool eink_found; extern bool pmu_found; extern bool isUSBPowered; -#if defined(T_WATCH_S3) || defined(T_LORA_PAGER) +#ifdef HAS_DRV2605 #include extern Adafruit_DRV2605 drv; #endif diff --git a/src/platform/esp32/architecture.h b/src/platform/esp32/architecture.h index 53b23124d2..ba3b949ac9 100644 --- a/src/platform/esp32/architecture.h +++ b/src/platform/esp32/architecture.h @@ -203,6 +203,8 @@ #define HW_VENDOR meshtastic_HardwareModel_M5STACK_C6L #elif defined(HELTEC_WIRELESS_TRACKER_V2) #define HW_VENDOR meshtastic_HardwareModel_HELTEC_WIRELESS_TRACKER_V2 +#elif defined(T_WATCH_ULTRA) +#define HW_VENDOR meshtastic_HardwareModel_T_WATCH_ULTRA #endif // ----------------------------------------------------------------------------- diff --git a/src/platform/extra_variants/t_watch_ultra/variant.cpp b/src/platform/extra_variants/t_watch_ultra/variant.cpp new file mode 100644 index 0000000000..6dd62ef494 --- /dev/null +++ b/src/platform/extra_variants/t_watch_ultra/variant.cpp @@ -0,0 +1,31 @@ +#include "configuration.h" + +#ifdef T_WATCH_ULTRA + +#include "Arduino.h" +#include "TouchDrvCSTXXX.hpp" +#include "input/TouchScreenImpl1.h" +#include + +static TouchDrvCST92xx touchDrv; + +static bool readTouch(int16_t *x, int16_t *y) +{ + return touchDrv.isPressed() && touchDrv.getPoint(x, y, 1); +} + +// T-Watch Ultra specific init +void lateInitVariant() +{ + if (config.display.displaymode != meshtastic_Config_DisplayConfig_DisplayMode_COLOR) { + pinMode(SCREEN_TOUCH_INT, INPUT_PULLUP); + touchDrv.setPins(-1, SCREEN_TOUCH_INT); + if (touchDrv.begin(Wire, TOUCH_SLAVE_ADDRESS, I2C_SDA, I2C_SCL)) { + touchScreenImpl1 = new TouchScreenImpl1(TFT_WIDTH, TFT_HEIGHT, readTouch); + touchScreenImpl1->init(); + } else { + LOG_ERROR("failed to initialize CST92xx"); + } + } +} +#endif \ No newline at end of file diff --git a/variants/esp32s3/t-deck-pro/variant.h b/variants/esp32s3/t-deck-pro/variant.h index 35cb99435c..cb233b1b6e 100644 --- a/variants/esp32s3/t-deck-pro/variant.h +++ b/variants/esp32s3/t-deck-pro/variant.h @@ -30,6 +30,7 @@ // vibration motor #define PIN_VIBRATION 2 +#define HAS_DRV2605 1 // Have SPI interface SD card slot #define HAS_SDCARD diff --git a/variants/esp32s3/t-watch-ultra/pins_arduino.h b/variants/esp32s3/t-watch-ultra/pins_arduino.h new file mode 100644 index 0000000000..fda6940811 --- /dev/null +++ b/variants/esp32s3/t-watch-ultra/pins_arduino.h @@ -0,0 +1,93 @@ +#ifndef Pins_Arduino_h +#define Pins_Arduino_h + +#include + +// #ifndef digitalPinToInterrupt +// #define digitalPinToInterrupt(p) (((p) < 48) ? (p) : -1) +// #endif + +#define USB_VID 0x303a +#define USB_PID 0x8227 +#define USB_MANUFACTURER "LILYGO" +#define USB_PRODUCT "T-Watch-Ultra" + +#define DISP_WIDTH 502 +#define DISP_HEIGHT 410 + +// QSPI interface display +#define DISP_D0 (38) +#define DISP_D1 (39) +#define DISP_D2 (42) +#define DISP_D3 (45) +#define DISP_SCK (40) +#define DISP_CS (41) +#define DISP_RST (37) +#define DISP_TE (6) + +// Interrupt IO port +#define TP_INT (12) +#define RTC_INT (1) +#define PMU_INT (7) +#define NFC_INT (5) +#define SENSOR_INT (8) +#define NFC_CS (4) + +// PDM microphone +#define MIC_SCK (17) +#define MIC_DAT (18) + +// MAX98357A +#define I2S_BCLK (9) +#define I2S_WCLK (10) +#define I2S_DOUT (11) + +#define SD_CS (21) + +// TX, RX pin connected to GPS +static const uint8_t TX = 43; +static const uint8_t RX = 44; + +// BHI260,PCF85063,AXP2101,DRV2605L share I2C Bus +static const uint8_t SDA = 3; +static const uint8_t SCL = 2; + +// Default sd cs pin +static const uint8_t SS = SD_CS; +static const uint8_t MOSI = 34; +static const uint8_t MISO = 33; +static const uint8_t SCK = 35; + +#define GPS_TX (TX) +#define GPS_RX (RX) +#define GPS_PPS (13) + +#define TP_SDA (SDA) +#define TP_SCL (SCL) + +// LoRa and SD card share SPI bus -> variant.h +// #define LORA_SCK (SCK) // share spi bus +// #define LORA_MISO (MISO) // share spi bus +// #define LORA_MOSI (MOSI) // share spi bus +// #define LORA_CS (36) +// #define LORA_RST (47) +// #define LORA_BUSY (48) +// #define LORA_IRQ (14) + +// External expansion chip IO definition +#define EXPANDS_DRV_EN (6) +#define EXPANDS_DISP_EN (7) +#define EXPANDS_TOUCH_RST (8) +#define EXPANDS_SD_DET (10) + +// Peripheral definition exists +#define USING_XL9555_EXPANDS +#define USING_PCM_AMPLIFIER +#define USING_PDM_MICROPHONE +#define USING_PMU_MANAGE +#define USING_INPUT_DEV_TOUCHPAD +#define USING_ST25R3916 +#define USING_BHI260_SENSOR +#define HAS_SD_CARD_SOCKET + +#endif /* Pins_Arduino_h */ diff --git a/variants/esp32s3/t-watch-ultra/platformio.ini b/variants/esp32s3/t-watch-ultra/platformio.ini new file mode 100644 index 0000000000..5a152de7be --- /dev/null +++ b/variants/esp32s3/t-watch-ultra/platformio.ini @@ -0,0 +1,63 @@ +; LilyGo T-Watch S3 +[env:t-watch-ultra] +extends = esp32s3_base +board = t-watch-ultra +board_check = true +board_build.partitions = default_16MB.csv +upload_protocol = esptool + +build_flags = ${esp32_base.build_flags} -Ivariants/esp32s3/t-watch-ultra + -D T_WATCH_ULTRA + -D RADIOLIB_EXCLUDE_SX128X=1 + -D RADIOLIB_EXCLUDE_SX127X=1 + -D RADIOLIB_EXCLUDE_LR11X0=1 + -D HAS_SDCARD + -D SDCARD_CS=21 +; -DPCF85063_RTC=0x51 +; -DHAS_BMA423=1 + +lib_deps = ${esp32s3_base.lib_deps} + lovyan03/LovyanGFX#develop ; TODO: does not yet contain Panel_CO5300 amoled driver + adafruit/Adafruit DRV2605 Library@^1.2.4 + earlephilhower/ESP8266Audio@^1.9.9 + earlephilhower/ESP8266SAM@^1.0.1 + lewisxhe/SensorLib@0.3.1 + +[env:t-watch-ultra-tft] +board_level = extra +extends = env:t-watch-ultra +build_flags = + ${env:t-watch-ultra.build_flags} + -D CONFIG_DISABLE_HAL_LOCKS=1 + -D INPUTDRIVER_BUTTON_TYPE=0 + -D HAS_SCREEN=1 + -D HAS_TFT=1 + -D USE_I2S_BUZZER + -D RAM_SIZE=5120 + -D LV_LVGL_H_INCLUDE_SIMPLE + -D LV_CONF_INCLUDE_SIMPLE + -D LV_COMP_CONF_INCLUDE_SIMPLE + -D LV_USE_SYSMON=0 + -D LV_USE_PROFILER=0 + -D LV_USE_PERF_MONITOR=0 + -D LV_USE_MEM_MONITOR=0 + -D LV_USE_LOG=0 + -D USE_LOG_DEBUG + -D LOG_DEBUG_INC=\"DebugConfiguration.h\" + -D RADIOLIB_SPI_PARANOID=0 + -D LGFX_SCREEN_WIDTH=410 + -D LGFX_SCREEN_HEIGHT=502 + -D DISPLAY_SIZE=410x502 ; portrait mode + -D DISPLAY_SET_RESOLUTION + -D LGFX_DRIVER=LGFX_TWATCH_ULTRA + -D GFX_DRIVER_INC=\"graphics/LGFX/LGFX_T_WATCH_ULTRA.h\" +; -D LVGL_DRIVER=LVGL_T_WATCH_ULTRA +; -D LV_USE_ST7796=1 + -D VIEW_320x240 + -D USE_PACKET_API + -D MAP_FULL_REDRAW + -D CUSTOM_TOUCH_DRIVER + +lib_deps = + ${env:t-watch-ultra.lib_deps} + ${device-ui_base.lib_deps} \ No newline at end of file diff --git a/variants/esp32s3/t-watch-ultra/variant.h b/variants/esp32s3/t-watch-ultra/variant.h new file mode 100644 index 0000000000..b79b8507bf --- /dev/null +++ b/variants/esp32s3/t-watch-ultra/variant.h @@ -0,0 +1,86 @@ + +// CO5300 TFT AMOLED +#define CO5300_CS 41 +#define CO5300_SCK 40 +#define CO5300_RESET 37 +#define CO5300_TE 6 +#define CO5300_IO0 38 +#define CO5300_IO1 39 +#define CO5300_IO2 42 +#define CO5300_IO3 45 +#define CO5300_SPI_HOST SPI2_HOST +#define SPI_FREQUENCY 75000000 +#define SPI_READ_FREQUENCY 16000000 // irrelevant +#define TFT_HEIGHT 502 +#define TFT_WIDTH 410 +#define TFT_OFFSET_X 22 +#define TFT_OFFSET_Y 0 +#define TFT_OFFSET_ROTATION 0 +#define SCREEN_TRANSITION_FRAMERATE 5 // fps + +#define HAS_TOUCHSCREEN 1 +#define SCREEN_TOUCH_INT 12 +#define TOUCH_I2C_PORT 0 +#define TOUCH_SLAVE_ADDRESS 0x1A +#define WAKE_ON_TOUCH + +#define BUTTON_PIN 0 + +#define USE_POWERSAVE +#define SLEEP_TIME 120 + +// External expansion chip XL9555 +#define USE_XL9555 + +// MAX98357A +#define HAS_I2S +#define DAC_I2S_BCK 9 +#define DAC_I2S_WS 10 +#define DAC_I2S_DOUT 11 +#define DAC_I2S_MCLK 0 // TODO + +#define HAS_AXP2101 +// #define PMU_IRQ 7 +#define HAS_RTC 1 +#define HAS_DRV2605 1 + +#define I2C_SDA 3 +#define I2C_SCL 2 +#define I2C_NO_RESCAN + +#define HAS_GPS 1 +#define GPS_BAUDRATE 38400 +#define GPS_RX_PIN 44 +#define GPS_TX_PIN 43 +#define PIN_GPS_PPS 13 + +// SPI interface SD card slot +#define SPI_MOSI MOSI +#define SPI_SCK SCK +#define SPI_MISO MISO +#define SPI_CS 21 +#define SD_SPI_FREQUENCY 75000000U + +#define USE_SX1262 +// #define USE_SX1280 + +#define LORA_SCK 35 +#define LORA_MISO 33 +#define LORA_MOSI 34 +#define LORA_CS 36 + +#define LORA_DIO0 -1 // a No connect on the SX1262 module +#define LORA_RESET 47 +#define LORA_DIO1 14 // SX1262 IRQ +#define LORA_DIO2 48 // SX1262 BUSY +#define LORA_DIO3 + +#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 1.8 + +#define USE_VIRTUAL_KEYBOARD 1 +#define DISPLAY_CLOCK_FRAME 1 diff --git a/variants/esp32s3/tlora-pager/variant.h b/variants/esp32s3/tlora-pager/variant.h index 2875f6804f..29f7eb3fe6 100644 --- a/variants/esp32s3/tlora-pager/variant.h +++ b/variants/esp32s3/tlora-pager/variant.h @@ -70,6 +70,9 @@ #define DAC_I2S_DIN 17 #define DAC_I2S_MCLK 10 +// haptic driver +#define HAS_DRV2605 1 + // gyroscope BHI260AP #define HAS_BHI260AP