perf(lcd): cache idle eye frames and anchor blink timing
This commit is contained in:
@@ -104,6 +104,12 @@
|
||||
#define LCD_DIRECT_EMOTE_DMA_ROWS 16U
|
||||
#define LCD_DIRECT_EMOTE_CLOSED_ROWS 14U
|
||||
#define LCD_DIRECT_EMOTE_CLOSED_THRESHOLD 232U
|
||||
/* 眼睛包围盒四周留 2px;缓存包含此区域内原有静态脸部像素。 */
|
||||
#define LCD_DIRECT_EMOTE_CACHE_X 39
|
||||
#define LCD_DIRECT_EMOTE_CACHE_Y 63
|
||||
#define LCD_DIRECT_EMOTE_CACHE_WIDTH 242U
|
||||
#define LCD_DIRECT_EMOTE_CACHE_HEIGHT 97U
|
||||
#define LCD_DIRECT_EMOTE_CACHE_COUNT 9U
|
||||
#define LCD_DIRECT_EMOTE_EYES_X 41
|
||||
#define LCD_DIRECT_EMOTE_EYES_Y 65
|
||||
#define LCD_DIRECT_EMOTE_OPEN_MS 2000U
|
||||
@@ -259,10 +265,25 @@ static gfx_mesh_img_point_q8_t s_emote_eye_rest[LCD_DIRECT_EMOTE_MESH_POINTS];
|
||||
static uint16_t *s_emote_dma_pixels;
|
||||
static esp_err_t s_emote_flush_error;
|
||||
static bool s_emote_transfer_fault;
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
/* 只在 GFX 渲染锁内访问;计数区域提交,步骤内有提交才算一次画面更新。 */
|
||||
static uint32_t s_emote_completed_regions;
|
||||
static uint64_t s_emote_copy_us;
|
||||
static uint64_t s_emote_spi_us;
|
||||
#endif
|
||||
static gfx_obj_t *s_emote_closed_eyes;
|
||||
static gfx_image_dsc_t s_emote_closed_image;
|
||||
static uint8_t *s_emote_closed_pixels;
|
||||
static bool s_emote_show_closed;
|
||||
static const uint8_t s_emote_cache_closures[LCD_DIRECT_EMOTE_CACHE_COUNT] = {
|
||||
0, 16, 24, 64, 80, 128, 160, 192, LCD_DIRECT_EMOTE_CLOSED_THRESHOLD,
|
||||
};
|
||||
static gfx_image_dsc_t s_emote_cached_images[LCD_DIRECT_EMOTE_CACHE_COUNT];
|
||||
static uint8_t *s_emote_cached_pixels[LCD_DIRECT_EMOTE_CACHE_COUNT];
|
||||
static uint16_t *s_emote_capture_pixels;
|
||||
static gfx_obj_t *s_emote_cached_eyes;
|
||||
static bool s_emote_cache_ready;
|
||||
static int s_emote_cache_current = -1;
|
||||
static bool s_emote_active;
|
||||
#endif
|
||||
|
||||
@@ -304,6 +325,29 @@ static bool IRAM_ATTR lcd_direct_on_color_trans_done(esp_lcd_panel_io_handle_t p
|
||||
}
|
||||
|
||||
#if CONFIG_TQ_LCD_EMOTE_GFX_TEST
|
||||
/* 复制 GFX 输出与缓存窗口的交集。兼容整个屏幕或任意分块的 flush。 */
|
||||
static void lcd_direct_emote_capture(uint16_t *dst, int x1, int y1, int x2, int y2,
|
||||
const uint16_t *src)
|
||||
{
|
||||
int left = x1 > LCD_DIRECT_EMOTE_CACHE_X ? x1 : LCD_DIRECT_EMOTE_CACHE_X;
|
||||
int top = y1 > LCD_DIRECT_EMOTE_CACHE_Y ? y1 : LCD_DIRECT_EMOTE_CACHE_Y;
|
||||
int right_limit = LCD_DIRECT_EMOTE_CACHE_X + LCD_DIRECT_EMOTE_CACHE_WIDTH;
|
||||
int bottom_limit = LCD_DIRECT_EMOTE_CACHE_Y + LCD_DIRECT_EMOTE_CACHE_HEIGHT;
|
||||
int right = x2 < right_limit ? x2 : right_limit;
|
||||
int bottom = y2 < bottom_limit ? y2 : bottom_limit;
|
||||
if (left >= right || top >= bottom) {
|
||||
return;
|
||||
}
|
||||
for (int y = top; y < bottom; ++y) {
|
||||
memcpy(dst + (y - LCD_DIRECT_EMOTE_CACHE_Y) * LCD_DIRECT_EMOTE_CACHE_WIDTH +
|
||||
left - LCD_DIRECT_EMOTE_CACHE_X,
|
||||
src + (y - y1) * (x2 - x1) + left - x1,
|
||||
(right - left) * sizeof(uint16_t));
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_emote_prepare_cache(void);
|
||||
|
||||
static void lcd_direct_emote_flush(gfx_disp_t *disp,
|
||||
int x1,
|
||||
int y1,
|
||||
@@ -311,6 +355,12 @@ static void lcd_direct_emote_flush(gfx_disp_t *disp,
|
||||
int y2,
|
||||
const void *data)
|
||||
{
|
||||
/* 离屏预热期间只捕获 GFX 实际合成结果,不写 LCD、不计播放帧率。 */
|
||||
if (s_emote_capture_pixels != NULL) {
|
||||
lcd_direct_emote_capture(s_emote_capture_pixels, x1, y1, x2, y2, data);
|
||||
(void)gfx_disp_flush_ready(disp, false);
|
||||
return;
|
||||
}
|
||||
portENTER_CRITICAL(&s_state_lock);
|
||||
bool active = s_emote_active;
|
||||
portEXIT_CRITICAL(&s_state_lock);
|
||||
@@ -334,7 +384,14 @@ static void lcd_direct_emote_flush(gfx_disp_t *disp,
|
||||
if (rows > (size_t)(y2 - y)) {
|
||||
rows = (size_t)(y2 - y);
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
const int64_t copy_start_us = esp_timer_get_time();
|
||||
#endif
|
||||
memcpy(s_emote_dma_pixels, source, width * rows * sizeof(uint16_t));
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
s_emote_copy_us += esp_timer_get_time() - copy_start_us;
|
||||
const int64_t spi_start_us = esp_timer_get_time();
|
||||
#endif
|
||||
(void)xSemaphoreTake(s_transfer_done_sem, 0);
|
||||
esp_err_t err = esp_lcd_panel_draw_bitmap(s_panel, x1, y, x2, y + rows,
|
||||
s_emote_dma_pixels);
|
||||
@@ -344,6 +401,9 @@ static void lcd_direct_emote_flush(gfx_disp_t *disp,
|
||||
/* 超时后不再复用可能仍被 DMA 读取的缓冲,重启前禁止此路径传输。 */
|
||||
s_emote_transfer_fault = true;
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
s_emote_spi_us += esp_timer_get_time() - spi_start_us;
|
||||
#endif
|
||||
if (err != ESP_OK) {
|
||||
s_emote_flush_error = err;
|
||||
ESP_LOGE(TAG, "composed emote transfer failed: %s", esp_err_to_name(err));
|
||||
@@ -352,6 +412,11 @@ static void lcd_direct_emote_flush(gfx_disp_t *disp,
|
||||
source += width * rows;
|
||||
y += rows;
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
if (s_emote_flush_error == ESP_OK) {
|
||||
++s_emote_completed_regions;
|
||||
}
|
||||
#endif
|
||||
(void)gfx_disp_flush_ready(disp, false);
|
||||
}
|
||||
|
||||
@@ -544,6 +609,10 @@ static esp_err_t lcd_direct_emote_init(void)
|
||||
s_emote_hud = gfx_img_create(s_emote_disp);
|
||||
ESP_RETURN_ON_FALSE(s_emote_hud != NULL, ESP_ERR_NO_MEM, TAG, "create HUD failed");
|
||||
ESP_RETURN_ON_ERROR(gfx_img_set_src(s_emote_hud, &s_emote_hud_image), TAG, "set HUD failed");
|
||||
esp_err_t cache_err = lcd_direct_emote_prepare_cache();
|
||||
if (cache_err != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Eye cache unavailable, retain live mesh: %s", esp_err_to_name(cache_err));
|
||||
}
|
||||
s_emote_ready = true;
|
||||
ESP_LOGI(TAG,
|
||||
"esp_emote_gfx idle test ready (%u fps, PSRAM composed frame, %u-row DMA staging)",
|
||||
@@ -602,9 +671,12 @@ static esp_err_t lcd_direct_emote_update_hud(bool force, bool *changed)
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_emote_wait(uint32_t duration_ms)
|
||||
static esp_err_t lcd_direct_emote_wait_until(int64_t deadline_us)
|
||||
{
|
||||
const int64_t deadline_us = esp_timer_get_time() + (int64_t)duration_ms * 1000;
|
||||
/* 即使已经迟到,也检查取消;追赶时不忙等、不跳过眼型。 */
|
||||
if (lcd_direct_should_stop_idle()) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
while (esp_timer_get_time() < deadline_us) {
|
||||
if (lcd_direct_should_stop_idle()) {
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
@@ -634,9 +706,19 @@ static esp_err_t lcd_direct_emote_wait(uint32_t duration_ms)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_emote_wait(uint32_t duration_ms)
|
||||
{
|
||||
return lcd_direct_emote_wait_until(esp_timer_get_time() + (int64_t)duration_ms * 1000);
|
||||
}
|
||||
|
||||
static int64_t lcd_direct_emote_step_deadline(int64_t blink_start_us, size_t step)
|
||||
{
|
||||
return blink_start_us + (int64_t)(step + 1U) * LCD_DIRECT_EMOTE_STEP_MS * 1000;
|
||||
}
|
||||
|
||||
/* 同一张眼睛纹理连续收缩并弯曲;没有第二张眼型参与混合。
|
||||
* closure: 0=睁眼,255=闭眼。Q8 网格保留亚像素精度。 */
|
||||
static esp_err_t lcd_direct_emote_set_eye_closure(uint8_t closure)
|
||||
static esp_err_t lcd_direct_emote_deform_eye_closure(uint8_t closure)
|
||||
{
|
||||
bool closed = closure >= LCD_DIRECT_EMOTE_CLOSED_THRESHOLD;
|
||||
if (closed != s_emote_show_closed) {
|
||||
@@ -680,6 +762,117 @@ static esp_err_t lcd_direct_emote_set_eye_closure(uint8_t closure)
|
||||
LCD_DIRECT_EMOTE_EYES_Y + offset_y);
|
||||
}
|
||||
|
||||
/* 同一任务获取/释放 GFX 锁。缓存只在 LCD 初始化时生成,失败完整回退。 */
|
||||
static esp_err_t lcd_direct_emote_prepare_cache(void)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(gfx_emote_lock(s_emote_handle), TAG, "lock eye cache failed");
|
||||
const int64_t start_us = esp_timer_get_time();
|
||||
const size_t bytes = LCD_DIRECT_EMOTE_CACHE_WIDTH * LCD_DIRECT_EMOTE_CACHE_HEIGHT * 2U;
|
||||
esp_err_t result = ESP_OK;
|
||||
for (size_t i = 0; i < LCD_DIRECT_EMOTE_CACHE_COUNT && result == ESP_OK; ++i) {
|
||||
s_emote_cached_pixels[i] = heap_caps_calloc(1, bytes, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
|
||||
if (s_emote_cached_pixels[i] == NULL) {
|
||||
result = ESP_ERR_NO_MEM;
|
||||
break;
|
||||
}
|
||||
s_emote_cached_images[i] = (gfx_image_dsc_t) {
|
||||
.header.cf = GFX_COLOR_FORMAT_RGB565,
|
||||
.header.magic = C_ARRAY_HEADER_MAGIC,
|
||||
.header.w = LCD_DIRECT_EMOTE_CACHE_WIDTH,
|
||||
.header.h = LCD_DIRECT_EMOTE_CACHE_HEIGHT,
|
||||
.data_size = bytes,
|
||||
.data = s_emote_cached_pixels[i],
|
||||
};
|
||||
result = lcd_direct_emote_deform_eye_closure(s_emote_cache_closures[i]);
|
||||
if (result == ESP_OK) {
|
||||
s_emote_capture_pixels = (uint16_t *)s_emote_cached_pixels[i];
|
||||
gfx_disp_refresh_all(s_emote_disp);
|
||||
result = gfx_refr_now(s_emote_handle);
|
||||
s_emote_capture_pixels = NULL;
|
||||
}
|
||||
}
|
||||
s_emote_capture_pixels = NULL;
|
||||
esp_err_t restore_err = lcd_direct_emote_deform_eye_closure(0);
|
||||
if (result == ESP_OK) {
|
||||
result = restore_err;
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
s_emote_cached_eyes = gfx_img_create(s_emote_disp);
|
||||
result = s_emote_cached_eyes != NULL ? ESP_OK : ESP_ERR_NO_MEM;
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
result = gfx_img_set_src(s_emote_cached_eyes, &s_emote_cached_images[0]);
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
result = gfx_obj_set_pos(s_emote_cached_eyes, LCD_DIRECT_EMOTE_CACHE_X, LCD_DIRECT_EMOTE_CACHE_Y);
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
result = gfx_obj_set_visible(s_emote_eyes_open, false);
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
result = gfx_obj_set_visible(s_emote_closed_eyes, false);
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
s_emote_cache_current = 0;
|
||||
s_emote_cache_ready = true;
|
||||
ESP_LOGI(TAG, "Eye cache ready frames=%u PSRAM=%uB prepare_us=%llu (no Flash images)",
|
||||
(unsigned)LCD_DIRECT_EMOTE_CACHE_COUNT,
|
||||
(unsigned)(bytes * LCD_DIRECT_EMOTE_CACHE_COUNT),
|
||||
(unsigned long long)(esp_timer_get_time() - start_us));
|
||||
} else {
|
||||
if (s_emote_cached_eyes != NULL) {
|
||||
(void)gfx_obj_delete(s_emote_cached_eyes);
|
||||
s_emote_cached_eyes = NULL;
|
||||
}
|
||||
for (size_t i = 0; i < LCD_DIRECT_EMOTE_CACHE_COUNT; ++i) {
|
||||
free(s_emote_cached_pixels[i]);
|
||||
s_emote_cached_pixels[i] = NULL;
|
||||
}
|
||||
(void)gfx_obj_set_visible(s_emote_eyes_open, true);
|
||||
(void)gfx_obj_set_visible(s_emote_closed_eyes, false);
|
||||
s_emote_show_closed = false;
|
||||
}
|
||||
esp_err_t unlock_err = gfx_emote_unlock(s_emote_handle);
|
||||
return result != ESP_OK ? result : unlock_err;
|
||||
}
|
||||
|
||||
static int lcd_direct_emote_cache_index(uint8_t closure)
|
||||
{
|
||||
if (closure >= LCD_DIRECT_EMOTE_CLOSED_THRESHOLD) {
|
||||
closure = LCD_DIRECT_EMOTE_CLOSED_THRESHOLD;
|
||||
}
|
||||
for (size_t i = 0; i < LCD_DIRECT_EMOTE_CACHE_COUNT; ++i) {
|
||||
if (s_emote_cache_closures[i] == closure) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static esp_err_t lcd_direct_emote_set_eye_closure(uint8_t closure)
|
||||
{
|
||||
if (!s_emote_cache_ready) {
|
||||
return lcd_direct_emote_deform_eye_closure(closure);
|
||||
}
|
||||
const int index = lcd_direct_emote_cache_index(closure);
|
||||
ESP_RETURN_ON_FALSE(index >= 0, ESP_ERR_INVALID_ARG, TAG, "eye closure missing from cache");
|
||||
if (index == s_emote_cache_current) {
|
||||
return ESP_OK; /* 闭眼保持不失效、不传输。 */
|
||||
}
|
||||
esp_err_t err = gfx_img_set_src(s_emote_cached_eyes, &s_emote_cached_images[index]);
|
||||
if (err == ESP_OK) {
|
||||
s_emote_cache_current = index;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
static uint64_t lcd_direct_emote_fps_x100(uint32_t frames, uint64_t elapsed_us)
|
||||
{
|
||||
return elapsed_us > 0 ? (uint64_t)frames * 100000000ULL / elapsed_us : 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t lcd_direct_play_emote_face_until_pending(const lcd_direct_request_t *request)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(s_emote_handle != NULL && s_emote_eyes_open != NULL,
|
||||
@@ -702,7 +895,7 @@ static esp_err_t lcd_direct_play_emote_face_until_pending(const lcd_direct_reque
|
||||
if (result == ESP_OK) {
|
||||
result = unlock_err;
|
||||
}
|
||||
ESP_LOGI(TAG, "esp_emote_gfx idle playback started (composed mesh/arc blink)");
|
||||
ESP_LOGI(TAG, "esp_emote_gfx idle playback started (cached=%d)", s_emote_cache_ready);
|
||||
|
||||
/* 约 170ms 闭合、34ms 停顿、204ms 睁开,保持单一轮廓。 */
|
||||
static const uint8_t blink_closure[] = {
|
||||
@@ -718,40 +911,103 @@ static esp_err_t lcd_direct_play_emote_face_until_pending(const lcd_direct_reque
|
||||
if (result != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
const int64_t blink_start_us = esp_timer_get_time();
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
uint64_t draw_us_total = 0;
|
||||
uint32_t draw_us_max = 0;
|
||||
uint32_t late_frames = 0;
|
||||
uint32_t eye_updates = 0;
|
||||
/* lock / compose / PSRAM-copy / SPI-submit-and-wait,均为墙钟时间。 */
|
||||
uint64_t cost_total_us[4] = {0};
|
||||
uint32_t cost_max_us[4] = {0};
|
||||
#endif
|
||||
for (size_t i = 0; i < sizeof(blink_closure) / sizeof(blink_closure[0]) && result == ESP_OK; ++i) {
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
const int64_t frame_start_us = esp_timer_get_time();
|
||||
#endif
|
||||
result = gfx_emote_lock(s_emote_handle);
|
||||
if (result != ESP_OK) {
|
||||
break;
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
const int64_t lock_acquired_us = esp_timer_get_time();
|
||||
const uint64_t copy_before_us = s_emote_copy_us;
|
||||
const uint64_t spi_before_us = s_emote_spi_us;
|
||||
const uint32_t regions_before = s_emote_completed_regions;
|
||||
#endif
|
||||
result = lcd_direct_emote_set_eye_closure(blink_closure[i]);
|
||||
if (result == ESP_OK) {
|
||||
result = lcd_direct_emote_refresh();
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
const uint64_t copy_us = s_emote_copy_us - copy_before_us;
|
||||
const uint64_t spi_us = s_emote_spi_us - spi_before_us;
|
||||
const uint64_t locked_us = esp_timer_get_time() - lock_acquired_us;
|
||||
const uint64_t transfer_us = copy_us + spi_us;
|
||||
const uint32_t costs[4] = {
|
||||
(uint32_t)(lock_acquired_us - frame_start_us),
|
||||
(uint32_t)(locked_us > transfer_us ? locked_us - transfer_us : 0),
|
||||
(uint32_t)copy_us,
|
||||
(uint32_t)spi_us,
|
||||
};
|
||||
for (size_t cost = 0; cost < 4; ++cost) {
|
||||
cost_total_us[cost] += costs[cost];
|
||||
if (costs[cost] > cost_max_us[cost]) {
|
||||
cost_max_us[cost] = costs[cost];
|
||||
}
|
||||
}
|
||||
if (result == ESP_OK && s_emote_completed_regions != regions_before) {
|
||||
++eye_updates;
|
||||
}
|
||||
#endif
|
||||
unlock_err = gfx_emote_unlock(s_emote_handle);
|
||||
if (result == ESP_OK) {
|
||||
result = unlock_err;
|
||||
}
|
||||
if (result == ESP_OK) {
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
const uint32_t elapsed_us = (uint32_t)(esp_timer_get_time() - frame_start_us);
|
||||
draw_us_total += elapsed_us;
|
||||
const uint32_t period_us = LCD_DIRECT_EMOTE_STEP_MS * 1000U;
|
||||
if (elapsed_us < period_us) {
|
||||
/* 绘制时间属于本帧预算,不再额外固定睡 34ms。 */
|
||||
result = lcd_direct_emote_wait((period_us - elapsed_us + 999U) / 1000U);
|
||||
} else {
|
||||
++late_frames;
|
||||
/* 过载仍给其他任务调度机会,并在下一步检查 pending。 */
|
||||
result = lcd_direct_emote_wait(1U);
|
||||
if (elapsed_us > draw_us_max) {
|
||||
draw_us_max = elapsed_us;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
if (elapsed_us >= LCD_DIRECT_EMOTE_STEP_MS * 1000U) {
|
||||
++late_frames;
|
||||
}
|
||||
#endif
|
||||
/* 所有步骤锚定同一时间轴,tick/调度超时不累积到后续截止时间。
|
||||
* 绘制确实过慢时不跳帧,也不增加固定等待;下一步继续检查取消。 */
|
||||
result = lcd_direct_emote_wait_until(
|
||||
lcd_direct_emote_step_deadline(blink_start_us, i));
|
||||
}
|
||||
}
|
||||
#if CONFIG_TQ_LCD_EMOTE_FPS_LOG
|
||||
if (result == ESP_OK) {
|
||||
ESP_LOGI(TAG, "emote blink composed draw_us_avg=%llu late_frames=%u/12",
|
||||
(unsigned long long)(draw_us_total / 12U), (unsigned)late_frames);
|
||||
const uint64_t blink_us = esp_timer_get_time() - blink_start_us;
|
||||
const uint32_t steps = sizeof(blink_closure) / sizeof(blink_closure[0]);
|
||||
const uint64_t step_fps = lcd_direct_emote_fps_x100(steps, blink_us);
|
||||
const uint64_t update_fps = lcd_direct_emote_fps_x100(eye_updates, blink_us);
|
||||
/* 整轮结束再打日志,串口输出不落在被测眨眼窗口中。 */
|
||||
ESP_LOGI(TAG, "emote_fps blink_us=%llu steps=%u step_fps=%llu.%02llu "
|
||||
"eye_updates=%u update_fps=%llu.%02llu draw_avg_us=%llu "
|
||||
"draw_max_us=%u late_steps=%u/%u",
|
||||
(unsigned long long)blink_us, (unsigned)steps,
|
||||
(unsigned long long)(step_fps / 100), (unsigned long long)(step_fps % 100),
|
||||
(unsigned)eye_updates,
|
||||
(unsigned long long)(update_fps / 100), (unsigned long long)(update_fps % 100),
|
||||
(unsigned long long)(draw_us_total / steps), (unsigned)draw_us_max,
|
||||
(unsigned)late_frames, (unsigned)steps);
|
||||
ESP_LOGI(TAG, "emote_cost lock_avg_us=%llu lock_max_us=%u "
|
||||
"compose_avg_us=%llu compose_max_us=%u "
|
||||
"copy_avg_us=%llu copy_max_us=%u spi_avg_us=%llu spi_max_us=%u",
|
||||
(unsigned long long)(cost_total_us[0] / steps), (unsigned)cost_max_us[0],
|
||||
(unsigned long long)(cost_total_us[1] / steps), (unsigned)cost_max_us[1],
|
||||
(unsigned long long)(cost_total_us[2] / steps), (unsigned)cost_max_us[2],
|
||||
(unsigned long long)(cost_total_us[3] / steps), (unsigned)cost_max_us[3]);
|
||||
}
|
||||
#endif
|
||||
++cycles;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user