From 85b2804a4ab5cb78629ba5e472339647c3f260e5 Mon Sep 17 00:00:00 2001 From: Stanislav N Mikhailov Date: Fri, 27 Mar 2026 19:28:57 +0300 Subject: [PATCH] Thermometr: drive frames at 60Hz IRQ and animate text bounce --- Examples/Thermometr/src/main.c | 92 ++++++++++++++++++++++++++++++---- 1 file changed, 81 insertions(+), 11 deletions(-) diff --git a/Examples/Thermometr/src/main.c b/Examples/Thermometr/src/main.c index 7adc21f..6fefb1c 100644 --- a/Examples/Thermometr/src/main.c +++ b/Examples/Thermometr/src/main.c @@ -8,14 +8,25 @@ #define WIDTH 320 #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() - display_submit(); + (void)t; + frame_tick_due = true; /* Схлопываем тики: если опоздали, лишние просто пропускаются */ + return true; } +static inline void wait_for_irq(void) +{ + __asm volatile ("wfi"); +} + +static void on_frame_done(void) {} + int main() { stdio_init_all(); @@ -29,30 +40,89 @@ int main() }; display_init(&cfg); - - display_submit(); /* Запускаем конвейер кадра */ + const int64_t frame_period_us = -16667; /* 60 Hz, отрицательное значение = стабильный период */ + bool timer_ok = add_repeating_timer_us(frame_period_us, frame_timer_cb, NULL, &frame_timer); + hard_assert(timer_ok); 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; while (1) { 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(); render_begin(&rc, buf, WIDTH, HEIGHT); render_clear(&rc, RGB16(9,19,9)); 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)); - draw_string(&rc, 50, 90, L"Проверка кириллицы", RGB565(255, 255, 255)); - draw_string(&rc, 45, 110, L"Proverka latinyanskogo", RGB565(0, 0, 255)); - draw_string(&rc, 35, 130, L"1234567890!@#$%%^&*()", RGB565(255, 0, 0)); - phase += 0.08f; + render_sine_wave(&rc, WIDTH*3, 100, 2.0f, 0, HEIGHT / 2, phase, RGB16(0,255,0)); + draw_string(&rc, 50, text1_y, L"Проверка кириллицы", RGB565(255, 255, 255)); + draw_string(&rc, 45, text2_y, L"Proverka latinyanskogo", RGB565(0, 0, 255)); + draw_string(&rc, 35, text3_y, L"1234567890!@#$%%^&*()", RGB565(255, 0, 0)); + + 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) { phase -= 6.2831853f; } + + display_submit(); } }