libc/kbd: recovery по Rx-overrun SIO (залипание клавиш) + kbd_raw_sync

Симптом (интермиттентный): при отпускании shift+стрелка иногда стрелка
залипает.  Диагностика: на чистом одновременном release break-коды
обрабатываются верно (проверено MCP) → drain-логика ISR корректна.
Остаточное залипание = переполнение 3-байтного аппаратного FIFO SIO при
пачке скан-кодов (F0 12 E0 F0 74 = 5 байт) во время длинных DI-окон →
потерян break → залипание.

Фикс: трамплин после drain читает RR1 SIO (бит5 = Rx Overrun), при
overrun делает Error Reset (WR0=0x30) и взводит _kbdraw_overrun.
Новый kbd_raw_sync() (звать раз в кадр) по флагу сбрасывает всё
held-состояние _kbdraw_down (какой break потерян — неизвестно; реально
зажатые перечитаются).  pop_ctrl_tick зовёт kbd_raw_sync().  Буфер W2-
трамплина 288→320 (трамплин 244 Б).

ВНИМАНИЕ: путь overrun НЕ проверен детерминированно (баг интермиттентный,
зависит от тайминга DI) — ТРЕБУЕТ ПРОВЕРКИ на железе/в длинной сессии.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-18 12:26:42 +03:00
parent cbae48dbc4
commit 3c0baacbf6
7 changed files with 60 additions and 4 deletions
+4 -4
View File
@@ -30,10 +30,10 @@
#define _IRQ_VEC_BUF_SIZE (256 + 257)
/* Буфер под W2-копию кадрового трамплина (small/huge — _irq_tramp в
* W1). С запасом над реальным размером трамплина (225 Б после
* FIFO-drain цикла в raw-клавиатурной ветке, 2026-07-16 проверять
* __irq_tramp_end при правках, запас держать ≥ 60 Б). */
#define _IRQ_TRAMP_BUF_SIZE 288
* W1). С запасом над реальным размером трамплина (244 Б после
* FIFO-drain + overrun-recovery в raw-клавиатурной ветке, 2026-07-18
* проверять __irq_tramp_end при правках, запас держать ≥ 60 Б). */
#define _IRQ_TRAMP_BUF_SIZE 320
extern uint8_t _irq_vec_buf[_IRQ_VEC_BUF_SIZE];
+16
View File
@@ -104,6 +104,22 @@ void _irq_tramp(void) __naked
in a, (#_IRQ_SIO_A) ; ещё байт в FIFO?
rrca ; бит 0 CF
jr C, tr_kbd_drain ; да вычерпать следующий
;; --- FIFO опустошён: проверить Rx-overrun (потерян ли байт?) ---
;; RR1 SIO бит5 = Rx Overrun Error. При overrun break-код мог
;; потеряться (клавиша «залипнет») взводим _kbdraw_overrun, чтобы
;; kbd_raw_sync() в главном цикле снял held-состояние; и Error Reset
;; (WR0 команда 0x30), иначе бит залипнет. (z84c15 SIO, Z80-совм.)
ld a, #1
out (#_IRQ_SIO_A), a ; указатель на RR1
in a, (#_IRQ_SIO_A) ; читаем RR1 (указатель авто-сброс в 0)
bit 5, a
jr Z, tr_kbd_noovr
ld a, #0x30
out (#_IRQ_SIO_A), a ; WR0 Error Reset
ld a, #1
ld (__kbdraw_overrun), a
tr_kbd_noovr:
pop de
pop hl
pop af