I’m trying to understand some of the behaviour that I’m seeing from Kaleidosocope, and I’m at a loss.
I started out by thinking about a keymap with two keys defined as
Key_LeftShift (or any modifier). Looking at the code, it seems like holding both of those keys down, plus a letter key – e.g.
A – would result in a single erroneous HID report if one of those
lshift keys (whichever one gets handled last) was released, because it would call
hid::releaseKey(), clearing the bit for
lshift in the report, and possibly resulting in this output, despite the fact that a
shift key was being held the whole time:
I tried it out, and noticed that this doesn’t happen. I’m still not sure why, but I thought it might be because of repeat-rate limiting done by the OS. So I tried to slow down the keyboard by adding a single line at the end of
I figured, with a guaranteed one-second gap between reports, the OS would certainly show what was happening. It didn’t. Instead, I saw very surprising things happen when I tapped multiple keys simultaneously. For example, when I very quickly rolled over
l, I saw this:
I was expecting the first key to be detected would be in one report alone, so the repeated
j characters were not surprising, but on the next report after that, I thought I’d get the
k and the
l simultaneously, so whichever was detected first by the OS (
k, most likely, because its bit appears first in the key report) would appear only once, then get masked. Here’s what I expected:
…or maybe just:
…because, by the next loop, the scanner will have had time to do a couple hundred scan cycles. (I’m also trying to figure out how the scanners work). If it worked that way, though, I guess I probably wouldn’t see any output unless I got lucky or held the keys down long enough.
Anyway, I’m just flummoxed. I added some serial debugging code to
Keyboard.sendReportUnchecked(), and it shows this happening (the bitfield is the byte from
l; the decimal number is
40313: 00100000 41317: 01100000 42321: 11100000 43325: 11000000 44328: 10000000 45333: 00000000
[Padded with zeroes for readability]
The first line shows a report with
j alone. Then, one second later, there’s a report with both
k, but not
l. This is ~one full second after all three keys were released!
Then, one more second passes, and
k is added to the report. Then, almost three seconds and two full reports after the key was released, the
j is finally removed from the key report. Then
k, then, finally – five seconds after it was released – a report is sent with
Now, I’m not complaining about any actual behaviour here; it’s utterly ridiculous to have a one-second delay added to the main loop, of course. But I’m trying to understand how this all works, and I’m stumped by this one. What’s going on here?