The Cardco Cardkey is a numeric keypad that was made specifically for the Vic-20 and C64. I wanted to get one, since I am learning 6502 machine language programming, which involves entering hexadecimal numbers. I wanted to see if I could use the keypad as a hexadecimal keypad, since entering hex numbers on a standard C64 keyboard can be a pain.
Essentially, the Cardkey is an external device that connects to one of the joystick ports, and requires a driver to activate it. The driver can also be used to reprogram the keypad keys, so it is possible to turn the Cardkey into a hexadecimal keypad if needed. This page has more information about the Cardkey, including a D64 image of the incredibly-hard-to-find driver. The manual for the Cardkey can be found on Bombjack.org.
The Cardkey sometimes shows up on Ebay, but collectors are always on the lookout for such things, so it’s not always easy to find one. So, I decided to make my own Cardkey clone by using a simple matrix keypad and an Arduino Uno.
How it works
I couldn’t find a schematic of the Cardkey online, but the Deskthority wiki indicates that the Atari CX85 keypad can also be used on the Vic-20 or C64, and it can be activated with the Cardkey driver. This indicates that the CX85 works under the same principle as the Cardkey, and since the schematic for the CX85 is available online, I decided to base my keypad clone on the CX85 instead.
The CX85 works by producing scan-codes that pull the pins on the joystick port to ground. When you activate the Cardco keypad driver, the driver reads the scan-codes on the joystick port and determines which key on the keypad was pressed. This wiki has links to the technical reference notes of the CX85 and includes a schematic as well.
The CX85 uses a 74C923 20-key encoder, along with a hex inverter buffer to create the scan-codes (listed in the schematic). The problem with implementing this circuit is the 20-key encoder, which is hard to find nowadays. You can probably find these on Ebay, but I decided to use the Arduino as a substitute. The Arduino Keypad library is used to generate the signals that go to the hex inverter.
Scan-codes
I found an old keypad with a keyboard matrix circuit on Ebay for a decent price (less than 20 USD, including shipping). The fist step was to figure out the rows and columns that corresponded to the matrix of my keypad. The keypad had a connector for the output pins; when you press a button on the keypad, two of the pins are connected: one is a row pin and the other is a column pin. Using a multimeter (and some patience) I found all pairs of pins corresponding to each key press.
After some trial and error, I found the following matrix representation for my keypad:
C1 C2 C3 C4 R1 { % , , * , } R2 { 3 , 7 , + , } R3 { 2 , 6 , . , = } R4 { 1 , 5 , 9 , - } R5 { 0 , 4 , 8 , }
As you can see, not all positions of the matrix are used (there are only 16 keys and 20 positions available). Basically, I figured out the matrix by numbering the output pins from 1 to 9, and I used a spreadsheet to figure out how the keys were grouped together (I looked for commonalities among they keys).
When you press on a key, the keypad sends a scan-code to the joystick port of the computer on pins 1, 2, 3, 4, and 6. For example, using the Cardkey driver, pressing on the number 7 key should pull pin 6 (Joystick Fire) to ground (to indicate that a key is pressed), and pin 4 (Joystick right) should also be pulled low; the remaining pins are kept high. In binary, this is represented as 11000 for pins 6 (Fire), 4 (Right), 3 (Left), 2 (Down), 1 (Up), where 1 means pulling the pin low and 0 means pulling the pin high. In hexadecimal, the binary is represented as 0x18 (note: in reality, the high bit is not really used for pin 6 (Fire); see CX85 documentation for more details about this representation.) When the key is released, pin 6 on the joystick port is pulled high, to indicate that no key is pressed.
The scan-codes for the the CX85 actually differ from the scan-codes that the Cardkey driver expects. After a some trial and error, I found the following scan-codes for the Cardkey. The scan-codes listed here correspond to the keys in the keypad matrix (see above):
- The Arduino sends the following scan-codes to the hex inverter
C1 C2 C3 C4 R1 { 0xEC , , 0xED , } R2 { 0xE3 , 0xE7 , 0xEA , } R3 { 0xE2 , 0xE6 , 0xEE , 0xEF } R4 { 0xE1 , 0xE5 , 0xE9 , 0xEB } R5 { 0xE0 , 0xE4 , 0xE8 , }
- The hex inverter sends the following scan-codes to the joystick Port
C1 C2 C3 C4 R1 { 0x13 , , 0x12 , } R2 { 0x1C , 0x18 , 0x15 , } R3 { 0x1D , 0x19 , 0x11 , 0x10 } R4 { 0x1E , 0x1A , 0x16 , 0x14 } R5 { 0x1F , 0x1B , 0x17 , }
If you have a different matrix layout, you only need to match the scan-codes to the appropriate keys.
Implementation
On the Arduino, I used input pins D5, D4, D3, and D2 for the columns (C1, C2, C3 and C4). Pins D10, D9, D8, D7, and D6 where used for the 5 rows (R1, R2, R3, R4 and R5). The 9 output pins from my keypad correspond to these 5 rows + 4 columns, so I attached the appropriate keypad pins to the appropriate row and column pins on the Arduino.
Pins D14, D15, D16, D17 and D18 on the Arduino are used as output pins, and are connected to the Joystick port via a small 4049 hex inverter circuit (for reference: D14 = Up, D15 = Down, D16 = Left, D17 = Right and D18 = Fire).
A small 4049 hex inverter circuit is used to convert the outputs from pins D14, D15, D16, D17 and D18 to the appropriate scan-codes that the Cardkey driver will understand. I use the Arduino to power the circuit, and the Arduino itself is powered via USB (I thought about using the 5V line from the Vic-20 or the C64 to power the whole thing, but that’s probably not a good idea). The benefit of using a USB cable to power the Arduino is that I can always use it to update or tweak the Arduino sketch that drives the keypad. The Arduino sketch is given below. Here is a schematic of the hex inverter circuit:
I put everything in an enclosure to make everything pretty:
And here’s the final product! Not to shabby…
Arduino Sketch
To make the keypad work, I use an Arduino sketch that emulates the 20-key encoder. The sketch relies on the Keypad library, which you can get here.
The sketch is written to work with my keypad matrix, but can be modified to suit your needs. You can get it here. The sketch also implements keyboard repeat, so that holding down on a key for more than a half-second repeats the key. Don’t forget to enable the keypad by loading the Cardkey driver (found on this page). Enjoy!