Transition performance issues?

Description

Hello,

I have a simple example where a small circle grows when I touched it.
I noticed the animation isn’t super smooth, I think I see lines or something when the circle is growing.

I noticed the FPS drop to 15fps and CPU goes up to 80% - 85%
I tried different tickers but no luck.

Wondering what exactly is happening and how can I improve this, to make the animation extra smooth.

I’m using a Waveshare ESP32-S3 2.1inch Touch LCD.

What LVGL version are you using?

9.2.2

What do you want to achieve?

Smoother animation

What have you tried so far?

Different tickers

/*** Alternative solution to xTaskGetTickCount ***/
static auto tick_get_cb = []() -> uint32_t {
      return esp_timer_get_time() / 1000ULL;
};

(...)

lv_tick_set_cb(tick_get_cb);

currently using lv_tick_set_cb(xTaskGetTickCount);

I didn’t see any difference between the two

Code to reproduce

Transitions:

  /* A default transition */
  static lv_style_transition_dsc_t trans_def;
  lv_style_transition_dsc_init(&trans_def, props, lv_anim_path_bounce, 350, 0, NULL);

  /* A special transition when going to pressed state */
  static lv_style_transition_dsc_t trans_pr;
  lv_style_transition_dsc_init(&trans_pr, props, lv_anim_path_bounce, 150, 0, NULL);

LVGL Init:

// LCD is 480x480
static uint8_t buf1[(LCD_WIDTH * LCD_HEIGHT / 10) * BYTE_PER_PIXEL + 500];
static uint8_t buf2[(LCD_WIDTH * LCD_HEIGHT / 10) * BYTE_PER_PIXEL + 500];

(...)

void initLVGL(void) {
  lv_init();
  lv_tick_set_cb(xTaskGetTickCount);

  lv_display_t *disp_drv = lv_display_create(LCD_WIDTH, LCD_HEIGHT);

  /* Initialize the draw buffer */
  lv_display_set_buffers(disp_drv, buf1, buf2, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);

  /* Set the display resolution */
  lv_display_set_physical_resolution(disp_drv, LCD_HEIGHT, LCD_WIDTH);

  /* Set flush callback */
  lv_display_set_flush_cb(disp_drv, flushDisplay);
  
  /* Enable AntiAlias */
  lv_display_set_antialiasing(disp_drv, true);

  /* Initialize the input device driver */
  lv_indev_t *indev = lv_indev_create();
  lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
  lv_indev_set_read_cb(indev, touchPadRead);
}

Screenshot and/or video

Jan-03-2025 18-14-29

Your issue isnt based on tick, but on disp driver bus speed. Basic school match…

Okay…

is there anything I can do to improve this?

Maybe when you provide info about display … basic match if display is 1 bit SPI then 480x480x16x30FPS require bus speed 110.6MHz
max on ESP is 80, too memory and MCU numbers is basd on same math.
When yu animate only little part you can do .
But all part of sw require perfect optimal code for smooth…
Most important is display driver and flushcb.

1 Like

I’m using a ESP32-S3 with a ST7701 display.

Its my first time working with these devices so bare with me :wink:

I’m currenly modifying the demo file that came with the device so there’s alot of code here that I didn’t write nor understand.

The flush cb:

void flushDisplay(lv_display_t *disp, const lv_area_t *area, uint8_t *color_p) {
    LCD_addWindow(area->x1, area->y1, area->x2, area->y2, color_p);
    lv_display_flush_ready(disp);
}

Display_ST7701.h

#pragma once
#include <inttypes.h>

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_lcd_panel_ops.h"
#include "esp_lcd_panel_io.h"
#include "esp_lcd_panel_rgb.h"

#include "driver/spi_master.h"
#include "driver/gpio.h"
#include "freertos/task.h"

#include "TCA9554PWR.h"
#include "LVGL_Driver.h"
#include "Touch_CST820.h"

#define LCD_CLK_PIN   2
#define LCD_MOSI_PIN  1 
#define LCD_Backlight_PIN   6 

// Backlight   
#define PWM_Channel     1       // PWM Channel   
#define Frequency       20000   // PWM frequencyconst         
#define Resolution      10      // PWM resolution ratio     MAX:13
#define Dutyfactor      500     // PWM Dutyfactor      

