Нужна процедура опроса клавиатуры, желательно наиболее полная, висящая на прерывании, а если будет с буфером, то вообще супер.
Драйвер клавиатуры для IS-DOS под расширенную клавиатуру Кворумов.
Опрос на прерываниях и с буфером на 32 байта.
Периодически пытаюсь осилить, но никак не получается.
Например непонятен кусок:
LB1FC: LD HL,FLGKBD
INC HL
Сразу нельзя LD HL,FLGKBD+1 сделать?
LB1D9: LD HL,TKBDD-'0' ;В СИСТЕМНОЙ ОБЛАСТИ
BIT 4,B ;+CAPS SHIFT ?
JR NZ,LB1E6 ;ДА
TKBDD это что за таблица?
И непонятны переменные:
BUF_KB
FLGKBD
KSTAT0
KSTAT4
LASTK
REPDEL
REPPER
Какого типа они должны быть(сколько вешать в байтах)?
Процедура из TFM instrument editor. Возвращает код нажатия, код отжатия (с установленным 7-м битом) или признак нажатия BREAK (NC). Учитывает дребезг клавиатуры и возможность того, что сложные клавиши дадут нажатие буквы/цифры раньше, чем нажатие CS или SS.
Процедура KEYB должна висеть на прерываниях. Имеется буфер на keybfsz нажатий.
IYKEY
IY0
HALT ;чтобы клава не тормозила из-за KBoff
CALL GETKEY
IYJR JZ IY0 ;для FNDNXT
IYKQ LD A,40,(IYJR),A
CALL 8020
LD A,(23560)
RET
REUNI
BIT 2,(IY+48)
RET Z
RECAP CP "Є
RET NC
XOR 1
CP "Ё
RET NC
XOR 1
CP "р
JNC BECAPRL
CP "░
RET NC
CP "а
JNC BECAPOK
CP "Р
JNC BECAPRL
CP "А
JNC BECAPOK
CP "@
RET Z
CP "_
RET Z
CP "A
RET C
CP "{
RET NC
CP "[
JC $+5
CP "a
RET C
BECAPOK XOR 80
BECAPRL XOR #70
RET
;#205: "BHY6..." (39 байт, SS=#E)
ssSpc=1;32
csEnt=2;13
ssEnt=3;13
;CS+3=4
;CS+4=5
;CS+2=6
;CS+1=7
;CS+5=8
;CS+8=9
;CS+6=10
;CS+7=11
;CS+0=12
;Ent=13
;SS+CS=14
;CS+9=15
csSpc=16;32
;Ext+key=CS+key
KEYB
;для autosav и моргания ovr
LD HL,(23672)
INC HL
LD (23672),HL
KBoff
NOP
;сканировать клавиатуру
LD HL,OLDSCAN
LD BC,#FEFE
KEYBSC LD D,(HL)
IN A,(C)
LD (HL),A
INC HL
LD (HL),D ;старый скан
INC HL
RLC B
JC KEYBSC
;время CS и SS
tss=$+1
tcs=$+2
LD BC,0
;если нажат CS+SS, то OK (у CS код 14)
;если нажат только CS, то снимаем его из матрицы
;SS снимаем с матрицы всегда
XOR A
LD HL,OLDSCAN+14
BIT 1,(HL) ;ss
SET 1,(HL) ;снимаем ss
JNZ freess ;ss отжат
INC C
JNZ okss ;max=255
DEC C
JR okss
freess LD C,A ;=0
okss
LD HL,OLDSCAN
BIT 0,(HL) ;cs
JNZ freecs ;cs отжат
INC C
DEC C
JNZ $+3 ;ss нажат => EXT
INC (HL) ;снимаем cs, когда нет ss
INC B
JNZ okcs ;max=255
DJNZ okcs ;DEC B:JR всегда
freecs LD B,A ;=0
okcs
LD (tss),BC
;ВСЕ события пишем в буфер (чтобы не терять одновременные)
LD DE,#00D8
LD C,32
KEYBX LD HL,OLDSCAN+15
RRC C
LD B,8
KEYBX1 LD A,(HL) ;было отжато=1
;CPL ;0
DEC HL
;OR (HL) ;нажато=0
XOR (HL)
AND C
;JNZ KEYBX1N
JZ KEYBX1N
LD A,(HL)
AND C ;Z=нажатие
PUSH BC
PUSH HL
LD BC,(tss)
;E=#D8..#FF
;пребразовать скан-код E в код клавиши D
LD D,0
JZ KBpress ;Z=нажатие
LD HL,TCURKEYS-#D8
ADD HL,DE
LD D,(HL) ;под каким кодом была нажата эта клавиша
SET 7,D ;признак отжатия в коде клавиши
XOR A
LD (KBcode),A ;выкл. автоповтор
JR KBpressQ
KBpress
LD HL,#205-#D8
XOR A
CP C
JZ $+5
LD HL,TSSKEYS-#D8
CP B
JZ $+5
LD HL,TCSKEYS-#D8 ;ex#=cs#
ADD HL,DE
LD A,(HL) ;код клавиши
LD HL,TCURKEYS-#D8
ADD HL,DE
LD (HL),A ;для отжатия - под каким кодом нажата клавиша
LD D,A
LD (KBcode),A
LD (KBbc),BC
LD A,15
LD (KBtime),A
KBpressQ
CALL PUTKEY
KBpressQQ
POP HL
POP BC
KEYBX1N
INC E
DEC HL
DJNZ KEYBX1
JNZ KEYBX
;INC D
;DEC D
;RET NZ ;что-то изменилось - нет автоповтора
LD HL,OLDSCAN
LD A,-1
LD B,8
AND (HL) ;"что-то нажато" (SS снят с матрицы, "CS"=EXT)
INC HL,HL
DJNZ $-3
CPL
AND 31
RET Z ;ничего не нажато
;нажата старая(?) кнопка
KBtime=$+1
LD A,15
DEC A
JZ YEpKEYauto ;автоповтор (старые D,B,C)
;автоповтору не время
LD (KBtime),A ;постепенно убавляем до 1
;и после 1 больше не попадем на убавление
;а сразу на повтор
RET
YEpKEYauto
KBbc=$+1
LD BC,0
KBcode=$+1
LD D,0
PUTKEY
GKEYADR=$+1
LD HL,KEYBUFF ;адрес конца списка
LD A,D
OR A
RET Z ;нет события
CP 32
JNC YEpNUPR
;не складировать автоповтор cs3, cs4, cs9, cs0!
;вообще управляющие клавиши
DEC HL,HL,HL
CP (HL)
RET Z ;еще старую копию не забрали!
INC HL,HL,HL
YEpNUPR
;есть ли место в буфере?
LD A,L
CP KEYBUFFEND
RET Z ;нет места!
LD (HL),D
INC HL
LD (HL),C
INC HL
LD (HL),B
INC HL
LD (HL),0 ;маркер конца списка
LD (GKEYADR),HL
IFN sobyt
LD HL,(SOBYTS)
INC HL
LD (SOBYTS),HL
ENDIF
SET 5,(IY+1)
RET
GETKEY
;возвращает A,B<->C,ничего не портит
;Z=no keys
PUSH HL
LD HL,KBoff
LD (HL),201 ;запрет опроса клавы
;если запрет на изменение буфера, то можно потерять событие
LD HL,KEYBUFF
LD A,(HL)
OR A
JZ GETKpop ;no keys in buff
LD A,(HL)
PUSH DE
LD D,H,E,L
INC HL
LD B,(HL);в обр.порядке для совместимости
INC HL
LD C,(HL)
INC HL
PUSH BC
LD BC,keybfsz-1*3
LDIR
EXD
LD (HL),B
LD HL,(GKEYADR)
DEC HL,HL,HL
LD (GKEYADR),HL
PUSH AF
LD A,L
CP KEYBUFF
JZ $+6
SET 5,(IY+1)
POP AF
;CALL RECAP
INC B ;NZ
POP BC
POP DE
GETKpop
LD HL,KBoff
LD (HL),0
POP HL
LD (23560),A
RET
TCURKEYS
;таблица для отжатия - кем является каждая клетка матрицы
;т.е. под каким кодом она нажата
DS 40
TCSKEYS
;a-la #205
DB "bhy",10,8,"tgv"
DB "nju",11,5,"rfc"
DB "mki",9,4,"edx"
DB 0,"lo",15,6,"wsz"
DB csSpc,csEnt,"p",12,7,"qa",14
TSSKEYS
;a-la #205
DB "*^[&%>}/"
DB ",-]'$<{?"
DB ".+",ssI,"(#",ssE,"\`"
DB 0,"=",";",")@",ssW,"|:"
DB ssSpc,ssEnt,34,"_!",ssQ,"~"
;CS+SS ищется в TCSKEYS
DISPLAY $
;за 3 байта до KEYBUFF должен быть симв>=32
KEYBUFF
DS 3*keybfsz ;key,tss,tcs
KEYBUFFEND
DB 0 ;конец самого буфера (после кнопки кладут 0)
OLDSCAN
DS 16,-1;от CS.. до Spc..
;новая,старая,новая,...
Oleg N. Cher
27.11.2014, 15:59
Нужна процедура опроса клавиатуры, желательно наиболее полная, висящая на прерывании, а если будет с буфером, то вообще супер.Буферизованный опрос клавиатуры (http://zx.oberon2.ru/forum/viewtopic.php?f=10&t=221), реализованный для ZXDev. Коды клавиш берутся из LAST_K, соответственно, работает автоповтор клавиш. Исходник оформлен для сборки компилятором SDCC.
#define KeyBufSize 8
// Возвращает количество клавиш в буфере.
unsigned char Input_Available (void);
// Возвращает код нажатой клавиши.
// Если нажатых клавиш нет, ожидает.
char Input_Read (void);
// Вызывайте из обработчика прерываний IM 2.
void Input_RunMe50Hz (void);
/*--------------------------------- Cut here ---------------------------------*/
char Input_keyBuf [KeyBufSize];
/* Закономерно считаем, что более актуальны клавиши, нажатые позднее,
поэтому при переполнении буфера будем удалять из него нажатые ранее.
Эта стратегия кажется более удачной, чем игнорирование всех клавиш,
нажатых после переполнения буфера (как в контроллере клавиатуры IBM PC). */
char Input_Read (void) {
__asm
LOOPrptbuf$:
LD HL,#_Input_keysAvailable+1
LD A,(HL)
OR A
JR Z,LOOPrptbuf$
DEC (HL)
.globl _Input_keyOut
_Input_keyOut: ; Read a key:
LD HL,#_Input_keyBuf ; key := keyBuf[keyOut];
LD C,(HL)
INC HL ; keyOut := (keyOut+1) MOD KeyBufSize;
LD A,L
SUB #<_Input_keyBuf+KeyBufSize
JR NZ,Save_keyOut$
LD HL,#_Input_keyBuf
Save_keyOut$:
LD (_Input_keyOut+1),HL
LD L,C ; RETURN key
__endasm;
} //Input_Read
void Input_RunMe50Hz (void) __naked {
__asm
LD IY,#0x5C3A
RST 0x38
BIT 5,1(IY)
RET Z
RES 5,1(IY)
_Input_keyIn:
LD HL,#_Input_keyBuf ; Add a key:
LD A,-50(IY) ; keyBuf[keyIn] := CHR(keyCode);
LD (HL),A
INC HL
LD A,L
SUB #<_Input_keyBuf+KeyBufSize
JR NZ,Save_keyIn$
LD HL,#_Input_keyBuf
Save_keyIn$:
LD (_Input_keyIn+1),HL
.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
ADC #0
LD (_Input_keysAvailable+1),A
RET C
JR _Input_keyOut
__endasm;
} //Input_RunMe50Hz
/*--------------------------------- Cut here ---------------------------------*/
unsigned char Input_Available (void) {
__asm
LD HL,(_Input_keysAvailable+1)
__endasm;
} //Input_AvailableВопросы, предложения, критика?
Oleg N. Cher
25.12.2014, 14:46
В приведённом выше коде есть баг (!). Было:
.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #8 ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
ADC #0
LD (_Input_keysAvailable+1),A
RET C
JR _Input_keyOutСтало:
.globl _Input_keysAvailable
_Input_keysAvailable:
LD A,#0 ; Check overflow:
CP #KeyBufSize ; IF keysAvailable > 8 THEN keysAvailable := 8 END;
JR NC,_Input_keyOut
INC A
LD (_Input_keysAvailable+1),A
RETБаг связан с тем, что не было учтено влияние команды ADC #0 на флаг переноса, и процедура реагировала без переполнения буфера как на его переполнение.
Powered by vBulletin® Version 4.2.5 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot