Random Colored Lines in Display (GC9A01)

Description

Hi, I’m using LGVL with style (without theme), and getting two problems:
1 - Some random colored lines
2 - If I increase (lv_style_set_scale_width) more than 12, my aplication locks

I have upload this video to explain this situation

What MCU/Processor/Board and compiler are you using?

I’m using NUCLEO F446RE, LCD GC9A01, and Keil mdk-arm with cubeMX.

What LVGL version are you using?

Last version in github repo.

What do you want to achieve?

I want to fix these bugs to advance with my project.

What have you tried so far?

I have tried add a lv_disp_buffer with some differents sizes.

Code to reproduce

LCD_Init();
  lv_init();
  tft_init();
	
	lv_disp_buf_t disp_buf_2;
	lv_color_t buf2_1[LV_HOR_RES_MAX * 10];
	lv_color_t buf2_2[LV_HOR_RES_MAX * 10];
	//lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * 10);
	
	//Write codes screen_lmeter0
	lv_obj_t * linemeter1 = lv_linemeter_create(lv_disp_get_scr_act(NULL), NULL);

	//Write style LV_LINEMETER_PART_MAIN for screen_lmeter0
	static lv_style_t style_screen_linemeter1_main;
	lv_style_init(&style_screen_linemeter1_main);
	
	//Write style state: LV_STATE_DEFAULT for style_screen_linemeter1_main
	lv_style_set_radius(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 0);
	lv_style_set_bg_color(&style_screen_linemeter1_main, LV_STATE_DEFAULT, lv_color_make(0x00, 0x00, 0x00));
	lv_style_set_bg_grad_color(&style_screen_linemeter1_main, LV_STATE_DEFAULT, lv_color_make(0x00, 0x00, 0x00));
	lv_style_set_bg_grad_dir(&style_screen_linemeter1_main, LV_STATE_DEFAULT, LV_GRAD_DIR_VER);
	lv_style_set_bg_opa(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 255);
	lv_style_set_line_color(&style_screen_linemeter1_main, LV_STATE_DEFAULT, lv_color_make(0x0c, 0xb3, 0x00));
	lv_style_set_line_width(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 12);
	lv_style_set_line_opa(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 255);
	lv_style_set_scale_grad_color(&style_screen_linemeter1_main, LV_STATE_DEFAULT, lv_color_make(0xf6, 0x09, 0x09));
	lv_style_set_scale_end_color(&style_screen_linemeter1_main, LV_STATE_DEFAULT, lv_color_make(0x97, 0x95, 0x97));
	lv_style_set_scale_width(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 12);
	lv_style_set_scale_end_line_width(&style_screen_linemeter1_main, LV_STATE_DEFAULT, 10);
	
	lv_obj_add_style(linemeter1, LV_LINEMETER_PART_MAIN, &style_screen_linemeter1_main);
	
	lv_obj_set_pos(linemeter1, 0, 0);
	lv_obj_set_size(linemeter1, 240, 240);
	lv_linemeter_set_scale(linemeter1, 270, 25);
	lv_linemeter_set_range(linemeter1, 0, 126);
	lv_linemeter_set_value(linemeter1, 100);
	//lv_linemeter_set_angle_offset(linemeter1, 0);```

I would rather suspect your flush function.

Here is my flush code, I don’t know what is my mistake. Can U help me?

/**
 * @file lv_port_disp_templ.c
 *
 */

 /*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1

/*********************
 *      INCLUDES
 *********************/
#include "tft.h"
#include "lcd.h"
#include "main.h"
/*********************
 *      DEFINES
 *********************/
 #define USB_SPI_DMA 1
/**********************
 *      TYPEDEFS
 **********************/

/**********************
 *  STATIC PROTOTYPES
 **********************/
static void disp_init(void);
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);

/**********************
 *  STATIC VARIABLES
 **********************/
static lv_disp_drv_t display_drv;                         /*Descriptor of a display driver*/
#if USB_SPI_DMA
static lv_disp_drv_t * disp_p;
#endif
/**********************
 *      MACROS
 **********************/
extern SPI_HandleTypeDef hspi1;
extern DMA_HandleTypeDef hdma_spi1_tx;
/**********************
 *   GLOBAL FUNCTIONS
 **********************/

