diff --git a/docs/source/Plugin/P095_commands.repl b/docs/source/Plugin/P095_commands.repl index e88f9821ec..98b3cf2ddf 100644 --- a/docs/source/Plugin/P095_commands.repl +++ b/docs/source/Plugin/P095_commands.repl @@ -31,7 +31,7 @@ " | ``tftcmd,clear`` "," - | Clear the display, using the default background color. + | Clear the display, using the **default** background color. For clearing with a custom background color see the ``,clear[,]`` command. " " | ``tftcmd,backlight,`` diff --git a/docs/source/Plugin/P116.rst b/docs/source/Plugin/P116.rst index 6e2a42d139..afddf033a0 100644 --- a/docs/source/Plugin/P116.rst +++ b/docs/source/Plugin/P116.rst @@ -28,7 +28,7 @@ The ST7735, ST7789 and ST7796 chip families drive color TFT displays in various This plugin supports these display models: -* **ST7735** with resolutions 128 x 128, 128 x 160 and 80 x 160 pixels +* **ST7735** with resolutions 128 x 128, 128 x 160, 80 x 160 and 135 x 240 pixels * **ST7789** with resolutions 240 x 320, 240 x 240, 240 x 280 and 135 x 240 pixels * **ST7796** with resolution of 320 x 480 pixels. @@ -140,6 +140,7 @@ Available options: * *ST7735 128 x 160px* Allows 16 lines of text in the smallest font scaling setting. * *ST7735 80 x 160px* Allows 16 lines of text in the smallest font scaling setting. * *ST7735 80 x 160px (Color inverted)* Special color inverted configuration as used in f.e. M5Stack StickC. +* *ST7735 135 x 240px* Added to support a revision of the TTGO T-Display 16MB Flash module, that won't work with the ST7789 driver, the seller is claiming to use, but does work with this specially crafted ST7735 driver. * *ST7789 240 x 320px* Allows 32 lines of text in the smallest font scaling setting. Predefined text only goes to 24, extra lines can be displayed from rules or external commands. * *ST7789 240 x 240px* Allows 24 lines of text in the smallest font scaling setting. * *ST7789 240 x 280px* Allows 28 lines of text in the smallest font scaling setting. Predefined text only goes to 24, extra lines can be displayed from rules or external commands. @@ -260,6 +261,10 @@ Change log .. versionadded:: 2.0 ... + |added| 2024-03-26 Add support for ST7735, 135x240 resolution + + |added| 2022-07-06 Add support for ST7735 (Color inverted), for M5StickC support + |added| 2021-11-06 Add support for ST7796 displays |added| 2021-08 Moved from an external forum to ESPEasy. diff --git a/docs/source/Plugin/P116_TFTDisplayModelOptions.png b/docs/source/Plugin/P116_TFTDisplayModelOptions.png index a17199a9ce..6719b106c6 100644 Binary files a/docs/source/Plugin/P116_TFTDisplayModelOptions.png and b/docs/source/Plugin/P116_TFTDisplayModelOptions.png differ diff --git a/docs/source/Plugin/P116_commands.repl b/docs/source/Plugin/P116_commands.repl index 50d2b90622..6a6702d432 100644 --- a/docs/source/Plugin/P116_commands.repl +++ b/docs/source/Plugin/P116_commands.repl @@ -28,7 +28,7 @@ " | ``st77xxcmd,clear`` "," - | Clear the display, using the default background color. + | Clear the display, using the **default** background color. For clearing with a custom background color see the ``,clear[,]`` command. " " | ``st77xxcmd,backlight,`` diff --git a/lib/Adafruit_ST77xx/Adafruit_ST7735.cpp b/lib/Adafruit_ST77xx/Adafruit_ST7735.cpp index 2ddd4e2429..4f688a90f2 100644 --- a/lib/Adafruit_ST77xx/Adafruit_ST7735.cpp +++ b/lib/Adafruit_ST77xx/Adafruit_ST7735.cpp @@ -181,6 +181,17 @@ static const uint8_t PROGMEM 0x00, 0x00, // XSTART = 0 0x00, 0x9F }, // XEND = 159 + #if ST7735_EXTRA_INIT + Rcmd2black135x240[] = { // 7735R init, part 2 (mini 160x80) + 2, // 2 commands in list: + ST77XX_CASET, 4, // 1: Column addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 0x00, 135, // XEND = 135 + ST77XX_RASET, 4, // 2: Row addr set, 4 args, no delay: + 0x00, 0x00, // XSTART = 0 + 240 >> 8, 240 & 0xFF }, // XEND = 240 + #endif // if ST7735_EXTRA_INIT + Rcmd3[] = { // 7735R init, part 3 (red or green tab) 4, // 4 commands in list: ST7735_GMCTRP1, 16 , // 1: Gamma Adjustments (pos. polarity), 16 args + delay: @@ -243,6 +254,15 @@ void Adafruit_ST7735::initR(uint8_t options) { sendCommand(ST77XX_INVON, &data, 0); // Write twice... _colstart = 26; _rowstart = 1; + #if ST7735_EXTRA_INIT + } else if (options == INITR_BLACKTAB135x240) { + _height = ST7735_TFTHEIGHT_240; + _width = ST7735_TFTWIDTH_135; + displayInit(Rcmd2black135x240); + const uint8_t data = 0x00; + sendCommand(ST77XX_INVON, &data, 0); + sendCommand(ST77XX_INVON, &data, 0); // Write twice... + #endif // if ST7735_EXTRA_INIT } else { // colstart, rowstart left at default '0' values displayInit(Rcmd2red); @@ -288,6 +308,10 @@ void Adafruit_ST7735::setRotation(uint8_t m) { case 0: if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) { madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #endif // if ST7735_EXTRA_INIT } else { madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST7735_MADCTL_BGR; } @@ -298,6 +322,13 @@ void Adafruit_ST7735::setRotation(uint8_t m) { } else if (tabcolor == INITR_MINI160x80) { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_80; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + _height = ST7735_TFTHEIGHT_240; + _width = ST7735_TFTWIDTH_135; + _colstart = 53; + _rowstart = 40; + #endif // if ST7735_EXTRA_INIT } else { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_128; @@ -308,6 +339,10 @@ void Adafruit_ST7735::setRotation(uint8_t m) { case 1: if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) { madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB; + #endif // if ST7735_EXTRA_INIT } else { madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST7735_MADCTL_BGR; } @@ -318,6 +353,13 @@ void Adafruit_ST7735::setRotation(uint8_t m) { } else if (tabcolor == INITR_MINI160x80) { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_80; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + _width = ST7735_TFTHEIGHT_240; + _height = ST7735_TFTWIDTH_135; + _colstart = 52; + _rowstart = 40; + #endif // if ST7735_EXTRA_INIT } else { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_128; @@ -328,6 +370,10 @@ void Adafruit_ST7735::setRotation(uint8_t m) { case 2: if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) { madctl = ST77XX_MADCTL_RGB; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #endif // if ST7735_EXTRA_INIT } else { madctl = ST7735_MADCTL_BGR; } @@ -338,6 +384,13 @@ void Adafruit_ST7735::setRotation(uint8_t m) { } else if (tabcolor == INITR_MINI160x80) { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_80; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + _height = ST7735_TFTHEIGHT_240; + _width = ST7735_TFTWIDTH_135; + _colstart = 52; + _rowstart = 40; + #endif // if ST7735_EXTRA_INIT } else { _height = ST7735_TFTHEIGHT_160; _width = ST7735_TFTWIDTH_128; @@ -348,6 +401,10 @@ void Adafruit_ST7735::setRotation(uint8_t m) { case 3: if ((tabcolor == INITR_BLACKTAB) || (tabcolor == INITR_MINI160x80)) { madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + madctl = ST77XX_MADCTL_RGB; + #endif // if ST7735_EXTRA_INIT } else { madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST7735_MADCTL_BGR; } @@ -358,6 +415,13 @@ void Adafruit_ST7735::setRotation(uint8_t m) { } else if (tabcolor == INITR_MINI160x80) { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_80; + #if ST7735_EXTRA_INIT + } else if (tabcolor == INITR_BLACKTAB135x240) { + _width = ST7735_TFTHEIGHT_240; + _height = ST7735_TFTWIDTH_135; + _colstart = 53; + _rowstart = 40; + #endif // if ST7735_EXTRA_INIT } else { _width = ST7735_TFTHEIGHT_160; _height = ST7735_TFTWIDTH_128; diff --git a/lib/Adafruit_ST77xx/Adafruit_ST7735.h b/lib/Adafruit_ST77xx/Adafruit_ST7735.h index 6d138bce3c..935dda4e30 100644 --- a/lib/Adafruit_ST77xx/Adafruit_ST7735.h +++ b/lib/Adafruit_ST77xx/Adafruit_ST7735.h @@ -3,6 +3,22 @@ #include "Adafruit_ST77xx.h" +/** + * 2024-03-17 tonhuisman: Add additional initialization sequences for ST7735 displays, with the intention to get 'm working + * on some devices that seem to use peculiarly configured hardware like LiliGO TTGO T-Display (16MB flash), + * and possibly the T-Display S3 + * By default only enabled on ESP32, unless -D ST7735_EXTRA_INIT=1 is defined, f.e. via the build script + */ + +#ifndef ST7735_EXTRA_INIT // Enable setting from 'outside', like Platformio.ini +# ifdef ESP8266 +# define ST7735_EXTRA_INIT 0 +# endif // ifdef ESP8266 +# ifdef ESP32 +# define ST7735_EXTRA_INIT 1 +# endif // ifdef ESP32 +#endif + // some flags for initR() :( #define INITR_GREENTAB 0x00 #define INITR_REDTAB 0x01 @@ -14,6 +30,7 @@ #define INITR_MINI160x80 0x04 #define INITR_HALLOWING 0x05 #define INITR_GREENTAB160x80 0x06 +#define INITR_BLACKTAB135x240 0x07 // Some register settings #define ST7735_MADCTL_BGR 0x08 diff --git a/lib/Adafruit_ST77xx/Adafruit_ST7789.cpp b/lib/Adafruit_ST77xx/Adafruit_ST7789.cpp index 9fd2f00e41..6467aeb53b 100644 --- a/lib/Adafruit_ST77xx/Adafruit_ST7789.cpp +++ b/lib/Adafruit_ST77xx/Adafruit_ST7789.cpp @@ -76,6 +76,167 @@ static const uint8_t PROGMEM ST77XX_DISPON , ST_CMD_DELAY, // 9: Main screen turn on, no args, delay 10 }; // 10 ms delay +#if ST7789_EXTRA_INIT +static const uint8_t PROGMEM // Source: https://github.com/Xinyuan-LilyGO/TTGO-T-Display + alt1_st7789[] = { // Init commands for 7789 screens Alternative 1 + 21, // 21 commands in list: + ST77XX_SLPOUT, ST_CMD_DELAY, // 1: Out of sleep mode, no args, w/delay + 120, // 120 ms delay + ST77XX_NORON, ST_CMD_DELAY, // 2: Normal display on, no args, w/delay + 10, // 10 ms delay + ST77XX_MADCTL, 1, // 3: Mem access ctrl (directions), 1 arg: + 0x08, // Row/col addr, bottom-top refresh + 0xB6, 2, // 4: ?JXL240 datasheet? + 0x0A, 0x82, + ST77XX_COLMOD, 1+ ST_CMD_DELAY, // 5: Set color mode, 1 arg + delay: + 0x55, // 16-bit color + 10, // 10 ms delay + ST77XX_PORCTRL, 5, // 6: Porch control, Framerate setting + 0x0c, 0x0c, 0x00, 0x33, 0x33, + ST77XX_GCTRL, 1, // 7: Gate control, Voltages VGH/VGL + 0x35, + ST77XX_VCOMS, 1, // 8: Power settings + 0x28, + ST77XX_LCMCTRL, 1, // 9: LCM Control + 0x0C, + ST77XX_VDVVRHEN, 2, // 10: VDV & VRH command enable + 0x01, 0xFF, + ST77XX_VRHS, 1, // 11: VRH set + 0x10, + ST77XX_VDVSET, 1, // 12: VDV set + 0x20, + ST77XX_FRCTR2, 1, // 13: FR Control 2 + 0x0F, + ST77XX_PWCTRL1, 2, // 14: Power Control 1 + 0xA4, 0xA1, + ST77XX_PVGAMCTRL, 14, // 15: Positive Voltage Gamma control + 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + ST77XX_NVGAMCTRL, 14, // 16: Negative Voltage Gamma control + 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + ST77XX_INVON, ST_CMD_DELAY, // 17: hack + 10, + ST77XX_CASET , 4, // 18: Column addr set, 4 args, no delay: + 0x00, + 0, // XSTART = 0 + 0, + 240, // XEND = 240 + ST77XX_RASET , 4, // 19: Row addr set, 4 args, no delay: + 0x00, + 0, // YSTART = 0 + 320>>8, + 320&0xFF, // YEND = 320 + ST77XX_INVON, ST_CMD_DELAY, // 20: Normal display on, no args, w/delay + 10, // 10 ms delay + ST77XX_DISPON, ST_CMD_DELAY, // 21: Main screen turn on, no args, delay + 255 // 120 ms delay + }; + +static const uint8_t PROGMEM // Source: https://github.com/Bodmer/TFT_eSPI (ST7789_init.h, _NOT_ INIT_SEQUENCE_3) + alt2_st7789[] = { // Init commands for 7789 screens Alternative 2 + 21, // 21 commands in list: + ST77XX_SLPOUT, ST_CMD_DELAY, // 1: Out of sleep mode, no args, w/delay + 120, // 120 ms delay + ST77XX_NORON, ST_CMD_DELAY, // 2: Normal display on, no args, w/delay + 10, // 10 ms delay + ST77XX_MADCTL, 1, // 3: Mem access ctrl (directions), 1 arg: + 0x08, // Row/col addr, bottom-top refresh + 0xB6, 2, // 4: ?JXL240 datasheet? + 0x0A, 0x82, + ST77XX_RAMCTRL, 2, // 5: RAM control + 0x00, 0xE0, // 5 to 6-bit conversion: r0 = r5, b0 = b5 + ST77XX_COLMOD, 1+ ST_CMD_DELAY, // 6: Set color mode, 1 arg + delay: + 0x55, // 16-bit color + 10, // 10 ms delay + ST77XX_PORCTRL, 5, // 7: Porch control, Framerate setting + 0x0c, 0x0c, 0x00, 0x33, 0x33, + ST77XX_GCTRL, 1, // 8: Gate control, Voltages VGH/VGL + 0x35, + ST77XX_VCOMS, 1, // 9: Power settings + 0x28, + ST77XX_LCMCTRL, 1, // 10: LCM Control + 0x0C, + ST77XX_VDVVRHEN, 2, // 11: VDV & VRH command enable + 0x01, 0xFF, + ST77XX_VRHS, 1, // 12: VRH set + 0x10, + ST77XX_VDVSET, 1, // 13: VDV set + 0x20, + ST77XX_FRCTR2, 1, // 14: FR Control 2 + 0x0F, + ST77XX_PWCTRL1, 2, // 15: Power Control 1 + 0xA4, 0xA1, + ST77XX_PVGAMCTRL, 14, // 16: Positive Voltage Gamma control + 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x32, 0x44, 0x42, 0x06, 0x0E, 0x12, 0x14, 0x17, + ST77XX_NVGAMCTRL, 14, // 17: Negative Voltage Gamma control + 0xD0, 0x00, 0x02, 0x07, 0x0A, 0x28, 0x31, 0x54, 0x47, 0x0E, 0x1C, 0x17, 0x1B, 0x1E, + ST77XX_INVON, ST_CMD_DELAY, // 18: hack + 10, + ST77XX_CASET , 4, // 19: Column addr set, 4 args, no delay: + 0x00, + 0, // XSTART = 0 + 0, + 239, // XEND = 239 + ST77XX_RASET , 4, // 20: Row addr set, 4 args, no delay: + 0x00, + 0, // YSTART = 0 + 319>>8, + 319&0xFF, // YEND = 319 + ST77XX_DISPON, ST_CMD_DELAY, // 21: Main screen turn on, no args, delay + 120 // 120 ms delay + }; + +static const uint8_t PROGMEM // Source: https://github.com/Bodmer/TFT_eSPI (ST7789_init.h, _WITH_ INIT_SEQUENCE_3) + alt3_st7789[] = { // Init commands for 7789 screens Alternative 2 + 18, // 18 commands in list: + ST77XX_SLPOUT, ST_CMD_DELAY, // 1: Out of sleep mode, no args, w/delay + 120, // 120 ms delay + ST77XX_NORON, ST_CMD_DELAY, // 2: Normal display on, no args, w/delay + 10, // 10 ms delay + ST77XX_MADCTL, 1, // 3: Mem access ctrl (directions), 1 arg: + 0x08, // Row/col addr, bottom-top refresh + 0xB6, 2, // 4: ?JXL240 datasheet? + 0x0A, 0x82, + ST77XX_COLMOD, 1+ ST_CMD_DELAY, // 5: Set color mode, 1 arg + delay: + 0x55, // 16-bit color + 10, // 10 ms delay + ST77XX_PORCTRL, 5, // 6: Porch control, Framerate setting + 0x0c, 0x0c, 0x00, 0x33, 0x33, + ST77XX_GCTRL, 1, // 7: Gate control, Voltages VGH/VGL + 0x75, + ST77XX_VCOMS, 1, // 8: Power settings + 0x28, + ST77XX_LCMCTRL, 1, // 9: LCM Control + 0x2C, + ST77XX_VDVVRHEN, 1, // 10: VDV & VRH command enable + 0x01, + ST77XX_VRHS, 1, // 11: VRH set + 0x1F, + ST77XX_FRCTR2, 1, // 12: FR Control 2 + 0x13, + ST77XX_PWCTRL1, 1, // 13: Power Control 1 + 0xA7, + ST77XX_PWCTRL1, 2, // 14: Power Control 1 + 0xA4, 0xA1, + 0xD6, 1, // 15: ? + 0xA1, + ST77XX_PVGAMCTRL, 14, // 16: Positive Voltage Gamma control + 0xF0, 0x05, 0x0A, 0x06, 0x06, 0x03, 0x2B, 0x32, 0x43, 0x36, 0x11, 0x10, 0x2B, 0x32, + ST77XX_NVGAMCTRL, 14, // 17: Negative Voltage Gamma control + 0xF0, 0x08, 0x0C, 0x0B, 0x09, 0x24, 0x2B, 0x22, 0x43, 0x38, 0x15, 0x16, 0x2F, 0x37, + // ST77XX_CASET , 4, // 18: Column addr set, 4 args, no delay: + // 0x00, + // 0, // XSTART = 0 + // 0, + // 239, // XEND = 239 + // ST77XX_RASET , 4, // 19: Row addr set, 4 args, no delay: + // 0x00, + // 0, // YSTART = 0 + // 319>>8, + // 319&0xFF, // YEND = 319 + ST77XX_DISPON, ST_CMD_DELAY, // 18: Main screen turn on, no args, delay + 120 // 120 ms delay + }; +#endif // if ST7789_EXTRA_INIT // clang-format on /**************************************************************************/ @@ -88,7 +249,7 @@ static const uint8_t PROGMEM the defines only, the values are NOT the same!) */ /**************************************************************************/ -void Adafruit_ST7789::init(uint16_t width, uint16_t height, uint8_t mode) { +void Adafruit_ST7789::init(uint16_t width, uint16_t height, uint8_t mode, uint8_t init_seq) { // Save SPI data mode. commonInit() calls begin() (in Adafruit_ST77xx.cpp), // which in turn calls initSPI() (in Adafruit_SPITFT.cpp), passing it the // value of spiMode. It's done this way because begin() really should not @@ -101,6 +262,8 @@ void Adafruit_ST7789::init(uint16_t width, uint16_t height, uint8_t mode) { // (Might get added similarly to other display types as needed on a // case-by-case basis.) + _init_seq = init_seq; + commonInit(NULL); if (width < 240) { @@ -123,7 +286,18 @@ void Adafruit_ST7789::init(uint16_t width, uint16_t height, uint8_t mode) { windowWidth = width; windowHeight = height; - displayInit(generic_st7789); + const uint8_t *init_ = generic_st7789; + + #if ST7789_EXTRA_INIT + if (1 == _init_seq) { + init_ = alt1_st7789; + } else if (2 == _init_seq) { + init_ = alt2_st7789; + } else if (3 == _init_seq) { + init_ = alt3_st7789; + } + #endif // if ST7789_EXTRA_INIT + displayInit(init_); setRotation(0); } @@ -140,28 +314,64 @@ void Adafruit_ST7789::setRotation(uint8_t m) { switch (rotation) { case 0: - madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB; + #if ST7789_EXTRA_INIT + if (_init_seq > 0) { + madctl = ST77XX_MADCTL_BGR; + _colstart = 52; + _rowstart = 40; + } else + #endif // if ST7789_EXTRA_INIT + { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB; + } _xstart = _colstart; _ystart = _rowstart; _width = windowWidth; _height = windowHeight; break; case 1: - madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #if ST7789_EXTRA_INIT + if (_init_seq > 0) { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_BGR; + _colstart = 40; + _rowstart = 53; + } else + #endif // if ST7789_EXTRA_INIT + { + madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + } _xstart = _rowstart; _ystart = _colstart; _height = windowWidth; _width = windowHeight; break; case 2: - madctl = ST77XX_MADCTL_RGB; + #if ST7789_EXTRA_INIT + if (_init_seq > 0) { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB; + _colstart2 = 53; + _rowstart2 = 40; + } else + #endif // if ST7789_EXTRA_INIT + { + madctl = ST77XX_MADCTL_RGB; + } _xstart = _colstart2; _ystart = _rowstart2; _width = windowWidth; _height = windowHeight; break; case 3: - madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + #if ST7789_EXTRA_INIT + if (_init_seq > 0) { + madctl = ST77XX_MADCTL_MV | ST77XX_MADCTL_MY | ST77XX_MADCTL_BGR; + _colstart2 = 40; + _rowstart2 = 52; + } else + #endif // if ST7789_EXTRA_INIT + { + madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB; + } _xstart = _rowstart2; _ystart = _colstart2; _height = windowWidth; diff --git a/lib/Adafruit_ST77xx/Adafruit_ST7789.h b/lib/Adafruit_ST77xx/Adafruit_ST7789.h index 7fe09d6f02..4714a9968d 100644 --- a/lib/Adafruit_ST77xx/Adafruit_ST7789.h +++ b/lib/Adafruit_ST77xx/Adafruit_ST7789.h @@ -3,6 +3,22 @@ #include "Adafruit_ST77xx.h" +/** + * 2024-03-09 tonhuisman: Add additional initialization sequences for ST7789 displays, with the intention to get 'm working + * on some devices that seem to use peculiarly configured hardware like LiliGO TTGO T-Display (16MB flash), + * and possibly the T-Display S3 + * By default only enabled on ESP32, unless -D ST7789_EXTRA_INIT=1 is defined, f.e. via the build script + */ + +#ifndef ST7789_EXTRA_INIT // Enable setting from 'outside', like Platformio.ini +# ifdef ESP8266 +# define ST7789_EXTRA_INIT 0 +# endif // ifdef ESP8266 +# ifdef ESP32 +# define ST7789_EXTRA_INIT 1 +# endif // ifdef ESP32 +#endif + /// Subclass of ST77XX type display for ST7789 TFT Driver class Adafruit_ST7789 : public Adafruit_ST77xx { public: @@ -14,7 +30,7 @@ class Adafruit_ST7789 : public Adafruit_ST77xx { #endif // end !ESP8266 void setRotation(uint8_t m); - void init(uint16_t width, uint16_t height, uint8_t spiMode = SPI_MODE0); + void init(uint16_t width, uint16_t height, uint8_t spiMode = SPI_MODE0, uint8_t init_seq = 0u); protected: uint8_t _colstart2 = 0, ///< Offset from the right @@ -23,6 +39,7 @@ class Adafruit_ST7789 : public Adafruit_ST77xx { private: uint16_t windowWidth; uint16_t windowHeight; + uint8_t _init_seq = 0u; }; #endif // _ADAFRUIT_ST7789H_ diff --git a/lib/Adafruit_ST77xx/Adafruit_ST77xx.h b/lib/Adafruit_ST77xx/Adafruit_ST77xx.h index fcf0c6f6e8..9a299b51f9 100644 --- a/lib/Adafruit_ST77xx/Adafruit_ST77xx.h +++ b/lib/Adafruit_ST77xx/Adafruit_ST77xx.h @@ -33,8 +33,10 @@ #define ST7735_TFTWIDTH_128 128 // for 1.44 and mini #define ST7735_TFTWIDTH_80 80 // for mini +#define ST7735_TFTWIDTH_135 135 #define ST7735_TFTHEIGHT_128 128 // for 1.44" display #define ST7735_TFTHEIGHT_160 160 // for 1.8" and mini display +#define ST7735_TFTHEIGHT_240 240 #define ST_CMD_DELAY 0x80 // special signifier for command lists @@ -63,11 +65,48 @@ #define ST77XX_MADCTL 0x36 #define ST77XX_COLMOD 0x3A +#define ST77XX_RAMCTRL 0xB0 // RAM control +#define ST77XX_RGBCTRL 0xB1 // RGB control +#define ST77XX_PORCTRL 0xB2 // Porch control +#define ST77XX_FRCTRL1 0xB3 // Frame rate control +#define ST77XX_PARCTRL 0xB5 // Partial mode control +#define ST77XX_GCTRL 0xB7 // Gate control +#define ST77XX_GTADJ 0xB8 // Gate on timing adjustment +#define ST77XX_DGMEN 0xBA // Digital gamma enable +#define ST77XX_VCOMS 0xBB // VCOMS setting +#define ST77XX_LCMCTRL 0xC0 // LCM control +#define ST77XX_IDSET 0xC1 // ID setting +#define ST77XX_VDVVRHEN 0xC2 // VDV and VRH command enable +#define ST77XX_VRHS 0xC3 // VRH set +#define ST77XX_VDVSET 0xC4 // VDV setting +#define ST77XX_VCMOFSET 0xC5 // VCOMS offset set +#define ST77XX_FRCTR2 0xC6 // FR Control 2 +#define ST77XX_CABCCTRL 0xC7 // CABC control +#define ST77XX_REGSEL1 0xC8 // Register value section 1 +#define ST77XX_REGSEL2 0xCA // Register value section 2 +#define ST77XX_PWMFRSEL 0xCC // PWM frequency selection +#define ST77XX_PWCTRL1 0xD0 // Power control 1 +#define ST77XX_VAPVANEN 0xD2 // Enable VAP/VAN signal output +#define ST77XX_CMD2EN 0xDF // Command 2 enable +#define ST77XX_PVGAMCTRL 0xE0 // Positive voltage gamma control +#define ST77XX_NVGAMCTRL 0xE1 // Negative voltage gamma control +#define ST77XX_DGMLUTR 0xE2 // Digital gamma look-up table for red +#define ST77XX_DGMLUTB 0xE3 // Digital gamma look-up table for blue +#define ST77XX_GATECTRL 0xE4 // Gate control +#define ST77XX_SPI2EN 0xE7 // SPI2 enable +#define ST77XX_PWCTRL2 0xE8 // Power control 2 +#define ST77XX_EQCTRL 0xE9 // Equalize time control +#define ST77XX_PROMCTRL 0xEC // Program control +#define ST77XX_PROMEN 0xFA // Program mode enable +#define ST77XX_NVMSET 0xFC // NVM setting +#define ST77XX_PROMACT 0xFE // Program action + #define ST77XX_MADCTL_MY 0x80 #define ST77XX_MADCTL_MX 0x40 #define ST77XX_MADCTL_MV 0x20 #define ST77XX_MADCTL_ML 0x10 #define ST77XX_MADCTL_RGB 0x00 +#define ST77XX_MADCTL_BGR 0x08 #define ST77XX_RDID1 0xDA #define ST77XX_RDID2 0xDB diff --git a/src/_P116_ST77xx.ino b/src/_P116_ST77xx.ino index ef010cd917..ac85828e88 100644 --- a/src/_P116_ST77xx.ino +++ b/src/_P116_ST77xx.ino @@ -8,6 +8,13 @@ // History: +// 2024-03-17 tonhuisman: Add support for another alternative initialization for ST7735 displays, as the display controller +// used on the LilyGO TTGO T-Display (16 MB) seems to be a ST7735, despite being documented as ST7789 +// By default (also) only enabled on ESP32 builds +// Disabled the ST7789 alternatives for now, as that's not verified on any hardware +// 2024-03-09 tonhuisman: Add support for alternative initialization sequences for ST7789 displays, like used on +// some LilyGO models like the TTGO T-Display (16 MB Flash), and possibly the T-Display S3 +// By default only enabled on ESP32 builds // 2023-02-27 tonhuisman: Implement support for getting config values, see AdafruitGFX_Helper.h changelog for details // 2022-07-06 tonhuisman: Add support for ST7735sv M5Stack StickC (Inverted colors) // 2021-11-16 tonhuisman: P116: Change state from Development to Testing @@ -80,16 +87,16 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) case PLUGIN_WEBFORM_SHOW_GPIO_DESCR: { - const char* separator = event->String1.c_str(); // contains the NewLine sequence + const char *separator = event->String1.c_str(); // contains the NewLine sequence string = strformat( F("CS: %s%sDC: %s%s RES: %s%sBtn: %s%sBckl: : %s"), - formatGpioLabel(PIN(0), false).c_str(), + formatGpioLabel(PIN(0), false).c_str(), separator, - formatGpioLabel(PIN(1), false).c_str(), + formatGpioLabel(PIN(1), false).c_str(), separator, - formatGpioLabel(PIN(2), false).c_str(), + formatGpioLabel(PIN(2), false).c_str(), separator, - formatGpioLabel(P116_CONFIG_BUTTON_PIN, false).c_str(), + formatGpioLabel(P116_CONFIG_BUTTON_PIN, false).c_str(), separator, formatGpioLabel(P116_CONFIG_BACKLIGHT_PIN, false).c_str()); success = true; @@ -142,10 +149,18 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) ST77xx_type_toString(ST77xx_type_e::ST7735s_128x160), ST77xx_type_toString(ST77xx_type_e::ST7735s_80x160), ST77xx_type_toString(ST77xx_type_e::ST7735s_80x160_M5), + # if P116_EXTRA_ST7735 + ST77xx_type_toString(ST77xx_type_e::ST7735s_135x240), + # endif // if P116_EXTRA_ST7735 ST77xx_type_toString(ST77xx_type_e::ST7789vw_240x320), ST77xx_type_toString(ST77xx_type_e::ST7789vw_240x240), ST77xx_type_toString(ST77xx_type_e::ST7789vw_240x280), ST77xx_type_toString(ST77xx_type_e::ST7789vw_135x240), + # if P116_EXTRA_ST7789 + ST77xx_type_toString(ST77xx_type_e::ST7789vw1_135x240), + ST77xx_type_toString(ST77xx_type_e::ST7789vw2_135x240), + ST77xx_type_toString(ST77xx_type_e::ST7789vw3_135x240), + # endif // if P116_EXTRA_ST7789 ST77xx_type_toString(ST77xx_type_e::ST7796s_320x480) }; const int optionValues4[] = { @@ -153,13 +168,21 @@ boolean Plugin_116(uint8_t function, struct EventStruct *event, String& string) static_cast(ST77xx_type_e::ST7735s_128x160), static_cast(ST77xx_type_e::ST7735s_80x160), static_cast(ST77xx_type_e::ST7735s_80x160_M5), + # if P116_EXTRA_ST7735 + static_cast(ST77xx_type_e::ST7735s_135x240), + # endif // if P116_EXTRA_ST7735 static_cast(ST77xx_type_e::ST7789vw_240x320), static_cast(ST77xx_type_e::ST7789vw_240x240), static_cast(ST77xx_type_e::ST7789vw_240x280), static_cast(ST77xx_type_e::ST7789vw_135x240), + # if P116_EXTRA_ST7789 + static_cast(ST77xx_type_e::ST7789vw1_135x240), + static_cast(ST77xx_type_e::ST7789vw2_135x240), + static_cast(ST77xx_type_e::ST7789vw3_135x240), + # endif // if P116_EXTRA_ST7789 static_cast(ST77xx_type_e::ST7796s_320x480) }; - constexpr int optCount4 = sizeof(optionValues4) / sizeof(optionValues4[0]); + constexpr int optCount4 = NR_ELEMENTS(optionValues4); addFormSelector(F("TFT display model"), F("type"), optCount4, diff --git a/src/src/PluginStructs/P116_data_struct.cpp b/src/src/PluginStructs/P116_data_struct.cpp index 3e88fcf499..1aa994c334 100644 --- a/src/src/PluginStructs/P116_data_struct.cpp +++ b/src/src/PluginStructs/P116_data_struct.cpp @@ -11,10 +11,18 @@ const __FlashStringHelper* ST77xx_type_toString(const ST77xx_type_e& device) { case ST77xx_type_e::ST7735s_128x160: return F("ST7735 128 x 160px"); case ST77xx_type_e::ST7735s_80x160: return F("ST7735 80 x 160px"); case ST77xx_type_e::ST7735s_80x160_M5: return F("ST7735 80 x 160px (Color inverted)"); + # if P116_EXTRA_ST7735 + case ST77xx_type_e::ST7735s_135x240: return F("ST7735 135 x 240px"); + # endif // if P116_EXTRA_ST7735 case ST77xx_type_e::ST7789vw_240x320: return F("ST7789 240 x 320px"); case ST77xx_type_e::ST7789vw_240x240: return F("ST7789 240 x 240px"); case ST77xx_type_e::ST7789vw_240x280: return F("ST7789 240 x 280px"); case ST77xx_type_e::ST7789vw_135x240: return F("ST7789 135 x 240px"); + # if P116_EXTRA_ST7789 + case ST77xx_type_e::ST7789vw1_135x240: return F("ST7789 135 x 240px (alt1)"); + case ST77xx_type_e::ST7789vw2_135x240: return F("ST7789 135 x 240px (alt2)"); + case ST77xx_type_e::ST7789vw3_135x240: return F("ST7789 135 x 240px (alt3)"); + # endif // if P116_EXTRA_ST7789 case ST77xx_type_e::ST7796s_320x480: return F("ST7796 320 x 480px"); } return F("Unsupported type!"); @@ -53,6 +61,14 @@ void ST77xx_type_toResolution(const ST77xx_type_e& device, y = 280; break; case ST77xx_type_e::ST7789vw_135x240: + # if P116_EXTRA_ST7789 + case ST77xx_type_e::ST7789vw1_135x240: + case ST77xx_type_e::ST7789vw2_135x240: + case ST77xx_type_e::ST7789vw3_135x240: + # endif // if P116_EXTRA_ST7789 + # if P116_EXTRA_ST7735 + case ST77xx_type_e::ST7735s_135x240: + # endif // if P116_EXTRA_ST7735 x = 135; y = 240; break; @@ -144,7 +160,16 @@ bool P116_data_struct::plugin_init(struct EventStruct *event) { initRoptions = INITR_GREENTAB160x80; // 80x160px ST7735sv, inverted (M5Stack StickC) } - // fall through + // fall through + # if P116_EXTRA_ST7735 + case ST77xx_type_e::ST7735s_135x240: + + if (initRoptions == 0xFF) { + initRoptions = INITR_BLACKTAB135x240; // 135x240px + } + + // fall through + # endif // if P116_EXTRA_ST7735 case ST77xx_type_e::ST7735s_80x160: { if (initRoptions == 0xFF) { @@ -163,11 +188,28 @@ bool P116_data_struct::plugin_init(struct EventStruct *event) { case ST77xx_type_e::ST7789vw_240x240: case ST77xx_type_e::ST7789vw_240x280: case ST77xx_type_e::ST7789vw_135x240: + # if P116_EXTRA_ST7789 + case ST77xx_type_e::ST7789vw1_135x240: + case ST77xx_type_e::ST7789vw2_135x240: + case ST77xx_type_e::ST7789vw3_135x240: + # endif // if P116_EXTRA_ST7789 { st7789 = new (std::nothrow) Adafruit_ST7789(PIN(0), PIN(1), PIN(2)); if (nullptr != st7789) { - st7789->init(_xpix, _ypix, SPI_MODE2); + uint8_t init_seq = 0; // Default/original initialisation + + # if P116_EXTRA_ST7789 + + if (ST77xx_type_e::ST7789vw1_135x240 == _device) { + init_seq = 1; + } else if (ST77xx_type_e::ST7789vw2_135x240 == _device) { + init_seq = 2; + } else if (ST77xx_type_e::ST7789vw3_135x240 == _device) { + init_seq = 3; + } + # endif // if P116_EXTRA_ST7789 + st7789->init(_xpix, _ypix, SPI_MODE2, init_seq); st77xx = st7789; } break; @@ -330,7 +372,7 @@ bool P116_data_struct::plugin_read(struct EventStruct *event) { gfxHelper->setColumnRowMode(bitRead(P116_CONFIG_FLAGS, P116_CONFIG_FLAG_USE_COL_ROW)); // Restore column mode int16_t curX, curY; gfxHelper->getCursorXY(curX, curY); // Get current X and Y coordinates, - UserVar.setFloat(event->TaskIndex, 0, curX); // and put into Values + UserVar.setFloat(event->TaskIndex, 0, curX); // and put into Values UserVar.setFloat(event->TaskIndex, 1, curY); } } @@ -385,8 +427,8 @@ bool P116_data_struct::plugin_write(struct EventStruct *event, st77xx->fillScreen(_bgcolor); } else if (equals(arg1, F("backlight"))) { - String arg2 = parseString(string, 3); - int32_t nArg2{}; + String arg2 = parseString(string, 3); + int32_t nArg2{}; if ((P116_CONFIG_BACKLIGHT_PIN != -1) && // All is valid? validIntFromString(arg2, nArg2) && diff --git a/src/src/PluginStructs/P116_data_struct.h b/src/src/PluginStructs/P116_data_struct.h index 2144ebd8ff..675102456e 100644 --- a/src/src/PluginStructs/P116_data_struct.h +++ b/src/src/PluginStructs/P116_data_struct.h @@ -4,11 +4,30 @@ #include "../../_Plugin_Helper.h" #ifdef USES_P116 -# include // include Adafruit graphics library -# include // include Adafruit ST77xx TFT library -# include // include Adafruit ST7735 TFT library -# include // include Adafruit ST7789 TFT library -# include // include Adafruit ST7796 TFT library +# include // include Adafruit graphics library +# include // include Adafruit ST77xx TFT library +# include // include Adafruit ST7735 TFT library +# include // include Adafruit ST7789 TFT library +# include // include Adafruit ST7796 TFT library + +# if defined(ST7789_EXTRA_INIT) && !ST7789_EXTRA_INIT +# define P116_EXTRA_ST7789 0 // This will get disabled for ESP8266 in Adafruit_ST7789.h +# endif // if defined(ST7789_EXTRA_INIT) && !ST7789_EXTRA_INIT +# if defined(LIMIT_BUILD_SIZE) and !defined(P116_EXTRA_ST7789) +# define P116_EXTRA_ST7789 0 +# endif // if defined(LIMIT_BUILD_SIZE) and !defined(P116_EXTRA_ST7789) +# ifndef P116_EXTRA_ST7789 +# define P116_EXTRA_ST7789 0 // Disabled by default (not verified on any hardware yet) +# endif // ifndef P116_EXTRA_ST7789 +# if defined(ST7735_EXTRA_INIT) && !ST7735_EXTRA_INIT +# define P116_EXTRA_ST7735 0 // This will get disabled for ESP8266 in Adafruit_ST7735.h +# endif // if defined(ST7735_EXTRA_INIT) && !ST7735_EXTRA_INIT +# if defined(LIMIT_BUILD_SIZE) and !defined(P116_EXTRA_ST7789) +# define P116_EXTRA_ST7735 0 +# endif // if defined(LIMIT_BUILD_SIZE) and !defined(P116_EXTRA_ST7735) +# ifndef P116_EXTRA_ST7735 +# define P116_EXTRA_ST7735 1 +# endif // ifndef P116_EXTRA_ST7735 # include "../Helpers/AdafruitGFX_helper.h" // Use Adafruit graphics helper object # include "../CustomBuild/StorageLayout.h" @@ -74,6 +93,14 @@ enum class ST77xx_type_e : uint8_t { ST7789vw_135x240 = 6u, ST7796s_320x480 = 7u, ST7735s_80x160_M5 = 8u, + # if P116_EXTRA_ST7789 + ST7789vw1_135x240 = 9u, + ST7789vw2_135x240 = 10u, + ST7789vw3_135x240 = 11u, + # endif // if P116_EXTRA_ST7789 + # if P116_EXTRA_ST7735 + ST7735s_135x240 = 12u, + # endif // if P116_EXTRA_ST7735 }; enum class P116_CommandTrigger : uint8_t {