Commodore‎ > ‎C128‎ > ‎

Keyboard Scan

Here is a representation of how the keyboard of the Commodore 128 is connected to the I/O ports of the CIA#1 (at $DC00 and $DC01) and VIC-IIe (at $D02F).  Much of this is identical to the keyboard of the Commodore 64, because the C128 supports C64-mode.  In fact, it is like a C64 keyboard expanded with extra keys.

Commodore 64 and  128  Keyboard Matrix
 
$DC00 bit
$DC01 bit
0
$FE
1
$FD
2
$FB
3
$F7
4
$EF
5
$DF
6
$BF
7
$7F
0
$FE
INST
DEL
Return
CRSR =>
F7
F1
F3
F5
CRSR  ||
\/
1
$FD
#
3
W
A
$
4
Z
S
E
Left Shift
Shift Lock
2
$FB
%
5
R
D
&
6
C
F
T
X
3
$F7
'
7
Y
G
(
8
B
H
U
V
4
$EF
)
9
I
J
 
0
M
K
O
N
5
$DF
+
P
L
-
>
.
[
:
@
<
,
6
$BF
£
*
]
;
CLR
HOME
Right
Shift
=
^
?
/
7
$7F
!
1
<-
CTRL
"
2
Space
C=
Q
RUN
STOP
$D02F bit
$DC01 bit
0
$FE
1
$FD
2
$FB
3
$F7
4
$EF
5
$DF
6
$BF
7
$7F
0
$FE
HELP
8
5
TAB
2
4
7
1
1
$FD
ESC
+
-
LINE
FEED
Enter
6
9
3
2
$FB
ALT
0
.
/\
|
|
\/
<-
->
NO
SCROLL
 
$D505 bit
             
7
$7F
             
40/80
 
$0001 bit
           
6
$BF
 
           
CAPS
LOCK
 
 
CPU pin
         
NMI
   
         
Restore
   

  How to Use the Table  

The normal way (like done by the KERNAL ROM) is to store a value in $DC00 (or $D02F) as indicated on the left-most column that runs up-down the table. Which ever value you choose corresponds to the row of keys listed to the right. Then read a value from $DC01. If no key in that row is choosen, you will read $FF. Otherwise, the value you read will be listed at the top of the table, in the same column as the key that was pressed.

Let's do an example. To read the second $DC00 row, notice the value in left column is $FD. Store $FD in $DC00. In this row you can check 3(#), W, A, 4($), Z, S, E, and SHIFT keys.

Next read $DC01. If you read $FF then no keys in second row are pressed. If you read $EF then the "Z" key is pressed (notice at top of table above "Z" is value $EF).

Also note you must store $FF in the "row select register" you are not using. This means if you want to read from any 8 of the $DC00 rows (top 8 rows), you store $FF in $D02F because you are not using $D02F now. Likewise, to read any 3 of the $D02F rows, be sure to store $FF into $DC00.

Finally, when you are done checking the keyboard, it is a good idea to store $7F into $DC00 (and also $FF into $D02F). This is because the eigth row contains the STOP key, and the KERNAL ROM expects this row to be active so it can check for STOP key pressed by simply reading $DC01.


  Multiple Keys  

When multiple keys are pressed at the same time, things may be tricky. Sometimes it is simple. Assume user presses Right SHIFT key and presses RETURN key at the same time. When you store $FE into $DC00, you will read $FD from $DC01 (this is RETURN). When you store any of $FD, $FB, $F7, $EF, $DF, or $7F into $DC00 you will read $FF from $DC01 (no key). And when you store $BF into $DC00 then you will read $EF from $DC01 (this is Right SHIFT). This is "simple" because the keys are on different rows.

It is not simple if both keys are on the same row. Then you have to do binary math with the bit numbers (0 to 7) listed at the top of table. The formula is 255 - 2^k1 - 2^k2. Assume both Left SHIFT and "A" are pressed. The formula is 255 - 2^2 (A) - 2^7 (Left SHIFT). This is 255 - 4 - 128 = 123 = $7B. So when you store $FD in $DC00, you will read $7B in $DC01.

Another way to say this is if you read a value from $DC01 that is not $FF (the no key value) and is not listed at the top of the table, then there are two (or more) keys pressed in that row. In fact, when more than two keys are pressed, the procedure may fail due to false reads in some cases. This is because the keyboard is a simple set of contact switches with no diode protection to prevent "cross talk." That's a bit too complicated for me to try and explain here...
 

  Another View  

If the first table didn't help, maybe this GIF image will!  It shows the full C128 keyboard (International / U.S. version).  Each key shows the "keyscan code" of the physical key (in blue color, as a hexidecimal number).

 
C128 Keyboard with scancodes as blue hexidecimal numbers.
 

© H2Obsession, 2007, 2012
Comments