diff --git a/components/domain/include/domain.h b/components/domain/include/domain.h index 98eb608..ed79e28 100644 --- a/components/domain/include/domain.h +++ b/components/domain/include/domain.h @@ -182,6 +182,11 @@ esp_err_t screen_preview_show_raster(const uint8_t *raster, uint32_t timeout_ms, char *err, size_t err_len); +esp_err_t screen_preview_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len); // ---------- printer_protocol ---------- typedef enum { diff --git a/components/domain/src/screen_preview.c b/components/domain/src/screen_preview.c index 424a8dc..961b3aa 100644 --- a/components/domain/src/screen_preview.c +++ b/components/domain/src/screen_preview.c @@ -11,3 +11,12 @@ esp_err_t screen_preview_show_raster(const uint8_t *raster, { return platform_display_show_raster_1bpp(raster, raster_len, width, height, timeout_ms, err, err_len); } + +esp_err_t screen_preview_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len) +{ + return platform_display_show_png(png, png_len, timeout_ms, err, err_len); +} diff --git a/components/domain/src/voice_interaction_marker.c b/components/domain/src/voice_interaction_marker.c index 8e6590c..7720256 100644 --- a/components/domain/src/voice_interaction_marker.c +++ b/components/domain/src/voice_interaction_marker.c @@ -17,8 +17,9 @@ static const char *TAG = "voice_interaction"; #define VOICE_IMAGE_MARKER_REPEAT_SUPPRESS_MS 45000 #define VOICE_IMAGE_PRINT_THRESHOLD 160 #define VOICE_IMAGE_PRINT_MAX_HEIGHT 2200 +#define VOICE_IMAGE_PREVIEW_TIMEOUT_MS 200 #define VOICE_IMAGE_MARKER_TEMPLATE \ - "%s,黑白线稿风格,白色背景,主体居中,边缘清晰,细节简洁,高对比,避免大面积阴影和灰度渐变,适配热敏打印机打印。" + "%s,线稿风格,白色背景,边缘清晰,细节简洁,高对比,避免大面积阴影和灰度渐变,适配热敏打印机打印。" #define VOICE_IMAGE_MARKER_TEMPLATE_FALLBACK_SUBJECT "简洁卡通图案" typedef struct { @@ -228,6 +229,38 @@ static void voice_build_marker_image_prompt(const char *subject, } } +static void voice_try_preview_marker_png(const voice_image_generation_task_arg_t *task_arg, + const uint8_t *png, + size_t png_len) { + if (task_arg == NULL || png == NULL || png_len == 0) { + return; + } + + char preview_err[96] = {0}; + esp_err_t preview_rc = screen_preview_show_png(png, + png_len, + VOICE_IMAGE_PREVIEW_TIMEOUT_MS, + preview_err, + sizeof(preview_err)); + if (preview_rc == ESP_OK) { + ESP_LOGI(TAG, + "[stage] marker_image_preview_ok: dialog_id=%s png_bytes=%u", + task_arg->dialog_id[0] != '\0' ? task_arg->dialog_id : "-", + (unsigned)png_len); + return; + } + + if (preview_rc == ESP_ERR_NOT_SUPPORTED) { + return; + } + + ESP_LOGW(TAG, + "[stage] marker_image_preview_failed: dialog_id=%s rc=0x%x msg=%s", + task_arg->dialog_id[0] != '\0' ? task_arg->dialog_id : "-", + (unsigned)preview_rc, + preview_err[0] != '\0' ? preview_err : "preview failed"); +} + static esp_err_t voice_submit_marker_generated_image(const voice_image_generation_task_arg_t *task_arg, const image_generation_result_t *result, char *err, @@ -237,6 +270,8 @@ static esp_err_t voice_submit_marker_generated_image(const voice_image_generatio return ESP_ERR_INVALID_ARG; } + voice_try_preview_marker_png(task_arg, result->png, result->png_len); + uint16_t raster_width = 0; uint16_t raster_height = 0; uint8_t *raster = NULL; @@ -280,14 +315,18 @@ static esp_err_t voice_submit_marker_generated_image(const voice_image_generatio uint32_t job_id = 0; char submit_err[128] = {0}; - esp_err_t submit_rc = printer_protocol_submit_raster_job(raster, - raster_len, - raster_width, - raster_height, - NULL, - &job_id, - submit_err, - sizeof(submit_err)); + printer_print_options_t print_opt = { + .direct_ignore_precheck = true, + }; + esp_err_t submit_rc = printer_protocol_submit_raster_job_ex(raster, + raster_len, + raster_width, + raster_height, + NULL, + &print_opt, + &job_id, + submit_err, + sizeof(submit_err)); if (submit_rc != ESP_OK) { voice_fill_err(err, err_len, @@ -371,7 +410,6 @@ static void voice_image_generation_task(void *arg) { gen_err[0] != '\0' ? gen_err : "image generation failed"); } - printer_protocol_status_poll_pause_release(&status_poll_pause_token); image_generation_result_free(&result); voice_marker_image_generation_release(); image_generation_schedule_prewarm(); diff --git a/components/platform/include/platform.h b/components/platform/include/platform.h index 8c2b642..c1e7643 100644 --- a/components/platform/include/platform.h +++ b/components/platform/include/platform.h @@ -104,6 +104,11 @@ esp_err_t platform_display_show_raster_1bpp(const uint8_t *raster, uint32_t timeout_ms, char *err, size_t err_len); +esp_err_t platform_display_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len); void platform_display_deinit(void); // ---------- voice_audio ---------- diff --git a/components/platform/internal/display_lcd_decode_image.h b/components/platform/internal/display_lcd_decode_image.h index 59fac70..421ec6f 100644 --- a/components/platform/internal/display_lcd_decode_image.h +++ b/components/platform/internal/display_lcd_decode_image.h @@ -5,6 +5,14 @@ #include "esp_err.h" +esp_err_t platform_lcd_decode_png_rgb565(const uint8_t *png, + size_t png_len, + uint16_t **out_pixels, + uint16_t *out_width, + uint16_t *out_height, + char *err, + size_t err_len); + esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, uint16_t *out_width, uint16_t *out_height, diff --git a/components/platform/internal/display_lcd_module.h b/components/platform/internal/display_lcd_module.h index 21cc19b..aa7b5c6 100644 --- a/components/platform/internal/display_lcd_module.h +++ b/components/platform/internal/display_lcd_module.h @@ -18,6 +18,11 @@ esp_err_t lcd_module_show_raster_1bpp(const uint8_t *raster, uint32_t timeout_ms, char *err, size_t err_len); +esp_err_t lcd_module_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len); void lcd_module_deinit(void); #ifdef __cplusplus diff --git a/components/platform/src/direct_thermal_printer.c b/components/platform/src/direct_thermal_printer.c index ad65b50..01f332a 100644 --- a/components/platform/src/direct_thermal_printer.c +++ b/components/platform/src/direct_thermal_printer.c @@ -162,6 +162,14 @@ static esp_err_t config_input_pin(int gpio_num, bool pull_up, const char *name) return err; } +static esp_err_t ensure_shared_shift_pins_gpio_locked(void) { + esp_err_t err = config_output_pin(CONFIG_TQ_SPI_SHARED_MOSI_PIN, 0, "print_mosi"); + if (err != ESP_OK) { + return err; + } + return config_output_pin(CONFIG_TQ_SPI_SHARED_CLK_PIN, 0, "print_clk"); +} + static void set_stb_level_locked(int level) { int out_level = level ? strobe_active_level_locked() : strobe_idle_level_locked(); set_gpio_level_if_valid(CONFIG_TQ_PRINT_STB_12_PIN, out_level); @@ -507,11 +515,7 @@ esp_err_t platform_direct_printer_init(void) { if (err != ESP_OK) { return err; } - err = config_output_pin(CONFIG_TQ_SPI_SHARED_MOSI_PIN, 0, "print_mosi"); - if (err != ESP_OK) { - return err; - } - err = config_output_pin(CONFIG_TQ_SPI_SHARED_CLK_PIN, 0, "print_clk"); + err = ensure_shared_shift_pins_gpio_locked(); if (err != ESP_OK) { return err; } @@ -598,6 +602,11 @@ esp_err_t platform_direct_printer_connect(uint32_t timeout_ms) { } if (!s_state.connected) { + err = ensure_shared_shift_pins_gpio_locked(); + if (err != ESP_OK) { + xSemaphoreGive(s_state.lock); + return err; + } set_gpio_level_if_valid(CONFIG_TQ_KEY_PRINT_PIN, boost_on_level_locked()); vTaskDelay(pdMS_TO_TICKS(10)); safe_drive_off_locked(true); @@ -837,6 +846,14 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r return ESP_ERR_INVALID_STATE; } + esp_err_t rc = ensure_shared_shift_pins_gpio_locked(); + if (rc != ESP_OK) { + safe_drive_off_locked(true); + xSemaphoreGive(s_state.lock); + write_err(err, err_len, "direct printer gpio setup failed"); + return rc; + } + uint16_t strobe_on_us = (request->strobe_on_time_us > 0) ? request->strobe_on_time_us : runtime_policy_direct_printer_strobe_on_us(); @@ -863,7 +880,7 @@ esp_err_t platform_direct_printer_print(const platform_direct_print_request_t *r steps_per_line = s_state.debug.override_steps_per_line; } - esp_err_t rc = ESP_OK; + rc = ESP_OK; if (!request->ignore_precheck) { rc = precheck_before_print_locked(err, err_len); if (rc != ESP_OK) { diff --git a/components/platform/src/display_lcd_decode_image.c b/components/platform/src/display_lcd_decode_image.c index 5dfbfcd..25c3eb4 100644 --- a/components/platform/src/display_lcd_decode_image.c +++ b/components/platform/src/display_lcd_decode_image.c @@ -23,11 +23,13 @@ static void lcd_fill_err(char *err, size_t err_len, const char *msg) } } -esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, - uint16_t *out_width, - uint16_t *out_height, - char *err, - size_t err_len) +esp_err_t platform_lcd_decode_png_rgb565(const uint8_t *png, + size_t png_len, + uint16_t **out_pixels, + uint16_t *out_width, + uint16_t *out_height, + char *err, + size_t err_len) { esp_err_t ret = ESP_OK; @@ -35,22 +37,20 @@ esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, ESP_ERR_INVALID_ARG, TAG, "invalid output args"); + ESP_RETURN_ON_FALSE(png != NULL && png_len > 0, ESP_ERR_INVALID_ARG, TAG, "invalid png data"); *out_pixels = NULL; *out_width = 0; *out_height = 0; - const size_t png_len = (size_t)(lcd_demo_png_end - lcd_demo_png_start); - ESP_RETURN_ON_FALSE(png_len > 0, ESP_ERR_INVALID_SIZE, TAG, "empty png data"); - png_image image; memset(&image, 0, sizeof(image)); image.version = PNG_IMAGE_VERSION; - ESP_RETURN_ON_FALSE(png_image_begin_read_from_memory(&image, lcd_demo_png_start, png_len), - ESP_FAIL, - TAG, - "png header decode failed: %s", - image.message); + if (!png_image_begin_read_from_memory(&image, png, png_len)) { + const char *png_err = image.message[0] != '\0' ? image.message : "png header decode failed"; + lcd_fill_err(err, err_len, png_err); + return ESP_FAIL; + } ESP_GOTO_ON_FALSE(image.width > 0 && image.height > 0, ESP_ERR_INVALID_SIZE, fail, TAG, "invalid png size"); ESP_GOTO_ON_FALSE(image.width <= UINT16_MAX && image.height <= UINT16_MAX, ESP_ERR_INVALID_SIZE, @@ -59,21 +59,21 @@ esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, "png dimensions too large"); ESP_GOTO_ON_FALSE(image.width <= SIZE_MAX / image.height, ESP_ERR_INVALID_SIZE, fail, TAG, "png too large"); - image.format = PNG_FORMAT_RGB; - png_alloc_size_t rgb_size = PNG_IMAGE_SIZE(image); - ESP_GOTO_ON_FALSE(rgb_size > 0, ESP_ERR_INVALID_SIZE, fail, TAG, "png output size invalid"); + image.format = PNG_FORMAT_RGBA; + png_alloc_size_t rgba_size = PNG_IMAGE_SIZE(image); + ESP_GOTO_ON_FALSE(rgba_size > 0, ESP_ERR_INVALID_SIZE, fail, TAG, "png output size invalid"); - uint8_t *rgb = (uint8_t *)heap_caps_malloc((size_t)rgb_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); - if (rgb == NULL) { - rgb = (uint8_t *)heap_caps_malloc((size_t)rgb_size, MALLOC_CAP_8BIT); + uint8_t *rgba = (uint8_t *)heap_caps_malloc((size_t)rgba_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (rgba == NULL) { + rgba = (uint8_t *)heap_caps_malloc((size_t)rgba_size, MALLOC_CAP_8BIT); } - ESP_GOTO_ON_FALSE(rgb != NULL, ESP_ERR_NO_MEM, fail, TAG, "alloc rgb buffer failed"); + ESP_GOTO_ON_FALSE(rgba != NULL, ESP_ERR_NO_MEM, fail, TAG, "alloc rgba buffer failed"); png_alloc_size_t stride = PNG_IMAGE_ROW_STRIDE(image); - if (!png_image_finish_read(&image, NULL, rgb, stride, NULL)) { + if (!png_image_finish_read(&image, NULL, rgba, stride, NULL)) { const char *png_err = image.message[0] != '\0' ? image.message : "png decode failed"; lcd_fill_err(err, err_len, png_err); - heap_caps_free(rgb); + heap_caps_free(rgba); png_image_free(&image); return ESP_FAIL; } @@ -87,16 +87,25 @@ esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, } if (pixels == NULL) { lcd_fill_err(err, err_len, "alloc rgb565 buffer failed"); - heap_caps_free(rgb); + heap_caps_free(rgba); return ESP_ERR_NO_MEM; } for (size_t i = 0; i < pixel_count; ++i) { - const size_t base = i * 3u; - lv_color_t color = lv_color_make(rgb[base], rgb[base + 1u], rgb[base + 2u]); + const size_t base = i * 4u; + uint8_t r = rgba[base]; + uint8_t g = rgba[base + 1u]; + uint8_t b = rgba[base + 2u]; + uint8_t a = rgba[base + 3u]; + if (a < 255u) { + r = (uint8_t)((((uint32_t)r * (uint32_t)a) + (255u * (255u - (uint32_t)a)) + 127u) / 255u); + g = (uint8_t)((((uint32_t)g * (uint32_t)a) + (255u * (255u - (uint32_t)a)) + 127u) / 255u); + b = (uint8_t)((((uint32_t)b * (uint32_t)a) + (255u * (255u - (uint32_t)a)) + 127u) / 255u); + } + lv_color_t color = lv_color_make(r, g, b); pixels[i] = (uint16_t)color.full; } - heap_caps_free(rgb); + heap_caps_free(rgba); *out_pixels = pixels; *out_width = (uint16_t)image.width; @@ -111,3 +120,20 @@ fail: } return ret; } + +esp_err_t platform_lcd_decode_demo_png(uint16_t **out_pixels, + uint16_t *out_width, + uint16_t *out_height, + char *err, + size_t err_len) +{ + const size_t png_len = (size_t)(lcd_demo_png_end - lcd_demo_png_start); + ESP_RETURN_ON_FALSE(png_len > 0, ESP_ERR_INVALID_SIZE, TAG, "empty png data"); + return platform_lcd_decode_png_rgb565(lcd_demo_png_start, + png_len, + out_pixels, + out_width, + out_height, + err, + err_len); +} diff --git a/components/platform/src/display_lcd_module.c b/components/platform/src/display_lcd_module.c index cc3cafd..bca6150 100644 --- a/components/platform/src/display_lcd_module.c +++ b/components/platform/src/display_lcd_module.c @@ -187,6 +187,18 @@ static void lcd_free_lvgl_buffers(void) } } +static esp_err_t lcd_recover_panel_for_shared_spi(void) +{ + /* + * Printer bit-bang path reconfigures shared MOSI/CLK as GPIO. + * Re-initialize panel before each preview draw to restore SPI pin routing. + */ + if (s_lcd.initialized) { + lcd_module_deinit(); + } + return lcd_module_init(); +} + static void lcd_lvgl_flush_cb(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_map) { st7789p3_handle_t panel = (st7789p3_handle_t)disp_drv->user_data; @@ -346,6 +358,101 @@ static esp_err_t lcd_render_raster_to_rgb565(const uint8_t *raster, return ESP_OK; } +static esp_err_t lcd_scale_rgb565_to_preview(const uint16_t *src_pixels, + uint16_t src_w, + uint16_t src_h, + uint16_t **out_pixels, + uint16_t *out_w, + uint16_t *out_h, + char *err, + size_t err_len) +{ + if (src_pixels == NULL || src_w == 0 || src_h == 0 || out_pixels == NULL || out_w == NULL || out_h == NULL) { + lcd_fill_err(err, err_len, "invalid rgb565 image"); + return ESP_ERR_INVALID_ARG; + } + + *out_pixels = NULL; + *out_w = 0; + *out_h = 0; + lcd_calc_preview_size(src_w, src_h, out_w, out_h); + size_t pixel_count = (size_t)(*out_w) * (size_t)(*out_h); + if (pixel_count == 0 || pixel_count > SIZE_MAX / sizeof(uint16_t)) { + lcd_fill_err(err, err_len, "preview size invalid"); + return ESP_ERR_INVALID_SIZE; + } + + uint16_t *preview = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t), + MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (preview == NULL) { + preview = (uint16_t *)heap_caps_malloc(pixel_count * sizeof(uint16_t), MALLOC_CAP_8BIT); + } + if (preview == NULL) { + lcd_fill_err(err, err_len, "no memory"); + return ESP_ERR_NO_MEM; + } + + if (*out_w == src_w && *out_h == src_h) { + memcpy(preview, src_pixels, pixel_count * sizeof(uint16_t)); + *out_pixels = preview; + return ESP_OK; + } + + for (uint16_t y = 0; y < *out_h; ++y) { + uint16_t src_y = (uint16_t)(((uint32_t)y * src_h) / (*out_h)); + size_t src_row = (size_t)src_y * src_w; + size_t dst_row = (size_t)y * (*out_w); + for (uint16_t x = 0; x < *out_w; ++x) { + uint16_t src_x = (uint16_t)(((uint32_t)x * src_w) / (*out_w)); + preview[dst_row + x] = src_pixels[src_row + src_x]; + } + } + + *out_pixels = preview; + return ESP_OK; +} + +static esp_err_t lcd_apply_preview_locked(lv_color_t bg_color, char *err, size_t err_len) +{ + if (s_lcd.panel == NULL || s_lcd.preview_pixels == NULL) { + lcd_fill_err(err, err_len, "display panel not ready"); + return ESP_ERR_INVALID_STATE; + } + + uint16_t preview_w = s_lcd.preview_dsc.header.w; + uint16_t preview_h = s_lcd.preview_dsc.header.h; + if (preview_w == 0 || preview_h == 0 || preview_w > LCD_PANEL_H_RES || preview_h > LCD_PANEL_V_RES) { + lcd_fill_err(err, err_len, "invalid preview size"); + return ESP_ERR_INVALID_SIZE; + } + + esp_err_t draw_rc = st7789p3_fill_color(s_lcd.panel, (uint16_t)bg_color.full); + if (draw_rc != ESP_OK) { + lcd_fill_err(err, err_len, "display clear failed"); + return draw_rc; + } + + uint16_t x = (uint16_t)((LCD_PANEL_H_RES - preview_w) / 2u); + uint16_t y = (uint16_t)((LCD_PANEL_V_RES - preview_h) / 2u); + draw_rc = st7789p3_draw_bitmap(s_lcd.panel, + x, + y, + (uint16_t)(x + preview_w), + (uint16_t)(y + preview_h), + s_lcd.preview_pixels); + if (draw_rc != ESP_OK) { + lcd_fill_err(err, err_len, "display draw failed"); + return draw_rc; + } + + ESP_LOGI(TAG, "preview drawn directly: size=%ux%u offset=(%u,%u)", + (unsigned)preview_w, + (unsigned)preview_h, + (unsigned)x, + (unsigned)y); + return ESP_OK; +} + void lcd_module_deinit(void) { #if CONFIG_TQ_SCREEN_ENABLE @@ -474,7 +581,7 @@ esp_err_t lcd_module_show_raster_1bpp(const uint8_t *raster, #if !CONFIG_TQ_SCREEN_ENABLE return ESP_ERR_NOT_SUPPORTED; #else - ESP_RETURN_ON_ERROR(lcd_module_init(), TAG, "display init failed"); + ESP_RETURN_ON_ERROR(lcd_recover_panel_for_shared_spi(), TAG, "display init failed"); if (timeout_ms == 0) { timeout_ms = LCD_PREVIEW_TIMEOUT_MS_DEFAULT; @@ -515,16 +622,79 @@ esp_err_t lcd_module_show_raster_1bpp(const uint8_t *raster, s_lcd.preview_dsc.data_size = (uint32_t)((size_t)preview_w * preview_h * sizeof(uint16_t)); s_lcd.preview_dsc.data = (const uint8_t *)s_lcd.preview_pixels; - lv_obj_t *screen = lv_scr_act(); - lv_obj_set_style_bg_color(screen, lv_color_white(), LV_PART_MAIN); - lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN); - lv_img_set_src(s_lcd.preview_img, &s_lcd.preview_dsc); - lv_obj_clear_flag(s_lcd.preview_img, LV_OBJ_FLAG_HIDDEN); - lv_obj_center(s_lcd.preview_img); - lv_refr_now(s_lcd.lv_disp); - + esp_err_t draw_err = lcd_apply_preview_locked(lv_color_white(), err, err_len); lcd_lock_give(); - return ESP_OK; + return draw_err; +#endif +} + +esp_err_t lcd_module_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len) +{ +#if !CONFIG_TQ_SCREEN_ENABLE + return ESP_ERR_NOT_SUPPORTED; +#else + ESP_RETURN_ON_ERROR(lcd_recover_panel_for_shared_spi(), TAG, "display init failed"); + + if (timeout_ms == 0) { + timeout_ms = LCD_PREVIEW_TIMEOUT_MS_DEFAULT; + } + + uint16_t *src_pixels = NULL; + uint16_t src_w = 0; + uint16_t src_h = 0; + esp_err_t decode_err = platform_lcd_decode_png_rgb565(png, + png_len, + &src_pixels, + &src_w, + &src_h, + err, + err_len); + if (decode_err != ESP_OK) { + return decode_err; + } + + uint16_t *preview_pixels = NULL; + uint16_t preview_w = 0; + uint16_t preview_h = 0; + esp_err_t scale_err = lcd_scale_rgb565_to_preview(src_pixels, + src_w, + src_h, + &preview_pixels, + &preview_w, + &preview_h, + err, + err_len); + heap_caps_free(src_pixels); + if (scale_err != ESP_OK) { + return scale_err; + } + + if (!lcd_lock_take(timeout_ms)) { + heap_caps_free(preview_pixels); + lcd_fill_err(err, err_len, "display lock timeout"); + return ESP_ERR_TIMEOUT; + } + + if (s_lcd.preview_pixels != NULL) { + heap_caps_free(s_lcd.preview_pixels); + } + s_lcd.preview_pixels = preview_pixels; + + memset(&s_lcd.preview_dsc, 0, sizeof(s_lcd.preview_dsc)); + s_lcd.preview_dsc.header.always_zero = 0; + s_lcd.preview_dsc.header.w = preview_w; + s_lcd.preview_dsc.header.h = preview_h; + s_lcd.preview_dsc.header.cf = LV_IMG_CF_TRUE_COLOR; + s_lcd.preview_dsc.data_size = (uint32_t)((size_t)preview_w * preview_h * sizeof(uint16_t)); + s_lcd.preview_dsc.data = (const uint8_t *)s_lcd.preview_pixels; + + esp_err_t draw_err = lcd_apply_preview_locked(lv_color_white(), err, err_len); + lcd_lock_give(); + return draw_err; #endif } @@ -533,7 +703,7 @@ esp_err_t lcd_module_start_demo(void) #if !CONFIG_TQ_SCREEN_ENABLE return ESP_ERR_NOT_SUPPORTED; #else - ESP_RETURN_ON_ERROR(lcd_module_init(), TAG, "display init failed"); + ESP_RETURN_ON_ERROR(lcd_recover_panel_for_shared_spi(), TAG, "display init failed"); if (!lcd_lock_take(LCD_LOCK_TIMEOUT_MS)) { return ESP_ERR_TIMEOUT; } @@ -566,15 +736,12 @@ esp_err_t lcd_module_start_demo(void) s_lcd.preview_dsc.data_size = (uint32_t)((size_t)demo_w * demo_h * sizeof(uint16_t)); s_lcd.preview_dsc.data = (const uint8_t *)s_lcd.preview_pixels; - lv_obj_t *screen = lv_scr_act(); - lv_obj_set_style_bg_color(screen, lv_color_black(), LV_PART_MAIN); - lv_obj_set_style_bg_opa(screen, LV_OPA_COVER, LV_PART_MAIN); - - lv_img_set_src(s_lcd.preview_img, &s_lcd.preview_dsc); - lv_obj_clear_flag(s_lcd.preview_img, LV_OBJ_FLAG_HIDDEN); - lv_obj_center(s_lcd.preview_img); - lv_refr_now(s_lcd.lv_disp); + esp_err_t draw_err = lcd_apply_preview_locked(lv_color_black(), decode_err, sizeof(decode_err)); lcd_lock_give(); + if (draw_err != ESP_OK) { + ESP_LOGW(TAG, "demo draw failed: rc=0x%x msg=%s", (unsigned)draw_err, decode_err); + return draw_err; + } return ESP_OK; #endif } diff --git a/components/platform/src/display_st7789.c b/components/platform/src/display_st7789.c index d4125f9..ba19935 100644 --- a/components/platform/src/display_st7789.c +++ b/components/platform/src/display_st7789.c @@ -27,3 +27,12 @@ esp_err_t platform_display_show_raster_1bpp(const uint8_t *raster, { return lcd_module_show_raster_1bpp(raster, raster_len, width, height, timeout_ms, err, err_len); } + +esp_err_t platform_display_show_png(const uint8_t *png, + size_t png_len, + uint32_t timeout_ms, + char *err, + size_t err_len) +{ + return lcd_module_show_png(png, png_len, timeout_ms, err, err_len); +}