#define ESP_PANEL_LCD_WIDTH                       (480)
#define ESP_PANEL_LCD_HEIGHT                      (480)
#define ESP_PANEL_LCD_COLOR_BITS                  (16)
#define ESP_PANEL_LCD_RGB_PIXEL_BITS              (16)    // 24 | 16
#define ESP_PANEL_LCD_RGB_DATA_WIDTH              (16)
#define ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ          (16 * 1000 * 1000)
#define ESP_PANEL_LCD_RGB_TIMING_HPW              (8)
#define ESP_PANEL_LCD_RGB_TIMING_HBP              (10)
#define ESP_PANEL_LCD_RGB_TIMING_HFP              (50)
#define ESP_PANEL_LCD_RGB_TIMING_VPW              (3)
#define ESP_PANEL_LCD_RGB_TIMING_VBP              (8)
#define ESP_PANEL_LCD_RGB_TIMING_VFP              (8)
#define ESP_PANEL_LCD_RGB_FRAME_BUF_NUM           (2)     // 1/2/3
#define ESP_PANEL_LCD_RGB_BOUNCE_BUF_SIZE         (ESP_PANEL_LCD_WIDTH * 10)     // Bounce buffer size in bytes. This function is used to avoid screen drift.
                                                          // To enable the bounce buffer, set it to a non-zero value. Typically set to `ESP_PANEL_LCD_WIDTH * 10`
                                                          // The size of the Bounce Buffer must satisfy `width_of_lcd * height_of_lcd = size_of_buffer * N`,
                                                          // where N is an even number.


////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////// Please update the following configuration according to your board spec ////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#define ESP_PANEL_LCD_PIN_NUM_RGB_HSYNC           (38)
#define ESP_PANEL_LCD_PIN_NUM_RGB_VSYNC           (39)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DE              (40)
#define ESP_PANEL_LCD_PIN_NUM_RGB_PCLK            (41)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA0           (5)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA1           (45)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA2           (48)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA3           (47)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA4           (21)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA5           (14)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA6           (13)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA7           (12)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA8           (11)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA9           (10)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA10          (9)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA11          (46)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA12          (3)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA13          (8)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA14          (18)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DATA15          (17)
#define ESP_PANEL_LCD_PIN_NUM_RGB_DISP            (-1)

#define ESP_PANEL_LCD_BK_LIGHT_ON_LEVEL           (1)
#define ESP_PANEL_LCD_BK_LIGHT_OFF_LEVEL !ESP_PANEL_LCD_BK_LIGHT_ON_LEVEL

#define EXAMPLE_ENABLE_PRINT_LCD_FPS            (1)

extern esp_lcd_panel_handle_t panel_handle;   
bool example_on_vsync_event(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_data);
void ST7701_Init();

void LCD_Init();
void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint8_t* color);


#define MIN_BRIGHTNESS 10
#define MAX_BRIGHTNESS 100
#define BREATH_STEP 1

extern int backlight;
void initBacklight();
void setBrightness(uint8_t Light); 

void breathingEffect(); 
void initBrightnessAnimations();

Display_ST7701.cpp

#include "Display_ST7701.h"  
      
spi_device_handle_t SPI_handle = NULL;     
esp_lcd_panel_handle_t panel_handle = NULL;            
void ST7701_WriteCommand(uint8_t cmd)
{
  spi_transaction_t spi_tran = {
    .cmd = 0,
    .addr = cmd,
    .length = 0,
    .rxlength = 0,
  };
  spi_device_transmit(SPI_handle, &spi_tran);
}
void ST7701_WriteData(uint8_t data)
{
  spi_transaction_t spi_tran = {
    .cmd = 1,
    .addr = data,
    .length = 0,
    .rxlength = 0,
  };
  spi_device_transmit(SPI_handle, &spi_tran);
}

void ST7701_CS_EN(){
  Set_EXIO(EXIO_PIN3,Low);
  vTaskDelay(pdMS_TO_TICKS(10));
}
void ST7701_CS_Dis(){
  Set_EXIO(EXIO_PIN3,High);
  vTaskDelay(pdMS_TO_TICKS(10));
}
void ST7701_Reset(){
  Set_EXIO(EXIO_PIN1,Low);
  vTaskDelay(pdMS_TO_TICKS(10));
  Set_EXIO(EXIO_PIN1,High);
  vTaskDelay(pdMS_TO_TICKS(50));
}
void ST7701_Init()
{
  spi_bus_config_t buscfg = {
    .mosi_io_num = LCD_MOSI_PIN,
    .miso_io_num = -1,
    .sclk_io_num = LCD_CLK_PIN,
    .quadwp_io_num = -1,
    .quadhd_io_num = -1,
    .max_transfer_sz = 64, // ESP32 S3 max size is 64Kbytes
  };
  spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO);
  spi_device_interface_config_t devcfg = {
    .command_bits = 1,
    .address_bits = 8,
    .mode = SPI_MODE0,
    .clock_speed_hz = 40000000,
    .spics_io_num = -1,                      
    .queue_size = 1,            // Not using queues
  };
  spi_bus_add_device(SPI2_HOST, &devcfg, &SPI_handle);            

  ST7701_CS_EN();
  ST7701_WriteCommand(0xFF);
  ST7701_WriteData(0x77);
  ST7701_WriteData(0x01);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x10);

  ST7701_WriteCommand(0xC0);
  ST7701_WriteData(0x3B);//Scan line	
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xC1);
  ST7701_WriteData(0x0B);	//VBP
  ST7701_WriteData(0x02);

  ST7701_WriteCommand(0xC2);
  ST7701_WriteData(0x07);
  ST7701_WriteData(0x02);

  ST7701_WriteCommand(0xCC);
  ST7701_WriteData(0x10);

  ST7701_WriteCommand(0xCD);//RGB format
  ST7701_WriteData(0x08);

  ST7701_WriteCommand(0xB0); // IPS   
  ST7701_WriteData(0x00); // 255 
  ST7701_WriteData(0x11); // 251    
  ST7701_WriteData(0x16); // 247  down
  ST7701_WriteData(0x0e); // 239    
  ST7701_WriteData(0x11); // 231    
  ST7701_WriteData(0x06); // 203    
  ST7701_WriteData(0x05); // 175 
  ST7701_WriteData(0x09); // 147    
  ST7701_WriteData(0x08); // 108    
  ST7701_WriteData(0x21); // 80  
  ST7701_WriteData(0x06); // 52   
  ST7701_WriteData(0x13); // 24    
  ST7701_WriteData(0x10); // 16    
  ST7701_WriteData(0x29); // 8    down
  ST7701_WriteData(0x31); // 4    
  ST7701_WriteData(0x18); // 0   

  ST7701_WriteCommand(0xB1);//  IPS	   
  ST7701_WriteData(0x00);//  255 
  ST7701_WriteData(0x11);//  251
  ST7701_WriteData(0x16);//  247   down
  ST7701_WriteData(0x0e);//  239
  ST7701_WriteData(0x11);//  231
  ST7701_WriteData(0x07);//  203    
  ST7701_WriteData(0x05);//  175
  ST7701_WriteData(0x09);//  147  
  ST7701_WriteData(0x09);//  108  
  ST7701_WriteData(0x21);//  80 
  ST7701_WriteData(0x05);//  52   
  ST7701_WriteData(0x13);//  24 
  ST7701_WriteData(0x11);//  16 
  ST7701_WriteData(0x2a);//  8  down 
  ST7701_WriteData(0x31);//  4  
  ST7701_WriteData(0x18);//  0  

  ST7701_WriteCommand(0xFF);
  ST7701_WriteData(0x77);
  ST7701_WriteData(0x01);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x11);

  ST7701_WriteCommand(0xB0);  //VOP  3.5375+ *x 0.0125
  ST7701_WriteData(0x6d);  //5D
  
  ST7701_WriteCommand(0xB1); 	//VCOM amplitude setting  
  ST7701_WriteData(0x37);  //
  
  ST7701_WriteCommand(0xB2); 	//VGH Voltage setting  
  ST7701_WriteData(0x81);	//12V

  ST7701_WriteCommand(0xB3);
  ST7701_WriteData(0x80);

  ST7701_WriteCommand(0xB5); 	//VGL Voltage setting  
  ST7701_WriteData(0x43);	//-8.3V

  ST7701_WriteCommand(0xB7);
  ST7701_WriteData(0x85);

  ST7701_WriteCommand(0xB8);
  ST7701_WriteData(0x20);

  ST7701_WriteCommand(0xC1);
  ST7701_WriteData(0x78);

  ST7701_WriteCommand(0xC2);
  ST7701_WriteData(0x78);

  ST7701_WriteCommand(0xD0);
  ST7701_WriteData(0x88);

  ST7701_WriteCommand(0xE0);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x02);

  ST7701_WriteCommand(0xE1);
  ST7701_WriteData(0x03);	
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x04);	
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x20);
  ST7701_WriteData(0x20);

  ST7701_WriteCommand(0xE2);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	  
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE3);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x11);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE4);
  ST7701_WriteData(0x22);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE5);		
  ST7701_WriteData(0x05);	
  ST7701_WriteData(0xEC);	
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x07);	
  ST7701_WriteData(0xEE);	
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE6);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x11);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE7);
  ST7701_WriteData(0x22);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xE8);		
  ST7701_WriteData(0x06);	
  ST7701_WriteData(0xED);	
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x08);	
  ST7701_WriteData(0xEF);	
  ST7701_WriteData(0xA0); 
  ST7701_WriteData(0xA0);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0xEB);
  ST7701_WriteData(0x00); 	
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x40);
  ST7701_WriteData(0x40);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);  

  ST7701_WriteCommand(0xED);  
  ST7701_WriteData(0xFF); 
  ST7701_WriteData(0xFF);  
  ST7701_WriteData(0xFF); 	
  ST7701_WriteData(0xBA); 		
  ST7701_WriteData(0x0A); 	
  ST7701_WriteData(0xBF); 	
  ST7701_WriteData(0x45); 	
  ST7701_WriteData(0xFF); 
  ST7701_WriteData(0xFF);  
  ST7701_WriteData(0x54); 	
  ST7701_WriteData(0xFB); 	
  ST7701_WriteData(0xA0); 	
  ST7701_WriteData(0xAB); 	
  ST7701_WriteData(0xFF); 
  ST7701_WriteData(0xFF); 
  ST7701_WriteData(0xFF); 

  ST7701_WriteCommand(0xEF);
  ST7701_WriteData(0x10); 
  ST7701_WriteData(0x0D); 
  ST7701_WriteData(0x04); 
  ST7701_WriteData(0x08); 
  ST7701_WriteData(0x3F); 
  ST7701_WriteData(0x1F);

  ST7701_WriteCommand(0xFF);
  ST7701_WriteData(0x77);
  ST7701_WriteData(0x01);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x13);

  ST7701_WriteCommand(0xEF);
  ST7701_WriteData(0x08);

  ST7701_WriteCommand(0xFF);
  ST7701_WriteData(0x77);
  ST7701_WriteData(0x01);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);
  ST7701_WriteData(0x00);


  ST7701_WriteCommand(0x36);
  ST7701_WriteData(0x00);

  ST7701_WriteCommand(0x3A);
  ST7701_WriteData(0x66);

  ST7701_WriteCommand(0x11);
  
  vTaskDelay(pdMS_TO_TICKS(480));

  ST7701_WriteCommand(0x20);

  vTaskDelay(pdMS_TO_TICKS(120));

  ST7701_WriteCommand(0x29); 
  ST7701_CS_Dis();

  //  RGB
  esp_lcd_rgb_panel_config_t rgb_config = {
    .clk_src = LCD_CLK_SRC_DEFAULT,
    .timings =  {
      .pclk_hz = ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ,
      .h_res = ESP_PANEL_LCD_HEIGHT,
      .v_res = ESP_PANEL_LCD_WIDTH,
      .hsync_pulse_width = ESP_PANEL_LCD_RGB_TIMING_HPW,
      .hsync_back_porch = ESP_PANEL_LCD_RGB_TIMING_HBP,
      .hsync_front_porch = ESP_PANEL_LCD_RGB_TIMING_HFP,
      .vsync_pulse_width = ESP_PANEL_LCD_RGB_TIMING_VPW,
      .vsync_back_porch = ESP_PANEL_LCD_RGB_TIMING_VBP,
      .vsync_front_porch = ESP_PANEL_LCD_RGB_TIMING_VFP,
      .flags = {
        .hsync_idle_low = 0,  /*!< The hsync signal is low in IDLE state */
        .vsync_idle_low = 0,  /*!< The vsync signal is low in IDLE state */
        .de_idle_high = 0,    /*!< The de signal is high in IDLE state */
        .pclk_active_neg = false,
        .pclk_idle_high = 0,  /*!< The PCLK stays at high level in IDLE phase */
      },
    },
    .data_width = ESP_PANEL_LCD_RGB_DATA_WIDTH,
    .bits_per_pixel = ESP_PANEL_LCD_RGB_PIXEL_BITS,
    .num_fbs = ESP_PANEL_LCD_RGB_FRAME_BUF_NUM,
    .bounce_buffer_size_px = 10 * ESP_PANEL_LCD_HEIGHT,
    .psram_trans_align = 64,
    .hsync_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_HSYNC,
    .vsync_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_VSYNC,
    .de_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_DE,
    .pclk_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_PCLK,
    .disp_gpio_num = ESP_PANEL_LCD_PIN_NUM_RGB_DISP,
    .data_gpio_nums = {
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA0,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA1,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA2,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA3,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA4,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA5,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA6,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA7,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA8,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA9,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA10,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA11,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA12,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA13,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA14,
      ESP_PANEL_LCD_PIN_NUM_RGB_DATA15,
    },
    .flags = {
      .disp_active_low = 0,
      .refresh_on_demand = 0,
      .fb_in_psram = true,
      .double_fb = true,
      .no_fb = 0,
      .bb_invalidate_cache = 0,
    },
  };
  esp_lcd_new_rgb_panel(&rgb_config, &panel_handle); 
  esp_lcd_panel_reset(panel_handle);
  esp_lcd_panel_init(panel_handle);
}

