I am considering a 3.5" TFT ILI9481-based (480x320 pixels, 16 bpp) display with an ESP32-WROOM-32, and I am aiming for display moving pictures with no tearing at all. According to the ILI9481 datasheet, frame rate can be adjusted via the "Frame Rate and Inversion Control" command (ID C5h) as low as 42 Hz. This way, if its GRAM is filled with new data 42 times per second, no tearing effect should be noticed. That means roughly ~ 219,429 pixels per second ~= 438,858 bytes per second (considering 16 bpp).
Given the high bit rate needed to drive this display with no tearing effect, I chose to use one of the available I2S peripherals along with the DMA controller. According to the ESP32 datasheet, maximum DMA transfer size is 4,092 bytes, so the whole screen must be sent in chunks. However, I decide to set each transfer size to 3,840 bytes so it nicely fits into 320 (screen height) x 6 pixels, as each scene is composed of several layers of arbitrary size that are placed at arbitrary positions. Take into account this display is meant to draw from the upper right corner to the left bottom corner, as shown at the image below:
The code is written so two identically-sized buffers are defined, where one is being sent whereas another buffer is being prepared by the CPU, achieving a double buffering effect.
However, the following clock configuration allowed me the fastest bit rate I could use, but only achieved ~25 Hz:
Code: Select all
/* Set BCK TX clock rate. */
I2S1.sample_rate_conf.tx_bck_div_num = 4;
I2S1.clkm_conf.clkm_div_b = 1;
/* On the original example, it was set to zero. Why? */
I2S1.clkm_conf.clkm_div_a = 0;
/* Set clock frequency denominator. */
I2S1.clkm_conf.clkm_div_num = 4;
/* Enable use of APLL. */
I2S1.clkm_conf.clka_en = 0;
/* Enable interrupt trigger when a packet has been sent. */
I2S1.int_ena.out_total_eof = 1;
Thanks for your help,
Xavi