void tft_init(void)
{
    /*-------------------------
     * Initialize your display
     * -----------------------*/
    disp_init();

    /*-----------------------------
     * Create a buffer for drawing
     *----------------------------*/
    /* Example for 1) */
//    static lv_disp_buf_t disp_buf_1;
//    static lv_color_t buf1_1[LV_HOR_RES_MAX * 40];                      /*A buffer for 10 rows*/
//    lv_disp_buf_init(&disp_buf_1, buf1_1, NULL, LV_HOR_RES_MAX * 40);   /*Initialize the display buffer*/
		
		#define valor 40
    /* Example for 2) */
    static lv_disp_buf_t disp_buf_2;
    static lv_color_t buf2_1[LV_HOR_RES_MAX * valor];                        /*A buffer for 10 rows*/
    static lv_color_t buf2_2[LV_HOR_RES_MAX * valor];                        /*An other buffer for 10 rows*/
    lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * valor);   /*Initialize the display buffer*/

    /*-----------------------------------
     * Register the display in LittlevGL
     *----------------------------------*/
    lv_disp_drv_init(&display_drv);                    /*Basic initialization*/

    /*Set up the functions to access to your display*/

    /*Set the resolution of the display*/
    display_drv.hor_res = 240;
    display_drv.ver_res = 240;

    /*Used to copy the buffer's content to the display*/
    display_drv.flush_cb = disp_flush;

    /*Set a display buffer*/
    display_drv.buffer = &disp_buf_2;

    /*Finally register the driver*/
    lv_disp_drv_register(&display_drv);
}

/**********************
 *   STATIC FUNCTIONS
 **********************/

/* Initialize your display and the required peripherals. */
static void disp_init(void)
{
    /*You code here*/
}

/* Flush the content of the internal buffer the specific area on the display
 * You can use DMA or any hardware acceleration to do this operation in the background but
 * 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
    /*SPI transmit data without DMA*/
#if USB_SPI_DMA
    /*SPI transmit data with DMA*/
    LCD_Send_Data_DMA(area->x1, area->y1, area->x2, area->y2, (uint8_t *)color_p);
    disp_p = disp_drv;
#else
    LCD_Send_Data(area->x1, area->y1, area->x2, area->y2, (uint8_t *)color_p);
    lv_disp_flush_ready(disp_drv);
#endif
}

#if USB_SPI_DMA
void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
{
    lv_disp_flush_ready(disp_p);
}

void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
    HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
    HAL_Delay(500);
}
#endif

#else /* Enable this file at the top */

/* This dummy typedef exists purely to silence -Wpedantic. */
typedef int keep_pedantic_happy;
#endif

Hi, I fixed my problem.

The bug are caused by buffer initialization, I fixed this dividing by 2.

#define valor 40
    /* Example for 2) */
    static lv_disp_buf_t disp_buf_2;
    static lv_color_t buf2_1[LV_HOR_RES_MAX * valor];                        /*A buffer for 40 rows*/
    static lv_color_t buf2_2[LV_HOR_RES_MAX * valor];                        /*An other buffer for 40 rows*/
    lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * valor/2);   /*Initialize the display buffer*/

It seems to me that you are tinkering a bit :wink:.
Do you know why lowering the buffer size is working?
(Ok, the real buffer size is still the same as before, but you tell lvgl that buffer size is less)
I guess not.
There is still something wrong, and you should find the real cause.

What is your pixel size? 8-bit, or 16-bit?

You use the function

LCD_Send_Data_DMA (...)

As far as I can see ( weefnn / pandora, if this is the code you use), the function LCD_Send_Data_DMA is hard coded for 16-bit pixel (two bytes) as you can see in line 636.
That means, if you use 8-bit pixels, the function LCD_Send_Data_DMA may write more pixels as the buf2_1 provides.

If you use 16-bit pixels the function LCD_Send_Data_DMA would be OK in your case.
That means the size of buf2_1 matches the size which LCD_Send_Data_DMA may use.
But what’s about the strange pixels you see then?
The ‘strange pixels’ you see are some intermediate (more or less random) data which the CPU is generating while working.
That can mean, there might be some ‘wrong’ pointer, pointing anywhere into the buf2_1.
Or some string buffer overflow. In this case the strange pixels would occur at the start of buf2_1. But for this case you would still see the ‘strange pixels’.