Zephyr ILI9341 driver unable to update display area after set orientation

I have been testing out some of the popular LCD displays of different sizes & display controllers (ST7789V and ILI9341), and have run into a few issues that may be of interest to others.

Under Zephyr, the display orientation function for the ST7789V displays is not currently implemented. Only a stub exists in the driver. However, ILI9341 displays (Adafruit, Waveshare, etc) do support display rotation in the hardware and come in lots of different sizes and higher resolutions.

The display orientation function in the current Zephyr driver for the ILI9XXX displays works provided you maintain the set display mode (i.e. portrait or landscape). However, if you rotate the display area from portrait to landscape or vice versa, the ili9xxx_set_orientation() function in display_ili9xxx.c driver file doesn’t update the display area after rotation, i.e. portrait to landscape switch doesn’t work properly.

Other ILI9341 drivers (e.g. Adafruit IL9341 in the Arduino Framework) handle rotation correctly.

I have patched the driver for my projects but I have raised a bug report with Zephyr-RTOS folks, so hopefully we’ll have a proper fix.

To my surprise, I also found that the ILI9341 driver worked on ST7789V displays 1.14" 135x240 (RGB) IPS and Waveshare 240x240 IPS`. The former displays are quite inexpensive & excellent displays at only ~CAD$3, Waveshare sells for ~CAD$10.

These ST7789V displays have a CS (Chip Select) pin and may well have a controller that is similar the ILI9XXX controller. I’m in the process of reviewing the ST7789V & ILI9XXX datasheets, so will have a better insight later.

I’ve resolved the of issue of changing the ILI9XXX display orientation.

On initialization LVGL (Light & Versatile Graphics Library) configures its resolution but if you later change it via the ILI9XXX display API, a manual call to lv_disp_drv_update i required with the new settings.

I’ve written a new local function disp_update_orientation to enable the display orientation to be set.

After the invoking ILI9XXX display_set_orientation, the current display orientation is retrieved using display_get_capabilities. Depending on the orientation requested, lv_disp_drv->rotated is updated and lv_disp_drv_update invoked to update the display driver to the new orientation.

static void disp_update_orientation(enum display_orientation orientation) {
	lv_disp_t *lv_disp;
	const struct device *disp_dev;
	lv_disp_drv_t *lv_disp_drv;
    struct display_capabilities cap; 

	lv_disp = lv_disp_get_default();
	disp_dev = lv_disp->driver.user_data;
	lv_disp_drv = &lv_disp->driver;

    display_set_orientation(disp_dev,orientation);
    display_get_capabilities(disp_dev, &cap); 

	if (cap.current_orientation == DISPLAY_ORIENTATION_ROTATED_90 ||
	     cap.current_orientation == DISPLAY_ORIENTATION_ROTATED_270) {
            lv_disp_drv->rotated = 1;
	} else 
		lv_disp_drv->rotated = 0;

    // update display driver
	lv_disp_drv_update(lv_disp, lv_disp_drv);
	lv_obj_invalidate(lv_scr_act());
}
1 Like