Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10.1 6/24/83; site decwrl.UUCP Path: utzoo!linus!decvax!decwrl!lipman From: lipman@decwrl.UUCP Newsgroups: net.micro.cbm Subject: id AA16172; Fri, 24 Feb 84 06:50:10 pst Message-ID: <5795@decwrl.UUCP> Date: Fri, 24-Feb-84 09:50:20 EST Article-I.D.: decwrl.5795 Posted: Fri Feb 24 09:50:20 1984 Date-Received: Sat, 25-Feb-84 03:31:48 EST Sender: lipman@decwrl.UUCP Organization: DEC Western Research Lab, Los Altos, CA Lines: 94 Message-Id: <8402241450.AA16172@decwrl.ARPA> Date: Friday, 24 Feb 1984 06:47:37-PST From: vogon::goodenough (speling courtesy of clapped out VT100) To: net.micro.cbm Subject: C64 keyboard matrix exposed The on-board keyboard routines for the Commodore 64 have one major drawback: it is only possible to detect one key pressed at a time. Also the algorithm used is very inefficient - each time any key is held pressed, ALL 64 keys are scanned 60 times a second at interrupt level. If you are writing a real-time application in machine code, this overhead can be intolerable. Also for many applications, you want to allow more than one key to be pressed at any one time. With the correct information, reading the keyboard is kids stuff. Commodore don't give us that, but I've tracked it down. Here goes. First of all: how the hardware works. The 64 keys are divided into a matrix of 8 columns and 8 rows. You write the column select bit to $DC00, then read the 8 keys in that column from $DC01. [You'll instantly recognize these addresses as our old friends the games ports, which the logic shares. A joystick in games port 1 (nearest the space bar) will logically OR with 5 of the keys (N,S,E,W and Fire) - more later]. It's important to note that it's inverse logic: a zero bit output will select that column, and a key pressed will return a zero. If two keys are pressed in one column, two of the bits will be zero. If you write more than one zero bit, you'll OR together the keys pressed in the selected columns. That's all there is to the hardware - now the software. First a quick check to see if any keys at all are pressed: LDA #0 STA $DC00 ; select ALL columns LDA $DC01 ; read everything CMP #$FF ; any key pressed? BEQ ALDONE ; br if no key pressed Now it's up to you - select the column(s) you want, and read the keys in that (those) columns. If you only need to use a few keys in your application, then it's most efficient to cluster them in one or two columns. Very important - you have to filter out contact bounce. This is achieved by: BOUNCE LDA $DC01 ; read keys CMP $DC01 ; check them again BNE BOUNCE ; loop till no bounce Don't forget - a zero means TRUE, so to select column 0, you write $FE to $DC00. If F7 (function key) and Cursor Down are pressed, you'll read $EE from $DC01. Here's the table: \ROW 0 1 2 3 4 5 6 7 \ ----------------------------------------------------------------- COL 0 | INST/DEL RET CRSR R F7 F1 F3 F5 CRSR D | 1 | 3 W A 4 Z S E SHFT L | 2 | 5 R D 6 C F T X | 3 | 7 Y G 8 B H U V | 4 | 9 I J 0 M K O N | 5 | + P L - . : @ , | 6 | POUND * ; CLR/HOME SHFT R = ^ / | 7 | 1 L ARROW CTRL Z SPACE CMDR Q RUN/STOP ------------------------------------------------------------------- Joystick 1| N S W E FIRE ------------------------------------------------------------------- NOTE: The joystick is independent of which column you select. It will appear in all columns. The way the C64 scan works, it takes the last character in the last row it scans, which is column 7. For more than one joystick bit zero (selected), it will take the rightmost character in the table (highest bit). This is an expansion of what I've said in earlier contributions; now I've taken the trouble to find out exactly what does happen! [Note - joystick in rear port has no effect here, since $DC00 is write only for keyboard] Jeff. PS. To kill the C64 keyboard scan, you'll have to intercept the IRQ routine and call UDTIM yourself if you need that. If you don't intercept, you must disable interrupts between writing $DC00 and reading $DC01. If you want me to post details of this, let me know. UUCP: ... decvax!decwrl!rhea!vogon!goodenough ...allegra!decwrl!rhea!vogon!goodenough ... ucbvax!decwrl!rhea!vogon!goodenough ARPA: decwrl!rhea!vogon!goodenough@Berkeley decwrl!rhea!vogon!goodenough@SU-Shasta