| Home CBM ASCII-X BASIC C128 2MHz Border BASIC 7.80 BASIC 8 CPM Digimaster 128 Fast Serial for uIEC Games Interlace JiffySoft128 Keyboard Scan Media Player 128 Orig Interlace RGBI to S-Video RGBI to SCART RGBI to VGA RGB Conversion SAM 128 SID Player 128 VDC Interlace Mp128alpha N-progs D64plus Disk Escape Codes Hardware PCxface PETSCII Pet2asc Futurama IBM PC-AT Contact Games Glossary Hall of fame Hall of shame Miscellaneous Privacy policy Programming Twisty puzzles |
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.
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.
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...
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). © H2Obsession, 2007, 2012 | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||