firmware: Initial animation
This commit is contained in:
parent
0607f08b83
commit
84fb7553c5
@ -58,7 +58,7 @@
|
|||||||
idf.py set-target esp32s3
|
idf.py set-target esp32s3
|
||||||
'';
|
'';
|
||||||
gen-fonts.exec = ''
|
gen-fonts.exec = ''
|
||||||
for s in 120; do
|
for s in 40 180; do
|
||||||
DEBUG='*' lv_font_conv --font assets/Tungsten-Bold.ttf --bpp 4 --size $s -r 0x20-0x7F --no-compress \
|
DEBUG='*' lv_font_conv --font assets/Tungsten-Bold.ttf --bpp 4 --size $s -r 0x20-0x7F --no-compress \
|
||||||
--format lvgl --lv-include lvgl.h --lv-font-name lv_font_tungsten_"$s" -o main/font/tungsten_"$s".c
|
--format lvgl --lv-include lvgl.h --lv-font-name lv_font_tungsten_"$s" -o main/font/tungsten_"$s".c
|
||||||
done
|
done
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS "valconomy.c" "ui.c" "lcd.c" "usb.c" "font/tungsten_120.c" "img/bg.c"
|
SRCS "valconomy.c" "ui.c" "lcd.c" "usb.c" "font/tungsten_40.c" "font/tungsten_180.c" "img/bg.c"
|
||||||
INCLUDE_DIRS ".")
|
INCLUDE_DIRS ".")
|
||||||
|
@ -26,17 +26,35 @@
|
|||||||
#define LVGL_TASK_PRIORITY 2
|
#define LVGL_TASK_PRIORITY 2
|
||||||
#define LVGL_TASK_STACK_SIZE (8 * 1024)
|
#define LVGL_TASK_STACK_SIZE (8 * 1024)
|
||||||
|
|
||||||
|
#define WAIT_VSYNC 0
|
||||||
|
|
||||||
static const char *TAG = "valconomy-lcd";
|
static const char *TAG = "valconomy-lcd";
|
||||||
|
|
||||||
// LVGL library is not thread-safe, we will call LVGL APIs from different tasks, so use a mutex to protect it
|
// LVGL library is not thread-safe, we will call LVGL APIs from different tasks, so use a mutex to protect it
|
||||||
static SemaphoreHandle_t lvgl_mtx = NULL;
|
static SemaphoreHandle_t lvgl_mtx = NULL;
|
||||||
|
#if WAIT_VSYNC
|
||||||
|
static SemaphoreHandle_t sem_vsync_end = NULL;
|
||||||
|
static SemaphoreHandle_t sem_gui_ready = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
static bool val_on_vsync(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx) {
|
static bool val_on_vsync(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *event_data, void *user_ctx) {
|
||||||
return false;
|
BaseType_t high_task_awoken = pdFALSE;
|
||||||
|
#if WAIT_VSYNC
|
||||||
|
if (xSemaphoreTakeFromISR(sem_gui_ready, &high_task_awoken) == pdTRUE) {
|
||||||
|
xSemaphoreGiveFromISR(sem_vsync_end, &high_task_awoken);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return high_task_awoken == pdTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void val_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
|
static void val_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) {
|
||||||
esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp);
|
esp_lcd_panel_handle_t panel_handle = lv_display_get_user_data(disp);
|
||||||
|
#if WAIT_VSYNC
|
||||||
|
xSemaphoreGive(sem_gui_ready);
|
||||||
|
xSemaphoreTake(sem_vsync_end, portMAX_DELAY);
|
||||||
|
#endif
|
||||||
|
|
||||||
// pass the draw buffer to the driver
|
// pass the draw buffer to the driver
|
||||||
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
|
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
|
||||||
lv_disp_flush_ready(disp);
|
lv_disp_flush_ready(disp);
|
||||||
@ -225,6 +243,13 @@ lv_display_t *val_setup_lvgl(esp_lcd_panel_handle_t lcd_panel, esp_lcd_touch_han
|
|||||||
// set the callback which can copy the rendered image to an area of the display
|
// set the callback which can copy the rendered image to an area of the display
|
||||||
lv_display_set_flush_cb(display, val_lvgl_flush_cb);
|
lv_display_set_flush_cb(display, val_lvgl_flush_cb);
|
||||||
|
|
||||||
|
#if WAIT_VSYNC
|
||||||
|
sem_vsync_end = xSemaphoreCreateBinary();
|
||||||
|
assert(sem_vsync_end);
|
||||||
|
sem_gui_ready = xSemaphoreCreateBinary();
|
||||||
|
assert(sem_gui_ready);
|
||||||
|
#endif
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Register event callbacks");
|
ESP_LOGI(TAG, "Register event callbacks");
|
||||||
esp_lcd_rgb_panel_event_callbacks_t cbs = {
|
esp_lcd_rgb_panel_event_callbacks_t cbs = {
|
||||||
.on_vsync = val_on_vsync,
|
.on_vsync = val_on_vsync,
|
||||||
|
@ -5,9 +5,14 @@
|
|||||||
static const lv_font_t *font_normal = &lv_font_montserrat_24;
|
static const lv_font_t *font_normal = &lv_font_montserrat_24;
|
||||||
|
|
||||||
static lv_color_t color_primary, color_secondary;
|
static lv_color_t color_primary, color_secondary;
|
||||||
static lv_color_t color_text_hero;
|
static lv_color_t color_text_hero, color_text_subtitle;
|
||||||
|
|
||||||
static lv_style_t s_hero;
|
static lv_style_t s_hero, s_subtitle;
|
||||||
|
|
||||||
|
static lv_obj_t *o_container = NULL;
|
||||||
|
|
||||||
|
static lv_anim_timeline_t *at_active = NULL;
|
||||||
|
static lv_obj_t *o_active = NULL;
|
||||||
|
|
||||||
static void b_cfg_cb(lv_event_t *e) {
|
static void b_cfg_cb(lv_event_t *e) {
|
||||||
lv_obj_t *box = lv_msgbox_create(NULL);
|
lv_obj_t *box = lv_msgbox_create(NULL);
|
||||||
@ -16,21 +21,71 @@ static void b_cfg_cb(lv_event_t *e) {
|
|||||||
lv_msgbox_add_close_button(box);
|
lv_msgbox_add_close_button(box);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ui_home() {
|
static void setup_next_state() {
|
||||||
lv_obj_t *i_bg = lv_image_create(lv_screen_active());
|
if (at_active) {
|
||||||
lv_image_set_src(i_bg, &ui_img_bg);
|
lv_anim_timeline_delete(at_active);
|
||||||
|
at_active = NULL;
|
||||||
|
}
|
||||||
|
if (o_active) {
|
||||||
|
lv_obj_delete(o_active);
|
||||||
|
o_active = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
lv_obj_t *l_test = lv_label_create(lv_screen_active());
|
o_active = lv_obj_create(o_container);
|
||||||
lv_obj_add_style(l_test, &s_hero, 0);
|
lv_obj_center(o_active);
|
||||||
lv_label_set_text(l_test, "VAL TIME");
|
lv_obj_set_style_bg_opa(o_active, LV_OPA_0, 0);
|
||||||
|
lv_obj_set_style_border_width(o_active, 0, 0);
|
||||||
|
lv_obj_set_size(o_active, lv_pct(100), lv_pct(100));
|
||||||
|
|
||||||
lv_obj_t *b_cfg = lv_button_create(lv_screen_active());
|
at_active = lv_anim_timeline_create();
|
||||||
lv_obj_align(b_cfg, LV_ALIGN_BOTTOM_RIGHT, -10, -10);
|
}
|
||||||
lv_obj_add_event_cb(b_cfg, b_cfg_cb, LV_EVENT_CLICKED, NULL);
|
|
||||||
|
|
||||||
lv_obj_t *l_cfg = lv_label_create(b_cfg);
|
static void anim_y_cb(void *var, int32_t v) {
|
||||||
lv_label_set_text(l_cfg, LV_SYMBOL_SETTINGS);
|
lv_obj_set_y(var, v);
|
||||||
lv_obj_center(l_cfg);
|
}
|
||||||
|
static void anim_opa_cb(void *var, int32_t v) {
|
||||||
|
lv_obj_set_style_opa(var, v, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void val_ui_none() {
|
||||||
|
setup_next_state();
|
||||||
|
|
||||||
|
lv_obj_t *l_main = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_main, &s_hero, 0);
|
||||||
|
lv_obj_center(l_main);
|
||||||
|
lv_label_set_text_static(l_main, "HELLO MS!");
|
||||||
|
|
||||||
|
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||||
|
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||||
|
lv_obj_center(l_subtitle);
|
||||||
|
lv_label_set_text_static(l_subtitle, "THERE'S ALWAYS TIME FOR VAL...");
|
||||||
|
|
||||||
|
lv_obj_update_layout(o_active);
|
||||||
|
lv_obj_set_pos(
|
||||||
|
l_subtitle, -(lv_obj_get_width(l_main) - lv_obj_get_width(l_subtitle)) / 2, lv_obj_get_height(l_main) / 2);
|
||||||
|
|
||||||
|
// Animations
|
||||||
|
lv_anim_t a_hello_in;
|
||||||
|
lv_anim_init(&a_hello_in);
|
||||||
|
lv_anim_set_var(&a_hello_in, l_main);
|
||||||
|
lv_anim_set_values(
|
||||||
|
&a_hello_in,
|
||||||
|
(lv_obj_get_height(o_container) - lv_obj_get_height(l_main)) / 2, 0);
|
||||||
|
lv_anim_set_exec_cb(&a_hello_in, anim_y_cb);
|
||||||
|
lv_anim_set_path_cb(&a_hello_in, lv_anim_path_ease_in);
|
||||||
|
lv_anim_set_duration(&a_hello_in, 500);
|
||||||
|
|
||||||
|
lv_anim_t a_sub;
|
||||||
|
lv_anim_init(&a_sub);
|
||||||
|
lv_anim_set_var(&a_sub, l_subtitle);
|
||||||
|
lv_anim_set_values(&a_sub, 0, 255);
|
||||||
|
lv_anim_set_exec_cb(&a_sub, anim_opa_cb);
|
||||||
|
lv_anim_set_path_cb(&a_sub, lv_anim_path_linear);
|
||||||
|
lv_anim_set_duration(&a_sub, 750);
|
||||||
|
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_hello_in);
|
||||||
|
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||||
|
lv_anim_timeline_start(at_active);
|
||||||
}
|
}
|
||||||
|
|
||||||
void val_lvgl_ui(lv_display_t *disp) {
|
void val_lvgl_ui(lv_display_t *disp) {
|
||||||
@ -38,6 +93,7 @@ void val_lvgl_ui(lv_display_t *disp) {
|
|||||||
color_secondary = lv_color_hex(0xf7518f);
|
color_secondary = lv_color_hex(0xf7518f);
|
||||||
|
|
||||||
color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
|
color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
|
||||||
|
color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 2);
|
||||||
|
|
||||||
// init default theme
|
// init default theme
|
||||||
lv_theme_default_init(
|
lv_theme_default_init(
|
||||||
@ -47,8 +103,32 @@ void val_lvgl_ui(lv_display_t *disp) {
|
|||||||
// lv_sysmon_hide_performance(disp);
|
// lv_sysmon_hide_performance(disp);
|
||||||
|
|
||||||
lv_style_init(&s_hero);
|
lv_style_init(&s_hero);
|
||||||
lv_style_set_text_font(&s_hero, &lv_font_tungsten_120);
|
lv_style_set_text_font(&s_hero, &lv_font_tungsten_180);
|
||||||
lv_style_set_text_color(&s_hero, color_text_hero);
|
lv_style_set_text_color(&s_hero, color_text_hero);
|
||||||
|
|
||||||
ui_home();
|
lv_style_init(&s_subtitle);
|
||||||
|
lv_style_set_text_font(&s_subtitle, &lv_font_tungsten_40);
|
||||||
|
lv_style_set_text_color(&s_subtitle, color_text_subtitle);
|
||||||
|
|
||||||
|
// Background
|
||||||
|
lv_obj_t *i_bg = lv_image_create(lv_screen_active());
|
||||||
|
lv_image_set_src(i_bg, &ui_img_bg);
|
||||||
|
|
||||||
|
// Content container
|
||||||
|
o_container = lv_obj_create(lv_screen_active());
|
||||||
|
lv_obj_set_style_bg_opa(o_container, LV_OPA_0, 0);
|
||||||
|
lv_obj_set_style_border_width(o_container, 0, 0);
|
||||||
|
lv_obj_set_style_pad_all(o_container, 0, 0);
|
||||||
|
lv_obj_set_size(o_container, lv_pct(100), lv_pct(100));
|
||||||
|
|
||||||
|
// Settings button
|
||||||
|
lv_obj_t *b_cfg = lv_button_create(lv_screen_active());
|
||||||
|
lv_obj_align(b_cfg, LV_ALIGN_BOTTOM_RIGHT, -10, -10);
|
||||||
|
lv_obj_add_event_cb(b_cfg, b_cfg_cb, LV_EVENT_CLICKED, NULL);
|
||||||
|
|
||||||
|
lv_obj_t *l_cfg = lv_label_create(b_cfg);
|
||||||
|
lv_label_set_text(l_cfg, LV_SYMBOL_SETTINGS);
|
||||||
|
lv_obj_center(l_cfg);
|
||||||
|
|
||||||
|
val_ui_none();
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
#include "lvgl.h"
|
#include "lvgl.h"
|
||||||
|
|
||||||
LV_FONT_DECLARE(lv_font_tungsten_120)
|
LV_FONT_DECLARE(lv_font_tungsten_40)
|
||||||
|
LV_FONT_DECLARE(lv_font_tungsten_180)
|
||||||
|
|
||||||
LV_IMAGE_DECLARE(ui_img_bg);
|
LV_IMAGE_DECLARE(ui_img_bg);
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "usb.h"
|
#include "usb.h"
|
||||||
|
#include "lcd.h"
|
||||||
|
|
||||||
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
|
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
|
|||||||
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
|
CONFIG_ESPTOOLPY_FLASHFREQ_120M=y
|
||||||
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
CONFIG_ESPTOOLPY_FLASHSIZE_8MB=y
|
||||||
CONFIG_PARTITION_TABLE_CUSTOM=y
|
CONFIG_PARTITION_TABLE_CUSTOM=y
|
||||||
|
CONFIG_COMPILER_OPTIMIZATION_PERF=y
|
||||||
CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=n
|
CONFIG_USJ_ENABLE_USB_SERIAL_JTAG=n
|
||||||
CONFIG_SPIRAM=y
|
CONFIG_SPIRAM=y
|
||||||
CONFIG_SPIRAM_MODE_OCT=y
|
CONFIG_SPIRAM_MODE_OCT=y
|
||||||
@ -20,7 +21,6 @@ CONFIG_ESP_WIFI_DPP_SUPPORT=y
|
|||||||
CONFIG_FREERTOS_HZ=1000
|
CONFIG_FREERTOS_HZ=1000
|
||||||
CONFIG_TINYUSB_DEBUG_LEVEL=0
|
CONFIG_TINYUSB_DEBUG_LEVEL=0
|
||||||
CONFIG_TINYUSB_HID_COUNT=1
|
CONFIG_TINYUSB_HID_COUNT=1
|
||||||
CONFIG_LV_DEF_REFR_PERIOD=24
|
|
||||||
CONFIG_LV_USE_LOG=y
|
CONFIG_LV_USE_LOG=y
|
||||||
CONFIG_LV_LOG_PRINTF=y
|
CONFIG_LV_LOG_PRINTF=y
|
||||||
CONFIG_LV_FONT_MONTSERRAT_24=y
|
CONFIG_LV_FONT_MONTSERRAT_24=y
|
||||||
|
Loading…
Reference in New Issue
Block a user