I've spent the last few days full-time working on this code. New versions of my USBASP and Teensy ADB converter code (renamed projects for clarity):
blargg-adb-usbasp-3.zip* Now merges extra ADB events with next where possible, making better use of limited USB update opportunities.
* Eliminated adjustable ADB polling rate, as higher rates only hurt, and improved USB synchronization made adjustable polling impossible.
* Consolidated sources.
* Using 16-bit timer1 for everything.
blargg-adb-teensy-2.zip* Changed polling to 12ms (83Hz). Works better with M0116. Can still be adjusted back to 8ms (125Hz) in main.c
* Fixed dropped key when it's pressed and released in same ADB event.
* Reorganized code to be in sync with v-usb version.
* Disable interrupts for all ADB transactions.
* Send each ADB event byte as a separate USB report. This ensures things are in order and cleanly handles cases when the same key is pressed then released in a single ADB event.
More research* The M0116
can generate key down and key up in same event word.
* Just as keyboard can report key down then key up in same event (key down in upper byte), it can report key up then key down in same event (in this case, the key up is in the upper byte).
* The keyboards buffer up key presses done faster than ADB polling. In a test on the M0116, I polled ADB only once every four seconds. Pressing a, waiting until it appeared, then pressing 123456 quickly resulted in 1234 being received over the next 16 seconds. So buffer is 4 keys. And on the M3501, it buffers 16 key presses. It even buffers the relative order of presses and releases of multiple keys, replaying everything as it occurred. So it's likely that the buffers are actually 8 and 32 events, respectively, holding key press and release events until they're read by host. I never realized how involved the driver in a keyboard could be.
* Power key presses are buffered just as others.
* Power key press generates 7F7F, and release FFFF. These special encodings are necessary to differentiate between the FF merely meaning no event (the 7F7F isn't necessary; press could be encoded like any other key).
* A 12ms ADB polling rate is ideal, even for the M3501; 8ms only improves maximum key press rate by a hair, and 4ms just makes it far worse.
Handling key press and release in same eventWith the Teensy USB, the host can poll it as quickly as every 2ms, so handling key press and release in same event is trivial: just handle each as a separate USB report. In my Teensy code I always handle the two ADB bytes separately, since this preserves the order of key presses as well.
An easy way to check whether your handling of this is working is to lower your ADB polling rate to say once a second, ensuring that any key presses result in a key down and key up in the same event.
In my V-USB code, where USB polling is only 8ms, I intelligently defer and merge ADB events across polls, to keep the report rate as high as posssible. As the code shows, this is very involved and I wouldn't recommend it on the Teensy at all.
TimingsWith my improved Teensy and V-USB code, I get what might be the best possible timings on the M3501 (the M0116 timings are the same as before):
41.7Hz M3501 blargg-adb-usbasp-3
38.5Hz M3501 blargg-adb-teensy-2
The M3501 polls around 122Hz, which would suggest a 61Hz maximum key press rate. But, for debouncing purposes, it might require two polls of the key released before it will register another key press. If this is true, then the maximum key press rate would be 40.7Hz.
Disabling interrupts during ADBFor the Teensy code, interrupts should be disabled for
all of ADB code, including when sending. The USB hardware means that you don't need interrupts enabled constantly. I mention this hasu because I think your current ADB code only disables interrupts when receiving from the keyboard.
Continuing the search for the dropped keys problemThe latest Teensy code I posted is worthy of continued testing for the dropped keys problem. tufty, if you could give this a try on your M0116, that'd be great. I can then continue my earlier list of things to try if even this doesn't work.