ESP32-S3 LCD Interface??......... - Page 1
Forum section: electronics / projects

author: Smokey
author_rank: Super Contributor
timestamp: October 06, 2023, 05:38:20 am
content: It looks like the ESP32-S3 has a built in LCD interface that supports "8-bit ~16-bit parallel RGB, I8080, and MOTO6800 interfaces".Module Datasheet =https://www.espressif.com/sites/default/files/documentation/esp32-s3-wroom-1_wroom-1u_datasheet_en.pdfChip Datasheet =https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdfTech Reference Manual =https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdfHardware Design Guide =https://www.espressif.com/sites/default/files/documentation/esp32-s3_hardware_design_guidelines_en.pdfThat interface, coupled with the PSRAM up to 8MB for a frame buffer, sounds like it would make an interesting LCD display driver up to decent sizes for a seriously low price compared to alternatives.I'm looking to give this a shot, but I have two concerns due to the minimal information out there:1) Software/lib support.2) Hardware pinout and configuration.I feel like the main reason to use these parts like ESP32 is typically due to the community projects as examples, but I'm having a hard time finding anyone that is using the LCD controller on these things now. If the only software support is for SPI displays that doesn't efficiently use the PSRAM for a framebuffer, then it's not worth playing with this now and I'll use a SSD1963 or something instead.I've also been bit by the hardware IO multiplexer pin mapping/configuration on an earlier ESP32. Having a multiplexer is great and all, but there are some important exceptions that I feel like aren't' clearly enough noted. Input only digital pins (should have seen that in the table, my bad)... Unusable ADC channel when Wifi is enabled (why?)... Power up glitches only only some pins(fun!) ... etc...So the question of the day...Has anyone used the ESP32-S3 LCD controller to directly drive an RGB lcd, and even better be able to point me to a working schematic example with the connections between the thing and an actual display, and even better-er with a working software repo?

author: Smokey
author_rank: Super Contributor
timestamp: October 06, 2023, 10:20:20 pm
content: Here is another thing...Some of the libraries for open source stuff essentially hard code certain pins for whatever function they are doing. I get why they do this, because they were designed to work with some specific hardware shield, which is the only thing out there that does that function so why make changing the pinout easy to do in software if it's something no one will ever need to do because they are all using the same hardware boards?The problem with this is that instead of just using the library or whatever, I need to fork it to make a core change to where ever the pin definitions are. That sucks.So if possible it make sense to just use the pins that the most popular shields use.... but I can't find any RGB shields at the moment for this particular project.

author: Smokey
author_rank: Super Contributor
timestamp: October 10, 2023, 08:05:16 am
content: Software example with pin usage:https://github.com/espressif/esp-idf/blob/272b4091f1f1ff169c84a4ee6b67ded4a005a8a7/examples/peripherals/lcd/rgb_panel/main/rgb_lcd_example_main.c

author: Smokey
author_rank: Super Contributor
timestamp: December 08, 2023, 09:00:39 pm
content: New question.I have an RGB LCD controller that supports both DE and SYNC modes, and it's selectable with a hardware jumper on the PCB. That is all good, but the question becomes:How do you tell the esp32-s3 to operate in either DE or SYNC modes?If you check out the example configuration linked above, there are hardware pin options for both the DE and the SYNC pins but no option for what actual mode the processor will use.What am I missing here? What sets the DE or SYNC modes in software? Are both modes even supported by the esp32-s3?

author: zapta
author_rank: Super Contributor
timestamp: December 09, 2023, 06:19:48 am
content: LVGL is a popular open source package to implement advanced user interfaces on embbeded systems and it allows you to plug in the function that transfers portions of the frame buffer to the display. In other words, it's not SPI or I2C specific and you can plug any interface you want.https://docs.lvgl.io/latest/en/html/overview/drawing.html#mechanism-of-screen-refreshingI used it for example with RP2040 for fast 16 bit parallel frame buffer using the programable PIO logic.https://twitter.com/DustinWattsNL/status/1430049782379294738

