lovyan03 / LovyanGFX

SPI LCD graphics library for ESP32 (ESP-IDF/ArduinoESP32) / ESP8266 (ArduinoESP8266) / SAMD51(Seeed ArduinoSAMD51)
Other
1.02k stars 187 forks source link

Lilygo AMOLED series #547

Open Starbane opened 1 month ago

Starbane commented 1 month ago

Carefully written requests are more likely to be given priority. 丁寧に記述された要望は優先して対応される可能性が高くなります。 Lilygo have a fantastic lineup of beautiful AMOLED displayed ESP32-S3 with and without touch. They use display chip that is not supported by TFT_eSPI or AarduinoGFX, AdafruitGFX or LovyanGFX.

There is support for bit banging a TFT_eSprite to the display and that's it. It is slower than needed. All tree boards use QSPI and are fairly quick. With native support in LovyanGFX they would be super fast!.

Their software bundle is pretty good but restrictive since Lilygo more or less force you to use their display and touch library SensorLib and the implementations does not play nice with other implementations of SPI master and I2C/I2S.

Support for LovyanGFX on these boards would greatly increase the usability of the boards as well as be a good addition to the display chips supported by LovyanGFX

Device Name (デバイスの名称・型番等)

Lilygo AMOLED 1.47 inch using display chip SH8501 Lilygo AMOLED 1.91 inch using display chip RM67162 Lilygo AMOLED 2.41 inch using display chip RM690B0

URL of Device Specifications document (仕様書等のURL)

The documentation for the three boards can be found here on GitHUB:

https://github.com/Xinyuan-LilyGO/LilyGo-AMOLED-Series.git

URL of the store where we can purchase (商品を購入できるURL)

https://www.lilygo.cc/products/t-display-s3-amoled (various models of 1.47 and 1.91 inch displays) https://www.lilygo.cc/products/t4-s3 the 2.41 inch variant.

FeralAI commented 1 month ago

I've done a bit of digging to see what it would take to support these modules, and the main piece missing right now is support for Quad SPI buses. All 3 of these displays use QSPI. If nobody else takes this on, it's likely something I'll be looking into very soon for one of my current projects.

I have the AMOLED Lite (1.47") and the T3 AMOLED Non-touch (1.91") versions in hand, and waiting on the the T3 AMOLED Touch (1.91") and T4 S3 (2.41") to ship from Lilygo.

Starbane commented 1 month ago

I might be new to GitHub customs but this issue was a "Device support request" and #549 was a feature request so why close them? how would you differentiate between them?

Starbane commented 1 month ago

I've done a bit of digging to see what it would take to support these modules, and the main piece missing right now is support for Quad SPI buses. All 3 of these displays use QSPI. If nobody else takes this on, it's likely something I'll be looking into very soon for one of my current projects.

I have the AMOLED Lite (1.47") and the T3 AMOLED Non-touch (1.91") versions in hand, and waiting on the the T3 AMOLED Touch (1.91") and T4 S3 (2.41") to ship from Lilygo.

I have a working embryo to QSPI driver. @nikthefix also has one very similar working over at thread https://github.com/Xinyuan-LilyGO/T-Display-S3-AMOLED/issues/2#issue-1680748130

Starbane commented 1 month ago

@FeralAI you wanna collaborate on the QSPI integration into LovyanGFX?

nikthefix commented 1 month ago

@Starbane Arduino_GFX (moononournation) recently added QSPI support in his library. His PDQ demo works well on the Lilygo T-Display-Amoled-1.91"

Not sure if he went for the 'frame buffer' approach or if there's tighter integration with the GFX components. I'm still working on anti-tearing in my 'stand-alone' driver but almost finished now. Give me a shout if you want to compare notes.

nik

moononournation commented 1 month ago

yes, the canvas class is some sort of framebuffer

nikthefix commented 1 month ago

@moononournation Yes indeed. I quite like the idea of detaching the GFX code from the display / bus drivers. I think it's simpler - like LVGL. When the ESP32-P4 arrives we'll have all the MIPI-DSI displays too! Modularity will help there I'm sure.

nik

Starbane commented 1 month ago

I got my T4-S3 in the mail today and it broke my Bus/Driver but it should not since it is command compatible.

I got a set pixel function working on the 1.91 inch AMOLED but it is slow, 12 pixels/ms. It is mainly due to the lack of drawing capabilities of the chip. Not much more than memory write to use. and it is sequential over the address window :(.

Here is a code snippet from my lib for you to ponder, specially if it helps getting support on LovyanGFX :) I have a GitLab rep but will not publish it here for obvious reasons.

void RM67162::drawPixel(const int16_t x, const int16_t y, uint16_t color) {
        setAddrWindow(x,y,x,y);

        spi_transaction_ext_t t;
        memset(&t, 0, sizeof(t));
        t.base.flags = SPI_TRANS_MODE_QIO;
        t.base.cmd = 0x32 ;
        t.base.addr = 0x002C00;
        t.base.tx_buffer = &color;
        t.base.length = 16;
        _qspi.setCS();
        _qspi.pollingTransaction((spi_transaction_t *)&t);
        _qspi.clrCS();
    }
_qspi is my bus class I am willing to collab and give access to my code on request only!
nikthefix commented 1 month ago

@Starbane drawPixel() is discrete and slow. Try pushColors() for a continuous write to GRAM from a *buffer. ESP frame buffer needs to be in PSRAM for capacity.

nik

nikthefix commented 1 month ago

@Starbane Here's an example for the 1.91" using just raw pushColors() - no GFX library: Lilygo_amoled_191_raw_push.zip

Tested with ESP_Arduino Alpha 3.

Notes:

GPIO 38 needs to be OUTPUT HIGH for the touch version of the Lilygo 1.91" board (display_enable).

The drawing capabilities of the chip are never going to be a problem. The S3 is more than capable of rendering a full screen at 50fps in the case of the 1.91" display used here. It's just a matter of optimization. I'm working on it! :)

https://github.com/Xinyuan-LilyGO/T-Display-S3-AMOLED/issues/2#issuecomment-2028337383

The init codes for the T3-Amoled display are compatible with the T4 but are not optimal. Check the datasheet for the T4 display to see the differences.

nik

Starbane commented 1 month ago

@Starbane Here's an example for the 1.91" using just raw pushColors() - no GFX library: Lilygo_amoled_191_raw_push.zip

Tested with ESP_Arduino Alpha 3.

Notes:

GPIO 38 needs to be OUTPUT HIGH for the touch version of the Lilygo 1.91" board (display_enable).

The drawing capabilities of the chip are never going to be a problem. The S3 is more than capable of rendering a full screen at 50fps in the case of the 1.91" display used here. It's just a matter of optimization. I'm working on it! :)

Xinyuan-LilyGO/T-Display-S3-AMOLED#2 (comment)

The init codes for the T3-Amoled display are compatible with the T4 but are not optimal. Check the datasheet for the T4 display to see the differences.

nik

Well I can't get the T4 to even turn on the display I will paste in the output from my boot and perhaps if @nikthefix or @FeralAI can spot something wrong?! Please remember that it is a T4 not the 1.91 inch. 1.91 actually works with it´s init sequence.

16:46:27.077 > --- lib/Devices/src/Bus/QSPI.cpp (75): configure D0 pin:   14
16:46:27.077 > --- lib/Devices/src/Bus/QSPI.cpp (76): configure D1 pin:   10
16:46:27.077 > --- lib/Devices/src/Bus/QSPI.cpp (77): configure D2 pin:   16
16:46:27.078 > --- lib/Devices/src/Bus/QSPI.cpp (78): configure D3 pin:   12
16:46:27.078 > --- lib/Devices/src/Bus/QSPI.cpp (79): configure D4 pin:   -1
16:46:27.078 > --- lib/Devices/src/Bus/QSPI.cpp (80): configure D5 pin:   -1
16:46:27.078 > --- lib/Devices/src/Bus/QSPI.cpp (81): configure D6 pin:   -1
16:46:27.079 > --- lib/Devices/src/Bus/QSPI.cpp (82): configure D7 pin:   -1
16:46:27.079 > --- lib/Devices/src/Bus/QSPI.cpp (83): configure SCK pin:  15
16:46:27.079 > --- lib/Devices/src/Bus/QSPI.cpp (84): configure RST pin:  13
16:46:27.079 > --- lib/Devices/src/Bus/QSPI.cpp (85): configure CS pin:   11
16:46:27.080 > --- lib/Devices/src/Bus/QSPI.cpp (86): configure DC pin:   -1
16:46:27.080 > --- lib/Devices/src/Bus/QSPI.cpp (87): configure TE pin:   -1
16:46:27.080 > --- lib/Devices/src/Bus/QSPI.cpp (88): configure PMIC pin: 9
16:46:27.081 > --- lib/Devices/src/Bus/QSPI.cpp (89): configure Address bits:    24
16:46:27.081 > --- lib/Devices/src/Bus/QSPI.cpp (90): configure Command bits:    8
16:46:27.081 > --- lib/Devices/src/Bus/QSPI.cpp (91): configure Max Trans. Size: 262152
16:46:27.081 > --- lib/Devices/src/Bus/QSPI.cpp (92): configure Bus Speed:       36000000
16:46:27.082 > --- lib/Devices/src/Bus/QSPI.cpp (93): configure Bus Mode:        0
16:46:27.082 > --- lib/Devices/src/Bus/QSPI.cpp (94): configure Bus Queue Size:  17
16:46:27.082 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = fe00, data =  0x20, length = 1
16:46:27.083 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 2600, data =  0xa, length = 1
16:46:27.083 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 2400, data =  0x80, length = 1
16:46:27.084 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 5a00, data =  0x51, length = 1
16:46:27.084 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 5b00, data =  0x2e, length = 1
16:46:27.085 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = fe00, data =  0x0, length = 1
16:46:27.085 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 3a00, data =  0x55, length = 1
16:46:27.086 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = c200, data =  0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x21 0x0 0x0 0x0 0x0 0x35 0x0 0x0 0x0 0x0 0x0 0x0 0x0, length = 21
16:46:27.097 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 3500, data =  0x0, length = 1
16:46:27.097 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 5100, data =  0x0, length = 1
16:46:27.098 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 1100, data =  0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x80 0x0 0x0 0x0 0x0 0x29 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0 0x0 0x51 0x0 0x0 0xff 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x1 0x0 0x0 0x0 0x3f 0xfe 0x6 0x3c 0x8 0x8a 0x0 0x42 0x0 0x0 0x0 0x0 0xf4 0x74 0xc9 0x3f 0xd 0x0 0x0 0x0 0x39 0x9d 0x0 0x82 0xe0 0xbd 0xce 0x3f 0xd0 0x74 0xc9 0x3f 0xea 0xbf 0xf1 0xfe 0xff 0xff 0xff 0xff 0x30 0xbc 0xce 0x3f 0x1c 0x0 0x0 0x0, length = 80
16:46:27.220 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 2900, data =  0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x20 0x0 0x0 0x0 0x0 0x51 0x0 0x0 0xff 0x0 0x0 0x0, length = 20
16:46:27.231 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 5100, data =  0xff, length = 1
16:46:27.231 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 3600, data =  0x60, length = 1
16:46:27.528 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 3600, data =  0x0, length = 1
16:46:27.560 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 2a00, data =  0x0 0x0 0x2 0x57, length = 4
16:46:27.560 >     lib/Devices/src/Display/RM67162.cpp (124): sendCommand addr = 2b00, data =  0x0 0x0 0x1 0xc1, length = 4

I am assuming that my pushColors are ok since it works on the 1.91. My setup/loop is so plain:

#include <Arduino.h>

#include <LilyGo/AMOLED_2.41_TOUCH.hpp>
#include <TFT_eSPI.h>

Display::Amoled display;
TFT_eSPI tft;
TFT_eSprite screen(&tft);

void setup() {
#ifdef USE_LOGGING
    Serial.begin(115200);

    logDebug("Waiting for Serial communication to establish...");
    delay(2000);
#endif

    display.begin();
    tft.begin();

    display.setRotation(1);

    screen.createSprite(display.width(), display.height());

    screen.fillSprite(TFT_BLUE);

    display.pushSprite(0,0,);
}

void loop(void) {
    delay(1000);
}
nikthefix commented 1 month ago

@Starbane For the T4, GPIO pin 9 needs to be OUTPUT HIGH for display enable.

Here's the same raw pushColors sketch modified for the T4:

If you're gonna be rolling your own drivers for the Lilygo boards then you must look at the board specific hardware schematics as the pinouts are possibly different - definitely in this case.

t4_spectrum_raw.zip

nik

Starbane commented 1 month ago

I do that as part of the initialization:

        if (_config.pmicen != -1) {
            if(digitalPinCanOutput(_config.pmicen)) {
                pinMode(_config.pmicen, OUTPUT);
                digitalWrite(_config.pmicen, HIGH);
            } else {
                logError("QSPI - Failed to initialize bus, PMICEn not a output pin");
                return DEVICE_BUS_CONFIG_ERROR;
            }
        }

So it has to be something different.

nikthefix commented 1 month ago

@Starbane Does my test code work?

Starbane commented 1 month ago

Yes it works. So something is off in my code. I suspect my QSPI bus driver is not working. but the thing is that it is working on the 1.91 inch board but not on the 2.41 inch board. That have me baffled!

Starbane commented 1 month ago

If I include TFT_eSPI into you example it stops working just like mine code. So the line

#include <TFT_eSPI.h>

breaks your example for me

Starbane commented 1 month ago

It seems that it is the order of the including that is the problem. As well as if I do tft.begin() on the TFT_eSPI.

I managed to get it to work but with a strange offset on the screen. According to my testing I have a screen that is 585 x 445 pixels since this code produces a one line box around the screen:

Display::Amoled display;
TFT_eSPI tft;
TFT_eSprite screen(&tft);

void setup() {
    display.begin();
//    tft.begin();

    screen.createSprite(display.width(), display.height());

    screen.fillSprite(TFT_WHITE);
    screen.fillRect(2,15,display.width()-4,display.height()-16, TFT_BLACK);

    display.pushSprite(0,0,screen);
}

When I try TFT_eSPI with your code I get the same results, the display is still 585x445 not as advertised 600x450 Anyone wanna try to educate me? (hint hint @lewisxhe)?

nikthefix commented 1 month ago

@Starbane Check that your TFT_eSPI User_Setup.h display option is the default ILI9341_DRIVER. You'd think it shouldn't make a difference but I've found certain 'overrides' for each display profile which may explain why the #include order is critical in your experiments.

Also, if you look at the Lilygo supplied example files (buried deep in the display driver) you'll see that the T4 display has a native 16px offset requirement in the y-axis. This is one of the critical differences between the 1.91 and 2.41 displays.

Here's a conversion of Volos' T4 demo to use Alpha 3 and my scaled down driver with TFT_eSPI. It includes the offset. All credit to Volos for this amazing UI: https://www.youtube.com/watch?v=XaxYSqeFJ6w&t=50s

There's no touch function in this version of the demo:

nik coolUI.zip

github-actions[bot] commented 7 hours ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.