PDA

Просмотр полной версии : Процедура опроса клавиатуры



DimkaM
08.10.2010, 15:25
Нужна процедура опроса клавиатуры, желательно наиболее полная, висящая на прерывании, а если будет с буфером, то вообще супер.

psb
08.10.2010, 15:47
и мне одну, пожалуйста!

Лас
08.10.2010, 15:49
1. http://www.worldofspectrum.org/infoseekid.cgi?id=2000076
2. 21132

DimkaM
08.10.2010, 16:01
а по русски нет ни у кого?

---------- Post added at 16:01 ---------- Previous post was at 16:00 ----------


и мне одну, пожалуйста!
Можешь по сылке Лас'а забрать, мне не жалко.

caro
08.10.2010, 16:35
Драйвер клавиатуры для IS-DOS под расширенную клавиатуру Кворумов.
Опрос на прерываниях и с буфером на 32 байта.

DimkaM
08.10.2010, 18:03
Драйвер клавиатуры для IS-DOS под расширенную клавиатуру Кворумов.
Опрос на прерываниях и с буфером на 32 байта.
Супер, то что нужно, а на русскую расскладку я даже и не расчитывал.

psb
08.10.2010, 18:17
Можешь по сылке Лас'а забрать, мне не жалко.
они без буфера.

DimkaM
08.10.2010, 18:18
Для IS-DOS по симпатичней выглядит, без СР/Мовских заморочек.
У Кворума получается лишний порт клавиатуры присутствует?!

DimkaM
27.06.2011, 11:10
Драйвер клавиатуры для 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
Какого типа они должны быть(сколько вешать в байтах)?

alone
27.06.2011, 12:58
Процедура из 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..
;новая,старая,новая,...

tiboh
27.06.2011, 18:13
Процедура попроще:

XOR A
LD (23560),A
LD IY,#5C3A
RST 56

Вешается на прерывания. Последнюю нажатую клавишу можно получить из ячейки по адресу 23560.

По адресам 23561 и 23562 можно изменить задержку опроса клавиш.

Автор процедуры Fyrex/Mayhem.

DimkaM
27.06.2011, 18:21
Немного не то. Нужна с буфером.

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 на флаг переноса, и процедура реагировала без переполнения буфера как на его переполнение.