A brief history of keyboard encoding (2023)
kbd.news
kbd.news
Back in the 80s when electronics were expensive, someone figured out that you could detect all key-presses on a keyboard with just a couple of microphones. There was no wiring to any of the key switches, instead there was a long metal bar underneath the keyboard with a microphone on each side. Pressing a key made a little metal hammer hit that bar, and the difference of arrival between the two microphones was then used to figure out which key had been pressed.
Here's a presentation from Keycon 2014 about it (starts at 1:46:01, description of how it works starts at 1:50:30): https://www.youtube.com/live/AvszDsr1js8?t=6361
e.g. the Ferris Sweep: https://github.com/davidphilipbarr/Sweep
That has 17 keys per side, which is the most you can do with the 18 GPIOs broken out by the popular Pro Micro modules, but with something like the RP2040 you could scale it up to 29 keys per side if desired.
Some early iterations of split keyboards did use a parallel bus between the halves instead, which allowed them to have a single matrix spanning both sides which was read by a single MCU, but that went out of style since the cables were unwieldy and MCUs are cheap. Now they all use two MCUs linked over serial, or wireless.
Simplicity is weird.
"Matrix scan [is in] use in all keyboards today. [...] matrix scan keyboards not only allow for an unlimited number of overlapping keystrokes, but they can correctly identify each and every simultaneously-held key"
I found the hard way that this is not true. Took me a while to figure out why some weird keyboard shortcuts were not working only to find that it's a hardware limitation.
Here's a simple test for your laptop keyboard: try LeftShift+RightShift+Q and see if it prints anything. Repeat with the other letters of the alphabet. In my case I get nothing for several letters such as X, T and M.
Inexpensive keyboards often forego the per-key diodes in favour of cheaper/thinner construction, and to prevent phantom inputs the controller registers nothing when the matrix scan shows keypresses that might be the result of ghosting.
Microsoft has published a table of key combinations that are required to work in Windows, and it does not include combos of two modifiers of the same type .. with one exception: Both Windows keys have to work together. (You'd not often find a laptop keyboard that has two Windows keys though)
There's otherwise a convention when constructing (diode-less) keyboards to put the modifier keys outside the keyboard matrix altogether so as to guarantee that you'd avoid key-combo collisions with them. I.e. each of the Control, Shift, Alt/Option, Windows/Command/Super keys would get its own dedicated GPIO pin on the controller.
BTW. On the old Amiga platform, the rollover issue was handled in a prudent way: Keyboards that did not have NKRO all had a standard keyboard matrix that was published in a reference manual which software developers could consult to figure out which key combos that were viable and which were not. Also here the modifier keys were outside the matrix.
KeyPress event, serial 37, synthetic NO, window 0x1e00001, root 0x7b2, subw 0x0, time 58826694, (-660,975), root:(1171,2000), state 0x10, keycode 38 (keysym 0x61, a), same_screen YES, XLookupString gives 1 bytes: (61) "a" XmbLookupString gives 1 bytes: (61) "a" XFilterEvent returns: False
KeyRelease event, serial 37, synthetic NO, window 0x1e00001, root 0x7b2, subw 0x0, time 58826840, (-660,975), root:(1171,2000), state 0x10, keycode 38 (keysym 0x61, a), same_screen YES, XLookupString gives 1 bytes: (61) "a" XFilterEvent returns: False
Cool stuff.
What is the historical reason for having the OS manage the keyboard layout instead of the keyboard itself? If I tap on the key Z, it should, no matter what the OS wants, send Z, and the OS should receive and "print" Z. Why should the OS decide that sometimes Z becomes Y and other times Z (obviously depending on the layout)?
The same question applies to missing F keys (F19..?). Why should the OS limit itself to what keys it receives? I believe USB can transmit enough keycodes to include all available keys on all platforms.
The same applies to capital letters. Why is there only one keycode for "a" and "A"? The keyboard should send KC_SHFT+KC_A to let the OS know it is a capitalized A. Couldn't there just be another keycode for that? Why the OS should care if I pressed the shift or not? It should receive capital A. Isn't it the keyboard job to send the right keycode for whatever combination I tap?
We can run through USB gigabytes of 4K videos, but somehow we cannot have a separate keycode for each available letter in the world? Heck, QMK can send MIDI Notes through your keyboard, but somehow we cannot have a separate key for each letter in the world? I don't believe that nowadays it is a problem of memory or processing power.
I seriously believe that I'm missing something behind this architecture. Hope someone can explain the drawback in my way of thinking.
For example say we followed your suggestion and the keyboard had to be responsible for key mapping. This means it would probably need non-volatile memory for saving the keymap in use (or it would forget it when unplugged.) The extra component adds a bit more cost, and increases the chances of hardware failure. If you want to forego NV memory, the software would have to be responsible for initializing the keymap every time the keyboard is plugged in. But if the software is choosing which keymap to use anyway, then technically it's simpler to let the key mappping happen in software and not firmware.
2. For multilingual users. Allows them to switch keyboard layout easily. Even many European programmers switch to US-ANSI to get easier access to programming-language symbols such as ~ ^ [ { } ] , and back to type in their native layout which could have other symbols on those physical keys.
In 1986, an exceptional machine like the IRIS 2000 ran at 10MHz, and fully-loaded had 16MB RAM.
Do you need something as powerful as the ARM Cortex M7 to build a keyboard the way you're describing? Well, no, but you'd have trouble doing it with less than a 6502 or a Z80, and computer keyboards have existed for decades longer than those chips. Which were the entire CPU of microcomputers such as the Apple // and Commodore 128, respectively.
So it would be possible now, but it would require rearchitecting a basic system which is working fine, for every operating system which could conceivably use it.
Furthermore, most people would be inconvenienced by this. The two sides of the coin are, on the one hand, you plug in your mechanical keyboard into any computer and it Just Works. On the other hand are people who switch keyboard layouts. They outnumber the mech enthusiasts by what must be hundreds to one, switching layouts based on what one is doing is very common in Europe and ubiquitous in places where the language is written using a script which isn't derived from the Latin one.
So that's the historical reason why it didn't happen, and the contemporary reason why it still hasn't, and probably won't. This actually inconveniences me, I have to jump through several levels of hoop to put Unicode characters on the higher planes of my split-key, but it is what it is.