firmware: Initial animation
This commit is contained in:
		@@ -1,3 +1,3 @@
 | 
			
		||||
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 ".")
 | 
			
		||||
 
 | 
			
		||||
@@ -26,17 +26,35 @@
 | 
			
		||||
#define LVGL_TASK_PRIORITY   2
 | 
			
		||||
#define LVGL_TASK_STACK_SIZE (8 * 1024)
 | 
			
		||||
 | 
			
		||||
#define WAIT_VSYNC 0
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
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) {
 | 
			
		||||
  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) {
 | 
			
		||||
  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
 | 
			
		||||
  esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, px_map);
 | 
			
		||||
  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
 | 
			
		||||
  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_lcd_rgb_panel_event_callbacks_t cbs = {
 | 
			
		||||
    .on_vsync = val_on_vsync,
 | 
			
		||||
 
 | 
			
		||||
@@ -5,9 +5,14 @@
 | 
			
		||||
static const lv_font_t *font_normal = &lv_font_montserrat_24;
 | 
			
		||||
 | 
			
		||||
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) {
 | 
			
		||||
  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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void ui_home() {
 | 
			
		||||
  lv_obj_t *i_bg = lv_image_create(lv_screen_active());
 | 
			
		||||
  lv_image_set_src(i_bg, &ui_img_bg);
 | 
			
		||||
static void setup_next_state() {
 | 
			
		||||
  if (at_active) {
 | 
			
		||||
    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());
 | 
			
		||||
  lv_obj_add_style(l_test, &s_hero, 0);
 | 
			
		||||
  lv_label_set_text(l_test, "VAL TIME");
 | 
			
		||||
  o_active = lv_obj_create(o_container);
 | 
			
		||||
  lv_obj_center(o_active);
 | 
			
		||||
  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());
 | 
			
		||||
  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); 
 | 
			
		||||
  at_active = lv_anim_timeline_create();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
  lv_obj_t *l_cfg = lv_label_create(b_cfg);
 | 
			
		||||
  lv_label_set_text(l_cfg, LV_SYMBOL_SETTINGS);
 | 
			
		||||
  lv_obj_center(l_cfg);
 | 
			
		||||
static void anim_y_cb(void *var, int32_t v) {
 | 
			
		||||
  lv_obj_set_y(var, v);
 | 
			
		||||
}
 | 
			
		||||
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) {
 | 
			
		||||
@@ -38,6 +93,7 @@ void val_lvgl_ui(lv_display_t *disp) {
 | 
			
		||||
  color_secondary = lv_color_hex(0xf7518f);
 | 
			
		||||
 | 
			
		||||
  color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
 | 
			
		||||
  color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 2);
 | 
			
		||||
 | 
			
		||||
  // init default theme
 | 
			
		||||
  lv_theme_default_init(
 | 
			
		||||
@@ -47,8 +103,32 @@ void val_lvgl_ui(lv_display_t *disp) {
 | 
			
		||||
  // lv_sysmon_hide_performance(disp);
 | 
			
		||||
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
  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"
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,6 +7,7 @@
 | 
			
		||||
 | 
			
		||||
#include "common.h"
 | 
			
		||||
#include "usb.h"
 | 
			
		||||
#include "lcd.h"
 | 
			
		||||
 | 
			
		||||
#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_HID_INOUT_DESC_LEN)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user