SUBTTL Krmilnik Tipkovnice (RPKEY.ASM) v1.1,(C)26.11.90 OLEO
TITLE  REKLAMNI PANEL

.Z80	;Procesor je Z80A (Z8400)


.XLIST
IF1
	INCLUDE RPFNAMES.ASI
	INCLUDE RP.ASI
ENDIF
.LIST
.SALL

	PUBLIC	EN_NMI
	PUBLIC	KEY
	PUBLIC	RSTXT
	PUBLIC	ISBRK


;Resetira XT tipkovnico, ~e je KCLK low ve~ kot 20ms
RSTXT:	CLRP1 KCLKD
	ld a,60		;60*0.5ms=30ms (min)
rstxt0:	ld b,154	;500 us je 
	djnz $
	rst CLRWDT
	dec a
	jr nz,rstxt0
	SETP1 KCLKD
	CLRP1 KDATAD
	xor a		 ;nastavi status tipkovnice
	ld (KEYSTOGGLE),a
	ld (KEYSDOWN),a
	call SCANXT	;ugotovi ali se tipkovnica odziva
	ret  		;CY=1 ~e ni odziva, A=0AAh ~e je OK

	

;Bere tipko po XT protokolu
;Vhod: ni~
;Izhod: A=scan coda in CY=0 ~e je koda pravilna
;	CY=1 ~e scan koda ni na voljo
;Ne uporablja H,L in E registrov
SCANXT:	rst CLRWDT
	ld c,0		;c register hrani sprejeti byte
	ld b,5
	halt		;~akaj zdaj, da ne bo nepotrebne prekinitve
	SETP1 KDATAD	;omogo~i sprejem podatkov

sxt0:	TSTBIT KDATA,P1	;~akaj na start bit - 1
	jr nz,sxt11
	djnz sxt0
	CLRP1 KDATAD
	scf		;pri`gi CY ~e ni nobene kode na voljo
	ret
sxt11:	di		; kakor tudi ostale prekinitve
sxt1:	TSTBIT KCLK,P1	; - 2
	jr z,sxt1
	ld b,21		;~akaj na D0 bit - 3, a ne ve~ kot 200us
sxt2:	TSTBIT KCLK,P1	;11+7=18T ;NMI ni za pri~akovati v tem ~asu, ker
	jr z,sxt89	;7T/12T	  ;smo `e prej dovolj ~akali (HALT)
	djnz sxt2	;8T/13T ;; 18+7+13=38T -> 1 loop = 9.5us
	CLRP1 KDATAD	; TIME OVERRUN, zato blokiraj tipkovnico
	ei		;proces je sedaj lahko prekinjen
	scf		;data not available
	ret		;zato se vrni

sxt89:	ld a,(P1OUTMASK); izklju~i NMI
	or NMIEN
	out (P1),a
	ld(P1OUTMASK),a

sxt8:	TSTBIT KCLK,P1	; - 2
	jr z,sxt8
sxt9:	TSTBIT KCLK,P1	;~akaj na D0 bit - 3
	jr nz,sxt9
sxt3:	TSTBIT KCLK,P1	; - 4
	jr z,sxt3
	ld b,8		; pri~akujem 8 bitov podatkov
sxt4:	TSTBIT KDATA,P1	; berem podatek s tipkovnice
	ld d,a		; shranim Kdata v D
	TSTBIT KCLK,P1
	jr nz,sxt4
	or d		;A je bil 0
	jr z,sxt5
	scf		;~e je KDATA mark pri`gi CY
sxt5:	rr c		;zapi{em najprej D0 nato ponovim
sxt6:	TSTBIT KCLK,P1
	jr z,sxt6	;~akaj spet na naslednji bit
	djnz sxt4
	CLRP1 KDATAD	;blokiraj tipkovnico
	call EN_NMI	;omogo~i NMI prekinitve
	ei		;proces
	ld a,c		;A vsebuje scan kodo
	and a		;bri{i CY
	ret
	

;vklju~i NMI prekinitve in ohrani vse registre
EN_NMI:	push bc			;shrani BC
	push af			;kakor tudi AF
	ld a,(P1OUTMASK)
	and NOT NMIEN
	ld (P1OUTMASK),a	;`e prej nastavi masko
	ld b,a
	ld c, P1
