feat(ui): scene view + original fonts, 3MB apps
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
idf_component_register(
|
||||
SRCS "display_ui.cpp"
|
||||
"fonts/lv_font_orbitron_40.c"
|
||||
"fonts/lv_font_ibmplexmono_18.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES driver local_puzzles esp_timer
|
||||
)
|
||||
|
||||
@@ -59,6 +59,10 @@
|
||||
#include <LovyanGFX.hpp>
|
||||
#include "lvgl.h"
|
||||
|
||||
// Original UI fonts (fonts/ — copied from ui_freenove_allinone/src/ui/fonts/).
|
||||
LV_FONT_DECLARE(lv_font_orbitron_40);
|
||||
LV_FONT_DECLARE(lv_font_ibmplexmono_18);
|
||||
|
||||
static const char *TAG = "display_ui";
|
||||
|
||||
// ─── LovyanGFX device (faithful port of FreenoveLgfxDevice) ──────────────────
|
||||
@@ -171,10 +175,19 @@ typedef struct {
|
||||
lv_obj_t *value; // value label of a row
|
||||
} dui_row_t;
|
||||
|
||||
static lv_obj_t *s_scr_status; // status screen (no active step)
|
||||
static lv_obj_t *s_lbl_title;
|
||||
static dui_row_t s_row_ip, s_row_wake, s_row_step, s_row_armed, s_row_solved;
|
||||
static lv_obj_t *s_lbl_code;
|
||||
|
||||
// Scene view (active step) — structure mirrors the original ui_manager scene
|
||||
// frame: title (Orbitron), subtitle (IBM Plex Mono), symbol slot (the
|
||||
// assembled code, pulse effect = SceneEffect::kPulse default).
|
||||
static lv_obj_t *s_scr_scene;
|
||||
static lv_obj_t *s_scene_title; // step id, Orbitron 40, top-center
|
||||
static lv_obj_t *s_scene_subtitle; // armed puzzle, IBM Plex 18, bottom
|
||||
static lv_obj_t *s_scene_code; // assembled code, Orbitron 40, center
|
||||
|
||||
static lv_obj_t *make_row(lv_obj_t *parent, int y, const char *label_txt,
|
||||
dui_row_t *out) {
|
||||
lv_obj_t *lbl = lv_label_create(parent);
|
||||
@@ -195,8 +208,51 @@ static lv_obj_t *make_row(lv_obj_t *parent, int y, const char *label_txt,
|
||||
return val;
|
||||
}
|
||||
|
||||
// Pulse animation on the scene code — SceneEffect::kPulse equivalent.
|
||||
static void pulse_anim_cb(void *obj, int32_t v) {
|
||||
lv_obj_set_style_opa((lv_obj_t *) obj, (lv_opa_t) v, 0);
|
||||
}
|
||||
|
||||
static void build_scene_screen(void) {
|
||||
s_scr_scene = lv_obj_create(NULL);
|
||||
lv_obj_set_style_bg_color(s_scr_scene, lv_color_hex(0x000000), 0);
|
||||
lv_obj_set_style_bg_opa(s_scr_scene, LV_OPA_COVER, 0);
|
||||
|
||||
s_scene_title = lv_label_create(s_scr_scene);
|
||||
lv_obj_set_style_text_color(s_scene_title, lv_color_hex(COL_VALUE), 0);
|
||||
lv_obj_set_style_text_font(s_scene_title, &lv_font_orbitron_40, 0);
|
||||
lv_label_set_text(s_scene_title, "");
|
||||
lv_label_set_long_mode(s_scene_title, LV_LABEL_LONG_SCROLL_CIRCULAR);
|
||||
lv_obj_set_width(s_scene_title, DUI_HOR_RES - 24);
|
||||
lv_obj_set_style_text_align(s_scene_title, LV_TEXT_ALIGN_CENTER, 0);
|
||||
lv_obj_align(s_scene_title, LV_ALIGN_TOP_MID, 0, 24);
|
||||
|
||||
s_scene_code = lv_label_create(s_scr_scene);
|
||||
lv_obj_set_style_text_color(s_scene_code, lv_color_hex(COL_CODE), 0);
|
||||
lv_obj_set_style_text_font(s_scene_code, &lv_font_orbitron_40, 0);
|
||||
lv_label_set_text(s_scene_code, "");
|
||||
lv_obj_align(s_scene_code, LV_ALIGN_CENTER, 0, 16);
|
||||
|
||||
s_scene_subtitle = lv_label_create(s_scr_scene);
|
||||
lv_obj_set_style_text_color(s_scene_subtitle, lv_color_hex(COL_LABEL), 0);
|
||||
lv_obj_set_style_text_font(s_scene_subtitle, &lv_font_ibmplexmono_18, 0);
|
||||
lv_label_set_text(s_scene_subtitle, "");
|
||||
lv_obj_align(s_scene_subtitle, LV_ALIGN_BOTTOM_LEFT, 8, -10);
|
||||
|
||||
// Pulse on the code (original default scene effect).
|
||||
lv_anim_t a;
|
||||
lv_anim_init(&a);
|
||||
lv_anim_set_var(&a, s_scene_code);
|
||||
lv_anim_set_exec_cb(&a, pulse_anim_cb);
|
||||
lv_anim_set_values(&a, LV_OPA_COVER, LV_OPA_50);
|
||||
lv_anim_set_time(&a, 600);
|
||||
lv_anim_set_playback_time(&a, 600);
|
||||
lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE);
|
||||
lv_anim_start(&a);
|
||||
}
|
||||
|
||||
static void build_status_screen(void) {
|
||||
lv_obj_t *scr = lv_scr_act();
|
||||
lv_obj_t *scr = s_scr_status;
|
||||
lv_obj_set_style_bg_color(scr, lv_color_hex(COL_BG), 0);
|
||||
lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0);
|
||||
|
||||
@@ -232,6 +288,7 @@ static void build_status_screen(void) {
|
||||
}
|
||||
|
||||
static void apply_status(const display_status_t *s) {
|
||||
// Status screen rows
|
||||
lv_label_set_text(s_row_ip.value, s->ip[0] ? s->ip : "(aucune)");
|
||||
lv_label_set_text(s_row_wake.value, s->wake_active ? "oui" : "non");
|
||||
lv_label_set_text(s_row_step.value, s->step_id[0] ? s->step_id : "(aucune)");
|
||||
@@ -244,6 +301,23 @@ static void apply_status(const display_status_t *s) {
|
||||
char code[32];
|
||||
snprintf(code, sizeof(code), "Code: %s", s->code[0] ? s->code : "---");
|
||||
lv_label_set_text(s_lbl_code, code);
|
||||
|
||||
// Scene screen
|
||||
lv_label_set_text(s_scene_title, s->step_id);
|
||||
if (s->armed[0] && strcmp(s->armed, "none") != 0) {
|
||||
snprintf(tmp, sizeof(tmp), "enigme: %s", s->armed);
|
||||
} else {
|
||||
snprintf(tmp, sizeof(tmp), "resolues: %u", (unsigned) s->solved_count);
|
||||
}
|
||||
lv_label_set_text(s_scene_subtitle, tmp);
|
||||
lv_label_set_text(s_scene_code, s->code[0] ? s->code : "");
|
||||
|
||||
// Active step → scene view; idle → status view. Fade 240 ms, the
|
||||
// original ui_manager default transition (SceneTransition::kFade, 240).
|
||||
lv_obj_t *want = s->step_id[0] ? s_scr_scene : s_scr_status;
|
||||
if (lv_scr_act() != want) {
|
||||
lv_scr_load_anim(want, LV_SCR_LOAD_ANIM_FADE_ON, 240, 0, false);
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Raw splash (pre-LVGL, visible during the rest of boot) ───────────────────
|
||||
@@ -309,7 +383,9 @@ static void display_task(void *arg) {
|
||||
(void) arg;
|
||||
|
||||
// LVGL lives entirely on this task.
|
||||
s_scr_status = lv_scr_act();
|
||||
build_status_screen();
|
||||
build_scene_screen();
|
||||
|
||||
display_status_t local_status;
|
||||
memset(&local_status, 0, sizeof(local_status));
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
# Fonts — copied from ui_freenove_allinone/src/ui/fonts/ (original Arduino UI).
|
||||
# Generated LVGL 8 bitmap fonts (see each file header for lv_font_conv options).
|
||||
# Orbitron 40: scene titles/symbol. IBM Plex Mono 18: scene body text.
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -5,21 +5,27 @@
|
||||
# esp-sr component CMake glue).
|
||||
#
|
||||
# Total target: 16 MB flash (Freenove ESP32-S3 N16R8).
|
||||
# Layout (rough): 0x000000-0x020000 system, 0x020000-0x620000 apps (3×2 MB),
|
||||
# 0x620000-0x720000 model (SPIFFS 1 MB, esp-sr models),
|
||||
# 0x720000-0xC20000 storage (LittleFS 5 MB),
|
||||
# 0xC20000-0x1000000 unused (~3.87 MB headroom).
|
||||
# Layout (rough): 0x000000-0x020000 system, 0x020000-0x920000 apps (3×3 MB),
|
||||
# 0x920000-0xA20000 model (SPIFFS 1 MB, esp-sr models),
|
||||
# 0xA20000-0xF20000 storage (LittleFS 5 MB),
|
||||
# 0xF20000-0x1000000 unused (~0.87 MB headroom).
|
||||
#
|
||||
# App partition bumped 1.5 MB → 2 MB (2026-05-03) to give voice/STT/hints
|
||||
# slices and esp-sr integration ~25 % free space margin. OTA dual-bank
|
||||
# preserved (factory + ota_0 + ota_1 all 2 MB → rollback symmetry intact).
|
||||
#
|
||||
# Bumped 2 MB → 3 MB (2026-06-10, display_ui phase 2b): LVGL + LovyanGFX +
|
||||
# the original UI fonts left only 5 % app headroom; later UI phases (camera
|
||||
# preview, more fonts, effects) need room. NVS/otadata/phy offsets unchanged
|
||||
# (Wi-Fi creds survive); ota_0/ota_1/model/storage shift — LittleFS content
|
||||
# is lost on reflash (auto-reformats; re-push scenario via POST /game/scenario).
|
||||
#
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0x9000, 0x6000,
|
||||
otadata, data, ota, 0xf000, 0x2000,
|
||||
phy_init, data, phy, 0x11000, 0x1000,
|
||||
factory, app, factory, 0x20000, 0x200000,
|
||||
ota_0, app, ota_0, , 0x200000,
|
||||
ota_1, app, ota_1, , 0x200000,
|
||||
factory, app, factory, 0x20000, 0x300000,
|
||||
ota_0, app, ota_0, , 0x300000,
|
||||
ota_1, app, ota_1, , 0x300000,
|
||||
model, data, spiffs, , 0x100000,
|
||||
storage, data, littlefs,, 0x500000,
|
||||
|
||||
|
Reference in New Issue
Block a user