The first thing was to figure out how the keyboard worked. It's a standard matrix keyboard with an 8x8 matrix, for a total of 64 keys. This takes up 16 pins of a 20 pin connector. There is a 65th key, "Restore", that is on it's own, so another two pins of 20 used up. Pin 2 is blocked out as a key and pin 4 is nothing. More than enough pins on the RPi Pico to just read the keys all at once! There is surprisingly a lot to learn about the keyboard, and I found a really good blog here: http://www.c64os.com/post/howthekeyboardworks
Since I don't like python, and all the examples I could find on the web for the Pico were in Circuit Python I hacked up the example code for the hid_composite example on github (https://github.com/hathach/tinyusb). The keyboard works on a regular PC as well. I mapped all the keys to their equivalents according to the keymap on https://github.com/MiSTer-devel/C64_MiSTer, although I found the '£' and '↑' keys were reversed from the schematic on github, so I just changed the keycodes in the header file. Also, the '=' key in MiSTer also mapped to the + key, which is also the F10 key, so I had to hunt for that but eventually I found it is actually mapped to the 'End' key.
The pins are connected to their GPIO equivalents on the rp2040, except for pins 1 and 3. So, keyboard pin 5 connects to GPIO5, keyboard pin 17 connects to GPIO17, etc. 1 and 3 connect to 4 or 21, the order doesn't matter since the key is actually just a momentary switch completing a circuit, and only connect the RESTORE key.
How the code works is it basically turns a particular row "on" one at a time by setting it's GPIO pin to output HIGH. It then checks each column (which are all set to input, and internally pulled low) to see if there is a complete circuit. In other words, if you read a particular column's GPIO pin results in a HIGH reading, you know the key is pressed. I finish scanning the complete keyboard, then send the keycodes that were pressed, up to 6 keycodes can be sent at once.
Current bugs to be worked out: the shift lock key doesn't seem to work with other keys in the same column scan (Run/Stop / , N V X and UP/DOWN) . It's interesting because the shift lock key is literally the hard coded left shift key, and when that is pressed all the other keys work.
In order for the function keys to work with modifiers, e.g. to send Alt-F4 you need to press C= + shift + F3, the solution I've come up with is for the right shift key to be used with those modifiers and the left shift key to work as a normal shift key. Thus, pressing right shift+F3 is F4. Left shift+Right shift+F3 is shift F4. This also works for the cursor keys - the right shift key gives the up and left arrow keys, and the left shift key allows for highlighting based on shift+arrow keys.
One possible future enhancement would be to add joystick support.
A long term stretch goal would be for the keyboard to identify whether it's attached to a MiSTer FPGA (and a Commodore core is active) or a regular PC, and adjust the behaviour accordingly. It might also be nice to connect the keyboard directly to the IO pins of the MiSTer and recreate the old CIA chips, but I don't know that I'll have that much time to work on it.
Code is available on github.