You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

630 lines
21 KiB

;__________________________________________________________________________________________________
;
; PARALLEL PORT KEYBOARD DRIVER FOR N8VEM
; SUPPORT KEYBOARD/MOUSE ON VDU AND N8
;
; ORIGINAL CODE BY DR JAMES MOXHAM
; ROMWBW ADAPTATION BY WAYNE WARTHEN
;__________________________________________________________________________________________________
;
;__________________________________________________________________________________________________
; DATA CONSTANTS
;__________________________________________________________________________________________________
;
#IF (PLATFORM == PLT_N8)
PPK_PPI .EQU PPI2 ; PPI PORT BASE FOR N8
#ELSE
PPK_PPI .EQU 0F4H ; PPI PORT BASE FOR VDU
#ENDIF
PPK_PPIA .EQU PPK_PPI + 0 ; KEYBOARD PPI PORT A
PPK_PPIB .EQU PPK_PPI + 1 ; KEYBOARD PPI PORT B
PPK_PPIC .EQU PPK_PPI + 2 ; KEYBOARD PPI PORT C
PPK_PPIX .EQU PPK_PPI + 3 ; KEYBOARD PPI CONTROL PORT
;
;__________________________________________________________________________________________________
; KEYBOARD INITIALIZATION
;__________________________________________________________________________________________________
;
PPK_INIT:
CALL PPK_SETPORTC ; SETS PORT C SO CAN INPUT AND OUTPUT
CALL PPK_RESET ; RESET TO THE KEYBOARD
LD A,200 ; 1 SECOND DELAY AS KEYBOARD SENDS STUFF BACK WHEN RESET
CALL PPK_DELAY ; IGNORE ANYTHING BACK AFTER A RESET
LD A,0 ; EMPTY KB QUEUE
LD (PPK_QLEN),A
XOR A
RET
;
;__________________________________________________________________________________________________
; KEYBOARD STATUS
;__________________________________________________________________________________________________
;
PPK_STAT:
CALL PPK_PROCESS ; CALL KEYBOARD ROUTINE
LD A,(PPK_QLEN) ; ASK IF KEYBOARD HAS KEY WAITING
OR A ; SET FLAGS
JP Z,CIO_IDLE ; NO DATA, EXIT VIA IDLE PROCESSING
LD A,$FF ; SIGNAL DATA PENDING
RET
;
;__________________________________________________________________________________________________
; KEYBOARD READ
;__________________________________________________________________________________________________
;
PPK_READ:
CALL PPK_STAT ; CHECK TO SEE IF KEY READY
JR Z,PPK_READ ; IF NOT, LOOP
CALL PPK_GETKEY ; GET IT
LD E,A ; PUT KEY WHERE IT BELONGS
XOR A ; SIGNAL SUCCESS
RET
;
;__________________________________________________________________________________________________
; KEYBOARD FLUSH
;__________________________________________________________________________________________________
;
PPK_FLUSH:
LD A,0 ; EMPTY KB QUEUE
LD (PPK_QLEN),A ; SAVE IT
XOR A ; SIGNAL SUCCESS
RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;__PPK_GETKEY______________________________________________________________________________________
;
; GET KEY PRESS VALUE
;__________________________________________________________________________________________________
PPK_GETKEY:
LD A,(PPK_QLEN) ; GET QUEUE POINTER
OR A
RET Z ; ABORT IF QUEUE EMPTY
PUSH BC ; STORE BC
LD B,A ; STORE QUEUE COUNT FOR LATER
PUSH HL ; STORE HL
LD A,(PPK_QUEUE) ; GET TOP BYTE FROM QUEUE
PUSH AF ; STORE IT
LD HL,PPK_QUEUE ; GET POINTER TO QUEUE
PPK_GETKEY1: ;
INC HL ; POINT TO NEXT VALUE IN QUEUE
LD A,(HL) ; GET VALUE
DEC HL ;
LD (HL),A ; MOVE IT UP ONE
INC HL ;
DJNZ PPK_GETKEY1 ; LOOP UNTIL DONE
LD A,(PPK_QLEN) ; DECREASE QUEUE POINTER BY ONE
DEC A ;
LD (PPK_QLEN),A
POP AF ; RESTORE VALUE
POP HL ; RESTORE HL
POP BC ; RESTORE BC
RET
;__PPK_RESET________________________________________________________________________________________
;
; RESET THE KEYBOARD
;__________________________________________________________________________________________________
PPK_RESET:
CALL PPK_DATAHIGH ;
CALL PPK_CLOCKHIGH ;
LD B,255 ;
SF1: DJNZ SF1 ;
CALL PPK_CLOCKLOW ; STEP 1
LD B,255 ;
SF2: DJNZ SF2 ;
CALL PPK_DATALOW ; STEP 2
CALL PPK_CLOCKHIGH ; STEP 3
CALL PPK_WAITCLOCKLOW ; STEP 4
LD B,9 ; 8 DATA BITS + 1 PARITY BIT LOW
SF3: PUSH BC ;
CALL PPK_DATAHIGH ; STEP 5
CALL PPK_WAITCLOCKHIGH ; STEP 6
CALL PPK_WAITCLOCKLOW ; STEP 7
POP BC ;
DJNZ SF3 ;
CALL PPK_DATAHIGH ; STEP9
CALL PPK_WAITCLOCKLOW ; STEP 10 COULD READ THE ACK BIT HERE IF WANT TO
CALL PPK_WAITCLOCKHIGH ; STEP 11
LD B,255 ;
SF4: DJNZ SF4 ; FINISH UP DELAY
RET
;__PPK_SETPORTC_____________________________________________________________________________________
;
; SETUP PORT C OF 8255 FOR KEYBOARD
;__________________________________________________________________________________________________
PPK_SETPORTC:
LD A,10000010B ; A=OUT B=IN, C HIGH=OUT, CLOW=OUT
OUT (PPK_PPIX),A ; PPI CONTROL PORT
LD A,00000000B ; PORT A TO ZERO AS NEED THIS FOR COMMS TO WORK
OUT (PPK_PPIA),A ; PPI PORT A
CALL PPK_DATAHIGH ;
CALL PPK_CLOCKHIGH ;
LD A,0 ;
LD (CAPSLOCK),A ; SET CAPSLOCK OFF TO START
LD (CTRL),A ; CONTROL OFF
LD (NUMLOCK),A ; NUMLOCK OFF
RET
;_________________________________________________________________________________________________
;
; PORT C BIT ROUTINES
;__________________________________________________________________________________________________
PPK_PORTCBIT0HIGH: ;
LD A,01110001B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT1HIGH: ;
LD A,01110011B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT2HIGH: ;
LD A,01110101B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT3HIGH: ;
LD A,01110111B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT0LOW: ;
LD A,01110000B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT1LOW: ;
LD A,01110010B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT2LOW: ;
LD A,01110100B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_PORTCBIT3LOW: ;
LD A,01110110B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_DATAHIGH:
PPK_PORTCBIT4HIGH: ;
LD A,01111001B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_DATALOW: ;
PPK_PORTCBIT4LOW: ;
LD A,01111000B ; SEE THE 8255 DATA SHEET
JP PPK_SETBITS ;
PPK_CLOCKHIGH: ;
PPK_PORTCBIT5HIGH: ;
LD A,01111011B ; BIT 5 HIGH
JP PPK_SETBITS ;
PPK_CLOCKLOW: ;
PORTCBIT5LOW: ;
LD A,01111010B ;
PPK_SETBITS: ;
OUT (PPK_PPIX),A ;
RET ;
;__PPK_WAITCLOCKLOW_________________________________________________________________________________
;
; WAITCLOCKLOW SAMPLES DATA BIT 0, AND WAITS TILL
; IT GOES LOW, THEN RETURNS
; ALSO TIMES OUT AFTER 0 001 SECONDS
; USES A, CHANGES B
;__________________________________________________________________________________________________
PPK_WAITCLOCKLOW:
LD B,255 ; FOR TIMEOUT COUNTER
PPK_WAITCLOCKLOW1:
IN A,(PPK_PPIB) ; GET A BYTE FROM PORT B
BIT 1,A ; TEST THE CLOCK BIT
RET Z ; EXIT IF IT WENT LOW
DJNZ PPK_WAITCLOCKLOW1 ; LOOP B TIMES
RET
;__PPK_WAITCLOCKHIGH_________________________________________________________________________________
;
; WAITCLOCKHIGH SAMPLES DATA BIT 0, AND WAITS TILL
; IT GOES HIGH, THEN RETURNS
; ALSO TIMES OUT AFTER 0 001 SECONDS
; USES A, CHANGES B
;__________________________________________________________________________________________________
PPK_WAITCLOCKHIGH:
LD B,255 ; FOR TIMEOUT COUNTER
PPK_WAITCLOCKHIGH1:
IN A,(PPK_PPIB) ; GET A BYTE FROM PORT B
BIT 1,A ; TEST THE CLOCK BIT
RET NZ ; EXIT IF IT WENT HIGH
DJNZ PPK_WAITCLOCKHIGH1 ; LOOP B TIMES
RET
;__PPK_DELAY________________________________________________________________________________________
;
; PASS A - DELAY IS B*0 005 SECONDS, BCDEHL ALL PRESERVED
;__________________________________________________________________________________________________
PPK_DELAY:
PUSH BC ; STORE ALL VARIABLES
PUSH DE ;
PUSH HL ;
LD B,A ; PUT THE VARIABLE DELAY IN B
LD DE,1 ;
PPK_DELAY1:
LD HL,740 ; ADJUST THIS VALUE FOR YOUR CLOCK 1481=3 68MHZ, 3219=8MHZ (TEST WITH A=1000=10 SECS)
PPK_DELAY2:
SBC HL,DE ; HL-1
JR NZ,PPK_DELAY2
DJNZ PPK_DELAY1
POP HL ; RESTORE VARIABLES
POP DE ;
POP BC ;
RET ;
;__PPK_PROCESS______________________________________________________________________________________
;
; A=0 IF WANT TO KNOW IF A BYTE IS AVAILABLE, AND A=1 TO ASK FOR THE BYTE
;__________________________________________________________________________________________________
PPK_PROCESS:
CALL PPK_SKIP ; DON'T TEST EVERY ONE AS TAKES TIME
OR A ; IS IT ZERO
RET Z ; RETURN IF ZERO
CALL PPK_WAITBYTE ; TEST KEYBOARD TIMES OUT AFTER A BIT
CALL PPK_DECODECHAR ; RETURNS CHAR OR 0 FOR THINGS LIKE KEYUP, SOME RETURN DIRECTLY TO CP/M
RET ; RETURN TO CP/M
;-----------------------------------------------
; CPM CALLS THE KEYBOARD QUITE FREQUENTLY IF A KEYBOARD WAS LIKE A UART WHICH CAN BE CHECKED
; WITH ONE INSTRUCTION, THAT WOULD BE FINE BUT CHECKING A KEYBOARD INVOLVES PUTTING THE CLOCK LINE LOW
; THEN WAITING SOME TIME FOR A POSSIBLE REPLY, THEN READING IN BITS WITH TIMEOUTS AND THEN RETURNING
; THIS SLOWS DOWN A LOT OF CP/M PROCESSES, EG TRY TYPE MYPROG AND PRINTING OUT TEXT
PPK_SKIP:
LD B,0 ;
LD A,(SKIPCOUNT) ;
DEC A ; SUBTRACT 1
LD (SKIPCOUNT),A ; STORE IT BACK
CP 0 ;
JP NZ,PPK_SKIP1 ; WORDSTAR IS VERY SLOW EVEN TRIED A VALUE OF 5 TO 200 HERE
LD A,200 ; ONLY ACT ON EVERY N CALLS - BIGGER=BETTER BECAUSE THIS SUB IS QUICKER THAN READBITS
LD (SKIPCOUNT),A ; RESET COUNTER
LD B,1 ; FLAG TO SAY RESET COUNTER
PPK_SKIP1: ;
LD A,B ; RETURN THE VALUE IN A
RET
;__PPK_DECODECHAR____________________________________________________________________________________
;
; DECODE CHARACTER PASS A AND PRINTS OUT THE CHAR
; ON THE LCD SCREEN
;__________________________________________________________________________________________________
PPK_DECODECHAR:
CP 0 ; IS IT ZERO
RET Z ; RETURN IF A ZERO - NO NEED TO DO ANYTHING
CP 0F0H ; IS A KEY UP (NEED TO DO SPECIAL CODE FOR SHIFT)
JP Z,DECKEYUP ; IGNORE CHAR UP
CP 0E0H ; TWO BYTE KEYPRESSES
JP Z,TWOBYTE ;
CP 058H ; CAPS LOCK SO TOGGLE
JP Z,CAPSTOG ;
CP 12H ; SHIFT (DOWN, BECAUSE UP WOULD BE TRAPPED BY 0F ABOVE)
JP Z,SHIFTDOWN ;
CP 59H ; OTHER SHIFT KEY
JP Z,SHIFTDOWN ;
CP 014H ; CONTROL KEY
JP Z,CONTROLDOWN ;
CP 05AH ; ENTER KEY
JP Z,RETURN ;
CP 066H ; BACKSPACE KEY
JP Z,BACKSPACE ;
CP 0DH ; TAB KEY
JP Z,TABKEY ;
CP 076H ; ESCAPE KEY
JP Z,ESCAPE ;
LD C,A ;
LD B,0 ; ADD BC TO HL
LD HL,PPK_KEYMAP ; OFFSET TO ADD
ADD HL,BC ;
JP TESTCONTROL ; IS THE CONTROL KEY DOWN?
DC1: LD A,(CAPSLOCK) ;
CP 0 ; IS IT 0, IF SO THEN DON'T ADD THE CAPS OFFSET
JR Z,DC2 ;
LD C,080H ; ADD ANOTHER 50H TO SMALLS TO GET CAPS
ADD HL,BC ;
DC2: LD A,(HL) ;
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
TESTCONTROL:
LD A,(CTRL) ;
CP 0 ; IS CONTROL BEING HELD DOWN?
JP Z,DC1 ; NO SO GO BACK TO TEST CAPS LOCK ON
LD A,(HL) ; GET THE LETTER, SHOULD BE SMALLS
SUB 96 ; A=97 SO SUBTRACT 96 A=1=^A
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ; RETURN INSTEAD OF THE RET AFTER DC2
TABKEY: ;
LD A,9 ;
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;TAB
BACKSPACE: ;
LD A,8 ; BACKSPACE
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
ESCAPE: ;
LD A,27 ;
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
RETURN: ;
LD A,13 ; CARRIAGE RETURN
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
DECKEYUP:
CALL PPK_WAITBYTE ; IGNORE KEY UP THROW AWAY THE CHARACTER UNLESS A SHIFT
CP 012H ; IS IT A SHIFT
JP Z,SHIFTUP ;
CP 59H ; OTHER SHIFT KEY
JP Z,SHIFTUP ;
CP 014H ; CONTROL UP
JP Z,CONTROLUP ; CONTROL UP
LD A,0 ; NOTHING CAPTURED SO SEND BACK A ZERO
RET
TWOBYTE:; ALREADY GOT EO SO GET THE NEXT CHARACTER
CALL PPK_WAITBYTE
CP 0F0H ; SEE THE NOTES - KEYUP FOR E0 KEYS IS EO F0 NN NOT F0 EO!!
JP Z,TWOBYTEUP ;
CP 071H ; DELETE
JP Z,DELETEKEY ;
CP 05AH ; RETURN ON NUMBER PAD
JP Z,RETURNKEY ;
CP 072H ;
JP Z,DOWNARROW ;
CP 074H ;
JP Z,RIGHTARROW ;
CP 06BH ;
JP Z,LEFTARROW ;
CP 075H ;
JP Z,UPARROW ;
CP 070H ;
JP Z,INSERT ;
CP 07DH ;
JP Z,PAGEUP ;
CP 07AH ;
JP Z,PAGEDOWN ;
CP 06CH ;
JP Z,HOME ;
CP 069H ;
JP Z,END ;
LD A,0 ; RETURNS NOTHING
RET
TWOBYTEUP: ;EXPECT A BYTE AND IGNORE IT
CALL PPK_WAITBYTE ;
LD A,0 ;
RET ;
HOME: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'?' ; ?
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'W' ; W
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
END: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'?' ; ?
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'Q' ; Q
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
DOWNARROW: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'B' ; B
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
RIGHTARROW: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'C' ; C
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
LEFTARROW: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'D' ; D
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
UPARROW: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'A' ; A
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
INSERT: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'?' ; ?
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'P' ; P
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
PAGEUP: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'?' ; ?
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'Y' ; Y
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
PAGEDOWN: ;
LD A,1BH ; ESC
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'?' ; ?
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
LD A,'S' ; S
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
CONTROLDOWN: ; SAME CODE AS SHIFTDOWN BUT DIFF LOCATION
LD A,0FFH ;
LD (CTRL),A ; CONTROL DOWN
LD A,0 ;
RET ;
CONTROLUP: ; CONTROL KEY UP SEE SHIFT FOR EXPLANATION
LD A,0 ;
LD (CTRL),A ;
LD A,0 ;
RET ;
RETURNKEY: ;
LD A,13 ;
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
DELETEKEY: ;
LD A,07FH ; DELETE KEY VALUE THAT CP/M USES
CALL PPK_ENQUEUE ; STORE ON KB QUEUE
RET ;
CAPSTOG: ;
LD A,(CAPSLOCK) ;
XOR 11111111B ; SWAP ALL THE BITS
LD (CAPSLOCK),A ;
LD A,0 ; RETURNS NOTHING
RET ;
SHIFTDOWN: ; SHIFT IS SPECIAL - HOLD IT DOWN AND IT AUTOREPEATS
; SO ONCE IT IS DOWN, TURN CAPS ON AND IGNORE ALL FURTHER SHIFTS
; ONLY AN F0+SHIFT TURNS CAPS LOCK OFF AGAIN
LD A,0FFH ;
LD (CAPSLOCK),A ;
LD A,0 ; RETURNS NOTHING
RET ;
SHIFTUP: ; SHIFTUP TURNS OFF CAPS LOCK DEFINITELY
LD A,0 ;
LD (CAPSLOCK),A ;
LD A,0 ; RETURNS NOTHING
RET ;
;__PPK_ENQUEUE______________________________________________________________________________________
;
; STORE A BYTE IN THE KEYBOARD QUEUE
; A: BYTE TO ENQUEUE
;__________________________________________________________________________________________________
PPK_ENQUEUE:
PUSH DE ; STORE DE
PUSH HL ; STORE HL
PUSH AF ; STORE VALUE
LD A,(PPK_QLEN) ; PUT QUEUE POINTER IN A
CP 15 ; IS QUEUE FULL
JP P,PPK_ENQUEUE1 ; YES, ABORT
LD HL,PPK_QUEUE ; GET QUEUE POINTER
PUSH HL ; MOVE HL TO BC
POP BC ;
LD H,0 ; ZERO OUT H
LD L,A ; PLACE QUEUE POINTER IN L
ADD HL,BC ; POINT HL AT THE NEXT LOACTION TO ADD VALUE
POP AF ; RESTORE VALUE
LD (HL),A ; ENQUEUE VALUE
LD A,(PPK_QLEN) ; GET QUEUE POINTER
INC A ; INC IT
LD (PPK_QLEN),A ;STORE QUEUE POINTER
PPK_ENQUEUE1:
POP HL ; RESTORE HL
POP DE ; RESTORE DE
RET
;__PPK_WAITBYTE_____________________________________________________________________________________
;
; WAIT FOR A BYTE - TESTS A NUMBER OF TIMES IF THERE IS A KEYBOARD INPUT,
; OVERWRITES ALL REGISTERS, RETURNS BYTE IN A
;__________________________________________________________________________________________________
PPK_WAITBYTE:
CALL PPK_CLOCKHIGH ; TURN ON KEYBOARD
LD HL,500 ; NUMBER OF TIMES TO CHECK 200=SLOW TYPE
; 10=ERROR, 25 ?ERROR 50 OK -
; THIS DELAY HAS TO BE THERE OTHERWISE WEIRD KEYUP ERRORS
PPK_WAITBYTE1:
PUSH HL ; STORE COUNTER
CALL PPK_READBITS ; TEST FOR A LOW ON THE CLOCK LINE
POP HL ; GET THE COUNTER BACK
CP 0 ; TEST FOR A ZERO BACK FROM READBITS
JR NZ,PPK_WAITBYTE2 ; IF NOT A ZERO THEN MUST HAVE A BYTE IE A KEYBOARD PRESS
LD DE,1 ; LOAD WITH 1
SBC HL,DE ; SUBTRACT 1
JR NZ,PPK_WAITBYTE1 ; LOOP WAITING FOR A RESPONSE
PPK_WAITBYTE2:
PUSH AF ; STORE THE VALUE IN A
CALL PPK_CLOCKLOW ; TURN OFF KEYBOARD
POP AF ; GET BACK BYTE AS CLOCKLOW ERASED IT
RET
;__PPK_READBITS_____________________________________________________________________________________
;
; READBITS READS 11 BITS IN FROM THE KEYBOARD
; FIRST BIT IS A START BIT THEN 8 BITS FOR THE BYTE
; THEN A PARITY BIT AND A STOP BIT
; RETURNS AFTER ONE MACHINE CYCLE IF NOT LOW
; USES A, B,D, E
; RETURNS A=0 IF NO DATA, A= SCANCODE (OR PART THEREOF)
;__________________________________________________________________________________________________
PPK_READBITS:
IN A,(PPK_PPIB)
BIT 1,A ; TEST THE CLOCK BIT
JR Z,PPK_READBITS1 ; IF LOW THEN START THE CAPTURE
LD A,0 ; RETURNS A=0 IF NOTHING
RET
PPK_READBITS1:
CALL PPK_WAITCLOCKHIGH ; IF GETS TO HERE THEN MUST BE LOW SO WAIT TILL HIGH
LD B,8 ; SAMPLE 8 TIMES
LD E,0 ; START WITH E=0
PPK_READBITS2:
LD D,B ; STORE BECAUSE WAITCLOCKHIGH DESTROYS
CALL PPK_WAITCLOCKLOW ; WAIT TILL CLOCK GOES LOW
IN A,(PPK_PPIB) ; SAMPLE THE DATA LINE
RRA ; MOVE THE DATA BIT INTO THE CARRY REGISTER
LD A,E ; GET THE BYTE WE ARE BUILDING IN E
RRA ; MOVE THE CARRY BIT INTO BIT 7 AND SHIFT RIGHT
LD E,A ; STORE IT BACK AFTER 8 CYCLES 1ST BIT READ WILL BE IN B0
CALL PPK_WAITCLOCKHIGH ; WAIT TILL GOES HIGH
LD B,D ; RESTORE FOR LOOP
DJNZ PPK_READBITS2 ; DO THIS 8 TIMES
CALL PPK_WAITCLOCKLOW ; GET THE PARITY BIT
CALL PPK_WAITCLOCKHIGH
CALL PPK_WAITCLOCKLOW ; GET THE STOP BIT
CALL PPK_WAITCLOCKHIGH
LD A,E ; RETURNS WITH ANSWER IN A
RET
PPK_KEYMAP:
; THE TI CHARACTER CODES, OFFSET FROM LABEL BY KEYBOARD SCAN CODE
.DB $00, $00, $00, $00, $00, $00, $00, $00
.DB $00, $00, $00, $00, $00, $09, "`", $00 ; $09=TAB
.DB $00, $00, $00, $00, $00, "q", "1", $00
.DB $00, $00, "z", "s", "a", "w", "2", $00
.DB $00, "c", "x", "d", "e", "4", "3", $00
.DB $00, " ", "v", "f", "t", "r", "5", $00
.DB $00, "n", "b", "h", "g", "y", "6", $00
.DB $00, $00, "m", "j", "u", "7", "8", $00
.DB $00, ",", "k", "i", "o", "0", "9", $00
.DB $00, ".", "/", "l", ";", "p", "-", $00
.DB $00, $00, $27, $00, "[", "=", $00, $00 ; $27=APOSTROPHE
.DB $00, $00, $00, "]", $00, $5C, $00, $00 ; $5C=BACKSLASH
.DB $00, $00, $00, $00, $00, $00, $00, $00
.DB $00, "1", $00, "4", "7", $00, $00, $00
.DB "0", ".", "2", "5", "6", "8", $00, $00
.DB $00, "+", "3", "-", "*", "9", $00, $00
PPK_SHIFTKEYMAP:
.DB $00, $00, $00, $00, $00, $00, $00, $00
.DB $00, $00, $00, $00, $00, $09, "~", $00 ; $09=TAB
.DB $00, $00, $00, $00, $00, "Q", "!", $00
.DB $00, $00, "Z", "S", "A", "W", "@", $00
.DB $00, "C", "X", "D", "E", "$", "#", $00
.DB $00, " ", "V", "F", "T", "R", "%", $00
.DB $00, "N", "B", "H", "G", "Y", "^", $00
.DB $00, $00, "M", "J", "U", "&", "*", $00
.DB $00, "<", "K", "I", "O", ")", "(", $00
.DB $00, ">", "?", "L", ":", "P", "_", $00
.DB $00, $00, $22, $00, "{", "+", $00, $00 ; $22=DBLQUOTE
.DB $00, $00, $00, "}", $00, "|", $00, $00
.DB $00, $00, $00, $00, $00, $00, $00, $00
.DB $00, "1", $00, "4", "7", $00, $00, $00
.DB "0", ".", "2", "5", "6", "8", $00, $00
.DB $00, "+", "3", "-", "*", "9", $00, $00
;
;==================================================================================================
; PARALLEL PORT KEYBOARD DRIVER - DATA
;==================================================================================================
;
CAPSLOCK .DB 0 ; CAPS LOCK TOGGLED FLAG, $00=NO, $FF=YES
CTRL .DB 0 ; CTRL KEY PRESSED FLAG, $00=NO, $FF=YES
NUMLOCK .DB 0 ; NUM LOCK TOGGLED FLAG, $00=NO, $FF=YES
SKIPCOUNT .DB 0 ; SKIP COUNTER (SEE CODE COMMENTS)
PPK_QUEUE .FILL 16,0 ; 16 BYTE KB QUEUE
PPK_QLEN .DB 0 ; COUNT OF BYTES CURRENTLY IN QUEUE