diff --git a/firmware/.gitignore b/firmware/.gitignore index 8af1ba9..3396a99 100644 --- a/firmware/.gitignore +++ b/firmware/.gitignore @@ -5,3 +5,5 @@ sdkconfig.old *.swp /main/font/*.c /main/img/*.c +/assets/moon.png +/assets/star.png diff --git a/firmware/assets/moon_orig.png b/firmware/assets/moon_orig.png new file mode 100644 index 0000000..8bbb246 Binary files /dev/null and b/firmware/assets/moon_orig.png differ diff --git a/firmware/assets/star_orig.png b/firmware/assets/star_orig.png new file mode 100644 index 0000000..0c6705d Binary files /dev/null and b/firmware/assets/star_orig.png differ diff --git a/firmware/default.nix b/firmware/default.nix index 950df5e..c87ec3d 100644 --- a/firmware/default.nix +++ b/firmware/default.nix @@ -2,43 +2,6 @@ perSystem = { libMy, pkgs, ... }: let genImgsPy = pkgs.python3.withPackages (ps: with ps; [ pillow ]); - genImgs = pkgs.writeScriptBin "gen-imgs" '' - #!${genImgsPy}/bin/python - import itertools - import os - - from PIL import Image - - imgs = ['bg.png'] - for fname in imgs: - with Image.open(os.path.join('assets/', fname)) as img: - w = img.width - h = img.height - - data = [(r >> 3) << 11 | (g >> 2) << 5 | (b >> 3) for r, g, b in img.getdata()] - - basename = os.path.splitext(fname)[0] - with open(os.path.join('main/img/', basename + '.c'), 'w') as f: - f.write( - '#include <inttypes.h>\n\n' - '#include "lvgl.h"\n\n' - 'static const uint16_t _data[] = {\n') - - for group in itertools.batched(data, 20): - f.write(' ' + ' '.join(map(lambda i: f'{i:#x},', group)) + '\n') - - f.write('};\n\n') - - f.write( - f'const lv_image_dsc_t ui_img_{basename} = {{\n' - ' .header.magic = LV_IMAGE_HEADER_MAGIC,\n' - ' .header.cf = LV_COLOR_FORMAT_RGB565,\n' - f' .header.w = {w},\n' - f' .header.h = {h},\n' - ' .data_size = sizeof(_data) * 2,\n' - ' .data = (const uint8_t *)_data,\n' - '};\n') - ''; in { devenv.shells.firmware = libMy.withRootdir { @@ -46,7 +9,7 @@ esp-idf-esp32s3 picocom lv_font_conv - genImgs + imagemagick ]; env = { @@ -63,6 +26,12 @@ --format lvgl --lv-include lvgl.h --lv-font-name lv_font_tungsten_"$s" -o main/font/tungsten_"$s".c done ''; + gen-imgs.exec = '' + magick assets/moon_orig.png -resize 180x180 assets/moon.png + magick assets/star_orig.png -resize 180x180 assets/star.png + + ${genImgsPy}/bin/python gen-imgs.py + ''; }; }; }; diff --git a/firmware/gen-imgs.py b/firmware/gen-imgs.py new file mode 100755 index 0000000..27d7bc0 --- /dev/null +++ b/firmware/gen-imgs.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python3 +import itertools +import os +import struct + +from PIL import Image + +def rgb2h(r, g, b): + return (r >> 3) << 11 | (g >> 2) << 5 | (b >> 3) + +def bytes_line(bs): + return ' ' + ' '.join(map(lambda i: f'{i:#x},', bs)) + '\n' + +imgs = ['bg.png', 'moon.png', 'star.png'] +for fname in imgs: + alpha = [] + with Image.open(os.path.join('assets/', fname)) as img: + w = img.width + h = img.height + + if img.has_transparency_data: + has_alpha = True + data = [rgb2h(r, g, b) for r, g, b, _ in img.getdata()] + alpha = [a for _, _, _, a in img.getdata()] + else: + data = [rgb2h(r, g, b) for r, g, b in img.getdata()] + + basename = os.path.splitext(fname)[0] + with open(os.path.join('main/img/', basename + '.c'), 'w') as f: + f.write( + '#include <inttypes.h>\n\n' + '#include "lvgl.h"\n\n' + 'static const uint8_t _data[] = {\n') + + for group in itertools.batched(data, 10): + bs = bytearray() + for c in group: + bs += struct.pack('<H', c) + + f.write(bytes_line(bs)) + for group in itertools.batched(alpha, 20): + f.write(bytes_line(group)) + + f.write('};\n\n') + + f.write( + f'const lv_image_dsc_t ui_img_{basename} = {{\n' + ' .header.magic = LV_IMAGE_HEADER_MAGIC,\n' + f' .header.cf = LV_COLOR_FORMAT_RGB565{"A8" if alpha else ""},\n' + f' .header.w = {w},\n' + f' .header.h = {h},\n' + ' .data_size = sizeof(_data),\n' + ' .data = _data,\n' + '};\n') diff --git a/firmware/main/CMakeLists.txt b/firmware/main/CMakeLists.txt index 388d9e4..d318757 100644 --- a/firmware/main/CMakeLists.txt +++ b/firmware/main/CMakeLists.txt @@ -1,3 +1,3 @@ idf_component_register( - SRCS "valconomy.c" "ui.c" "lcd.c" "usb.c" "font/tungsten_40.c" "font/tungsten_180.c" "img/bg.c" + SRCS "valconomy.c" "ui.c" "lcd.c" "usb.c" "font/tungsten_40.c" "font/tungsten_180.c" "img/bg.c" "img/moon.c" "img/star.c" INCLUDE_DIRS ".") diff --git a/firmware/main/ui.c b/firmware/main/ui.c index 9fa50cd..98013a8 100644 --- a/firmware/main/ui.c +++ b/firmware/main/ui.c @@ -14,6 +14,23 @@ static lv_obj_t *o_container = NULL; static lv_anim_timeline_t *at_active = NULL; static lv_obj_t *o_active = NULL; +static const void* imgfont_get_path( + const lv_font_t *font, uint32_t unicode, uint32_t unicode_next, int32_t *offset_y, void *user_data) { + LV_UNUSED(font); + LV_UNUSED(unicode_next); + LV_UNUSED(offset_y); + LV_UNUSED(user_data); + + switch (unicode) { + case 0x1F319: + return &ui_img_moon; + case 0x2B50: + return &ui_img_star; + default: + return NULL; + } +} + static void b_cfg_cb(lv_event_t *e) { lv_obj_t *box = lv_msgbox_create(NULL); lv_msgbox_add_title(box, "Hello"); @@ -56,7 +73,7 @@ void val_ui_none() { 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_label_set_text_static(l_main, "HELLO \U0001F319\u2B50!"); lv_obj_t *l_subtitle = lv_label_create(o_active); lv_obj_add_style(l_subtitle, &s_subtitle, 0); @@ -108,7 +125,7 @@ void val_ui_none() { lv_anim_timeline_add(at_active, 0, &a_sub); lv_anim_timeline_add(at_active, 750, &a_hello_out); lv_anim_timeline_add(at_active, 1000, &a_val); - lv_anim_timeline_start(at_active); + // lv_anim_timeline_start(at_active); } void val_lvgl_ui(lv_display_t *disp) { @@ -125,8 +142,12 @@ void val_lvgl_ui(lv_display_t *disp) { font_normal); // lv_sysmon_hide_performance(disp); + lv_font_t *f_hero_emoji = lv_imgfont_create(180, imgfont_get_path, NULL); + assert(f_hero_emoji); + f_hero_emoji->fallback = &lv_font_tungsten_180; + lv_style_init(&s_hero); - lv_style_set_text_font(&s_hero, &lv_font_tungsten_180); + lv_style_set_text_font(&s_hero, f_hero_emoji); lv_style_set_text_color(&s_hero, color_text_hero); lv_style_init(&s_subtitle); diff --git a/firmware/main/ui.h b/firmware/main/ui.h index 5df141e..9d21da3 100644 --- a/firmware/main/ui.h +++ b/firmware/main/ui.h @@ -6,5 +6,7 @@ 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_moon); +LV_IMAGE_DECLARE(ui_img_star); void val_lvgl_ui(lv_display_t *disp); diff --git a/firmware/sdkconfig.defaults b/firmware/sdkconfig.defaults index c00aceb..db1704e 100644 --- a/firmware/sdkconfig.defaults +++ b/firmware/sdkconfig.defaults @@ -21,9 +21,11 @@ CONFIG_ESP_WIFI_DPP_SUPPORT=y CONFIG_FREERTOS_HZ=1000 CONFIG_TINYUSB_DEBUG_LEVEL=0 CONFIG_TINYUSB_HID_COUNT=1 +CONFIG_LV_DEF_REFR_PERIOD=24 CONFIG_LV_USE_LOG=y CONFIG_LV_LOG_PRINTF=y CONFIG_LV_FONT_MONTSERRAT_24=y CONFIG_LV_USE_SYSMON=y CONFIG_LV_USE_PERF_MONITOR=y +CONFIG_LV_USE_IMGFONT=y CONFIG_IDF_EXPERIMENTAL_FEATURES=y