LCD图片资源放入flash

This commit is contained in:
CSBOOK\44744
2026-06-28 17:54:18 +08:00
parent b06a4bc2bf
commit 4cc2089192
4 changed files with 149 additions and 37 deletions
+27 -19
View File
@@ -58,30 +58,28 @@ idf_component_register(
${platform_priv_requires} ${platform_priv_requires}
) )
target_add_binary_data(${COMPONENT_LIB}
"assets/lcd/buyunqian1.rle"
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_audio_prompt_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/assets/audio_prompts")
set(platform_lcd_asset_src_dir "${CMAKE_CURRENT_SOURCE_DIR}/assets/lcd")
set(platform_asset_image_dir "${CMAKE_CURRENT_BINARY_DIR}/asset_image") set(platform_asset_image_dir "${CMAKE_CURRENT_BINARY_DIR}/asset_image")
set(platform_asset_stage_stamp "${CMAKE_CURRENT_BINARY_DIR}/asset_image.stamp") set(platform_asset_stage_stamp "${CMAKE_CURRENT_BINARY_DIR}/asset_image.stamp")
file(GLOB_RECURSE platform_audio_prompt_files CONFIGURE_DEPENDS file(GLOB_RECURSE platform_audio_prompt_files CONFIGURE_DEPENDS
"${platform_audio_prompt_src_dir}/*.opus" "${platform_audio_prompt_src_dir}/*.opus"
) )
set(platform_lcd_flash_assets
buyunqian1
jichubiaoqing0
jichubiaoqing1
jichubiaoqing2
muyu0
muyu1
muyu2
)
set(platform_lcd_flash_asset_files)
foreach(lcd_rle_asset IN LISTS platform_lcd_flash_assets)
list(APPEND platform_lcd_flash_asset_files
"${platform_lcd_asset_src_dir}/${lcd_rle_asset}.rle"
)
endforeach()
set(platform_asset_stage_commands) set(platform_asset_stage_commands)
foreach(audio_file IN LISTS platform_audio_prompt_files) foreach(audio_file IN LISTS platform_audio_prompt_files)
@@ -93,6 +91,14 @@ foreach(audio_file IN LISTS platform_audio_prompt_files)
"${platform_asset_image_dir}/audio_prompts/${audio_rel_path}" "${platform_asset_image_dir}/audio_prompts/${audio_rel_path}"
) )
endforeach() endforeach()
foreach(lcd_rle_asset IN LISTS platform_lcd_flash_assets)
list(APPEND platform_asset_stage_commands
COMMAND ${CMAKE_COMMAND} -E make_directory "${platform_asset_image_dir}/lcd"
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${platform_lcd_asset_src_dir}/${lcd_rle_asset}.rle"
"${platform_asset_image_dir}/lcd/${lcd_rle_asset}.rle"
)
endforeach()
add_custom_command( add_custom_command(
OUTPUT "${platform_asset_stage_stamp}" OUTPUT "${platform_asset_stage_stamp}"
@@ -100,7 +106,9 @@ add_custom_command(
COMMAND ${CMAKE_COMMAND} -E make_directory "${platform_asset_image_dir}" COMMAND ${CMAKE_COMMAND} -E make_directory "${platform_asset_image_dir}"
${platform_asset_stage_commands} ${platform_asset_stage_commands}
COMMAND ${CMAKE_COMMAND} -E touch "${platform_asset_stage_stamp}" COMMAND ${CMAKE_COMMAND} -E touch "${platform_asset_stage_stamp}"
DEPENDS ${platform_audio_prompt_files} DEPENDS
${platform_audio_prompt_files}
${platform_lcd_flash_asset_files}
) )
littlefs_create_partition_image( littlefs_create_partition_image(
@@ -15,6 +15,7 @@ typedef struct {
typedef struct { typedef struct {
const lcd_direct_rle_run_t *runs; const lcd_direct_rle_run_t *runs;
uint32_t run_count; uint32_t run_count;
const char *path;
} lcd_direct_image_t; } lcd_direct_image_t;
typedef struct { typedef struct {
+113 -3
View File
@@ -8,9 +8,12 @@
#include "lcd_direct.h" #include "lcd_direct.h"
#include "lcd_direct_assets.h" #include "lcd_direct_assets.h"
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include "driver/gpio.h" #include "driver/gpio.h"
#include "driver/spi_master.h" #include "driver/spi_master.h"
@@ -85,6 +88,7 @@ static lcd_direct_request_t s_pending;
static uint32_t s_completion_count; static uint32_t s_completion_count;
static portMUX_TYPE s_state_lock = portMUX_INITIALIZER_UNLOCKED; static portMUX_TYPE s_state_lock = portMUX_INITIALIZER_UNLOCKED;
static uint16_t s_line_buffer[LCD_DIRECT_PIXELS_PER_TRANSFER]; static uint16_t s_line_buffer[LCD_DIRECT_PIXELS_PER_TRANSFER];
static lcd_direct_rle_run_t s_rle_file_chunk[128];
static void lcd_direct_signal_completion(void); static void lcd_direct_signal_completion(void);
@@ -330,9 +334,9 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
} }
} }
static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image, static esp_err_t lcd_direct_draw_rle_memory_image(const lcd_direct_image_t *image,
const lcd_direct_icon_draw_t *icons, const lcd_direct_icon_draw_t *icons,
size_t icon_count) size_t icon_count)
{ {
ESP_RETURN_ON_FALSE(image != NULL && image->runs != NULL, ESP_RETURN_ON_FALSE(image != NULL && image->runs != NULL,
ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_ARG,
@@ -385,6 +389,112 @@ static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image,
return ESP_OK; return ESP_OK;
} }
static esp_err_t lcd_direct_draw_rle_file_image(const lcd_direct_image_t *image,
const lcd_direct_icon_draw_t *icons,
size_t icon_count)
{
ESP_RETURN_ON_FALSE(image != NULL && image->path != NULL,
ESP_ERR_INVALID_ARG,
TAG,
"invalid file image");
errno = 0;
int fd = open(image->path, O_RDONLY);
if (fd < 0) {
ESP_LOGE(TAG, "open LCD asset failed path=%s errno=%d", image->path, errno);
return ESP_ERR_NOT_FOUND;
}
uint32_t run_index = 0;
uint32_t chunk_index = 0;
uint32_t chunk_count = 0;
uint32_t run_remaining = 0;
uint16_t run_color = 0;
esp_err_t result = ESP_OK;
for (uint16_t row_start = 0; row_start < LCD_DIRECT_HEIGHT; row_start += LCD_DIRECT_ROWS_PER_TRANSFER) {
uint16_t row_count = LCD_DIRECT_HEIGHT - row_start;
if (row_count > LCD_DIRECT_ROWS_PER_TRANSFER) {
row_count = LCD_DIRECT_ROWS_PER_TRANSFER;
}
const uint32_t pixels_needed = (uint32_t)LCD_DIRECT_WIDTH * row_count;
uint32_t buffered_pixels = 0;
while (buffered_pixels < pixels_needed) {
if (run_remaining == 0U) {
if (run_index >= image->run_count) {
break;
}
if (chunk_index >= chunk_count) {
const size_t runs_left = image->run_count - run_index;
const size_t runs_to_read = runs_left < (sizeof(s_rle_file_chunk) / sizeof(s_rle_file_chunk[0])) ?
runs_left :
(sizeof(s_rle_file_chunk) / sizeof(s_rle_file_chunk[0]));
const size_t bytes_to_read = runs_to_read * sizeof(s_rle_file_chunk[0]);
ssize_t bytes_read = read(fd, s_rle_file_chunk, bytes_to_read);
if (bytes_read != (ssize_t)bytes_to_read) {
ESP_LOGE(TAG,
"read LCD asset failed path=%s requested=%u read=%d errno=%d",
image->path,
(unsigned)bytes_to_read,
(int)bytes_read,
errno);
result = ESP_FAIL;
goto out;
}
chunk_index = 0;
chunk_count = runs_to_read;
}
run_color = lcd_direct_swap_color(s_rle_file_chunk[chunk_index].color);
run_remaining = s_rle_file_chunk[chunk_index].count;
chunk_index++;
run_index++;
}
uint32_t pixels_to_copy = run_remaining;
const uint32_t pixels_left = pixels_needed - buffered_pixels;
if (pixels_to_copy > pixels_left) {
pixels_to_copy = pixels_left;
}
for (uint32_t i = 0; i < pixels_to_copy; ++i) {
s_line_buffer[buffered_pixels + i] = run_color;
}
buffered_pixels += pixels_to_copy;
run_remaining -= pixels_to_copy;
}
while (buffered_pixels < pixels_needed) {
s_line_buffer[buffered_pixels++] = 0;
}
lcd_direct_overlay_icons(s_line_buffer, row_start, row_count, icons, icon_count);
result = lcd_direct_draw_rows(row_start, row_count);
if (result != ESP_OK) {
ESP_LOGE(TAG, "write image pixels failed path=%s", image->path);
goto out;
}
}
out:
close(fd);
return result;
}
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)
{
ESP_RETURN_ON_FALSE(image != NULL,
ESP_ERR_INVALID_ARG,
TAG,
"invalid image");
if (image->runs != NULL) {
return lcd_direct_draw_rle_memory_image(image, icons, icon_count);
}
return lcd_direct_draw_rle_file_image(image, icons, icon_count);
}
static esp_err_t lcd_direct_draw_asset_sequence_once(const lcd_direct_request_t *request) static esp_err_t lcd_direct_draw_asset_sequence_once(const lcd_direct_request_t *request)
{ {
ESP_RETURN_ON_FALSE(request != NULL, ESP_RETURN_ON_FALSE(request != NULL,
+8 -15
View File
@@ -2,46 +2,39 @@
#include <string.h> #include <string.h>
extern const uint8_t _binary_buyunqian1_rle_start[] asm("_binary_buyunqian1_rle_start"); #define LCD_ASSET_BASE_PATH "/littlefs/lcd/"
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 = { static const lcd_direct_image_t s_default_image = {
.runs = (const lcd_direct_rle_run_t *)_binary_buyunqian1_rle_start, .path = LCD_ASSET_BASE_PATH "buyunqian1.rle",
.run_count = 72552U, .run_count = 72552U,
}; };
static const lcd_direct_image_t s_basic_face_frames[] = { static const lcd_direct_image_t s_basic_face_frames[] = {
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing0_rle_start, .path = LCD_ASSET_BASE_PATH "jichubiaoqing0.rle",
.run_count = 5893U, .run_count = 5893U,
}, },
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing1_rle_start, .path = LCD_ASSET_BASE_PATH "jichubiaoqing1.rle",
.run_count = 4581U, .run_count = 4581U,
}, },
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_jichubiaoqing2_rle_start, .path = LCD_ASSET_BASE_PATH "jichubiaoqing2.rle",
.run_count = 3651U, .run_count = 3651U,
}, },
}; };
static const lcd_direct_image_t s_muyu_frames[] = { static const lcd_direct_image_t s_muyu_frames[] = {
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_muyu0_rle_start, .path = LCD_ASSET_BASE_PATH "muyu0.rle",
.run_count = 63459U, .run_count = 63459U,
}, },
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_muyu1_rle_start, .path = LCD_ASSET_BASE_PATH "muyu1.rle",
.run_count = 63665U, .run_count = 63665U,
}, },
{ {
.runs = (const lcd_direct_rle_run_t *)_binary_muyu2_rle_start, .path = LCD_ASSET_BASE_PATH "muyu2.rle",
.run_count = 63894U, .run_count = 63894U,
}, },
}; };