Odpovídáte na názor k článku Práce s klávesnicí na ZX Spectru. Názory mohou přidávat pouze registrovaní uživatelé. Nově přidané názory se na webu objeví až po schválení redakcí.
Zkusil jsem si napsat podprogram pro získání kodu klavesy. V akumulátoru je vrácen poziční kod - není to nijak zvlášt optimalizované. Formát je 5 bitů sloupec a 3 bity číslo řádku.
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
Pro otestovvání kodů klaves jsem využil "print_hex_number"
ENTRY_POINT equ $8000
ROM_OPEN_CHANNEL equ $1601
AT equ $16
;-------------------------------------------------------------------------------
GOTO_XY macro X,Y
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
ZNAK_XY macro X,Y,kod
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, kod ; kód znaku '*' pro tisk
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
org ENTRY_POINT
start:
ld A,2 ; číslo kanálu
call ROM_OPEN_CHANNEL ; otevření kanálu číslo 2 (screen)
main: GOTO_XY 5,5
call keyb
call print_hex_number
jp main
;-------------------------------------------------------------------------------
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
;-------------------------------------------------------------------------------
print_hex_number:
push AF ; uschovat A pro pozdější využití
rrca ; rotace o čtyři bity doprava
rrca
rrca
rrca
and $0f ; zamaskovat horní čtyři bity
call print_hex_digit; vytisknout hexa číslici
pop AF ; obnovit A
and $0f ; zamaskovat horní čtyři bity
call print_hex_digit; vytisknout hexa číslici
ret ; a návrat z podprogramu
;-------------------------------------------------------------------------------
print_hex_digit:
cp 0x0a ; test, jestli je číslice menší než 10
jr c, print_0_to_9 ; ok, hodnota je menší než 10, budeme tedy tisknout desítkovou číslici
add A, 65-10-48 ; ASCII kód znaku 'A', ovšem začínáme od desítky, ne od nuly (+ update pro další ADD)
print_0_to_9:
add A, 48 ; ASCII kód znaku '0'
rst 0x10 ; zavolání rutiny v ROM pro tisk jednoho znaku
ret ; návrat ze subrutiny
;-------------------------------------------------------------------------------
end ENTRY_POINT
No a ještě jeden program: klávesy E, S, D, X pohybují znakem po obrazovce
ENTRY_POINT equ $8000
ROM_OPEN_CHANNEL equ $1601
ROM_CLS equ $0DAF
AT equ $16
X0 equ 15
Y0 equ 10
XMIN equ 0
XMAX equ 31
YMIN equ 0
YMAX equ 21
ZNAK equ "#"
MEZERA equ " "
;-------------------------------------------------------------------------------
GOTO_XY macro X,Y
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
ZNAK_XY macro X,Y,kod
ld A, AT ; řídicí kód pro specifikaci pozice psaní
rst 0x10 ; zavolání rutiny v ROM
ld A, Y ; y-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, X ; x-ová souřadnice
rst 0x10 ; zavolání rutiny v ROM
ld A, kod ; kód znaku '*' pro tisk
rst 0x10 ; zavolání rutiny v ROM
endm
;-------------------------------------------------------------------------------
org ENTRY_POINT
start: call ROM_CLS
ld h,X0 ;pocatecni nastaveni X,Y
ld l,Y0
ZNAK_XY h,l,ZNAK
main: call delay
m01: call keyb
cp 0x26
call z,vpravo
cp 0x16
call z,vlevo
cp 0x25
call z,nahoru
cp 0x27
call z,dolu
jp main
;-------------------------------------------------------------------------------
keyb: push bc ;A - kod klavesy
push de
ld d,8 ;pocitadlo radku
ld c,0xF0 ;adresa portu
ld b,0xFE ;adresa prvniho radku
keyb01: in a,(c) ;nacteni portu
cpl ;negace
and 0x1F ;nastaveni hornich bitu
jp nz,keyb02 ;je stisknuta
ld a,b ;adresa dalsiho radku
rla
ld b,a
dec d ;pocitadlo radku
jp nz,keyb01 ;dalsi radek
pop de
pop bc
ret ;neni stisknuta zadna (A=00)
keyb02: rla ;nalezena prvni stisknuta klavesa
rla ;posun o 3 bity
rla
dec d
add a,d ;pricteni cisla radku
pop de
pop bc
ret ;stisknuta klavesa (A=sssssrrr)
;-------------------------------------------------------------------------------
vpravo:
ZNAK_XY h,l,MEZERA
ld a,h
cp XMAX
jr Z,vp0
inc h
vp0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
vlevo:
ZNAK_XY h,l,MEZERA
ld a,h
cp XMIN
jr Z,vl0
dec h
vl0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
dolu:
ZNAK_XY h,l,MEZERA
ld a,l
cp YMAX
jr Z,do0
inc l
do0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
nahoru:
ZNAK_XY h,l,MEZERA
ld a,l
cp YMIN
jr Z,na0
dec l
na0: ZNAK_XY h,l,ZNAK
ret
;-------------------------------------------------------------------------------
delay: push bc
push de
ld d,40
ld e,0
d01: dec e
jr nz, d01
dec d
jr nz, d01
pop de
pop bc
ret
end ENTRY_POINT