Description
I have been happy too soon with a previous thread that I posted at Screen orientation change in runtime, like a smartphone. The result is valid only for a full-screen button! When a smaller button is created, screen-rotation does not work.
What MCU/Processor/Board and compiler are you using?
STM32L4xx
What LVGL version are you using?
v7.3.x
What do you want to achieve?
Screen rotation in runtime for four angles DISP_0_DEG
, DISP_90_DEG
, DISP_180_DEG
, and DISP_270_DEG
What have you tried so far?
Rotation working for full-screen button only but not a smaller button
Code to reproduce
/*Function below shows how a point (x,y) transformed in my code*/
static lv_point_t orientation_change(lv_disp_t *disp, disp_orientation_t orientation, lv_point_t lv_point)
{
(void) disp;
//scanning direction in OLED's device space is not changed for different LVGL orientation
//we need to transform a point in VDB space (lv_point) to device space (dev_point)
lv_point_t dev_point;
switch(orientation)
{
case DISP_270_DEG:
dev_point.x = lv_point.y;
dev_point.y = (lv_disp_get_hor_res(NULL)-1)- lv_point.x;
break;
case DISP_180_DEG:
dev_point.x = (lv_disp_get_hor_res(NULL)-1)- lv_point.x;
dev_point.y = (lv_disp_get_ver_res(NULL)-1)- lv_point.y;
break;
case DISP_90_DEG:
dev_point.x = (lv_disp_get_ver_res(NULL)-1)- lv_point.y;
dev_point.y = lv_point.x;
break;
default:
dev_point.x = lv_point.x;
dev_point.y = lv_point.y;
}
return dev_point;
}
/* flush_cb*/
void my_flush_cb(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
disp_orientation_t orientation = display_orientation_get();
lv_point_t _lv_point = {area->x1, area->y1};
//In device space, the top left point dev_point1 is...
lv_point_t dev_point1 = orientation_change(lv_disp, orientation, _lv_point);
_lv_point.x = area->x2;
_lv_point.y = area->y2;
//In device space, the lower right point dev_point2 is...
lv_point_t dev_point2 = orientation_change(lv_disp, orientation, _lv_point);
switch(orientation)
{
case DISP_270_DEG:
case DISP_180_DEG:
oled_flush(dev_point2.y, dev_point1.y, (const color_t *)color_p);
break;
case DISP_90_DEG:
oled_flush(dev_point1.y, dev_point2.y, (const color_t *)color_p);
break;
default:
oled_flush(area->y1, area->y2, (const color_t *)color_p);
}
lv_disp_flush_ready(&lv_disp_drv);
}
/**
* @note Converting lv_color_t in byte to bit-mask for BLACK/WHITE display
*/
void my_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) {
(void) disp_drv;
(void) buf_w;
(void) opa;
lv_point_t _lv_point = {x, y};
//Transform orientation from LVGL VDB space to OLED's device space
lv_point_t dev_point = orientation_change(lv_disp, display_orientation_get(), _lv_point);
if (lv_color_to1(color) == 1) {
buf[BUFIDX(dev_point.x, dev_point.y)] |= PIXIDX(dev_point.x); //Set VDB pixel bit to 1 for other colors than BLACK
} else {
buf[BUFIDX(dev_point.x, dev_point.y)] &= ~PIXIDX(dev_point.x); //Set VDB pixel bit to 0 for BLACK color
}
}
/**
* @brief Callback to round display update for a whole line
*/
void my_rounder_cb(lv_disp_drv_t * disp_drv, lv_area_t * area)
{
(void) disp_drv;
/* Round area to a whole line */
if((display_orientation_get()==DISP_0_DEG) || (display_orientation_get()==DISP_180_DEG))
{
area->x1 = 0;
area->x2 = 63;
}
else
{
area->y1 = 0;
area->y2 = 63;
}
}
Screenshot and/or video
This video shows the screen initialized with orientation set to DISP_270_DEG
Problem
The OLED is a portrait-type of native resolution 64(w)*128(h) with scanning from top left to lower right. As you can see, the screen was initialized OK with a button in the middle with screen orientation init to DISP_270_DEG. The problem came when it was touched. I believe the flush callback should allow for data shift with color_p+=offset
in (const color_t *) color_p
but I am not sure.