author: Smokey
author_rank: Super Contributor
timestamp: December 09, 2023, 07:11:16 am
content: The design requirements for this particular project are such that we need to use the 16Bit RGB interface (so not SPI, or I8080). I think we are going to try to use the LovyanGFX library which has support for both the ESP32-S3 and RGB, but I'm still getting hung up on the hardware interface and hardware configuration.Because of the size of this particular display, I think it makes more sense to use SYNC mode than DE mode, but as I said it's not obvious how to force the ESP32 to do that.

author: Fire Doger
author_rank: Regular Contributor
timestamp: December 09, 2023, 04:54:23 pm
content: Set de pin number to -1As you can see in esp_lcd_panel_rgb.c there is this if inside lcd_rgb_panel_configure_gpioCode:if (panel_config->de_gpio_num < 0) {// Hsync and Vsync are required in HV modevalid_gpio = valid_gpio && (panel_config->hsync_gpio_num >= 0) && (panel_config->vsync_gpio_num >= 0);}You can trace it further from there to see how it is configured inside the library (component)It worked on me both with sync and de up to 800x480 with lvglI have used this devboardhttps://www.aliexpress.com/item/1005004952694042.htmlI didn't like that usb pins that can be used for jtag are used in capacitive ICRecently I found and an other board that if I remembered correctly usb pins are freehttps://www.makerfabs.com/esp32-s3-parallel-tft-with-touch-7-inch.html

author: Smokey
author_rank: Super Contributor
timestamp: August 31, 2025, 04:08:09 am
content: I'm back on this project again (back from the dead). I got the 800x320 displaysort ofworking with my custom ESP32-S3 board.I can get it to work up to a pixel clock of about 24MHz, but after that I get progressively worse tearing and screen distortion as the pixel clock goes up. This is true for both DE and SYNC modes on the ESP32, without much difference to the effects on either setting.Here is an example of the artifacts at 30MHz pixel clock. This should be a red background with a pink circle in the middle:If I run slower than 24MHz DCLK, the display appears clear but the update rate is clearly visible and you can see the scan line go from top to bottom as the screen writes. This makes smooth animations really hard to watch.LCD Driver =https://www.orientdisplay.com/wp-content/uploads/2021/03/EK9713.pdfESP32-S3 =https://www.espressif.com/sites/default/files/documentation/esp32-s3_datasheet_en.pdf=https://www.espressif.com/sites/default/files/documentation/esp32-s3_technical_reference_manual_en.pdfThe driver is supposed to support up to a 50MHz DCLK, and the esp32-S3 is supposed to support up to 40MHz.I've looked at the clock and pixel data lines on a scope at the LCD end of the ribbon cable and they look pretty clean with good rise/fall edges and without excessive ringing. They all run on an inner layer of the PCB with full ground plane coverage.I didn't length match, but all the parallel RGB data traces and pixel clock line are in the 2.04in - 3.46in length range. I think that should only result in something like a 250ps delay from shortest to longest, which should be well within the 8ns setup/hold time the LCD driver is expecting.I feel like I'm just missing something obvious to someone who works with LCDs a lot. Let me know what I'm doing and you can be my new personal hero.If you are in the LA area, have experience with RGB LCD stuff (preferably ESP32-S3 as a controller, but not required), and want to consult, hit me up since I'm not making any progress at this point.

author: Fire Doger
author_rank: Regular Contributor
timestamp: August 31, 2025, 04:50:55 pm
content: Screen refresh rate with FPS are 2 different things.For example, if you buy a 60Hz monitor, it will redraw the image 60 times per second.If you play a brand new game, with a graphics card from 2010 it won't be able to draw in ram a new image every 16ms. Lets assume it will be able to draw an image every 32ms.Your monitor will continue to refresh every 16ms even if your computer is not capable of sending new image every 16ms.In your case, your pixel count is 800x480. But that becomes 1056x525 if you count front and back porch (clocks blank pixels to "synchronize"). That's a total ~555k pixels.With 24Mhz clk you can fully update the screen (555k) at 44Hz (refresh rate). That's not something "clearly visible". But, the important thing is to have the prepared image as fast or faster than refresh rate.What you see as "scan line" is simple tearing.You have in your ram a "frame buffer". A matrix/array with raw pixel data.Whatever you write on the ram will be send "sometime" to the display. (By lcd peripheral, that's it's job)But you can also have 2 framebuffers! (More bellow)As in the example above, in your case, with 44Hz refresh rate, each pixel will take 22ms to be redrawn (time between scan line reaching the same pixel after looping over). So if you write a pixel in RAM, it may be send immediately, maybe in 2ms, maybe in 22ms, depends where was the scan line and your pixel position.Lets see how you can achieve 2 perfect frames of a moved circle.Single Buffer Implementation:A: You need to perform all RAM writesunder22ms! (If you increase the speed of DCLK this time reduces!)B: You need to time it perfectly so that your RAM writes are directly after the scan line. (i.e if MCU sends line 20, you change the pixels in line 19, when MCU sends line 21, you change the pixels in line 20, etc...)Double Buffer Implementation:You have as much time as you like.The MCU will send again and again buffer_1 (with 44Hz as calculated) with circle in position 1.You draw the circle in position 2 in buffer_2. The screen won't change while you write to the RAM because you don't write inside the active buffer, you write in 2.When you are ready, you instruct the MCU to change the active buffer from 1 to 2. When it will finish the current frame transmission, it will start using the buffer_2 to send to the screen and you won't see any tearing.You can say that there will be a transition time when the buffer_2 is transmitted for the first time. i.e line 20 will have the new circle, line 21 will have old circle, won't that be visible?No. Not with naked eye at 44hz. It will take (22ms/525Vlines) 0,04ms to draw line 21 after line 20. It just won't feel the same if you have it near a same device running at 60hz.What is clearly visible tearing is to update line after 22ms. This regularly happens when you have single frame buffer and no synchronization.The downside with double buffering is that you need double the RAMBut if you have double buffering it's best to crank up the refresh speed.On single buffering, you need as slow as possible scan line to be able to "catch it" while doing slow math and calculations.Bellow 20Hz it may start appear flickering.The implementation is a wild west. Depends on the library, what MCU offers, etc...I assume LVGL guys have thought of it extensively... If you making your own library you need to make it yourself.If you are using LVGL and you have enough RAM you can try to just change it to double buffering while keeping 24Mhz clock and see if the result is acceptable.In the attached example you can see that there is a flag CONFIG_EXAMPLE_DOUBLE_FB which configures 1 or 2 frame buffers.Quote from: Smokey on October 10, 2023, 08:05:16 am

author: Smokey
author_rank: Super Contributor
timestamp: September 02, 2025, 09:31:39 pm
content: Cool. I'm just an idiot. I had serial clocked data in my head, and this is parallel. You are right. I don't need to run the pixel clock nearly as fast as I was thinking. I think about 8MHz should give me around 20 screen refreshes a second.With that setup, the display no longer shows that tearing from the image I posted. Cool.New problem:I'm only writing to the frame buffer once, and the display is correctly showing the solid color background with the circle in the middle, but the black "scan line" is clearly visible moving from top to bottom at about 5-7Hz. That is just creating a static frame buffer and writing it directly with the IDF methods.If I include LVGL and have that draw the buffer, it appears that it gets the dimensions wrong and the location of the circle bounces around the display.

author: Fire Doger
author_rank: Regular Contributor
timestamp: September 04, 2025, 06:55:57 am
content: 8 MHz is quite slow.Keep in mind that the transfer isn’t just 800x480 pixels. It actually takes the same time as transferring 1056x525 pixels.As you can see in the attachment, 800x480 is your active/visible area, but it needs some blank periods (front porch, back porch) for the driver.(The drivers have also a minimum clk, I have seen a case before where it was playing perfectly, but on some screens on production the image was shifted. The issue was that our clock was bellow the minimum)1056x525 = ~555.000 px8.000.000 / 555.000 = 14.5 Hz It's slow...These displays doesn't have any internal memory, so if you send the data in slow rate, they don't have anything to display on glass.From experience on 800x480 screens (most of them have similar front/back porches) bellow ~20Mhz clk it's visible (to me at least) the scanline / flicker.I suggest leaving the clock somewhere around 20-24Mhz since you said that it was looking good at that frequency.