Anyway, I always kept a weak spot for these all-in one keyboard computers like the TSR-80, Atari 2600, VIC-20 and of course the Commodore C64. According to Wikipedia 12 to 17 million of these units were sold at the time making this a lot less rare.
(An uncertainty of 5 Million ? That's so weird there are even special pages dedicated to this mystery..)
Anyway, 12 million or more seems to be enough to saturate the demand even 30 years later and complete systems can be bought for 50 to 100 Euro's. Actually I own a complete system myself. It's a complete, working set including an original tape recorder and diskette drive. I might have to wipe the dust off and find a suitable TV-set to check if it's still 100%. In the meantime I thought it was a nice idea to have just an empty C64 housing with keyboard and use that as a keyboard for my PC. Or maybe mount a Raspberry Pi inside to turn it into a working Linux computer. Or connect it to a tablet running a C64 emulator like C64.EMU .
[ As usual, I'm not the first to think about this and there is even a complete interface for sale: the Keyrah V2. Better (or worse..) there is even an Etsy shop that has Commodore and many other computers converted to USB keyboards. But that's what I consider cheating. At least some hacking has to be done or it would be too easy ! My first thought was to use the Arduino Micro. While building my MAME cabinet I already discovered that this would have been the easiest way to implement a virtual USB keyboard. On the biosrythm blog there is already a complete description on how to use Arduino to get the C64 keyboard to USB, but he is using the Duemilanove . ]
I picked up an empty C64 from ebay.de for €30 and bought a Arduino Pro Micro for only €7,- (who said hobbies have to be expensive?)
The cable that sticks out on the right is the keyboard connector that used to be connected to the C64 motherboard.
First we obviously have to find out how the keyboard is actually wired. I found a neat diagram on the 'WaitingForFriday' blog:
Great, but it presents and unexpected surprise: we will need 16 Input / Outputs for reading this matrix. And the Micro Pro only has 9 digital I/O pins. My first idea was to expand the number of I/O pins by using some shift registers but then I remembered I also had some PICAXE chips in my toolbox. The PICAXE is a standard PIC micro-controller, pre-programmed with a Basic interpreter which makes programming real simple.And the PICAXE 28X2 has 16 freely configurable I/O pins so that should work fine.
This chip even has all the I/O pins nicely laid out,making it easy to route the connector to the chip.
Some soldering will be necessary though to split out the connector in sections that will go to B0..B7
C0...C3 and C4...C7.Unfortunately this does not work. The PICAXE does not have any pull up or down resistors on its pins, so when no key is pressed they are all floating which results in random values.Adding a 10K pull up resistor to each input solves this problem immediately.
It's still a lot of puzzling to detect the right keys, certainly in combination with the left-shift, right-shift or Commodore key but you can find a complete working version of the PICAXE software at the end of this page.
But since the PICAXE lacks an USB output we still need the Arduino Pro Micro to create a keyboard compatible output.
So the whole exercise has been a fun and useful learning experience, but in hindsight it would have been easier to use the Arduino Leonardo... After all, this is a Pro Micro, but with plenty I/O to implement everything on a single board.
'Commodore 64 Keyboard Decoder. Columns (A..H) connected to Port B. Rows (1..8) to port C 'Both ports have 10K Pull up resistor on each pin main: symbol ROWS = b1 symbol COLUMNS = b2 symbol ROW = b4 symbol COLUMN = b5 symbol KEY =b6 symbol CHECK_ROW = b11 symbol CHECK_COL = b12 symbol TEMP_SUB = b13 symbol TEMP_SUB1= b14 symbol SPECIAL_KEY_PRESSED = b15 symbol RIGHT_SHIFT = b16 symbol LEFT_SHIFT = b17 symbol CTRL =b18 symbol PREVIOUS_KEY =b19 symbol KEY_COUNT=b20 symbol KEY_DELAY = b21 PREVIOUS_KEY = 0 KEY_DELAY = 100 do ; Endless loop let dirsC = %11111111 ' switch all pins to outputs let dirsB = %00000000 ' switch all pins to inputs let pinsC = %00000000 ' switch all outputs low b1 = pinsB let dirsC = %00000000 ' switch all pins to inputs let dirsB = %11111111 ' switch all pins to outputs let pinsB = %00000000 ' switch all outputs low b2 = pinsC b3 = NOT b1 ROWS = NOT b2 COLUMNS=b3 'sertxd("B1,B2: ",#b1," ",#b2,13,10) 'Check if Left Shift is pressed CHECK_ROW = %00001000 CHECK_COL = %00000010 gosub CheckRowCol LEFT_SHIFT = SPECIAL_KEY_PRESSED 'Check if Right Shift is pressed CHECK_ROW = %00010000 CHECK_COL = %01000000 gosub CheckRowCol RIGHT_SHIFT = SPECIAL_KEY_PRESSED 'Check if Right Shift is pressed CHECK_ROW = %00000100 CHECK_COL = %00000001 gosub CheckRowCol CTRL = SPECIAL_KEY_PRESSED ROW = ncd ROWS COLUMN = ncd COLUMNS 'sertxd("B1,B2,ROW,COL: ",#b1," ",#b2," ",#ROW," ",#COLUMN,13,10) if ROW=0 or COLUMN=0 then goto reset_keycount ROW = ROW-1 COLUMN = COLUMN -1 b0 = 8*COLUMN + ROW if LEFT_SHIFT =1 OR RIGHT_SHIFT=1 then goto Shift_pressed lookup b0,("1",8,"cr cq23wa~zse45rdxcft67ygvbhu89ijnmko0+pl,.:@-$*;/~=???",13,"?ffff"),KEY goto Key_Pressed Shift_pressed: lookup b0,("!",8,"cr CQ",34,"#WA~ZSE$%RDXCFT&'YGVBHU()IJNMKO0+PL<>[@-$*]?~=???",13,"?ffff"),KEY Key_Pressed: 'sertxd("KEY PRESSED!",#ROW," ",#COLUMN," ",#b0,":",b1,13,10) if KEY = "~" then goto continue '~ marks an unprintable character (Only Shift is pressed) if KEY = PREVIOUS_KEY AND KEY_COUNT < KEY_DELAY then goto count_keys if KEY_COUNT <> KEY_DELAY then goto normal_delay KEY_DELAY = 3 normal_delay: KEY_COUNT =0 sertxd(KEY) serout A.0,T9600_8,(KEY) PREVIOUS_KEY = KEY goto continue count_keys: KEY_COUNT = KEY_COUNT+1 goto continue reset_keycount: KEY_COUNT=0 KEY=0 PREVIOUS_KEY =0 KEY_DELAY = 30 continue: loop ; next loop CheckRowCol: SPECIAL_KEY_PRESSED = 0 TEMP_SUB = ROWS and CHECK_ROW 'Check if a specific bit in ROWS is set if TEMP_SUB = 0 then goto NotPressed TEMP_SUB = COLUMNS and CHECK_COL 'Check if a specific bit in COLUMNS is set if TEMP_SUB = 0 then goto NotPressed TEMP_SUB = NOB ROWS 'Bit in ROWS and in COLUMNS found. Check how many bits in ROWS are set if TEMP_SUB = 1 then goto no_bit_reset 'If it is just one bit, do not reset it TEMP_SUB = NOT CHECK_ROW 'Invert all bits in the CHECK_ROW ROWS = ROWS and TEMP_SUB 'AND it with the ROWS to reset the bit we just found no_bit_reset: TEMP_SUB = NOB b2 if TEMP_SUB = 1 then goto no_bit_reset_2 TEMP_SUB= NOT CHECK_COL COLUMNS = COLUMNS and TEMP_SUB no_bit_reset_2: SPECIAL_KEY_PRESSED = 1 NotPressed: return