perf(lcd): cache idle eye frames and anchor blink timing

This commit is contained in:
chenjintao
2026-10-09 17:03:10 +08:00
parent b5c8aeb4fe
commit 89e8e3abc2
4 changed files with 382 additions and 19 deletions
+58
View File
@@ -0,0 +1,58 @@
from pathlib import Path
import re, subprocess, tempfile
src=(Path(__file__).resolve().parents[1]/'components/platform/src/lcd_direct.c').read_text()
def extract(name):
m=re.search(r'static [^;{}]+\b'+name+r'\([^;{}]*\)\s*\{',src)
a=m.start();b=src.index('{',a)+1;depth=1
while depth:
if src[b]=='{':depth+=1
if src[b]=='}':depth-=1
b+=1
return src[a:b]
prefix='''#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <assert.h>
#include <stdio.h>
#define ESP_OK 0
#define ESP_ERR_INVALID_STATE 1
#define LCD_DIRECT_EMOTE_STEP_MS 34U
#define LCD_DIRECT_PRESENTATION_WAIT_POLL_MS 20U
#define pdMS_TO_TICKS(x) ((x)/10)
#define ESP_RETURN_ON_ERROR(expr,...) do {int e=(expr);if(e)return e;}while(0)
typedef int esp_err_t;
typedef uint32_t TickType_t;
static int s_emote_handle, delays, stop_after, locks, unlocks;
static bool stop;
static int64_t now;
static int64_t esp_timer_get_time(void){return now;}
static bool lcd_direct_should_stop_idle(void){return stop;}
static int gfx_emote_lock(int h){++locks;return 0;}
static int gfx_emote_unlock(int h){++unlocks;return 0;}
static int lcd_direct_emote_update_hud(bool force,bool *changed){*changed=false;return 0;}
static int lcd_direct_emote_refresh(void){return 0;}
static void vTaskDelay(TickType_t ticks){assert(ticks>0);now+=ticks*10000;++delays;if(stop_after && delays>=stop_after)stop=true;}
'''
test='''int main(void){
for(size_t i=0;i<12;++i){
assert(lcd_direct_emote_step_deadline(123000,i)==123000+(int64_t)(i+1)*34000);
now+=13000;
assert(lcd_direct_emote_wait_until(lcd_direct_emote_step_deadline(0,i))==0);
assert(now>=(int64_t)(i+1)*34000 && now<(int64_t)(i+1)*34000+10000);
}
int64_t anchored=now;
now=0;
for(size_t i=0;i<12;++i){now+=13000;assert(lcd_direct_emote_wait(21)==0);}
assert(anchored<418000 && now>=480000);
now=200000;int before=delays;
assert(lcd_direct_emote_wait_until(100000)==0 && now==200000 && delays==before);
stop=true;assert(lcd_direct_emote_wait_until(100000)==1);
stop=false;stop_after=delays+1;assert(lcd_direct_emote_wait_until(now+100000)==1);
assert(locks==unlocks);
printf("PASS: fixed deadlines, 10ms tick drift reduction (anchored=%lldus), late/stop handling and paired HUD locks\\n",(long long)anchored);
}'''
with tempfile.TemporaryDirectory(prefix='emote-timeline-') as tmp:
c=Path(tmp)/'test.c';exe=Path(tmp)/'test'
c.write_text(prefix+'\n'.join(extract(n) for n in ['lcd_direct_emote_wait_until','lcd_direct_emote_wait','lcd_direct_emote_step_deadline'])+'\n'+test)
subprocess.run(['clang','-std=c11','-fsanitize=address,undefined',str(c),'-o',str(exe)],check=True)
subprocess.run([str(exe)],check=True)