Loading Animation Screen Smoothly

Description

I tried switching between screens with lv_scr_load_anim(), but it loads with low rendering speed. I have tried optimizing SPI Frequency and prj.conf, still no difference.

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

MCU: nRF52832
Display: 240x240 ST7789 and CST816S
Platform: Zephyr with nRF Connect

What LVGL version are you using?

8.4.0

What do you want to achieve?

Smooth screen transition animations

What have you tried so far?

Optimized SPI speed frequency and LV memory size

Code to reproduce

main code:

void switch_to_screen(int screen_index, lv_scr_load_anim_t anim)
{
        uint64_t screen_count = sizeof(create_screens) / sizeof(create_screens[0]);

        if (screen_index < 0 || screen_index >= screen_count)
        {
                LOG_ERR("Invalid screen number: %d", screen_index);
                return;
        }

        lv_obj_t *screen = create_screens[screen_index]();
        if (screen == NULL)
        {
                LOG_ERR("Failed to create screen %d", screen_index);
                return;
        }

        lv_scr_load_anim(screen, anim, DISPLAY_ANIMATION_TIME, DISPLAY_ANIMATION_DELAY, true);

        current_screen = screen;
}

static void handle_screen_gesture(lv_dir_t dir)
{
        lv_scr_load_anim_t anim = LV_SCR_LOAD_ANIM_NONE;

        uint64_t screen_count = sizeof(create_screens) / sizeof(create_screens[0]);

        if (dir == LV_DIR_TOP)
        {
                current_screen_index++;
                if (current_screen_index > screen_count - 1)
                {
                        current_screen_index = 0;
                }

                anim = LV_SCR_LOAD_ANIM_MOVE_TOP;
        }
        else if (dir == LV_DIR_BOTTOM)
        {
                current_screen_index--;
                if (current_screen_index < 0)
                {
                        current_screen_index = screen_count - 1;
                }

                anim = LV_SCR_LOAD_ANIM_MOVE_BOTTOM;
        }
        else if (dir == LV_DIR_RIGHT && current_screen_index != 0)
        {
                current_screen_index = 0;
                switch_to_screen(current_screen_index, anim);
                return;
        }
        else
        {
                LOG_WRN("Unknown gesture direction: %d", dir);
                return;
        }

        switch_to_screen(current_screen_index, anim);

        last_screen_index = current_screen_index;
}

static void on_lvgl_screen_gesture_event_callback(lv_event_t *e)
{
        lv_dir_t dir;
        lv_event_code_t code = lv_event_get_code(e);
        if (code == LV_EVENT_GESTURE)
        {
                dir = lv_indev_get_gesture_dir(lv_indev_get_act());
                if (dir == LV_DIR_TOP || dir == LV_DIR_BOTTOM || dir == LV_DIR_RIGHT)
                {
                        if (change_to_others_screen)
                        {
                                handle_others_screen_gesture(dir);
                        }
                        else
                        {
                                handle_screen_gesture(dir);
                        }
                }
        }
        else if (code == LV_EVENT_CLICKED)
        {
                uint32_t screen_count = sizeof(create_screens) / sizeof(create_screens[0]);

                if (last_screen_index == screen_count - 1)
                {
                        if (!change_to_others_screen)
                        {
                                change_to_others_screen = true;
                                current_others_screen_index = 0;

                                k_msleep(DISPLAY_ANIMATION_DELAY);
                                switch_to_others_screen(current_others_screen_index, LV_SCR_LOAD_ANIM_NONE);
                        }
                }
        }
        else
        {
                LOG_WRN("Unknown event code: %d", code);
        }

        lv_indev_wait_release(lv_indev_get_act());
}

lv_obj_t *create_screen0()
{
        lv_obj_t *screen = lv_obj_create(NULL);
        lv_obj_set_style_bg_color(screen, lv_color_hex(0x000033), LV_PART_MAIN);

        lv_obj_t *label = lv_label_create(screen);
        lv_label_set_text(label, "Screen 0: Welcome!");
        lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN);
        lv_obj_set_style_text_font(label, &lv_font_montserrat_22, LV_PART_MAIN);
        lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

        lv_obj_add_event_cb(screen, on_lvgl_screen_gesture_event_callback, LV_EVENT_GESTURE, NULL);

        return screen;
}

lv_obj_t *create_screen1()
{
        lv_obj_t *screen = lv_obj_create(NULL);
        lv_obj_set_style_bg_color(screen, lv_color_hex(0x003366), LV_PART_MAIN);

        lv_obj_t *label = lv_label_create(screen);
        lv_label_set_text(label, "Screen 1: Hello!");
        lv_obj_set_style_text_color(label, lv_color_white(), LV_PART_MAIN);
        lv_obj_set_style_text_font(label, &lv_font_montserrat_22, LV_PART_MAIN);
        lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);

        lv_obj_add_event_cb(screen, on_lvgl_screen_gesture_event_callback, LV_EVENT_GESTURE, NULL);

        return screen;
}

Board overlay:

/ {
    chosen {
        zephyr,display = &display;
    };

    aliases {
        input = &touch_screen;
    };

    leds {
        compatible = "gpio-leds";
        lcd_backlight: lcd_backlight {
            gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
            label = "LCD Backlight";
        };
    };

    lvgl_pointer_input:lvgl_pointer {
        compatible = "zephyr,lvgl-pointer-input";
        input = <&touch_screen>;
    };
};

&spi0 {
    compatible = "nordic,nrf-spim";

	display: st7789v@0 {
        label = "ST7789 Display";
		compatible = "sitronix,st7789v";
        spi-max-frequency = <DT_FREQ_M(32)>;
        reg = <0>;
        cmd-data-gpios = < &gpio0 27 GPIO_ACTIVE_LOW>;
        reset-gpios = < &gpio0 31 GPIO_ACTIVE_LOW>;
        width = <240>;
        height = <240>;
        x-offset = <0>;
        y-offset = <0>;
        vcom = <0x19>;
        gctrl = <0x35>;
        vrhs = <0x12>;
        vdvs = <0x20>;
        mdac = <0x00>;
        gamma = <0x01>;
        colmod = <0x05>;
        lcm = <0x2c>;
        porch-param = [0c 0c 00 33 33];
        cmd2en-param = [5a 69 02 01];
        pwctrl1-param = [a4 a1];
        pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23];
        nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23];
        ram-param = [00 F0];
        rgb-param = [CD 08 14];
	};
};

&i2c1 {
    touch_screen: cst186s@15 {
        label = "CST816S";
        compatible = "hynitron,cst816s";
        reg = <0x15>;
        irq-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
        rst-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
    };
};

prj.conf

CONFIG_LOG=y
CONFIG_SHELL=y

CONFIG_THREAD_STACK_INFO=y

CONFIG_MAIN_STACK_SIZE=2048

CONFIG_DISPLAY=y
CONFIG_DISPLAY_LOG_LEVEL_ERR=y

CONFIG_LVGL=y
CONFIG_LV_Z_MEM_POOL_SIZE=8192
CONFIG_LV_Z_SHELL=y
CONFIG_LV_MEM_CUSTOM=y
CONFIG_LV_USE_LOG=y
CONFIG_LV_USE_LABEL=y
CONFIG_LV_FONT_MONTSERRAT_22=y
CONFIG_LV_Z_POINTER_INPUT=y

CONFIG_INPUT=y
CONFIG_INPUT_CST816S=y
CONFIG_INPUT_CST816S_INTERRUPT=y

CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58=y

Screenshot and/or video