修复了SW2 双击后抖动,
icon 文件改为每帧只加载一次,整帧绘制期间复用,不再每 8 行重复读取。
This commit is contained in:
@@ -44,6 +44,10 @@
|
||||
#define CONFIG_TQ_KEY_DOUBLE_CLICK_MS 300
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TQ_KEY_POST_DOUBLE_CLICK_SUPPRESS_MS
|
||||
#define CONFIG_TQ_KEY_POST_DOUBLE_CLICK_SUPPRESS_MS 450
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TQ_KEY_INPUT_POLL_MS
|
||||
#define CONFIG_TQ_KEY_INPUT_POLL_MS 20
|
||||
#endif
|
||||
@@ -105,6 +109,7 @@ typedef struct {
|
||||
int64_t inactive_since_ms;
|
||||
int64_t press_start_ms;
|
||||
int64_t click_deadline_ms;
|
||||
int64_t suppress_until_ms;
|
||||
} control_plane_key_state_t;
|
||||
|
||||
static const control_plane_key_config_t s_key_configs[] = {
|
||||
@@ -312,6 +317,9 @@ static void control_plane_handle_debounced_transition(const control_plane_key_co
|
||||
|
||||
if (config->enable_double_click && state->click_pending && now_ms <= state->click_deadline_ms) {
|
||||
state->click_pending = false;
|
||||
state->debounce_pending = false;
|
||||
state->press_start_ms = 0;
|
||||
state->suppress_until_ms = now_ms + CONFIG_TQ_KEY_POST_DOUBLE_CLICK_SUPPRESS_MS;
|
||||
control_plane_emit_key_event(config,
|
||||
CONTROL_PLANE_KEY_EVENT_DOUBLE_CLICK,
|
||||
level,
|
||||
@@ -344,6 +352,11 @@ static void control_plane_process_key_timers(void)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state->suppress_until_ms > 0 && now_ms < state->suppress_until_ms) {
|
||||
state->debounce_pending = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (state->wait_inactive_before_press) {
|
||||
const int level = gpio_get_level(config->gpio_num);
|
||||
const bool pressed = control_plane_key_level_is_pressed(config, level);
|
||||
@@ -469,6 +482,21 @@ static void control_plane_key_input_task(void *arg)
|
||||
}
|
||||
|
||||
control_plane_key_state_t *state = &s_key_states[index];
|
||||
if (state->suppress_until_ms > 0 && irq_event.timestamp_ms < state->suppress_until_ms) {
|
||||
const bool pressed = control_plane_key_level_is_pressed(config, irq_event.level);
|
||||
state->raw_level = irq_event.level;
|
||||
state->debounce_pending = false;
|
||||
if (!pressed) {
|
||||
state->debounced_pressed = false;
|
||||
}
|
||||
ESP_LOGD(TAG,
|
||||
"suppressed gpio change key=%s gpio=%d level=%d",
|
||||
control_plane_key_id_name(config->key_id),
|
||||
(int)irq_event.gpio_num,
|
||||
irq_event.level);
|
||||
continue;
|
||||
}
|
||||
|
||||
state->raw_level = irq_event.level;
|
||||
state->debounce_pending = true;
|
||||
state->debounce_deadline_ms = irq_event.timestamp_ms + config->debounce_ms;
|
||||
|
||||
@@ -55,6 +55,12 @@ typedef struct {
|
||||
size_t step_count;
|
||||
} lcd_direct_request_t;
|
||||
|
||||
typedef struct {
|
||||
lcd_direct_icon_draw_t draw;
|
||||
const lcd_direct_icon_t *icon;
|
||||
lcd_direct_rle_run_t *loaded_runs;
|
||||
} lcd_direct_prepared_icon_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t cmd;
|
||||
uint8_t data[16];
|
||||
@@ -315,19 +321,18 @@ static lcd_direct_rle_run_t *lcd_direct_load_icon_runs(const lcd_direct_icon_t *
|
||||
return runs;
|
||||
}
|
||||
|
||||
static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
uint16_t row_start,
|
||||
uint16_t row_count,
|
||||
const lcd_direct_icon_draw_t *icons,
|
||||
size_t icon_count)
|
||||
static size_t lcd_direct_prepare_icons(const lcd_direct_icon_draw_t *icons,
|
||||
size_t icon_count,
|
||||
lcd_direct_prepared_icon_t *prepared,
|
||||
size_t prepared_capacity)
|
||||
{
|
||||
if (pixel_buffer == NULL || icons == NULL || icon_count == 0U) {
|
||||
return;
|
||||
if (icons == NULL || icon_count == 0U || prepared == NULL || prepared_capacity == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint16_t row_end = row_start + row_count;
|
||||
for (size_t icon_index = 0; icon_index < icon_count; ++icon_index) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[icon_index];
|
||||
size_t prepared_count = 0;
|
||||
for (size_t i = 0; i < icon_count && prepared_count < prepared_capacity; ++i) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[i];
|
||||
const lcd_direct_icon_t *icon = lcd_direct_icon(draw->icon_id);
|
||||
if (icon == NULL || icon->width == 0U || icon->height == 0U) {
|
||||
continue;
|
||||
@@ -337,11 +342,58 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
}
|
||||
|
||||
lcd_direct_rle_run_t *loaded_runs = NULL;
|
||||
const lcd_direct_rle_run_t *runs = icon->runs;
|
||||
if (runs == NULL) {
|
||||
if (icon->runs == NULL) {
|
||||
loaded_runs = lcd_direct_load_icon_runs(icon);
|
||||
runs = loaded_runs;
|
||||
if (loaded_runs == NULL) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
prepared[prepared_count] = (lcd_direct_prepared_icon_t) {
|
||||
.draw = *draw,
|
||||
.icon = icon,
|
||||
.loaded_runs = loaded_runs,
|
||||
};
|
||||
prepared_count++;
|
||||
}
|
||||
|
||||
return prepared_count;
|
||||
}
|
||||
|
||||
static void lcd_direct_release_prepared_icons(lcd_direct_prepared_icon_t *prepared, size_t prepared_count)
|
||||
{
|
||||
if (prepared == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < prepared_count; ++i) {
|
||||
free(prepared[i].loaded_runs);
|
||||
prepared[i].loaded_runs = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
uint16_t row_start,
|
||||
uint16_t row_count,
|
||||
const lcd_direct_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
if (pixel_buffer == NULL || icons == NULL || icon_count == 0U) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint16_t row_end = row_start + row_count;
|
||||
for (size_t icon_index = 0; icon_index < icon_count; ++icon_index) {
|
||||
const lcd_direct_icon_draw_t *draw = &icons[icon_index].draw;
|
||||
const lcd_direct_icon_t *icon = icons[icon_index].icon;
|
||||
if (icon == NULL || icon->width == 0U || icon->height == 0U) {
|
||||
continue;
|
||||
}
|
||||
if (draw->x >= LCD_DIRECT_WIDTH || draw->y >= LCD_DIRECT_HEIGHT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const lcd_direct_rle_run_t *runs = icon->runs != NULL ? icon->runs : icons[icon_index].loaded_runs;
|
||||
if (runs == NULL) {
|
||||
continue;
|
||||
}
|
||||
@@ -358,7 +410,6 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
const uint16_t overlay_y0 = draw->y;
|
||||
const uint16_t overlay_y1 = draw->y + draw_height;
|
||||
if (overlay_y1 <= row_start || overlay_y0 >= row_end) {
|
||||
free(loaded_runs);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -387,13 +438,11 @@ static void lcd_direct_overlay_icons(uint16_t *pixel_buffer,
|
||||
icon_pixel_pos = run_end;
|
||||
}
|
||||
}
|
||||
|
||||
free(loaded_runs);
|
||||
}
|
||||
}
|
||||
|
||||
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_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(image != NULL && image->runs != NULL,
|
||||
@@ -448,7 +497,7 @@ static esp_err_t lcd_direct_draw_rle_memory_image(const lcd_direct_image_t *imag
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_draw_rle_file_image(const lcd_direct_image_t *image,
|
||||
const lcd_direct_icon_draw_t *icons,
|
||||
const lcd_direct_prepared_icon_t *icons,
|
||||
size_t icon_count)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(image != NULL && image->path != NULL,
|
||||
@@ -547,10 +596,19 @@ static esp_err_t lcd_direct_draw_rle_image(const lcd_direct_image_t *image,
|
||||
ESP_ERR_INVALID_ARG,
|
||||
TAG,
|
||||
"invalid image");
|
||||
lcd_direct_prepared_icon_t prepared_icons[LCD_DIRECT_DEFAULT_ICON_COUNT];
|
||||
size_t prepared_icon_count = lcd_direct_prepare_icons(icons,
|
||||
icon_count,
|
||||
prepared_icons,
|
||||
sizeof(prepared_icons) / sizeof(prepared_icons[0]));
|
||||
esp_err_t err = ESP_OK;
|
||||
if (image->runs != NULL) {
|
||||
return lcd_direct_draw_rle_memory_image(image, icons, icon_count);
|
||||
err = lcd_direct_draw_rle_memory_image(image, prepared_icons, prepared_icon_count);
|
||||
} else {
|
||||
err = lcd_direct_draw_rle_file_image(image, prepared_icons, prepared_icon_count);
|
||||
}
|
||||
return lcd_direct_draw_rle_file_image(image, icons, icon_count);
|
||||
lcd_direct_release_prepared_icons(prepared_icons, prepared_icon_count);
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_draw_asset_sequence_once(const lcd_direct_request_t *request)
|
||||
|
||||
Reference in New Issue
Block a user