Checking the keyboard via the PIA
By Art Flexser

Checking the keyboard via the PIA


This tutorial will initiate you into the mysteries of how you can read the keyboard by checking the keyboard PIA (Peripheral Interface Adapter) directly, without having to resort to calling the POLCAT routine in the Color Basic ROM via JSR [$A000]. This method is, in fact, what POLCAT itself uses.

A reasonable question to consider at this point is WHY, when we have POLCAT, would we ever want to use any other method for getting keyboard input? There are several answers.

There are a number of situations where using POLCAT is much less efficient than need be. A typical situation is where the program we are designing needs to detect whether a specific key is being held down. POLCAT will detect only a new keypress, not whether a key detected on a previous call to POLCAT is still being held down. (This can be gotten around by shoving $FF’s into the keyboard rollover table at $152-159 to make POLCAT “forget” the previous detection of the key, a principle used in many key-repeat routines, but that is another story.) Further, in many cases, there is no need to determine WHAT particular key is down, but simply whether (say) the left arrow key is down or not. The method I am about to outline will allow a test for a specific key that involves a great deal less processing time than does the full determination of what key has been pressed. In addition, the method allows a very fast check of whether or not there is ANY key that is being currently held down.

Another limitation of POLCAT that the method of directly checking the keyboard PIA gets around is that POLCAT is useless for determining whether the shift key, by itself, has been pressed.

The current topic is one of those where some rudimentary hardware description is helpful. The CoCo contains a matrix keyboard consisting internally of 8 column and 7 row connections. Each key has its own unique row/column combination. When the key is pressed, the two wires corresponding to its column and its row are electrically connected to one another. The 8 columns are connected to a particular 8 pins on the keyboard PIA chip. This fact causes the voltages applied to the 8 keyboard columns to individually reflect the status of the 8 bits of location $FF02. If you stick a 1 into a particular bit of $FF02, the corresponding column of the keyboard will be held at +5 volts; if you put a zero into this bit, the keyboard column will be grounded, that is, held at 0 volts. Location $FF02 is used here as an output; that is, it is written to rather than read.

Now let us consider the seven keyboard row connections. These connect with seven other pins on the same PIA that are used as inputs rather than outputs. These seven input connections correspond to bits 0-6 of location $FF00. (The remaining bit 7 of $FF00 is used in connection with reading the joysticks, and is not affected by keyboard status.) These pins are normally kept at +5 volts, (so that the lower 7 bits of $FF00 all normally contain ones) EXCEPT when one of them is connected to ground by virtue of a key on the keyboard having been pressed. That is, if a keypress connects a row input with a column output that is at 0 volts (because the corresponding bit in $FF02 has been set to zero), the relevant row input bit in $FF00 will also assume a value of 0 instead of its normal value of 1. We now have all the information necessary for seeing how to detect whether a particular key is down, provided we know its row and column positions in the keyboard matrix. Suppose we wish to check the left arrow key’s status. This key happens to occupy Column 5 and Row 3 in the matrix. So, what we have to do is ground Column 5 only (bit 5 of $FF02), and then check whether Row 3 (bit 3 of $FF00) has also become grounded. If it has, we know the left arrow key is currently down. The code that accomplishes this is the following:

	LDA	#%11011111	ground Column 5 only
	STA	$FF02
	LDA	$FF00
	ANDA	#%00001000	check bit 3 (Row 3) status
	BEQ	KEYDWN	branch if arrow key is down

Note that the percent-sign notation I’ve used here to represent binary quantities is for clarity, and is illegal in the Edtasm+ assembler, though legal in some other assemblers. Legal Edtasm+ translations of the two illegal instructions would be LDA #$DF and ANDA #8. Note that the LDA instruction has ones in all bits EXCEPT the one corresponding to the keyboard column you’re grounding, whereas the ANDA instruction puts a one ONLY in the bit corresponding to the keyboard row you’re checking. (Refer to Tutorial A2 if you need a refresher on how the AND instruction works. ANDA #%00001000 sets all bit positions except bit 3 of the A-register to zero, and leaves bit 3 unchanged from its previous status. Recall that bits are numbered from 0 to 7, with bit 0 as the rightmost bit.)

Here is a table showing the layout of the keyboard matrix:

C O L U M N
0 ($FE) 1 ($FD) 2 ($FB) 3 ($F7) 4 ($EF) 5 ($DF) 6 ($BF) 7 ($7F)
@ A B C D E F G 0 (1)
H I J K L M N O 1 (2)
P Q R S T U V W 2 (4)
X Y Z up down left right space 3 (8)
0 1/! 2/" 3/# 4/$ 5/% 6/& 7/' 4 ($10)
8/( 9/) :/* ;/+ ,/< -/= ./> //? 5 ($20)
enter clear break alt ctrl F1 F2 shift 6 ($40)


In parentheses, I’ve added for each column what quantity to put in $FF02, and for each row, what quantity to AND the contents of $FF00 with. Note that the last row includes the ALT, CTRL, F1, and F2 keys that are on the '$4.95 keyboard' (Model 277-1019) sold by Radio Shack for a time and left over from the aborted 'Deluxe CoCo'.

A last topic is how to use the PIA to check very efficiently whether ANY key at all is being currently held down. To accomplish this, we need to ground ALL the keyboard columns (all bits of $FF02) simultaneously, and check whether there is a zero in ANY of the row bits (the lower 7 bits of $FF00):


	CLR	$FF02	ground all column bits
	LDA	$FF00
	ANDA	#$7F	strip off unused bit 7 of $FF00
	CMPA	#$7F	see if all 7 row bits = 1
	BEQ	NOKEY	branch if no key down

(A slightly more efficient, though harder to understand, version of the above code uses the instructions COMA, ASLA in place of ANDA #$7F, CMPA #$7F. This version is used in the fast break key check in the 1.2 Color Basic ROM at $A1C1 and is solely responsible for why this ROM runs BASIC programs a bit faster than 1.0 or 1.1 Color Basic.)



(c) 1986   Arthur J. Flexser