Rotation

LVGL supports rotation of the display in 90 degree increments.

The orientation of the display can be changed with lv_display_set_rotation(disp, LV_DISPLAY_ROTATION_xxx) where xxx is 0, 90, 180 or 270. This will swap the horizontal and vertical resolutions internally according to the set degree, however it will not perform the actual rotation. When changing the rotation, the LV_EVENT_SIZE_CHANGED event is emitted to allow for hardware reconfiguration. If your display panel and/or its driver chip(s) do not support rotation, lv_draw_sw_rotate() can be used to rotate the buffer in the Flush Callback function.

lv_display_rotate_area(display, &area) rotates the rendered area according to the current rotation settings of the display.

Note that in LV_DISPLAY_RENDER_MODE_DIRECT the small changed areas are rendered directly in the frame buffer so they cannot be rotated later. Therefore in direct mode only the whole frame buffer can be rotated. The same is true for LV_DISPLAY_RENDER_MODE_FULL.

In the case of LV_DISPLAY_RENDER_MODE_PARTIAL the small rendered areas can be rotated on their own before flushing to the frame buffer.

Below is an example for rotating when the rendering mode is LV_DISPLAY_RENDER_MODE_PARTIAL and the rotated image should be sent to a display controller.

/*Rotate a partially rendered area to another buffer and send it*/
void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
    lv_display_rotation_t rotation = lv_display_get_rotation(disp);
    lv_area_t rotated_area;
    if(rotation != LV_DISPLAY_ROTATION_0) {
        lv_color_format_t cf = lv_display_get_color_format(disp);
        /*Calculate the position of the rotated area*/
        rotated_area = *area;
        lv_display_rotate_area(disp, &rotated_area);
        /*Calculate the source stride (bytes in a line) from the width of the area*/
        uint32_t src_stride = lv_draw_buf_width_to_stride(lv_area_get_width(area), cf);
        /*Calculate the stride of the destination (rotated) area too*/
        uint32_t dest_stride = lv_draw_buf_width_to_stride(lv_area_get_width(&rotated_area), cf);
        /*Have a buffer to store the rotated area and perform the rotation*/
        static uint8_t rotated_buf[500*1014];
        int32_t src_w = lv_area_get_width(area);
        int32_t src_h = lv_area_get_height(area);
        lv_draw_sw_rotate(px_map, rotated_buf, src_w, src_h, src_stride, dest_stride, rotation, cf);
        /*Use the rotated area and rotated buffer from now on*/
        area = &rotated_area;
        px_map = rotated_buf;
    }
    my_set_window(area->x1, area->y1, area->x2, area->y2);
    my_send_colors(px_map);
}

Below is an example for rotating when the rendering mode is LV_DISPLAY_RENDER_MODE_PARTIAL and the image can be rotated directly into a frame buffer of the LCD peripheral.

/*Rotate a partially rendered area to the frame buffer*/
void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map)
{
    lv_color_format_t cf = lv_display_get_color_format(disp);
    uint32_t px_size = lv_color_format_get_size(cf);
    /*Calculate the position of the rotated area*/
    lv_area_t rotated_area = *area;
    lv_display_rotate_area(disp, &rotated_area);
    /*Calculate the properties of the source buffer*/
    int32_t src_w = lv_area_get_width(area);
    int32_t src_h = lv_area_get_height(area);
    uint32_t src_stride = lv_draw_buf_width_to_stride(src_w, cf);
    /*Calculate the properties of the frame buffer*/
    int32_t fb_stride = lv_draw_buf_width_to_stride(disp->hor_res, cf);
    uint8_t * fb_start = my_fb_address;
    fb_start += rotated_area.y1 * fb_stride + rotated_area.x1 * px_size;
    lv_display_rotation_t rotation = lv_display_get_rotation(disp);
    if(rotation == LV_DISPLAY_ROTATION_0) {
        int32_t y;
        for(y = area->y1; y <= area->y2; y++) {
            lv_memcpy(fb_start, px_map, src_stride);
            px_map += src_stride;
            fb_start += fb_stride;
        }
    }
    else {
        lv_draw_sw_rotate(px_map, fb_start, src_w, src_h, src_stride, fb_stride, rotation, cf);
    }
}