Thermometr: drive frames at 60Hz IRQ and animate text bounce

This commit is contained in:
Stanislav N Mikhailov
2026-03-27 19:28:57 +03:00
parent ef263dd064
commit 85b2804a4a
+81 -11
View File
@@ -8,14 +8,25 @@
#define WIDTH 320 #define WIDTH 320
#define HEIGHT 240 #define HEIGHT 240
#define TEXT_H 16
static volatile bool frame_tick_due = false;
static repeating_timer_t frame_timer;
static void on_frame_done(void) static bool frame_timer_cb(repeating_timer_t* t)
{ {
// В режиме SAFE смена буферов выполняется внутри submit() (void)t;
display_submit(); frame_tick_due = true; /* Схлопываем тики: если опоздали, лишние просто пропускаются */
return true;
} }
static inline void wait_for_irq(void)
{
__asm volatile ("wfi");
}
static void on_frame_done(void) {}
int main() int main()
{ {
stdio_init_all(); stdio_init_all();
@@ -29,30 +40,89 @@ int main()
}; };
display_init(&cfg); display_init(&cfg);
const int64_t frame_period_us = -16667; /* 60 Hz, отрицательное значение = стабильный период */
display_submit(); /* Запускаем конвейер кадра */ bool timer_ok = add_repeating_timer_us(frame_period_us, frame_timer_cb, NULL, &frame_timer);
hard_assert(timer_ok);
float phase = 0.0f; float phase = 0.0f;
int text1_y = 90;
int text2_y = 110;
int text3_y = 130;
int text1_dy = 1;
int text2_dy = 1;
int text3_dy = 1;
render_ctx_t rc; render_ctx_t rc;
while (1) while (1)
{ {
display_poll(); display_poll();
if (!frame_tick_due)
{
wait_for_irq();
continue;
}
frame_tick_due = false;
/* SAFE + 1 буфер: ожидание освобождения внутри display_get_draw_buffer() */ /* Пропускаем кадр, если предыдущий ещё уходит по DMA */
if (!display_ready())
{
continue;
}
/* SAFE + 1 буфер: при display_ready() блокировки здесь уже не будет */
uint16_t* buf = display_get_draw_buffer(); uint16_t* buf = display_get_draw_buffer();
render_begin(&rc, buf, WIDTH, HEIGHT); render_begin(&rc, buf, WIDTH, HEIGHT);
render_clear(&rc, RGB16(9,19,9)); render_clear(&rc, RGB16(9,19,9));
render_grid(&rc, 20, 20, 40, RGB16(12,26,13)); render_grid(&rc, 20, 20, 40, RGB16(12,26,13));
render_sine_wave(&rc, WIDTH, 50, 2.0f, 0, HEIGHT / 2, phase, RGB16(0,255,0)); render_sine_wave(&rc, WIDTH*3, 100, 2.0f, 0, HEIGHT / 2, phase, RGB16(0,255,0));
draw_string(&rc, 50, 90, L"Проверка кириллицы", RGB565(255, 255, 255)); draw_string(&rc, 50, text1_y, L"Проверка кириллицы", RGB565(255, 255, 255));
draw_string(&rc, 45, 110, L"Proverka latinyanskogo", RGB565(0, 0, 255)); draw_string(&rc, 45, text2_y, L"Proverka latinyanskogo", RGB565(0, 0, 255));
draw_string(&rc, 35, 130, L"1234567890!@#$%%^&*()", RGB565(255, 0, 0)); draw_string(&rc, 35, text3_y, L"1234567890!@#$%%^&*()", RGB565(255, 0, 0));
phase += 0.08f;
text1_y += text1_dy;
if (text1_y <= 0)
{
text1_y = 0;
text1_dy = 1;
}
else if (text1_y >= (HEIGHT - TEXT_H))
{
text1_y = HEIGHT - TEXT_H;
text1_dy = -1;
}
text2_y += text2_dy;
if (text2_y <= 0)
{
text2_y = 0;
text2_dy = 1;
}
else if (text2_y >= (HEIGHT - TEXT_H))
{
text2_y = HEIGHT - TEXT_H;
text2_dy = -1;
}
text3_y += text3_dy;
if (text3_y <= 0)
{
text3_y = 0;
text3_dy = 1;
}
else if (text3_y >= (HEIGHT - TEXT_H))
{
text3_y = HEIGHT - TEXT_H;
text3_dy = -1;
}
phase += 0.16f;
if (phase > 6.2831853f) if (phase > 6.2831853f)
{ {
phase -= 6.2831853f; phase -= 6.2831853f;
} }
display_submit();
} }
} }