diff --git a/components/control_plane/src/runtime/control_plane_key_input.c b/components/control_plane/src/runtime/control_plane_key_input.c index b87397a..e924c22 100644 --- a/components/control_plane/src/runtime/control_plane_key_input.c +++ b/components/control_plane/src/runtime/control_plane_key_input.c @@ -113,9 +113,9 @@ static const control_plane_key_config_t s_key_configs[] = { .long_press_ms = CONFIG_TQ_KEY_LONG_PRESS_MS, .double_click_ms = CONFIG_TQ_KEY_DOUBLE_CLICK_MS, .emit_press_release = true, - .enable_short_press = false, + .enable_short_press = true, .enable_long_press = false, - .enable_double_click = false, + .enable_double_click = true, }, { .key_id = CONTROL_PLANE_KEY_ID_SW2, diff --git a/components/control_plane/src/runtime/control_plane_system_events.c b/components/control_plane/src/runtime/control_plane_system_events.c index 77bc5fd..3b0bd27 100644 --- a/components/control_plane/src/runtime/control_plane_system_events.c +++ b/components/control_plane/src/runtime/control_plane_system_events.c @@ -31,6 +31,7 @@ #endif #define CONTROL_PLANE_PTT_HOLD_STEP_MS 80 +#define CONTROL_PLANE_PTT_HOLD_START_DELAY_MS 320 #define CONTROL_PLANE_PTT_HOLD_TASK_STACK 4096 #define CONTROL_PLANE_PTT_HOLD_TASK_PRIORITY 4 @@ -117,6 +118,14 @@ static void control_plane_ptt_hold_task(void *arg) (void)arg; ESP_LOGI(TAG, "PTT hold task started"); bool start_requested = false; + uint32_t waited_ms = 0; + + while (s_ptt_hold_active && + !s_stop_requested && + waited_ms < CONTROL_PLANE_PTT_HOLD_START_DELAY_MS) { + vTaskDelay(pdMS_TO_TICKS(CONTROL_PLANE_PTT_HOLD_STEP_MS)); + waited_ms += CONTROL_PLANE_PTT_HOLD_STEP_MS; + } while (s_ptt_hold_active && !s_stop_requested) { if (!control_plane_is_sta_connected()) { @@ -223,6 +232,18 @@ static void control_plane_dispatch_key_event(const control_plane_key_event_t *ev break; } + case CONTROL_PLANE_KEY_EVENT_DOUBLE_CLICK: { + const domain_expression_request_t request = { + .id = DOMAIN_EXPRESSION_MUYU, + .trigger = DOMAIN_EXPRESSION_TRIGGER_PTT_DOUBLE_CLICK, + }; + esp_err_t expr_err = domain_runtime_request_expression(&request); + if (expr_err != ESP_OK && expr_err != ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "PTT double-click expression failed: %s", esp_err_to_name(expr_err)); + } + break; + } + default: break; } diff --git a/components/domain/include/domain.h b/components/domain/include/domain.h index dcf13c6..0f56b54 100644 --- a/components/domain/include/domain.h +++ b/components/domain/include/domain.h @@ -87,6 +87,7 @@ typedef enum { DOMAIN_EXPRESSION_WIFI_DISCONNECTED, DOMAIN_EXPRESSION_WEALTH_SPIN, DOMAIN_EXPRESSION_WEALTH_DIRECTION, + DOMAIN_EXPRESSION_MUYU, } domain_expression_id_t; typedef enum { @@ -98,6 +99,7 @@ typedef enum { DOMAIN_EXPRESSION_TRIGGER_WIFI_RECONNECTED, DOMAIN_EXPRESSION_TRIGGER_MODEL_DIRECTION, DOMAIN_EXPRESSION_TRIGGER_DAILY_FORTUNE, + DOMAIN_EXPRESSION_TRIGGER_PTT_DOUBLE_CLICK, } domain_expression_trigger_t; typedef struct { diff --git a/components/domain/src/runtime/domain_runtime_adapters.c b/components/domain/src/runtime/domain_runtime_adapters.c index 3060529..baf948c 100644 --- a/components/domain/src/runtime/domain_runtime_adapters.c +++ b/components/domain/src/runtime/domain_runtime_adapters.c @@ -75,6 +75,8 @@ static const char *TAG = "domain_rt_adapters"; static const uint8_t s_server_error_frame_order[] = {0, 1, 2, 1, 0}; static const uint8_t s_wifi_disconnected_frame_order[] = {0, 1, 2, 3, 2, 1, 0}; +static const uint8_t s_basic_face_frame_order[] = {0, 1, 2}; +static const uint8_t s_muyu_frame_order[] = {0, 1, 2, 1}; /* * Wealth-direction reveal asset directories, indexed parallel to the direction @@ -119,10 +121,15 @@ static const domain_expression_catalog_entry_t s_expression_catalog[] = { { .id = DOMAIN_EXPRESSION_IDLE, .platform_request = { - .kind = PLATFORM_LCD_PRESENTATION_IDLE, + .kind = PLATFORM_LCD_PRESENTATION_ASSET_SEQUENCE, .priority = 120, .interrupt_current = true, .return_to_idle = false, + .asset_dir = "jichubiaoqing", + .frame_order = s_basic_face_frame_order, + .frame_order_count = sizeof(s_basic_face_frame_order) / sizeof(s_basic_face_frame_order[0]), + .repeat_count = 0, + .frame_ms = 100, }, }, { @@ -175,6 +182,21 @@ static const domain_expression_catalog_entry_t s_expression_catalog[] = { .frame_ms = DOMAIN_WEALTH_DIRECTION_FRAME_MS, }, }, + { + .id = DOMAIN_EXPRESSION_MUYU, + .platform_request = { + .kind = PLATFORM_LCD_PRESENTATION_ASSET_SEQUENCE, + .priority = 125, + .interrupt_current = true, + .return_to_idle = true, + .asset_dir = "muyu", + .frame_order = s_muyu_frame_order, + .frame_order_count = sizeof(s_muyu_frame_order) / sizeof(s_muyu_frame_order[0]), + .repeat_count = 25, + .frame_ms = 50, + .duration_ms = 10000, + }, + }, }; static void snapshot_domain_wifi_behavior_hooks(domain_wifi_behavior_hooks_t *out_hooks) diff --git a/components/platform/CMakeLists.txt b/components/platform/CMakeLists.txt index fc6d26d..70b66f9 100644 --- a/components/platform/CMakeLists.txt +++ b/components/platform/CMakeLists.txt @@ -63,6 +63,19 @@ target_add_binary_data(${COMPONENT_LIB} BINARY ) +foreach(lcd_rle_asset + jichubiaoqing0 + jichubiaoqing1 + jichubiaoqing2 + muyu0 + muyu1 + muyu2) + target_add_binary_data(${COMPONENT_LIB} + "assets/lcd/${lcd_rle_asset}.rle" + BINARY + ) +endforeach() + set(platform_audio_prompt_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/assets/audio_prompts") set(platform_asset_image_dir "${CMAKE_CURRENT_BINARY_DIR}/asset_image") set(platform_asset_stage_stamp "${CMAKE_CURRENT_BINARY_DIR}/asset_image.stamp") diff --git a/components/platform/assets/lcd/jichubiaoqing0.rle b/components/platform/assets/lcd/jichubiaoqing0.rle new file mode 100644 index 0000000..b53ac88 Binary files /dev/null and b/components/platform/assets/lcd/jichubiaoqing0.rle differ diff --git a/components/platform/assets/lcd/jichubiaoqing1.rle b/components/platform/assets/lcd/jichubiaoqing1.rle new file mode 100644 index 0000000..49de8da Binary files /dev/null and b/components/platform/assets/lcd/jichubiaoqing1.rle differ diff --git a/components/platform/assets/lcd/jichubiaoqing2.rle b/components/platform/assets/lcd/jichubiaoqing2.rle new file mode 100644 index 0000000..fb7d75f Binary files /dev/null and b/components/platform/assets/lcd/jichubiaoqing2.rle differ diff --git a/components/platform/assets/lcd/muyu0.rle b/components/platform/assets/lcd/muyu0.rle new file mode 100644 index 0000000..9b369aa Binary files /dev/null and b/components/platform/assets/lcd/muyu0.rle differ diff --git a/components/platform/assets/lcd/muyu1.rle b/components/platform/assets/lcd/muyu1.rle new file mode 100644 index 0000000..6329cf6 Binary files /dev/null and b/components/platform/assets/lcd/muyu1.rle differ diff --git a/components/platform/assets/lcd/muyu2.rle b/components/platform/assets/lcd/muyu2.rle new file mode 100644 index 0000000..6676bd0 Binary files /dev/null and b/components/platform/assets/lcd/muyu2.rle differ diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index 40afb08..137efad 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -361,6 +361,7 @@ typedef struct { size_t frame_order_count; uint16_t repeat_count; uint32_t frame_ms; + uint32_t duration_ms; } platform_lcd_presentation_request_t; /** diff --git a/components/platform/internal/lcd_direct_assets.h b/components/platform/internal/lcd_direct_assets.h index 4928c98..e77f6e0 100644 --- a/components/platform/internal/lcd_direct_assets.h +++ b/components/platform/internal/lcd_direct_assets.h @@ -34,6 +34,7 @@ typedef struct { #define LCD_DIRECT_DEFAULT_ICON_COUNT 5U const lcd_direct_image_t *lcd_direct_default_image(void); +const lcd_direct_image_t *lcd_direct_asset_frame(const char *asset_dir, uint8_t frame_index); const lcd_direct_icon_t *lcd_direct_icon(uint16_t icon_id); const lcd_direct_icon_draw_t *lcd_direct_default_icon_sequence(size_t *out_count); diff --git a/components/platform/src/lcd_direct.c b/components/platform/src/lcd_direct.c index 7432686..572d9a0 100644 --- a/components/platform/src/lcd_direct.c +++ b/components/platform/src/lcd_direct.c @@ -33,7 +33,6 @@ #define LCD_CMD_MADCTL 0x36 #define LCD_CMD_RAMCTRL 0xB0 -#define LCD_RAMCTRL_LE_BIT (1U << 3) static const char *TAG = "lcd_direct"; @@ -43,8 +42,11 @@ typedef struct { bool interrupt_current; bool return_to_idle; char asset_dir[PLATFORM_LCD_PRESENTATION_ASSET_DIR_MAX]; + uint8_t frame_order[PLATFORM_LCD_PRESENTATION_FRAME_ORDER_MAX]; + size_t frame_order_count; uint16_t repeat_count; uint32_t frame_ms; + uint32_t duration_ms; } lcd_direct_request_t; typedef struct { @@ -84,6 +86,8 @@ static uint32_t s_completion_count; static portMUX_TYPE s_state_lock = portMUX_INITIALIZER_UNLOCKED; static uint16_t s_line_buffer[LCD_DIRECT_PIXELS_PER_TRANSFER]; +static void lcd_direct_signal_completion(void); + static uint16_t lcd_direct_swap_color(uint16_t color) { #if CONFIG_TQ_SCREEN_SWAP_COLOR_BYTES @@ -166,11 +170,7 @@ static esp_err_t lcd_direct_panel_init(void) #else .rgb_ele_order = LCD_RGB_ELEMENT_ORDER_RGB, #endif -#if CONFIG_TQ_SCREEN_SWAP_COLOR_BYTES - .data_endian = LCD_RGB_DATA_ENDIAN_LITTLE, -#else .data_endian = LCD_RGB_DATA_ENDIAN_BIG, -#endif .bits_per_pixel = 16, }; ESP_RETURN_ON_ERROR(esp_lcd_new_panel_st7789(s_panel_io, &panel_config, &s_panel), @@ -207,9 +207,6 @@ static esp_err_t lcd_direct_panel_init(void) madctl |= 0x08; #endif uint8_t ramctrl[] = {0x00, 0xF0}; -#if CONFIG_TQ_SCREEN_SWAP_COLOR_BYTES - ramctrl[1] |= LCD_RAMCTRL_LE_BIT; -#endif ESP_RETURN_ON_ERROR(esp_lcd_panel_io_tx_param(s_panel_io, LCD_CMD_MADCTL, &madctl, 1), TAG, "panel MADCTL failed"); @@ -333,25 +330,6 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer, } } -static void lcd_direct_overlay_boot_marker(uint16_t *pixel_buffer, uint16_t row_start, uint16_t row_count) -{ - const uint16_t marker_color = lcd_direct_swap_color(0xFFFF); - const uint16_t row_end = row_start + row_count; - - for (uint16_t y = row_start; y < row_end; ++y) { - uint16_t local_y = y - row_start; - for (uint16_t x = 0; x < LCD_DIRECT_WIDTH; ++x) { - const bool border = y < 2U || y >= (LCD_DIRECT_HEIGHT - 2U) || - x < 2U || x >= (LCD_DIRECT_WIDTH - 2U); - const bool center_line = (x >= 158U && x <= 161U && y >= 100U && y <= 140U) || - (y >= 118U && y <= 121U && x >= 140U && x <= 180U); - if (border || center_line) { - pixel_buffer[(uint32_t)local_y * LCD_DIRECT_WIDTH + x] = marker_color; - } - } - } -} - static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image, const lcd_direct_icon_draw_t *icons, size_t icon_count) @@ -399,7 +377,6 @@ static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image, } lcd_direct_overlay_icons(s_line_buffer, row_start, row_count, icons, icon_count); - lcd_direct_overlay_boot_marker(s_line_buffer, row_start, row_count); ESP_RETURN_ON_ERROR(lcd_direct_draw_rows(row_start, row_count), TAG, "write image pixels failed"); @@ -408,12 +385,169 @@ static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image, return ESP_OK; } -static esp_err_t lcd_direct_draw_default_image(void) +static esp_err_t lcd_direct_draw_asset_sequence_once(const lcd_direct_request_t *request) { - size_t icon_count = 0; - const lcd_direct_icon_draw_t *icons = lcd_direct_default_icon_sequence(&icon_count); - ESP_LOGI(TAG, "Drawing default LCD image icons=%u", (unsigned)icon_count); - return lcd_direct_draw_rle_image(lcd_direct_default_image(), icons, icon_count); + ESP_RETURN_ON_FALSE(request != NULL, + ESP_ERR_INVALID_ARG, + TAG, + "invalid asset request"); + + const size_t frame_count = request->frame_order_count > 0U ? request->frame_order_count : 1U; + for (size_t i = 0; i < frame_count; ++i) { + bool stop = false; + portENTER_CRITICAL(&s_state_lock); + stop = s_stop_requested || s_pending_valid; + portEXIT_CRITICAL(&s_state_lock); + if (stop) { + return ESP_ERR_INVALID_STATE; + } + + const uint8_t frame_index = request->frame_order_count > 0U ? request->frame_order[i] : (uint8_t)i; + const lcd_direct_image_t *frame = lcd_direct_asset_frame(request->asset_dir, frame_index); + ESP_RETURN_ON_FALSE(frame != NULL, + ESP_ERR_NOT_FOUND, + TAG, + "LCD asset frame not found asset=%s frame=%u", + request->asset_dir, + (unsigned)frame_index); + + ESP_RETURN_ON_ERROR(lcd_direct_draw_rle_image(frame, NULL, 0), + TAG, + "draw asset frame failed"); + + const uint32_t frame_ms = request->frame_ms > 0U ? request->frame_ms : 100U; + vTaskDelay(pdMS_TO_TICKS(frame_ms)); + } + + return ESP_OK; +} + +static esp_err_t lcd_direct_draw_asset_sequence_for_duration(const lcd_direct_request_t *request, + TickType_t start_tick, + TickType_t duration_ticks) +{ + ESP_RETURN_ON_FALSE(request != NULL, + ESP_ERR_INVALID_ARG, + TAG, + "invalid timed asset request"); + + const size_t frame_count = request->frame_order_count > 0U ? request->frame_order_count : 1U; + while ((xTaskGetTickCount() - start_tick) < duration_ticks) { + for (size_t i = 0; i < frame_count; ++i) { + bool stop = false; + portENTER_CRITICAL(&s_state_lock); + stop = s_stop_requested || s_pending_valid; + portEXIT_CRITICAL(&s_state_lock); + if (stop) { + return ESP_ERR_INVALID_STATE; + } + + const uint8_t frame_index = request->frame_order_count > 0U ? request->frame_order[i] : (uint8_t)i; + const lcd_direct_image_t *frame = lcd_direct_asset_frame(request->asset_dir, frame_index); + ESP_RETURN_ON_FALSE(frame != NULL, + ESP_ERR_NOT_FOUND, + TAG, + "LCD asset frame not found asset=%s frame=%u", + request->asset_dir, + (unsigned)frame_index); + + ESP_RETURN_ON_ERROR(lcd_direct_draw_rle_image(frame, NULL, 0), + TAG, + "draw timed asset frame failed"); + + const TickType_t now = xTaskGetTickCount(); + const TickType_t elapsed_ticks = now - start_tick; + if (elapsed_ticks >= duration_ticks) { + return ESP_OK; + } + + const uint32_t frame_ms = request->frame_ms > 0U ? request->frame_ms : 100U; + const TickType_t frame_ticks = pdMS_TO_TICKS(frame_ms); + const TickType_t remaining_ticks = duration_ticks - elapsed_ticks; + vTaskDelay(frame_ticks < remaining_ticks ? frame_ticks : remaining_ticks); + } + } + + return ESP_OK; +} + +static esp_err_t lcd_direct_play_asset_sequence(const lcd_direct_request_t *request) +{ + ESP_RETURN_ON_FALSE(request != NULL, + ESP_ERR_INVALID_ARG, + TAG, + "invalid asset sequence"); + + if (request->asset_dir[0] == '\0' || + lcd_direct_asset_frame(request->asset_dir, + request->frame_order_count > 0U ? request->frame_order[0] : 0U) == NULL) { + ESP_LOGW(TAG, "LCD asset sequence unavailable, fallback to basic face asset=%s", request->asset_dir); + const lcd_direct_request_t fallback = { + .kind = PLATFORM_LCD_PRESENTATION_ASSET_SEQUENCE, + .asset_dir = "jichubiaoqing", + .frame_order = {0, 1, 2}, + .frame_order_count = 3, + .repeat_count = 1, + .frame_ms = 100, + }; + esp_err_t fallback_err = lcd_direct_draw_asset_sequence_once(&fallback); + if (fallback_err == ESP_OK && request->repeat_count > 0U) { + lcd_direct_signal_completion(); + } + return fallback_err; + } + + if (request->duration_ms > 0U) { + const TickType_t start_tick = xTaskGetTickCount(); + const TickType_t duration_ticks = pdMS_TO_TICKS(request->duration_ms); + esp_err_t err = lcd_direct_draw_asset_sequence_for_duration(request, start_tick, duration_ticks); + if (err != ESP_OK) { + return err; + } + lcd_direct_signal_completion(); + return ESP_OK; + } + + uint16_t remaining = request->repeat_count; + do { + esp_err_t err = lcd_direct_draw_asset_sequence_once(request); + if (err != ESP_OK) { + return err; + } + if (request->repeat_count > 0U) { + remaining--; + } + } while (request->repeat_count == 0U || remaining > 0U); + + lcd_direct_signal_completion(); + return ESP_OK; +} + +static esp_err_t lcd_direct_play_basic_face_until_pending(void) +{ + const lcd_direct_request_t request = { + .kind = PLATFORM_LCD_PRESENTATION_ASSET_SEQUENCE, + .asset_dir = "jichubiaoqing", + .frame_order = {0, 1, 2}, + .frame_order_count = 3, + .repeat_count = 0, + .frame_ms = 100, + }; + + while (true) { + bool stop = false; + portENTER_CRITICAL(&s_state_lock); + stop = s_stop_requested || s_pending_valid; + portEXIT_CRITICAL(&s_state_lock); + if (stop) { + return ESP_OK; + } + + esp_err_t err = lcd_direct_draw_asset_sequence_once(&request); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + return err; + } + } } static void lcd_direct_signal_completion(void) @@ -486,8 +620,6 @@ void lcd_direct_start_render_loop(void) portEXIT_CRITICAL(&s_state_lock); ESP_LOGI(TAG, "Direct LCD render loop started"); - esp_err_t default_draw_err = lcd_direct_draw_default_image(); - ESP_LOGI(TAG, "Direct LCD default image draw result=%s", esp_err_to_name(default_draw_err)); while (true) { bool stop = false; @@ -503,13 +635,33 @@ void lcd_direct_start_render_loop(void) if (xSemaphoreTake(s_lock, pdMS_TO_TICKS(1000)) == pdTRUE) { esp_err_t draw_err = ESP_OK; if (request.kind == PLATFORM_LCD_PRESENTATION_IDLE) { - draw_err = lcd_direct_draw_default_image(); + draw_err = lcd_direct_play_basic_face_until_pending(); + } else if (request.kind == PLATFORM_LCD_PRESENTATION_ASSET_SEQUENCE) { + draw_err = lcd_direct_play_asset_sequence(&request); + if (draw_err == ESP_OK && request.return_to_idle) { + lcd_direct_request_t idle = { + .kind = PLATFORM_LCD_PRESENTATION_IDLE, + }; + portENTER_CRITICAL(&s_state_lock); + s_pending = idle; + s_pending_valid = true; + portEXIT_CRITICAL(&s_state_lock); + } } else { draw_err = lcd_direct_draw_test_pattern(&request); } xSemaphoreGive(s_lock); - if (draw_err == ESP_OK && request.repeat_count > 0U) { - lcd_direct_signal_completion(); + if (draw_err != ESP_OK && draw_err != ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "LCD presentation draw failed: %s", esp_err_to_name(draw_err)); + } + } + } else { + if (xSemaphoreTake(s_lock, pdMS_TO_TICKS(1000)) == pdTRUE) { + esp_err_t idle_err = lcd_direct_play_basic_face_until_pending(); + xSemaphoreGive(s_lock); + if (idle_err != ESP_OK && idle_err != ESP_ERR_INVALID_STATE) { + ESP_LOGW(TAG, "LCD idle draw failed: %s", esp_err_to_name(idle_err)); + vTaskDelay(pdMS_TO_TICKS(100)); } } } @@ -587,10 +739,18 @@ esp_err_t lcd_direct_request_presentation(const platform_lcd_presentation_reques .return_to_idle = request->return_to_idle, .repeat_count = request->repeat_count, .frame_ms = request->frame_ms, + .duration_ms = request->duration_ms, }; if (request->asset_dir != NULL) { strlcpy(copied.asset_dir, request->asset_dir, sizeof(copied.asset_dir)); } + if (request->frame_order != NULL && request->frame_order_count > 0U) { + copied.frame_order_count = request->frame_order_count; + if (copied.frame_order_count > PLATFORM_LCD_PRESENTATION_FRAME_ORDER_MAX) { + copied.frame_order_count = PLATFORM_LCD_PRESENTATION_FRAME_ORDER_MAX; + } + memcpy(copied.frame_order, request->frame_order, copied.frame_order_count); + } TaskHandle_t task = NULL; portENTER_CRITICAL(&s_state_lock); diff --git a/components/platform/src/lcd_direct_assets.c b/components/platform/src/lcd_direct_assets.c index 6fa1413..111fbfc 100644 --- a/components/platform/src/lcd_direct_assets.c +++ b/components/platform/src/lcd_direct_assets.c @@ -1,19 +1,79 @@ -/* Generated from D:\Code\chaowan\lcd(1)\lcd\lcd\main\eye_image.c buyunqian1. */ #include "lcd_direct_assets.h" +#include + extern const uint8_t _binary_buyunqian1_rle_start[] asm("_binary_buyunqian1_rle_start"); extern const uint8_t _binary_buyunqian1_rle_end[] asm("_binary_buyunqian1_rle_end"); +extern const uint8_t _binary_jichubiaoqing0_rle_start[] asm("_binary_jichubiaoqing0_rle_start"); +extern const uint8_t _binary_jichubiaoqing1_rle_start[] asm("_binary_jichubiaoqing1_rle_start"); +extern const uint8_t _binary_jichubiaoqing2_rle_start[] asm("_binary_jichubiaoqing2_rle_start"); +extern const uint8_t _binary_muyu0_rle_start[] asm("_binary_muyu0_rle_start"); +extern const uint8_t _binary_muyu1_rle_start[] asm("_binary_muyu1_rle_start"); +extern const uint8_t _binary_muyu2_rle_start[] asm("_binary_muyu2_rle_start"); static const lcd_direct_image_t s_default_image = { .runs = (const lcd_direct_rle_run_t *)_binary_buyunqian1_rle_start, .run_count = 72552U, }; +static const lcd_direct_image_t s_basic_face_frames[] = { + { + .runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing0_rle_start, + .run_count = 5893U, + }, + { + .runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing1_rle_start, + .run_count = 4581U, + }, + { + .runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing2_rle_start, + .run_count = 3651U, + }, +}; + +static const lcd_direct_image_t s_muyu_frames[] = { + { + .runs = (const lcd_direct_rle_run_t *)_binary_muyu0_rle_start, + .run_count = 63459U, + }, + { + .runs = (const lcd_direct_rle_run_t *)_binary_muyu1_rle_start, + .run_count = 63665U, + }, + { + .runs = (const lcd_direct_rle_run_t *)_binary_muyu2_rle_start, + .run_count = 63894U, + }, +}; + const lcd_direct_image_t *lcd_direct_default_image(void) { return &s_default_image; } +const lcd_direct_image_t *lcd_direct_asset_frame(const char *asset_dir, uint8_t frame_index) +{ + if (asset_dir == NULL) { + return NULL; + } + + if (strcmp(asset_dir, "jichubiaoqing") == 0) { + if (frame_index < sizeof(s_basic_face_frames) / sizeof(s_basic_face_frames[0])) { + return &s_basic_face_frames[frame_index]; + } + return NULL; + } + + if (strcmp(asset_dir, "muyu") == 0) { + if (frame_index < sizeof(s_muyu_frames) / sizeof(s_muyu_frames[0])) { + return &s_muyu_frames[frame_index]; + } + return NULL; + } + + return NULL; +} + const lcd_direct_icon_t *lcd_direct_icon(uint16_t icon_id) { (void)icon_id; diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 804d340..9a48130 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -182,7 +182,7 @@ menu "Example Configuration" config TQ_KEY_DOUBLE_CLICK_MS int "Key double-click threshold (ms)" - default 300 + default 450 range 100 1000 depends on TQ_KEY_INPUT_ENABLE help diff --git a/sdkconfig.defaults b/sdkconfig.defaults index edd27f0..08c12ca 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -30,7 +30,7 @@ CONFIG_TQ_KEY_IRQ_QUEUE_LEN=16 CONFIG_TQ_KEY_INPUT_POLL_MS=20 CONFIG_TQ_KEY_DEBOUNCE_INTERVAL_MS=20 CONFIG_TQ_KEY_LONG_PRESS_MS=800 -CONFIG_TQ_KEY_DOUBLE_CLICK_MS=300 +CONFIG_TQ_KEY_DOUBLE_CLICK_MS=450 # Internal DMA-capable SRAM budget. TLS/auth/fortune flows, hardware AES DMA # bounce buffers, LCD DMA, and worker task stacks all need internal-only memory.