Closed zpm1066 closed 3 years ago
The current display width/height can be obtained using display_get_capabilities
. As you can see in https://github.com/zephyrproject-rtos/zephyr/blob/master/drivers/display/display_ili9xxx.c#L297, the returned values will take into account the current rotation. Is that part failing?
Thank you for your response.
The ili9xxx_get_capabilities()
function does return the expected display size, howeverili9xxx_set_orientation()
in /zephyr/drivers/display/display_ili9xxx.c
does not update the display width (x_resolution
) & height (y_resolution
) depending on the rotation.
From my understanding, in ili9xxx_set_orientation
, for example if we had display_width
and display_height
then for the rotations we would add the following:
0 & 180 degrees: display_width = ILI##t##_X_RES, display_height = ILI##t##_Y_RES
90 & 270 degrees: display_width = ILI##t##_Y_RES, display_height = ILI##t##_X_RES
In ili9xxx_set_orientation()
, the display orientation is correctly updated via data->orientation = orientation
, so that ili9xxx_get_capabilities()
returns the correct display resolution. Note that in ili9xxx_get_capabilities()
, for 90 & 270 degrees, width & height get updated correctly. However, the ILI9XXX controller still has the display size prior to rotation. Therefore, after rotation, we'll see part of the display not used (see photo 2 below) thoughili9xxx_get_capabilities()
will think it's working with the new resolution.
I have a patched version to work but since the x_resolution
& y_resolution
(and inversion
) are being held in a static const struct ili9xxx_config ili9xxx_config_##n
and we appear to be using struct ili9xxx_data
in display_ili9xxx.c
, we may want to extend ili9xxx_data
to add display_width, display_height (and display_inversion) so that rotation works correctly (and we can also add a new ili9xxx_set_inversion()
function).
I assume we have the ili9xxx_data
so that we leave ili9xxx_config_##n
as is.
Do you know where ILI##t##_X_RES and ILI##t##_Y_RES are defined?
Thank you for looking at this issue.
Attached show the portrait image, portrait rotated by 90 degrees, and portrait rotated by 90 degrees correctly.
@key1066 from the screenshot it looks like you are using LVGL. Is this a correct observation?
If yes did you updated the field rotated inlv_disp_drv_t
when you called ili9xxx_set_orientation
?
Thank you for your suggestion. Yes, I'm using LVGL. No, I haven't updated the field rotated in lv_disp_drv_t. I'll take a look at your link and preview further.
From my earlier review of LVGL, my understanding from LVGL is that it doesn't rotate the output data itself, it only changes the logical screen size. The ILI9341 driver would still need to inform the ILI92431 controller of the new display area after sending the command, for example, to rotate the display from portrait to landscape 320x240.
In photo #2, LVGL won't be able to access the area outside the display screen size (non-white area), hence part of the logical 320x240 display that LVGL sees is off screen.
In the case of the Zephyr driver, ili9xxx_set_orientation
changes the logical screen size from portrait to landscape so that display_get_capabilities
reflects the landscape screen size but the ILI9341 controller still has the screen in portrait mode.
I have also reviewed the Adafruit ILI9341 driver source. They have a similar rotation method like ili9xxx_set_orientation
but in addition to issuing the rotation command to the ILI9341 controller, their ILI9341 driver also updates the display screen size when rotating from portrait to landscape (or landscape to portrait), and the GFX basically works with the logical screen size. This is currently what I do in my patched version but like to see a proper fix.
I have the same ILI9341 displays working under the Arduino Framework using the Adafruit ILI9341 driver. Their demo app cycles through the rotations quite fast.
I think the problem here is that LVGL configures its resolution when it is initialized (see https://github.com/zephyrproject-rtos/zephyr/blob/master/lib/gui/lvgl/lvgl.c#L99) but if you later change it via the display API you need to manually call https://docs.lvgl.io/latest/en/html/porting/display.html#_CPPv418lv_disp_drv_updateP9lv_disp_tP13lv_disp_drv_t with the new settings. @key1066 can you try?
@vanwinkeljan, @gmarull, Thank you. Much appreciated. As per your suggestion, I've used lv_disp_drv_update() in a local function to update the display orientation at run time, as in below.
All works fine.
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());
}
I also use ST7789V displays and noticed that st7789v_set_orientation
in https://github.com/zephyrproject-rtos/zephyr/blob/master/drivers/display/display_st7789v.c#L256 isn't currently implemented.
Are there plans to implement this function at some stage or is there another reason as to why it is not implemented? Thanks.
I also use ST7789V displays and noticed that st7789v_set_orientation in https://github.com/zephyrproject-rtos/zephyr/blob/master/drivers/display/display_st7789v.c#L256 isn't currently implemented.
Are there plans to implement this function at some stage or is there another reason as to why it is not implemented?
@jfischer-no is there any reason why the function is not implemented?
@key1066 I assume we can close the issue?
Regarding ST7789: A few months ago, I did open an enhancement request for ST7789 set orientation but got no response, https://github.com/zephyrproject-rtos/zephyr/issues/32286.
Shall I open a separate bug for ST7789 set orientation in the hope it may get some attention?
FYI - @vanwinkeljan, some of ST7789 displays like from Waveshare and others with CS can use the ILI9XXX driver.
Describe the bug The ili9xxx_set_orientation() function rotates the display but doesn't update the display width and height after rotation, if applicable.
In the ILI9XXX driver (display_ili9xxx.c), ILI9XXX configuration is held in a static const struct with display size attributes x_resolution = 240 & y_resolution = 320. The display is configured for portrait mode. Display rotation works fine for 0 (normal) & 180 degrees but not for 90 or 270 degrees. After rotation, the display area is not being adjusted to cover the whole display area in landscape.
If the board overlay is configured for landscape mode (i.e. x_resolution = 320 & y_resolution = 240), then rotation for landscape views (90 & 270) are fine but incorrect when in portrait mode. Reason being that the display area is not being adjusted after rotation.
What have you tried to diagnose or workaround this issue? I have used several ILI9341 displays from 2.8", 2.4" and 2" sizes.
To Reproduce Build the Adafruit 2." TFT Touch Shield v2 examples, /zephyrproject/zephyr/samples/display/lvgl. I adapted the sample for Particle Xenon and BBC MicroBit v2 boards. The Particle Xenon board overlay is attached below.
Expected behavior The ili9xxx_set_orientation() function should correctly rotate the display for all supported rotations 0, 90, 180 and 270 degrees, and adjust the display area to cover whole of the screen size.
Impact Unable to use the whole display area for presentation of text and graphics.
Logs and console output Display size is defined in a static const ili9xxx_config structure and therefor fixed as 240x320 ili9xxx_set_orientation() can be used to rotate the display
With x_resolution = 240, y_resolution = 320 --- normal (0 deg): display fills 240x320 area, upside down --- 180 deg: display fills 240x320 area --- 90 deg: displays 240x240 to left in landscape 320x240 --- 270 deg: displays 240x240 to left in landscape 320x240
With x_resolution = 320, y_resolution = 240 --- 90 deg: display fills 320x240 area --- 270 deg: display fills 320x240 area, upside down --- normal: displays 240x240 up in portrait 240x320 --- 180 deg: displays 240x240 up in portrait 240x320
Environment (please complete the following information):
Additional context Here's the devicetree section from the Particle Xenon nRF52840 board overlay.
&spi0 { compatible = "nordic,nrf-spi"; status = "okay"; sck-pin = <47>; mosi-pin = <45>; miso-pin = <46>; cs-gpios = <&gpio1 8 GPIO_ACTIVE_LOW>; / D4 /