Two GC9A01 multiple displays with esp-idf

Hi, all I’m trying to use multiple display with lv_port_esp32 lib and lvgl_esp32_drivers
Both displays are shared the same SPI (SCL, SDA, DC) control by different CS pins (14 & 15)

I have modified the lvgl_helpers.c to allow register both displays


    static lv_color_t buf1[DISP_BUF_SIZE];
    static lv_color_t buf2[DISP_BUF_SIZE];
    static lv_disp_buf_t disp_buf;
    uint32_t size_in_px = DISP_BUF_SIZE;

    lv_disp_buf_init(&disp_buf, buf1, buf2, size_in_px);

    lv_disp_drv_t disp_drv;
    disp_drv.flush_cb = disp_driver_flush;

    disp_drv.buffer = &disp_buf;
    dis1 = lv_disp_drv_register(&disp_drv);

    //dis1 = lv_disp_get_default();


    static lv_color_t buf21[DISP_BUF_SIZE];
    static lv_color_t buf22[DISP_BUF_SIZE];
    static lv_disp_buf_t disp_buf2;

    lv_disp_buf_init(&disp_buf2, buf21, buf22, DISP_BUF_SIZE);

    lv_disp_drv_t disp_drv2;
    disp_drv2.flush_cb = disp_driver_flush;

    disp_drv2.buffer = &disp_buf2;
    dis2 = lv_disp_drv_register(&disp_drv2);

As well the disp_spi.c to allow spi_bus_add_device for different CS pin

void disp_spi_add_device_with_speed(spi_host_device_t host, int clock_speed_hz, int cs_pin)
    ESP_LOGI(TAG, "Adding SPI device");
    ESP_LOGI(TAG, "Clock speed: %dHz, mode: %d, CS pin: %d",
        clock_speed_hz, SPI_TFT_SPI_MODE, cs_pin);

    spi_device_interface_config_t devcfg={
        .clock_speed_hz = clock_speed_hz,
        .mode = SPI_TFT_SPI_MODE,
//		.mode = 3,
        .spics_io_num=cs_pin,              // CS pin
        .flags = 0,
        .flags = SPI_DEVICE_NO_DUMMY,

    disp_spi_add_device_config(host, &devcfg);

With use of lv_obj_t *scr1 = lv_disp_get_scr_act(dis1) & lv_obj_t *scr1 = lv_disp_get_scr_act(dis2)
To switch between displays, however, only the last init display shows graphs
I suspect the dis1 and dis2 are the same, is there any way to tell which is which by printout display information?


Have you also modified disp_driver_flush to send data to the correct display at the right time? That might be part of the issue, since the second display appears to have garbage on it (at least from the picture).

Thanks for the reply! I was thinking the same thing.

The flush callback was from this line

disp_drv.flush_cb = disp_driver_flush;

And ends here:

void GC9A01_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_map)
	uint8_t data[4];

	/*Column addresses*/
	GC9A01_send_cmd(0x2A);				//0x2A 
	data[0] = (area->x1 >> 8) & 0xFF;
	data[1] = area->x1 & 0xFF;
	data[2] = (area->x2 >> 8) & 0xFF;
	data[3] = area->x2 & 0xFF;
	GC9A01_send_data(data, 4);

	/*Page addresses*/
	GC9A01_send_cmd(0x2B);				//0x2B 
	data[0] = (area->y1 >> 8) & 0xFF;
	data[1] = area->y1 & 0xFF;
	data[2] = (area->y2 >> 8) & 0xFF;
	data[3] = area->y2 & 0xFF;
	GC9A01_send_data(data, 4);

	/*Memory write*/
	GC9A01_send_cmd(0x2C);				//0x2C 

	uint32_t size = lv_area_get_width(area) * lv_area_get_height(area);

	GC9A01_send_color((void*)color_map, size * 2);

It didn’t use the variable “drv”, how does it know which display to flush?
I have seem other drivers using this in the end of function:


However, it does not help… any thought will be appreciate!

The driver was written with the assumption that only one display is being used, so the flush_cb needs adaptation to select the right one.

The most reliable way of getting the display in flush_cb is to use _lv_refr_get_disp_refreshing(). In v7, you can also cast drv to lv_disp_t, but this no longer works in v8.