LCD图片资源放入flash
This commit is contained in:
@@ -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 {
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user