Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using two GC9A01 multiple displays at the same time #276

Closed
poky opened this issue Apr 29, 2021 · 4 comments
Closed

Using two GC9A01 multiple displays at the same time #276

poky opened this issue Apr 29, 2021 · 4 comments

Comments

@poky
Copy link

poky commented Apr 29, 2021

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

disp_spi_add_device(TFT_SPI_HOST,15);
    
    disp_driver_init();

    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;
    lv_disp_drv_init(&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();

    disp_spi_add_device(TFT_SPI_HOST,14);
    
    disp_driver_init();

    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;
    lv_disp_drv_init(&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
        //.spics_io_num=-1,
        .input_delay_ns=DISP_SPI_INPUT_DELAY_NS,
        .queue_size=1,
        .pre_cb=NULL,
        .post_cb=NULL,
#if defined (CONFIG_LVGL_TFT_DISPLAY_CONTROLLER_FT81X)
        .flags = 0,
#elif defined (CONFIG_LVGL_TFT_DISPLAY_CONTROLLER_RA8875)
        .flags = SPI_DEVICE_NO_DUMMY,
#else
        //.flags = SPI_DEVICE_NO_DUMMY | SPI_DEVICE_HALFDUPLEX,
#endif
    };

    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?

Also thought of the disp_driver_flush callback from this line:

disp_drv.flush_cb = disp_driver_flush;

It 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:

lv_disp_flush_ready(drv);

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

1a5fbd970b8f3545c6fabe261a59b4da66e57fc8

@tore-espressif
Copy link
Collaborator

Hello @poky ,
I didn't dig too deep into the code, but here are few tips:

  1. Let's assume that your modifications to the SPI driver are working (your spi send function can switch CS between displays)
  2. The you basically need to do this section of code https://github.com/lvgl/lv_port_esp32/blob/master/main/main.c#L85-126 (lines 85-126) twice: Define two drivers and their buffers and register them.
  3. This will create a separate task for each driver, the task calls disp_drv.flush_cb() with correct arguments, when needed
  4. I have a suspicion that your lv_disp_drv_t disp_drv; definition becomes invalid after disp_spi_add_device function exits, so please make it static or refactor

@poky
Copy link
Author

poky commented May 20, 2021

Thank you @tore-espressif
I have followed your suggestion, now it works independently!

335980

Another question, if I want to make it mirror, according to the LVGL doc

To mirror the image of the display to another display, you don't need to use the multi-display support. Just transfer the buffer received in drv.flush_cb to another display too.

I now have :

lv_disp_t* dis1;
lv_disp_t* dis2;

Could you suggest how do I suppose to send dis1's buffer to dis2?

Thanks!

@tore-espressif
Copy link
Collaborator

Good job :)

I've never tried mirroring, but this is the idea:

  1. You have just one driver, one buffer and one task
  2. You need to modify GC9A01.c driver to write/flush two devices at once
  3. Functions like GC9A01_send_cmd GC9A01_send_data GC9A01_send_color must send the same data to both displays
  4. Don't forget to initialize both displays and their pins (DC, RST, possibly BCKL) in GC9A01_init

@poky
Copy link
Author

poky commented Jun 5, 2021

Thank you! I have figured out how to do it, this issue may closed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants