I started the code for the ZX81 USB keyboard, with the USBKeyboardDemo1 sample in the Arduino Version of the V-USB library. As stated in the original post, either change the config.h file in the library to set USB_CFG_DMINUS_BIT to 3 rather than 4 or wire up the circuit with 2 and 4.
The ZX81 has just 40 keys arranged as 8 rows of 5 columns. 26 letters, 10 numbers leaves just 4 keys, shift, period, space and new line (enter). The columns are arranged as 5 4 3 2 1 1 2 3 4 5, and the rows aren't in order either.presumably to aid layout of the tracks on the membrane.
In order to get additional functionality, I've included 2 keymaps. One is the keys as the are, the second is when shift is held. Most of the keys, at least all the letters, are send as key with the shift modifier, but for the numbers I've added escape as shift 1, and used the arrows on the original keyboard overlay to make left, down, up and right from shift 5, 6, 7, 8, and delete as shift 0 ('rubout'). I don't have need for the symbols so have left them alone to allow upper and lower case letters. As a side note, the quotes are on the P key, and with the tokenised BASIC, when you were in keyword mode P was PRINT, so it made sense, you pressed P and PRINT came up, then next thing you generally wanted was a quote, so that was also there on the P key, you just needed to press SHIFT as well. It is because of that quick that even though when I need to type ", my hands go for SHIFT and 2 but I still think SHIFT P.
Initially testing had no debouncing in the code, so press P and you get ppppppppppppppppp. I wanted to maintain the option to press multiple keys, so I have an array of counters. Whenever the keypress is detected, the counter is incremented. If I go through a scan and it isn't pressed, the counter is zeroed. Once the counter reaches a set value the key is sent. I did reset the counter at that point, but the last revision of the code added a repeat option, so the counter continues to increment and every 500 detections, another keypress is sent. These values need to be tweaked to get the best results for the particular switches being used. I had two types of tact switches in the breadboarded version, they looked the same, one type clicked louder and needed lower debounce and repeat values that the other (cheaper) ones. The membrane again needed the values tweaking to get it so it would not miss fast presses, but wouldn't repeat too quickly on slow presses.