void LCD_Init() {
  ST7701_Reset();
  ST7701_Init();
  Touch_Init();
}

void LCD_addWindow(uint16_t Xstart, uint16_t Ystart, uint16_t Xend, uint16_t Yend,uint8_t* color) {
  Xend = Xend + 1;      // esp_lcd_panel_draw_bitmap: x_end End index on x-axis (x_end not included)
  Yend = Yend + 1;      // esp_lcd_panel_draw_bitmap: y_end End index on y-axis (y_end not included)
  if (Xend >= ESP_PANEL_LCD_WIDTH)
    Xend = ESP_PANEL_LCD_WIDTH;
  if (Yend >= ESP_PANEL_LCD_HEIGHT)
    Yend = ESP_PANEL_LCD_HEIGHT;
   
  esp_lcd_panel_draw_bitmap(panel_handle, Xstart, Ystart, Xend, Yend, color);                     // x_end End index on x-axis (x_end not included)
}

void initBacklight() {
  ledcAttach(LCD_Backlight_PIN, Frequency, Resolution);    
  ledcWrite(LCD_Backlight_PIN, Dutyfactor);               
}

void setBrightness(uint8_t brightness) {
  if(brightness > 100 || brightness < 0)
    printf("Brightness must be between 0 to 100\n");
  else{
    uint32_t backlight = brightness*10;
    ledcWrite(LCD_Backlight_PIN, backlight);
  }
}

