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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user