nmiwa:	in a, (c)	;12T 	;~akaj na INT1
	and INT1	;7T
	jr z, nmiwa    	;12/7T, suma:26T=6.5us pri 4MHz
	out (c),b      	;potrebno je samo {e vklju~iti NMI
	pop af		;obnovi registre
	pop bc
	ret

	
	


;konverzija scan kode v ascii
SCC	MACRO code, stb		;;Scan Code Check uporablja AF
	  LOCAL skip1, skip2
	  cp code
	  rst CLRWDT
	  jr nz, skip1
	  set stb,(IY+KEYSDOWN-RAMSTART)
	  scf
	  rst CLRWDT
	  ret
	skip1:
	  cp code OR 80h
	  rst CLRWDT
	  jr nz, skip2
	  res stb,(IY+KEYSDOWN-RAMSTART)
	  rst CLRWDT
	  scf
	  ret
	skip2:
	  rst CLRWDT
	ENDM

SCT	MACRO code, stb		;;Scan Code Toggle uporablja AF
	  LOCAL skip1, skip2, skt0, skt1, skt2
	  cp code
	  rst CLRWDT
	  jr nz, skip1
	  bit stb,(IY+KEYSDOWN-RAMSTART)
	  jr nz,skt0
	  bit stb,(IY+KEYSTOGGLE-RAMSTART)
	  jr nz,skt1
	  res stb,(IY+KEYSTOGGLE-RAMSTART)
	  jr skt2
	skt1:
	  set stb,(IY+KEYSTOGGLE-RAMSTART)
	skt2:
	  set stb,(IY+KEYSDOWN-RAMSTART)
	skt0:
	  scf
	  rst CLRWDT
	  ret
	skip1:
	  cp code OR 80h
	  rst CLRWDT
	  jr nz, skip2
	  res stb,(IY+KEYSDOWN-RAMSTART)
	  rst CLRWDT
	  scf
	  ret
	skip2:
	  rst CLRWDT
	ENDM

;Konverzija scan code v ascii
;vhod A=scan code
;izhod:	A=ASCI(SCANCODE), C=scan code in CY=0 ~e je uspe{na konverzija
;	A=0 ~e je tipka specialna (F1..F10, Ins, ...)
;	CY=1 ~e je konverzija neuspe{na (Break, Num, Shift ...)
;uporablja AF,BC,HL
SCASC:	
	SCC  36h,0	;Right shift
	SCC  2Ah,1	;Left shift
	SCC  1Dh,2	;Ctrl
	SCC  38h,3	;Alt
	SCT  46h,4	;Scroll Lock
	SCT  45h,5	;Num Lock
	SCT  3Ah,6	;Caps Lock
	SCT  52h,7	;Ins
	
	bit 7,a
	jr z,scasc2		;~e je make scan koda sko~i
	scf			;pri`gi CY ~e je bila break koda
	ret			; in se vrni
scasc2:
	cp 03Ah			;ali je koda>3A
	jr c,scasc3		;sko~i ~e ni ve~ja
	xor a			;sicer A=0
	and a			; ?
	ret

scasc3:	ld b,0			;BC pove koliko je offseta
	ld c,a			;v tabeli scan kod
	ld a,(KEYSDOWN)		;~e je shift pritisnjen
	and 3
	jr z,scasc0	       	;potem
	ld hl,XTSCTS		;je kazalec na tabelo s shiftom
	jr scasc1
scasc0:	ld hl,XTSCT 		;sicer je brez shifta
scasc1:	add hl,bc		;pri{tejem offset in
	ld a,(hl)		;`e dobim asci kodo tipke
	and a			;bri{i CY
	ret


XTSCT:	;tabela brez SHIFTA
	DEFM " 1234567890-="	;prva vrsta  
	DEFB 00,00		;BS in TAB
	DEFM "qwertyuiop{|"	;druga vrsta
	DEFB 00,00 		;CR,CTRL
	DEFM "asdfghjkl~}#"
	DEFB 00			;2A=lshift
	DEFM "`zxcvbnm,./"
	DEFB 00,00,00,32,00	;Rshift,prtsc,alt,spc,caps

XTSCTS:	;tabela s SHIFTOM
	DEFM " !"">$%^&*()_+"	;prva vrsta  
	DEFB 00,00		;BS in TAB
	DEFM "QWERTYUIOP[\"	;druga vrsta
	DEFB 13,00 		;CR,CTRL
	DEFM "ASDFGHJKL^]<"
	DEFB 00			;2A=lshift
	DEFM "@ZXCVBNM;:?"
	DEFB 00,00,00,32,00	;Rshift,prtsc,alt,spc,caps

;Skanira tipkovnico
;Vhod: ni~
;Izhod: A=ASCII koda, C=scan code, CY=0 ali CY=1 ~e koda ni na voljo
;	
KEY:	call SCANXT	;beri tipkovnico
	ret c
	call SCASC
	ret


;Skanira tipkovnico in ~e je bila pritisnjena BREAK tipka 
;vrne CY=0 ~e je bila pritisnjena tipka BREAK
ISBRK:	push hl
	call KEY
	pop hl
	ret c
iskey:	jr nz,isbrk
	ld a,c
	cp 044h		;ali je pritisnjen break (F10)
	jr nz, isbrk	;ponovi, ker ni bila prava koda
	and a		;bri{i CY
	ret


KTST::
	call RSTXT

IF 1
ktst1:	call SCANXT
	jr c,ktst1
	call SCASC
	jr c,ktst1
	VBIOS POAASC
	DB NUL
	jr ktst1
ELSE
ktst2:	call KEY
	jr c,ktst2
	ld a,c
	VBIOS POAHEX
	DB NUL
	jr ktst2
ENDIF

	END