Trouble getting good draw performance on 8bit ili9341
Posted: Wed Aug 02, 2023 1:40 am
I'm trying to verify my esp32s3 can drive my parallel display fast enough to get 60fps. As far as I can tell the esp32s3 should be able to drive parallel LCDs at 40Mhz and below.
So I took the i80 example and modified it such that I removed lvgl and drew via the lcd interface directly:
Unfortunately the timings I'm getting are about 72ms just for the `esp_lcd_panel_draw_bitmap()` call. That's only about 13fps, which seems incredibly low. Driving the parallel at 15Mhz (below what the esp32s3 and ili9341 seem to support) with 8bit parallel seems like it should only take ~11ms for 240x320 pixels. I tried to ensure that the buffer was in internal ram instead of PSRAM. Changing `EXAMPLE_LCD_PIXEL_CLOCK_HZ` didn't seem to make any changes.
Am I doing something wrong, or just calculating the theoretical value incorrectly?
So I took the i80 example and modified it such that I removed lvgl and drew via the lcd interface directly:
Code: Select all
esp_lcd_panel_io_handle_t io_handle = NULL;
esp_lcd_panel_io_i80_config_t io_config = {
.cs_gpio_num = EXAMPLE_PIN_NUM_CS,
.pclk_hz = EXAMPLE_LCD_PIXEL_CLOCK_HZ,
.trans_queue_depth = 10,
.dc_levels = {
.dc_idle_level = 0,
.dc_cmd_level = 0,
.dc_dummy_level = 0,
.dc_data_level = 1,
},
.flags = {
.swap_color_bytes = true,
},
// .on_color_trans_done = example_notify_lvgl_flush_ready,
// .user_ctx = &disp_drv,
.lcd_cmd_bits = EXAMPLE_LCD_CMD_BITS,
.lcd_param_bits = EXAMPLE_LCD_PARAM_BITS,
};
ESP_LOGI(TAG, "%lu", esp_get_free_internal_heap_size());
uint16_t *buffer;
// buffer = (uint16_t *)malloc(EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES);
buffer = (uint16_t *)heap_caps_malloc(EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES * 2, MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
ESP_LOGI(TAG, "%lu", esp_get_free_internal_heap_size());
#define COUNTS 60
uint64_t totals[COUNTS] = {0};
uint64_t mems[COUNTS] = {0};
uint64_t draws[COUNTS] = {0};
uint16_t count = 0;
while (1) {
struct timeval tv_start, tv_mem, tv_draw;
gettimeofday(&tv_start, NULL);
for(int i = 0; i < EXAMPLE_LCD_H_RES * EXAMPLE_LCD_V_RES; i++) {
buffer[i] = 0xF800;
}
gettimeofday(&tv_mem, NULL);
esp_lcd_panel_draw_bitmap(panel_handle, 0, 0, EXAMPLE_LCD_H_RES, EXAMPLE_LCD_V_RES, buffer);
gettimeofday(&tv_draw, NULL);
mems[count] = (tv_mem.tv_sec - tv_start.tv_sec) * 1000000 + (tv_mem.tv_usec - tv_start.tv_usec);
draws[count] = (tv_draw.tv_sec - tv_mem.tv_sec) * 1000000 + (tv_draw.tv_usec - tv_mem.tv_usec);
totals[count] = (tv_draw.tv_sec - tv_start.tv_sec) * 1000000 + (tv_draw.tv_usec - tv_start.tv_usec);
if (count < COUNTS - 1) {
count++;
} else {
uint64_t total = 0;
uint64_t mem = 0;
uint64_t draw = 0;
for(int i = 0; i < COUNTS; i++) {
total += totals[i];
mem += mems[i];
draw += draws[i];
}
ESP_LOGI(TAG, "Total: %llu, Mem: %llu, Draw: %llu", total / COUNTS, mem / COUNTS, draw / COUNTS);
count = 0;
}
}
Am I doing something wrong, or just calculating the theoretical value incorrectly?