Rotating the buffer in fbdev.c

Description

I am trying to rotate the screen on an external display (not simulator), which uses HDMI and the framebuffer.

What MCU/Processor/Board and compiler are you using?

HDMI display on Linux-PC

What LVGL version are you using?

7.x

What do you want to achieve?

Rotate the display from landscape to portrait.

What have you tried so far?

Changes in fbdev.c analogue to (example is for simulator) :

At the moment I have to multiply:

LV_HOR_RES_MAX by 2
LV_VER_RES_MAX by 1.2 (or LOW_VER_RES_MAX + LOW_VER_RES_MAX/4+1)

so

if LV_HOR_RES_MAX is 240, it has to be set to 480
and LV_VER_RES_MAX from 400 to 480

so that it works, I don’t know, what part is wrong.

Code to reproduce

fbdev.c change (code is largely copied from) :

The code block(s) should be formatted like:

void get_col2(const uint32_t * src, const lv_area_t * area, int32_t y, uint32_t * dest)
{
    lv_coord_t w = lv_area_get_width(area);
    lv_coord_t h = lv_area_get_height(area);

    lv_coord_t i;
    for(i = 0; i < h; i++) {
        dest[i] = src[y];
        src += w ;
    }
}


/**
 * Flush a buffer to the marked area
 * @param drv pointer to driver where this function belongs
 * @param area an area where to copy `color_p`
 * @param color_p an array of pixel to copy to the `area` part of the screen
 */
void fbdev_flush(lv_disp_drv_t * drv, const lv_area_t * area, lv_color_t * color_p)
{
    if(fbp == NULL ||
            area->x2 < 0 ||
            area->y2 < 0 ||
            area->x1 > (int32_t)vinfo.xres - 1 ||
            area->y1 > (int32_t)vinfo.yres - 1) {
        lv_disp_flush_ready(drv);
        return;
    }


    /*Truncate the area to the screen*/
    int32_t act_x1 = area->x1 < 0 ? 0 : area->x1;
    int32_t act_y1 = area->y1 < 0 ? 0 : area->y1;
    int32_t act_x2 = area->x2 > (int32_t)vinfo.xres - 1 ? (int32_t)vinfo.xres - 1 : area->x2;
    int32_t act_y2 = area->y2 > (int32_t)vinfo.yres - 1 ? (int32_t)vinfo.yres - 1 : area->y2;


    lv_coord_t w = (act_x2 - act_x1 + 1);
    long int location = 0;
    long int byte_location = 0;
    unsigned char bit_location = 0;

    /*32 or 24 bit per pixel*/
    if(vinfo.bits_per_pixel == 32 || vinfo.bits_per_pixel == 24) {
        // uint32_t * fbp32 = (uint32_t *)fbp;
        // int32_t y;
        // for(y = act_y1; y <= act_y2; y++) {
        //     location = (act_x1 + vinfo.xoffset) + (y + vinfo.yoffset) * finfo.line_length / 4;
        //     memcpy(&fbp32[location], (uint32_t *)color_p, (act_x2 - act_x1 + 1) * 4);
        //     color_p += w;
        // }
        lv_coord_t x2 = area->x2;
        if(x2 >= drv->ver_res) x2 = LV_VER_RES_MAX - 1;
        uint32_t* dest = (uint32_t *)fbp;
        dest +=  LV_HOR_RES_MAX * (LV_VER_RES_MAX - 1);
        dest -= LV_HOR_RES_MAX * area->x1;

        int32_t x;
        for(x = area->x1; x <= x2; x++) {
            get_col2(color_p, area, (x - area->x1), dest + area->y1);
            dest -= LV_HOR_RES_MAX;
        }

    }
...
}

Screenshot and/or video

Hi,

In v7.11 @embeddedt added a software rotation option. See here: https://github.com/lvgl/lvgl/blob/acf42d399977eecfc431f9dd0bbb070724bd8e0a/src/lv_hal/lv_hal_disp.h#L86-L87

1 Like

Awesome thanks to @embeddedt and you. I’ll have to look into it, how you did it. The operation has O(n^2) complexity as far as I see.

Besides enabling that software rotation option; which code should be implemented in runtime to get the display to rotate? What function should I call?

See Display interface — LVGL documentation