Your choiced display is without framebuffer memory , then your steps to optimize is minimal. FB as you can see is placed into SPIRAM and overdrived into display over RGB if on 16MHz. Measure this dot clock with scope and try set bigger values

`#define ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ          (16 * 1000 * 1000)`

or directly here

esp_lcd_rgb_panel_config_t rgb_config = {
    .clk_src = LCD_CLK_SRC_DEFAULT,
    .timings =  {
      .pclk_hz = ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ,

next double buffering require copy data between buffers and in SPIRAM is absurd. Switch to single buffer.

I don’t have an oscilloscope, though, i’d love to.

I removed the second buffer:

  lv_display_set_buffers(disp_drv, buf1, NULL, sizeof(buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);

Didn’t notice much difference.

Regarding :

#define ESP_PANEL_LCD_RGB_TIMING_FREQ_HZ          (16 * 1000 * 1000)

It seems that any value above that one, causes the screen to glitch. The higher the worst it gets.

I thought it could be the amount of screen pixels im trying to draw (the circle area of white pixels)

So I tried a “breathing” effect with just the border thinking it would be faster (less pixels)
interestingly, its not faster.

border

What happens is, the smaller the circle the faster.

It starts with 1px and grows to 480px diameter. The bigger the diameter the slower it gets.
You can see the CPU changes.

The smaller the diameter, the faster it gets. Its also here that its more obvious the screen glitches
Screenshot 2025-01-04 at 10.49.20
Screenshot 2025-01-04 at 10.49.08

I tried setting the max size of the circle to 150px and its much smoother and faster.
CPU remains with low usage (10% / 15%)

:thinking: I feel there are some hints here.

Did another small test, instead of growing a circle, I moved a circle with a fixed size (100px)
The CPU seems pretty stable.

So I think that growing the circle was causing the CPU to get slow because its actually rendering the whole bounding box area, not just the white border line.

:ok_hand:

Now the only mystery left is the “glitch” for fast animations.
I’m not sure this is something I can fix. Seems like its just the screen refresh rate hitting its limits.

move

1 Like