; ;Keyboard status ;provides label kbdst ;returns A=ASCII key,NZ else A=0,Z ;preserves all other registers ; ;MicroBee version with keyclick, fast repeat ; ;local equates ; kbrpdly equ 28h kbrpper equ 04h kbcldur equ 01h kbclper equ 24h ; pioa equ 00h piob equ 02h romrd equ 0Bh crtstat equ 0Ch crtaddr equ 0Ch crtdata equ 0Dh ; lpenh equ 16 lpenl equ 17 updh equ 18 updl equ 19 clupd equ 31 ; ; kbdst: push bc push de push hl ;Set ROM READ ld a,1 out (romrd),a ; ;Test if there was a previous key ld hl,kblkey+poff ld a,(hl) cp 0FFh jr z,kbnrpt ;skip if no previous key ; ;Test if previous key is still down ld b,3Ch ;debounce delay kbrplp: call poff+chkkey jr z,kbrpwt ;skip if repeating djnz kbrplp ;loop until sure not rept jr kbscmx ;skip if not repeating ; ;Candidate for a repeating key, is it allowed to do so kbrpwt: cp 53h ;LOCK jr z,kbwkey ; ;Same key, so test vertical retrace state kbsamk: ld hl,kblvrb+poff in a,(crtstat) and 20h cp (hl) jr z,kbwkey ;skip if still waiting ; ;Change in vertical retrace detected ld (hl),a ;store current state ld hl,kbrpcnt+poff dec (hl) ;count down twice for each blank jr nz,kbwkey ;skip if still waiting ; ;Key now repeating ld (hl),kbrpper ;set up repeat period ld a,(poff+kblkey) ;A=last key scan code jr kbdcod ; ;Test if any key is down kbnrpt: in a,(crtstat) and 40h jr z,kbnkey ;skip if no key ; ;Some key is down, scan matrix to find out which kbscmx: ld a,lpenl ;Clear LPEN strobe out (crtaddr),a in a,(crtdata) xor a ;start at matrix beginning ; ;Scan each location in keyboard matrix kbtslp: ld b,a ;B=code ld a,updh ;Set update reg to keyscan location out (crtaddr),a ld a,b and 03h out (crtdata),a ld a,updl out (crtaddr),a ld a,b and 0F0h out (crtdata),a ld a,clupd ;Clear Update strobe out (crtaddr),a out (crtdata),a kbtsl1: in a,(crtstat) ;wait until update rlca jr nc,kbtsl1 in a,(crtstat) ;Test if LPEN strobe occurred bit 6,a ld a,b ;A=code jr nz,kbgotk ;skip if got a key add a,10h adc a,0 ;carry to bit 0 cp 83h ;first non-key location jp nz,kbtslp+poff ;loop for next scan ; ;No key, reset last key flag kbnkey: ld (hl),0FFh kbwkey: xor a ;A=0,Z ; ;Exit keyboard status kbxt: push af ld a,lpenl out (crtaddr),a in a,(crtdata) xor a out (romrd),a pop af pop hl pop de pop bc ret ; ;LOCK key toggles flag kblkky: cp (hl) jr z,kbwkey ld (hl),a ld hl,kblock+poff ld a,1 xor (hl) ld (hl),a ;keyclick, return no code xor a ;return A,Z jr kbclk ; ;Test if special key kbgotk: cp 53h ;LOCK jr z,kblkky ; ;Calculate key scan code call poff+chkshft jr z,kbsh1 or 08h ;set bit 3 if shift key up kbsh1: call poff+chkctrl jr z,kbct1 or 04h ;set bit 2 if ctrl key up kbct1: ; ;Store last key scan code ld (hl),a ld hl,kbrpcnt+poff ld (hl),kbrpdly ; ;Decode scan matrix to ASCII kbdcod: rrca rrca rrca rrca ld l,a ;L=last keyscancode rotr 4 and 3Fh ;A=stripped down code cp 20h jr c,kbalfa cp 30h jr c,kbnum ;else A in 30..37, GREY key ; ;Use lookup table for Grey keys kbgrey: ld c,l ;C=flags for keys ld hl,kbgtb0+poff call poff+addhla ld a,(hl) ; ;Common return endpoint kbcom: cp 0FFh ;cause NZ to indicate key OK ; ;Click speaker, return AF kbclk: push af kbclp0: in a,(crtstat) and 20h jr z,kbclp0 ld h,kbcldur*2 kbclp1: in a,(piob) xor 40h out (piob),a ld a,kbclper/2 kbclp2: dec a jr nz,kbclp2 dec h jr nz,kbclp1 pop af jr kbxt ; ;Handle alphabetic keys kbalfa: bit 6,l ;test if ctrl was pushed jr z,kbcom ;return ctrl codes if yes add a,60h ;lower case chars ;if non alphabetic keys, skip cp 'a' jr c,kbnalf cp 'z'+1 jr nc,kbnalf ;handle caps lock on alphabetic keys ld h,a ld a,(poff+kblock) or a ld a,h jr z,kbshky ;skip if no lock kbswcs: xor 20h ;switch case ;if shift key pressed, switch case kbshky: bit 7,l ;test if shift was pushed jr nz,kbcom ;exit if no shift xor 20h ;switch case jr kbcom ; ;Non alphabetic keys kbnalf: cp 7Fh ;DEL key jr z,kbshky ;as for normal alpha keys jr kbswcs ;switch case for [\] keys ; ;Handle numeral keys kbnum: cp 2Ch ;don't switch case for ,./ keys jr nc,kbpnc ;skip for punctuation keys xor 10h ;switch case for numerals kbpnc: bit 7,l ;test if shift was pushed jr nz,kbcom ;skip if not pushed xor 10h ;switch case if shift pushed jr kbcom ; ;Lookup table for grey keys kbgtb0 equ $-30h db 1Bh ;ESC db 08h ;BS db 09h ;HT db 0Ah ;LF db 0Dh ;CR db 00h ;LOCK db 18h ;CAN db 20h ;SP ; ;Check shift key, return Z if pressed chkshft:push hl ld h,0F3h jr chkcom ; ;Check ctrl key, return Z if pressed chkctrl:push hl ld h,93h jr chkcom ; ;Check keyscan code A, returns Z if keypressed chkkey: push hl ld h,a ;Common code chkcom: ld l,a ;save A ;Set update reg to keyscan location ld a,updh out (crtaddr),a ld a,h and 03h out (crtdata),a ld a,updl out (crtaddr),a ld a,h and 0F0h out (crtdata),a ;Clear lpen flag ld a,lpenl out (crtaddr),a in a,(crtdata) ;Clear update flag ld a,clupd out (crtaddr),a out (crtdata),a ;Wait until update ckwupd: in a,(crtstat) rlca jr nc,ckwupd ;Return NZ if no key in a,(crtstat) cpl bit 6,a ;Restore A,HL ld a,l pop hl ret ; ;Variable space kblkey: db 0FFh ;last key scan code, 0FFh if no key ;bit 2=!ctrl key, bit 3=!shift key kblock: db 0 ;0=no lock,1=caps kblvrb: db 0 ;last vertical retrace blanking kbrpcnt:db 1 ;repeat down counter ; ;end of include file