Цитата:
;здесь обработка клавиатуры
Ld a,(OldWin0Page); восстанавливаем системную страницу
out (0x82),a
ld a,0
ld (scankey),a
LD C,0x31 ;Функция опроса клавиатуры без ожидания
RST 0x10
JR Z,int2body1
ld a,d
and 127 ;убираем седьмой бит
ld (scankey),a
int2body1:
Ld a,(Win0Page)
out (0x82),a
Почему-то это не работало...
Цитата:
;Клавиатура
SerialChAData EQU #18 ;регистр данных канала A последовательного порта контроллера Z84
SerialChACtrl EQU #19 ;контролирующий регистр канала A последовательного порта контроллера Z84
kbMoveUp EQU 0x75 ;стрелка вверх
kbMoveDown EQU 0x72 ;стрелка вниз
kbMoveLeft EQU 0x6B ;стрелка влево
kbMoveRight EQU 0x74 ;стрелка вправо
kbEsc EQU 0x76 ;ескейп
target defb 0 ;код нажатой клавиши
scankey defb 0
pflag defb 0
eflag defb 0 ;флаг расширенных кодов
fflag defb 0 ;флаг заполнения буфера
;_____________________________
;обработчик прерывания
int2m:
di
push af
push bc
push de
push hl
ld a,(tick)
cp 2
jr nc, int2body
inc a
ld (tick),a
int2body:
;здесь обработка клавиатуры AT[ps/2 scan set 2]
keys:
ld a,(target) ; проверяем переменную со сканкодом нажатой клавиши
or a
jp nz, keystep2 ;если не ноль, то переходим к отлову отжатия клавиши
;иначе проверяем сканкод нажатой клавиши
call scan
ld d,a
ld a,(fflag) ;проверяем буфер клавиатуры по флагу заполнения
or a
jp z, player ;если пуст - выходим
ld a,d
cp 0xF0; ;клавиша отжата?
jr nz, keystep11 ;нет - проверяем на байт расширения
call scan; ;иначе, освождаем буфер и выходим
jp player
keystep11:
cp 0xE0; ;проверка на байт расширения
jr nz,keystep12 ;если нерасширенный код, то переходим на обработку нерасширенных кодов
call scan ;иначе, читаем буфер и сравниваем с
cp 0xF0 ;кодом отжатия расширенного кода
jr nz,keystep13 ;если не отжатие, то расширенный код, переходим на обработку расширенных кодов
call scan ;иначе, освобождаем буфер и выходим
jp player
keystep13:
ld (target),a ;запоминаем расширенный код
ld a,1
ld (eflag),a ;устанавливаем флаг расширенного кода и выходим
jp player
keystep12:
ld (target),a ;запоминаем нерасширенный код
xor a
ld (eflag),a ;сбрасываем флаг расширенного кода и выходим
jp player
keystep2:
ld a,(eflag) ;по флагу расширенных кодов определяем какое отжатие ловить
or a
jr z, keystep_for_F0 ;если флаг сброшен, ловим простое отжатие F0 нерасширенных кодов
;иначе, отлов расширенного отжатия EOFO расширенных кодов
call scan
ld d,a
ld a,(fflag)
or a
jp z, player ;буфер пуст? да - выход
ld a,d
cp 0xE0 ;расширенный код?
jr nz,F0compare ;нет - проверка на обычное отжатие
call scan ;иначе,читаем буфер
cp 0xF0 ;проверка на расширенное отжатие
jr nz, player ;если не расширренное отжатие, то освобождаем буфер и выход
call scan ;иначе, читаем расширенный код клавиши, которая была отжата
ld b,a
ld a,(target)
cp b ;сравниваем код отжатой клавиши с клавишей, которая была нажата
jr nz, player ;если коды не совпадают - выход
;ld (scankey),a
xor a
ld (target),a ;иначе, сбрасываем переменную для кода нажатой клавиши
ld (eflag),a ; и сбрасываем флаг расширенных кодов
jr player ;выход
F0compare:
cp 0xF0 ;обычное отжатие?
jr nz, player ;нет -выход
call scan ;да - освобождаем буфер и выход
jr player
;отлов F0 (обычного отжатия нерасширенных кодов)
keystep_for_F0:
call scan ;читаем буфер
ld d,a
ld a,(fflag)
or a
jp z, player ;если буфер пуст - выход
ld a,d
cp 0xF0 ;обычное отжатие?
jr nz, E0compare ;если нет - проверка расширенных кодов
call scan ;иначе, читаем код отжатой клавиши
ld b,a
ld a,(target)
cp b ;сравниваем код отжатой клавиши с клавишей, которая была нажата
jr nz, player ;если коды не совпадают - выход
;ld (scankey),a
xor a
ld (target),a ;иначе, сбрасываем переменную для кода нажатой клавиши
jr player ;выход
E0compare: ;отлов расширенных кодов для освобождения буфера
cp 0xE0 ;расширенный код?
jr nz, player ;если нет - выход
call scan ;иначе, читаем буфер
cp 0xF0 ;расширенное отжатие?
jr nz, player ;если нет - выход
call scan ;иначе, освобождаем буфер от кода отжатой клавиши и выход
jr player
;работа c плеером
player:
pop hl
pop de
pop bc
pop af
ei
reti
;_______________________________
scan:
;проверка есть ли данные от клавиатуры
IN a,(SerialChACtrl) ;бит0 = 0 - нет данных;бит0 = 1 - есть данные
and 1
ld (fflag),a
JR z,scanexit
;если данные есть
IN a,(SerialChAData)
scanexit:
ret
Работает. Программа реагирует на клавиши направлений(стрелки) и ескейп. В каждое отдельное прерывание работает только треть кода: либо фиксация в переменной кода нажатой клавиши, либо отлов отжатия F0, или отлов отжатия расширенного кода E0F0. Прошу потестить на реале, так как есть подозрение что эмулятор не пропускает клавиши PrintScreen и Pause\Break. Нужно проверить - нажатие этих клавиш не приведёт ли к отключению реакции на клавиши? Алгоритм обработки нажатий реагирует на обычные( однобайтовые коды нажатий и двубайтовые отпусканий) и расширенные( двубайтовые для нажатий и трёхбайтовые для отпусканий) коды, но не на дополнительные. Вот, нажатие ПринтСкрин и Паузы может привести к непредсказуемым результатам, так как они имеют дополнительные коды( 4-6 байт). Есть подозрение, что нажатие Паузы заблокирует клавиатуру.