;KIDVR/ASM - LS-DOS 6.2 SUBTTL '' PAGE OFF *MOD ; LF EQU 10 CR EQU 13 KB0 EQU 0F401H ;Row 0 RAM address KB6 EQU 0F440H ;Row 6 RAM address SHIFT EQU 0F480H ;Row 7 RAM address ; KIDVR JR KIBGN ;Branch around linkage DW KILAST ;Last byte used DB 3,'$KI' DW KIDCB$ ;Pointer to DCB DW 0 ;Spare KIDATA$ DB 0 ;Last key entered DB 0 ;Repeat time check RPTINIT EQU $-KIDATA$ DB 22 ;22 * 33.3ms = .733 sec RPTRATE EQU $-KIDATA$ DB 2 ;2 x RTC rate KBROW0 EQU $-KIDATA$ DB -1,-1,-1,-1 ;Image of rows 0-3 KBROW4 EQU $-KIDATA$ DB -1,-1 ;Image of rows 4-5 KBROW6 EQU $-KIDATA$ DB -1,-1 ;Image of rows 6-7 ; ; Conversion table for keyboard row 7/8 ; KBTBL DB CR,1DH,1FH,1FH ; DB 80H,0,0BH,1BH ; DB LF,1AH,8,18H ; DB 9,19H,20H,20H ; DB 81H,91H,82H,92H ; DB 83H,93H ; ; ; Table to generate 5B-5F, 7B-7F ; SPCLTB DB ',/.;',CR ; ; Entry to keyboard driver ; KIBGN LD A,C ;Get the character PUSH AF ;Save flags CALL @KITSK ;Hook for KI task POP AF ; ; Screen print (Control-*) processing ; CALL TYPAHD ;Chain downstream RET NC ;Ret if not PUSH AF ;Save flag state CP ':' JR Z,$?1 ;Go if screen print POP AF RET ; ; Perform a screen print ; $?1 POP AF ;Clean the stack @VDPRT LD A,(DFLAG$) ;Check on Graphic bit RLCA LD A,3EH ;Init for LD a,'.' JR NC,$+4 ;Go if not Graphic LD A,0FEH ;Change to CPR n LD ($?4),A ;Stuff cpr or ld LD HL,KFLAG$ ;Reset the BREAK bit RES 0,(HL) PUSH HL ;Save on stack LD HL,0 ;Init for row,col $?2 LD B,1 ;Get a character at the CALL @VDCTL ; row-H, col-L JR NZ,$?6 ;Go on error CP 20H JR NC,$+4 ;Convert control codes ADD A,40H ; to cap A-Z, + CP 80H ;Cvrt anything from X'80' JR C,$?5 ; thru X'FF' to a '.' $?4 LD A,'.' ; unless graphic bit set $?5 CALL @PRT ;Print the char & loop JR NZ,$?6 INC L ;Bump column counter LD A,L ;Check for end-of-line SUB 80 JR NZ,$?2 ;Loop if not EOL LD L,A ;Reset to column 0 DEC L ;Adj for CR force EX (SP),HL ;Get KFLAG$ BIT 0,(HL) ;Exit with A=0 on EX (SP),HL ; entrance of BREAK JR NZ,$?6 INC H ;Bump row counter LD A,H ;Test for end of screen CP 24 LD A,CR JR NZ,$?5 ;Put the CR & loop $?6 LD A,CR ;Close out with CR if CALL @PRT ; BREAK key detected POP HL ;Pop the KFLAG RES 0,(HL) ; & reset BREAK bit JR NOCHAR ; ; Driver to scan the keyboard ; *MOD KISCAN LD IX,KIDATA$ ;Point to data area LD HL,KIDATA$+KBROW0 ;Load kbd image start LD BC,KB0 ;Load start of keyboard LD D,0 ;Zero the key counter $?1 LD A,(BC) ;Load 1st char from kbd LD E,A XOR (HL) ;XOR with old value JR NZ,$?2 ;Go if different INC D ;Bump key counter INC HL ;Bump image pointer RLC C ;Go to next row JP P,$?1 ;Loop until end of rows LD A,(BC) ;Get row 7 AND 078H ;Strip SHIFT, CTL LD E,A XOR (HL) JR NZ,$?2 LD A,(IX+0) ;Key down? It's same as OR A ; the last if so JR Z,NOCHAR ;Ret if no key LD A,(TIMER$) ;Do we repeat the SUB (IX+1) ; same key? SUB (IX+RPTINIT) ;Beyond 0.75 seconds? LD A,(BC) ;Get back row 7 LD E,A JR C,$?10 ;Go if yes NOCHAR OR 1 ;Else don't repeat LD A,0 ;Show NZ with A=0 RET ; ; Found change in key matrix ; $?2 LD (HL),E ;Stuff KB image with new AND E ; KB row value JP Z,NOKEY ;Go if new is none ; ; Convert the depressed key ; LD E,A ;Save the active bit LD A,D ;Calculate 8 * row RLCA RLCA RLCA LD D,A ;Save 8 * row LD C,1 ;Add 8 * row + column $?3 LD A,C AND E ;Check if bits match JR NZ,$?6 ;Go if match INC D ; else bump value RLC C ;Shift compare bit JR $?3 ;Loop to test next ; ; Key pressed was not an alpha ; $?4 SUB 90H ;Adjust for non-alpha JR NC,$?9 ;Go if special key ADD A,40H ;Cvrt to numeric/symbol CP 3CH ;Manipulate to get JR C,$?5 ; proper code XOR 10H $?5 BIT 0,E ;Check SHIFT JR Z,$?11 ;Go if unshift XOR 10H ; else adjust for SHIFT JR $?11 ; ; Found a key - Set up the function codes ; $?6 LD A,(SHIFT) ;P/u the SHIFT key LD E,A ;Merge RH & LH Shift keys AND 2 ;Only merge bit 1 RRCA ;Bit 1 to bit 0 OR E ;Merge bits 0 & 1 LD E,A ;Value of (RHorLH) shift LD A,D ;Load semi-converted ADD A,60H ;If alpha, convert to CP 80H ; correct value LD HL,KFLAG$ JR NC,$?4 ;Go if not alpha ; ; Alpha <@-Z> - If caps lock or , ; Convert to caps unless CLEAR ; BIT 2,E ;CTRL key down? JR NZ,CTLA2Z ;CTRL sets <00-1A> CP 60H ;Invert @ and ` JR NZ,$?7 XOR 20H ;Invert & bypass test JR $?8 ; for CAPs lock $?7 BIT 1,(IX+KBROW6) ;If CLEAR, don't test JR NZ,$?8 ; for CAPs lock BIT 5,(HL) ;Caps lock? JR NZ,TGLCASE $?8 BIT 0,E ;Shift key down? JR Z,$?11 ;Bypass if not shifted JR TGLCASE ;Convert to upper case CTLA2Z SUB 60H ;Convert CTRL A-Z JR NZ,$?11 ;Go on A-Z BIT 0,E ;Shifted? SCF ;Set C-flag for CTL-@ RET Z ; & return if unshifted LD A,1CH ; else set EOF error RET $?10 LD A,(TIMER$) ;Advance time check ADD A,(IX+RPTRATE) ; by 0.067 seconds JR $?12 ;Go output the key ; ; Special keys - rows 6 & 7 ; $?9 CP 11 ;Compress F1-F3 keys JR Z,CAPSKEY ; while checking for CAP JR C,$+4 ; F1-F3 to 8-10 SUB 4 LD HL,KBTBL ;Pt to special char table RLCA ;Index into table, BIT 0,E ; shifted code is +1 JR Z,$+3 INC A LD C,A ;Index the table LD B,0 ADD HL,BC LD A,(HL) ;Load char from table JR $?11 ;Bypass restore of char TGLCASE XOR 20H ;Toggle the case $?11 CP 80H ;BREAK key? JR NZ,$?11A ;Ck on disable LD HL,SFLAG$ ;Break disabled? BIT 4,(HL) JR NZ,$?11B ;Don't set bit if disabl LD HL,KFLAG$ SET 0,(HL) ; otherwise set it JR $?11A $?11B RLA ;Rotate bit-7 out $?11A BIT 1,(IX+KBROW6) ;CLEAR key pressed? JR Z,NOTALPH ;Go if not down LD D,A ;Save code RES 5,A ;Set to upper-case for SUB 'A' ; test A-Z CP 'Z'-'A'+1 LD A,D ;Get back actual char JR NC,$+4 ;Go if not A-Z XOR 20H ;Shift keyboard case OR 80H ;Set bit 7 for CLEAR key NOTALPH BIT 0,E ;SHIFT key down? JR Z,FIXCLR ;Go if not GOTSHFT CP 9FH ;Shift-clear? JR Z,FIXSCL ;Go if so TSTSPA CP 20H ;Shift 0 or shift sp? JR NZ,KEYOK ;Go if not BIT 0,(IX+KBROW4) ;Ck zero key JR Z,KEYOK ;Go if not down ; ; Toggle the caps lock bit in the KFLAG$ ; CAPSKEY LD A,20H ;CAPs wasn't 20H CASHK$ LD HL,KFLAG$ ;Reverse case by XOR (HL) ; flipping bit 5 LD (HL),A JR NOKEY FIXSCL XOR 80H ;Reset bit 7 FIXCLR CP 9FH ;Clear key? JR NZ,KEYOK ;Go if not NOKEY XOR A KEYOK LD (IX+0),A LD BC,0184H ;Delay TYPHK$ CALL PAUSE@ LD A,(TIMER$) ;Set initialization DELAY2 ADD A,(IX+RPTINIT) ; repeat key delay $?12 LD (IX+1),A ;Save new repeat time LD A,(IX+0) ;Check if any key OR A ; code was saved JP Z,NOCHAR ;Ret if none BIT 2,E ;Shift key down? SCF ;Init carry JR NZ,SPECL ;Ret if CTRL CCF DVREXIT BIT 7,A ;Z-flag set on non-CLEAR RET Z ;Go if not CLEAR+key SPECL PUSH AF ;Save code $?13 LD HL,SPCLTB ;Special char table RES 7,A ;Turn off "CLEAR" LD BC,5<8!5BH ;5 chars, starting char JR NC,$+3 ; if not CTRL DEC B ; else only 4 SPCLLP CP (HL) ;Is this it? JR Z,HIT ;Go if so XOR 10H ;Flip shift state CP (HL) ;Is that it? JR Z,HITWS ;Go if so XOR 10H ;Flip back INC HL ;Bump specl table ptr INC C ;Bump "convert to" char DJNZ SPCLLP ;Loop through table POP AF ;Not found in table JR C,CKCTL2 ;Ck CTL for C-flag CKCTL1 CP A ;Set Z-flag RET HITWS SET 5,C ;Move to LC set HIT POP AF ;Restore orig char LD A,C ;Load converted one CKCTL JR NC,CKCTL1 ;Go if ctl key not down AND 1FH ;Force ctl code CKCTL2 CP A ;Set Z-flag SCF ;Set C-flag for CTRL RET ; ; Check the type ahead buffer for any character ; *MOD TYPAHD CALL ENADIS_DO_RAM ;Bring up Keyboard ram LD HL,TYPBUF ;P/u start of type buffer LD (HL),0FFH ;Turn off type ahead JR C,$?1 ;Go on @GET JR Z,TYPON ;No PUT to *KI CP 3 ;CTL 3 function? JP Z,CLRTYP ;Clear buffer if so INC A JR Z,CTLFF ;Go if CTL 255 function XOR A ;Nothing done, No error JR TYPON ; ; Handle CTL-255 - scan keyboard into user rowbuf ; CTLFF LD HL,KB0 ;Start of keyboard image LD B,8 ;Do 8 rows $?0 LD A,(HL) ;P/u the image LD (IY),A ; and xfer to user buffer INC IY RL L DJNZ $?0 RET ; $?1 PUSH HL INC HL ;Bump to PUT pointer LD A,(HL) ; & pick it up INC HL ;Bump to GET pointer CP (HL) ;The same? JR Z,$?4 ;Go if so PUSH HL ;Save pointer to GETPTR LD E,(HL) ;P/u offset to buffer INC HL ;Pt to buffer start LD D,0 ;Add offset to start ADD HL,DE ; to point to char posn LD B,(HL) ;GET the stored char POP HL ;Rcvr GETPTR INC (HL) ;Bump by 1 for char LD A,80 ;Check for >80 CP (HL) ; after INC JR NC,$?2 ;Go if not at end LD (HL),0 ;Reset to start of buf $?2 LD A,(HL) ;If we emptied the DEC HL ; type-ahead buffer, CP (HL) ; update KFLAG$ CALL Z,R7KFLG ;Reset bit-7 if empty POP HL ;Pointed to & get switch LD (HL),0 ;Turn type back on LD A,B ;Transfer char/flag CP A ;Set flag "Z" RET ; ; No character in type ahead buffer - get from kbd ; $?4 CALL KISCAN ;Call keyboard driver POP HL ;Rcvr switch TYPON LD (HL),0 ;Type ahead back on RET ; ; Type ahead task 10 - scans keyboard & saves key ; TYPTSK$ DW $?5 ;Task entry for processor $?5 LD A,(DFLAG$) ;If type-ahead suppressed AND 2H ; then return RET Z CALL ENADIS_DO_RAM ;Bring up the keyboard LD HL,TYPBUF ;P/u type switch LD A,(HL) ;If previous driver is OR A ; currently executing, RET NZ ; do not stack more keys INC HL ;Bump to PUTPTR PUSH HL ; & save it KIHOOK CALL KISCAN ; and scan for a character POP HL RET NZ ;Ret if no char PUSH AF ; else xfer char POP BC ; & flag to BC CP 80H ;Check for PUSH AF PUSH HL CALL Z,$?6 ;If so clear type buf POP HL ;Restore POP AF CP 0C0H ;If CLEAR @, reset keybuf JR Z,$?6 LD E,(HL) ;P/u PUTPTR & compare LD A,E ;GETPTR INC HL CP (HL) JR Z,$?8 ;Jump if key buffer empty LD A,(TIMER$) ;Check if we expired the ADD A,(IX+RPTRATE) ; time interval between CP (IX+1) ; repeating keys JR NZ,$?7 ;Go if time not up ADD A,(IX+RPTRATE) ;Re-adjust time check so LD (IX+1),A ; we don't repeat in RET ; type-ahead task ; ; CLEAR @ control key entered, clear the buffer ; CLRTYP INC HL ;Bump to PUT pointer $?6 XOR A LD (HL),A ;1st PUT is loc'n 0 INC HL ;Pt to GETPTR LD (HL),A ;1st GET is loc'n 0 R7KFLG LD HL,KFLAG$ ;Show buffer empty RES 7,(HL) RET ; ; Char to stuff - check if buffer will overflow ; $?7 LD A,E ;P/u current PUT pointer INC A ;If the next loc'n wraaps CP (HL) ; to the GET loc'n, RET Z ; don't permit overrun $?8 PUSH HL ;Save ptr to GETPTR INC HL ;Pt to start of keybuf LD D,0 ; & calculate PUT loc'n ADD HL,DE LD (HL),B ;Store the char LD HL,KFLAG$ ;Show type buffer SET 7,(HL) ; is not empty POP HL ;Rcvr ptr to GETPTR DEC HL ;Backup to PUTPTR INC (HL) ;Bump past the char LD A,80 ;Check for >80 CP (HL) RET NC ;Back if not over 80 LD (HL),D ; else reset to 1st RET ; position in buf (0) ; ; Type ahead buffer area ; TYPBUF EQU 0FF80H ; ; TYPBUF+0 = On/Off Flag ; TYPBUF+1 = Storage pointer ; TYPBUF+2 = Retrieve pointer ; TYPBUF+3 = Start of actual buffer ; KILAST EQU $-1