/*
 * kbdpoll — измерение ПОТОЛКА «плотного опроса» клавиатуры.
 *
 * Вопрос, на который отвечает тест (applications/PoP/roomtest/TASKS.md,
 * KBD-1): при зажатом Shift часть нажатий расширенных клавиш теряется —
 * байт не доезжает до порта 0x18, потому что импульс запроса прерывания
 * пропускается примерно в 44 % случаев и трёхбайтовый FIFO SIO
 * переполняется.  Редкий опрос (несколько раз за кадр) не помог вовсе.
 * Здесь опрос идёт МАКСИМАЛЬНО плотно — вся программа только этим и
 * занята, — то есть измеряется ЛУЧШЕЕ, чего опрос в принципе может
 * достичь.  Если и здесь байты теряются, приём не спасёт и в игре, и
 * искать надо в эмуляции/железе, а не у нас.
 *
 * Как мерить (MAME, счётчики брейкпоинтами, машина не останавливается):
 *   1. Найти в .map адреса `_kbd_raw_poll` и хвоста карты `__kbdraw_down`.
 *   2. bpset <адрес чтения порта 0x18 внутри kbd_raw_poll>,1,{ b@СЧ1 = b@СЧ1+1 ; g }
 *      bpset <адрес установки make-бита>,E==0x6C && (b@_kbdraw_pending & 1)==0,
 *            { b@СЧ2 = b@СЧ2+1 ; g }
 *   3. Держать Left Shift, нажать Home ровно N раз
 *      (`:kbd:ms_naturl:P1.7` 0x0002 — Shift, `:kbd:ms_naturl:P2.5` 0x0001 — Home).
 *      Home выбран потому, что он расширенный (тот же «fake shift», что у
 *      стрелок), но в этой программе ничего не делает.
 *   4. Ожидание: байт ровно 10*N (нажатие E0 F0 12 + E0 6C, отпускание
 *      E0 F0 6C + E0 12), make'ов ровно N.
 *
 * Итог теста на экран не выводится СПЕЦИАЛЬНО: любой вывод — это работа,
 * которая разрежает опрос и портит замер.  Числа снимаются из памяти.
 *
 * Выход — ESC.  Чтобы отличить «программа жива» от «повисла», крутится
 * бордюр: цвет меняется раз в 4096 опросов (медленное мерцание = работаем).
 */

#include <kbd_raw.h>
#include <stdint.h>

__sfr __at (0xFE) io_border;

int main(void)
{
    uint16_t spin = 0;

    if (kbd_raw_open() != 0)
        return 1;

    /* Ничего, кроме опроса.  Ни vsync, ни графики, ни ввода-вывода —
     * иначе замеряли бы не потолок приёма, а свою же нагрузку. */
    while (!kbd_raw_down(KBD_ESC)) {
        kbd_raw_poll();
        if (++spin == 0)
            io_border ^= 4;   /* признак жизни: бит 2 (зелёный) */
    }

    kbd_raw_close();
    return 0;
}
