/*
 * gfx_set_fps_div — задать делитель кадровой частоты (frame pacing).
 * n: логический кадр = РОВНО n кадровых интервалов (1=50 fps дефолт,
 * 2=25, 3=~16.7, 4=12.5, ...; 0 трактуется как 1).  gfx_wait_vsync()
 * при n>=2 переключается со лучевого поллинга на счётчиковый путь
 * (docs/sprite-api-design.md §9е).
 *
 * n>=2: однократно ставит _gfx_frame_isr в ЦЕПОЧКУ кадровых IRQ
 *       (irq_chain_add — свой слот, не мешает собственному хендлеру
 *       приложения); повторные вызовы только меняют делитель.
 * n<=1: снимает ТОЛЬКО свой слот (irq_chain_remove, НЕ irq_remove —
 *       чтобы не снести хендлер приложения) и возвращает старый путь.
 *
 * Возврат 0 / -1+errno: EINVAL (данные не в W2 — неподходящий memory
 * mode, из irq_chain_add), ENOMEM (все слоты цепи заняты).  ТОЛЬКО этот
 * модуль ссылается на irq-механику и _gfx_frame_isr — программа без
 * вызова сеттера не линкует ни цепочку, ни ISR (DCE).
 */
#include "../_bgi.h"
#include <irq.h>

int gfx_set_fps_div(uint8_t n)
{
    if (n < 2) {
        /* Выключение: снять свой слот, если ставили. */
        if (_gfx_fps_div >= 2) {
            irq_chain_remove(_gfx_frame_isr);
            _gfx_fps_div = 1;
        }
        return 0;
    }

    /* Первое включение — занять слот цепи под свой ISR. */
    if (_gfx_fps_div < 2) {
        if (irq_chain_add(_gfx_frame_isr) != 0)
            return -1;             /* errno уже выставлен (EINVAL/ENOMEM) */
        /* База отсчёта — с текущего тика, чтобы первый wait не «опоздал». */
        _gfx_fps_last = _gfx_frame_tick;
    }
    _gfx_fps_div = n;
    return 0;
}
