From fabb357c04b60d6844ee5c06685ceb52888d6de4 Mon Sep 17 00:00:00 2001 From: Stanislav N Mikhailov Date: Sat, 4 Apr 2026 20:20:52 +0300 Subject: [PATCH] docs(scenarios): add usage scenarios for paint contract --- SCENARIOS.ru.md | 117 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 117 insertions(+) create mode 100644 SCENARIOS.ru.md diff --git a/SCENARIOS.ru.md b/SCENARIOS.ru.md new file mode 100644 index 0000000..2b43595 --- /dev/null +++ b/SCENARIOS.ru.md @@ -0,0 +1,117 @@ +# Сценарии использования display engine + +В движке используется явный контракт рисования: +- `display_begin_paint_try()` или `display_begin_paint_blocking()` открывает кадр и даёт буфер. +- `display_end_paint()` закрывает кадр и сразу отправляет его на экран. + +Главное правило: каждый успешный `begin` должен завершаться `display_end_paint()`. + +## 1. Обновление 50 Гц без разрывов (рекомендуется) + +Что получить: +- Тик 50 Гц от таймера. +- Если экран занят, кадр пропускается. +- Без разрывов и без блокировки основного цикла. + +Конфигурация: +- `mode = DISPLAY_MODE_SAFE` +- `buffer_count = 1` или `2` + +Последовательность: +1. `display_init(&cfg)` +2. В `main` на каждом тике: + - `buf = display_begin_paint_try()` + - если `buf == NULL` -> пропуск тика + - рисование + - `display_end_paint()` + +## 2. Простой блокирующий цикл + +Что получить: +- Максимально короткий код без проверок `NULL`. + +Конфигурация: +- `mode = DISPLAY_MODE_SAFE` +- обычно `buffer_count = 1` + +Последовательность: +1. `display_init(&cfg)` +2. В цикле: + - `buf = display_begin_paint_blocking()` + - рисование + - `display_end_paint()` + +Минус: +- Поток может ждать буфер и временно не выполнять другую работу. + +## 3. Неблокирующая анимация/UI + +Что получить: +- Главный цикл всегда остаётся отзывчивым. + +Конфигурация: +- `mode = DISPLAY_MODE_SAFE` +- лучше `buffer_count = 2` + +Последовательность: +1. `display_init(&cfg)` +2. В цикле: + - `buf = display_begin_paint_try()` + - если `buf == NULL` -> делаем другую логику и идём дальше + - рисование + - `display_end_paint()` + +## 4. RAW-режим (низкоуровневый ручной контроль) + +Что получить: +- Полный ручной контроль swap в RAW-режиме. + +Конфигурация: +- `mode = DISPLAY_MODE_RAW` +- `buffer_count = 2` + +Последовательность: +1. `buf = display_begin_paint_try()` +2. если `buf == NULL` -> пропуск итерации +3. рисование +4. `display_swap_buffers()` +5. `display_end_paint()` + +Примечание: +- В RAW swap остаётся ручным, а отправка кадра выполняется через `display_end_paint()`. + +## 5. Что нельзя делать + +1. Делать второй `begin`, не закрыв первый `display_end_paint()`. +2. Забывать `display_end_paint()` после успешного `begin`. +3. Вызывать `display_submit()` вручную внутри открытой paint-секции. + +## 6. Шаблон 50 Гц + +```c +static volatile bool frame_tick_due = false; + +static bool frame_timer_cb(repeating_timer_t* t) { + (void)t; + frame_tick_due = true; + return true; +} + +while (1) { + if (!frame_tick_due) { + __asm volatile ("wfi"); + continue; + } + frame_tick_due = false; + + uint16_t* buf = display_begin_paint_try(); + if (!buf) { + continue; + } + + // draw(buf) + + bool ok = display_end_paint(); + hard_assert(ok); +} +```