4

The "shift" key on a keyboard is different from other keys as it can edit the outputs of the other keys on the keyboard. But how does it do it? I have one hypothesis on how the shift key does what it does(This also applies to ctrl, alt, and command keys, albeit with different rules, but bear with me).

I think that the sixth bit of all of the other keys are connected to the SHIFT key via an XOR gate. This means that when the Shift key is on, the output of said 6th bit is inverted(For numbers it's the 5th bit). I used an ascii to binary converter to prove my hypothesis and it seems in check. Am I correct on how the shift key works, or is there something I missed?

  • 14
    What kind of keyboard? A PC/XT, PC/AT, PS/2, or USB keyboard from the PC world? A keyboard on a serial terminal? A keyboard on one of the many types of home computer in the 1970s and 1980s? – JdeBP Apr 30 at 20:07
  • An independent key-up and key down event for each key pressed or released supports software making shift keys, lock keys (caps lock, scroll lock, num lock), and auto repeat -- all fully under software control. – Erik Eidt Apr 30 at 20:36
  • I was thinking more of a commodore keyboard or something like that. – Trevor Mershon Apr 30 at 20:47
  • 1
    In e.g. a Commodore 64 keyboard, all keys but the RESTORE key are connected to an 8x8 keyboard matrix. – Janka May 1 at 1:51
  • 3
    Uh, the shift key on a keyboard elevates the array of typebars so that the capital letter (which is lower down on the arm than the lower-case letter) is the one that strikes the center of the platen. – Hot Licks May 2 at 1:31
25

That's how the shift key sometimes worked on old terminals and ASCII is designed around it.

But on a modern keyboard, the SHIFT key just does exactly the same as every other key on the keyboard: it sends a 'key down' signal and a 'key up' signal.

This doesn't affect any other signalling and the computer it is connected to determines the net effect.

| improve this answer | |
  • 7
    In the modern world that's just the rule that operating systems apply. If you load up something like a game and redefine shift to be the 'fire' key, you should find that you can fire without pressing any other keys. But you're right that back in the classic world modifiers like shift communicated nothing unless and until another key was pressed. EDIT: also, if you're a Windows user and haven't turned the feature off, press shift five times in succession. That brings up a prompt asking whether you want to use 'sticky keys', in which you press shift once to enable shift mode, again to disable. – Tommy Apr 30 at 16:15
  • 1
    This is exactly how the shift key worked on old terminals such as the Teletype Model 33, and the DEC VT05. Note that on those terminals, the key assignments were set up to support this, so a shifted 2 would emit the double-quote character ("). But fairly quickly, the computer industry switched to a layout more similar to what you would expect on a typewriter, where single and double-quote are on a key by themselves, and a shifted 2 emits the at character (@) instead of double-quote. This made it no longer practical to use an XOR gate by itself, but it improved usability for touch-typists. – Ken Gober Apr 30 at 16:30
  • 2
    Weired? No, not really. Keyboards are quite simple. What you discovered is essential the assignment that was used on early (mostly mechanical encoded) keyboards. Encoding was done within the keyboard and only 'cooked' characters were delivered, so SHIFT-1 pressed delivered an exclamation mark code to the computer. Nowadays keyboards work different. Each and every key press gets reported to the computer, were a driver works it into application codes. So for SHIFT-1 the keyboard transmits 4 messages (Shift-Press, A-Press, A-Release, Shift-Release) that get turned into an exclamation mark code. – Raffzahn Apr 30 at 16:36
  • 2
    @KenGober Only in the USA. UK English computer keyboards don't have single and double quotes on the same key. The @ and " key positions are swapped over compared with US English (and there are other differences as well). – alephzero Apr 30 at 16:52
  • 6
    @TrevorMershon: Shift lock (with sticky keys) and caps lock are not the same thing. They are equivalent for letter keys, but for digit keys the shift lock produces symbols, while the caps lock still produces digits. – Greg Hewgill Apr 30 at 20:59
7

From a pure hardware point of view, a significant amount of computers keyboards see each keypress as a bit set in a matrix of rows & columns, so with another operating system you could theorically map "shift" to another key.

So one could say that only the operating system makes the shift/control/alt keys different from others.

However there are some limitations when several keys are pressed, depending on the hardware.

A "famous" example is the Z-Out cheatmode on amiga: "press J+K for invincibility".

It worked perfectly on Amiga 500 model but with the A1200, J+K cannot be detected at the same time due to a different keyboard circuitry/cheaper design on the A1200 (a part of the reason is because they're next to each other on the same matrix line). So in that case you could not use "J" or "K" as shift since some combinations would not work.

On a day to day basis, all key combinations aren't useful. This J+K thing is just bad luck (and the only example I know).

But, as noted in a comment:

this are not true for all keyboards. PC/XT, PC/AT, PS/2, and suchlike keyboards have two microcontrollers and a serial link between the mainboard and the keyboard. The mainboard processors do not see a matrix of rows and columns, and the remote microcontrollers know that certain keys are modifiers, transmitting their codes as fake modifiers to make newer keyboards work with older machine firmwares

That comments tends to restrict my answer to other types of keyboards. It seems that the design of "serious" machines like IBM PCs of the time doesn't take into account multiple keypresses like other more hobbyist machines would, one of the reasons could be that hobbyist machines keyboards need to be more performant for games played with the keyboard.

(for instance the Oric 1/Atmos used a matrix and had no multiple keypress restrictions, you could query each key by row/column independently)

Hobbyist machines generally require a better multiple keypress handling or it would not be possible to move up & right at the same time & press fire for instance (note that the J+K impossibility on the A1200 machine isn't really a problem since in no sane mapping J could be up and K left, and for fire, game designers usually prefer ... shift, that is, when games can be played using the keyboard)

| improve this answer | |
  • 1
    The reason that the question needed clarification is that answers like this are not true for all keyboards. PC/XT, PC/AT, PS/2, and suchlike keyboards have two microcontrollers and a serial link between the mainboard and the keyboard. The mainboard processors do not see a matrix of rows and columns, and the remote microcontrollers know that certain keys are modifiers, transmitting their codes as fake modifiers to make newer keyboards work with older machine firmwares. Computer keyboards have had a significant range of architectures over the past half century. – JdeBP May 1 at 8:46
  • you're perfectly right. I'll edit to restrict to what I know :) – Jean-François Fabre May 1 at 9:34
  • "so with another operating system you could theorically map "shift" to another key" -- you can do it in practice too, it's one line for xmodmap on Linux. Some people like to remap Control to where Caps Lock is. I haven't tried it with Mac or Windows, so I don't know if they have a more fixed idea of what Shift and such should be. – ilkkachu May 2 at 8:18
  • As for J and K, well, everyone who has played Nethack knows they're down and up, not up and left ;) (But seriously, you definitely could play games on a DOS-era PC keyboard, and you also definitely got clashes where some keypresses would not get registered simultaneously. It depends on how the physical matrix was laid out, the serial line can send multiple key events just fine. – ilkkachu May 2 at 8:27
  • "On a day to day basis, all key combinations aren't useful." On a day to day basis, many combinations of typing-keys are useful, so that the software can correctly implement key rollover. Not that all software does implement it correctly -- many's the typo I've made due to the software misinterpreting key-up and key-down events and not understanding rollover (eset instead of est is a common one). – Rosie F May 2 at 17:18
3

Modifier keys were sometimes wired differently than other keys.

How to make a keyboard with 100 keys.

  • You can use a microcontroller with 100 inputs and eack switch connected on one side to the power supply and the other side to the microcontroller. Simple, but that's a lot of signals, fairly expensive.

  • You can arrange keys in a 10x10 matrix. The microcontroller will need 10 inputs and 10 outputs. The controller will alternatively scan each of the 10 columns and read the state of the 10 lines. Quickly enough to be transparent for the typist.

The problem with that second option is that when many keys are pressed simultaneously (more than 2) , it is sometimes impossible to determine all pressed keys because they make some short-circuits between lines and columns.

The cheap solution was to use additional inputs for the modifier keys that needed to be pressed at the same time as other keys.

The best solution now is to place a diode on each key, which allow any combination and of pressed keys.

| improve this answer | |
  • Another option if one only needs 8 modifiers would be to use a 16x8 matrix but put all the modifiers on the main diagonal and refrain from using of the 28 keys above it. That would allow unambiguous decoding of any combination of modifiers plus one other key without any diodes. – supercat Apr 30 at 21:49
1

The data output by keyboards varies with different computer systems and protocols. While your theory is certainly plausible, a typical keyboard outputs "scan codes", rather than ASCII codes - typically over a serial interface.

While modern PCs use USB as the physical interface, with the USB HID protocol running on top of that, the protocol dates back to the original IBM PC XT/AT keyboard interface which is still emulated in some parts of a modern OS.

In this protocol, shift keys are no different to the "regular" typematic keys and rely on software in the operating system to translate them to characters or to perform actions which have no ASCII-equivalent - like media keys on modern keyboards, or older (1980's) keyboards that could have a mouse or joystick connected to them, which also sent data over the keyboard interface.

The original IBM PC (XT)

Ref: [1] http://www.bitsavers.org/pdf/ibm/pc/xt/1502237_PC_XT_Technical_Reference_Apr83.pdf

The keyboard contained an Intel 8048 microcontroller which periodically scans the matrix of keyboard switches, monitors for changes in the switches, encodes the switch changes as "scan codes" and then sends the scan codes over the keyboard's serial interface.

The XT keyboard has 83 keys, so sends scan codes numbered 1 to 83.

Scan codes roughly correspond to the order of the switches in the switch matrix and are unrelated to ASCII.

Most scan codes are sent as a single byte, with bit 7 clear when the key is down (pressed), and set when the key is up (released).

For example, if you pressed key 30 which corresponds to A on a US layout:

| action  | hex  | binary   |
| ------- | ---- | -------- |
| press   | 0x1e | 00011110 |
| release | 0x9e | 10011110 |

The PC contained an Intel 8255 Programmable Peripheral Interface (PPI) chip which was directly connected to the keyboard port to receive the incoming data, and also to the PC's address and data bus, to output the (buffered) data when the keyboard IO port (0x60) was read by software running on the CPU.

Keyboards with different key layouts, like "QWERTY", "AZERTY", "QWERTZ" all output the same scan codes for the same physical key positions rather than what is printed on the key - when you press Q on a QWERTY keyboard, the keyboard sends scan code 0x10, and when you press A on an AZERTY keyboard, the keyboard also sends scan code 0x10.

This means that software in the PC needs to translate the scan codes to the characters you want, using a keyboard translation table. At the time, the MS DOS operating system was popular and the keyb program was used to load a keyboard layout corresponding to a country code.

So back to your question, how does a shift key work?

With the PC AT keyboard protocol (derived from the earlier XT standard), if you hold down the left shift key and press a letter key, the following scan codes are sent in order:

0x2A | left shift down
0x1E | A down - the A key on a US layout, that is to say :)
0x9E | A up
0xAA | left shift up

Note that the left and right shift keys are different keys and can have potentialy have different actions. Software also needs to be aware of this, so that it stays in "shifted" mode if both the shift keys are pressed, and one was released. Consider this sequence:

0x2A | left shift down
0x36 | right shift down
0xAA | left shift up
0x1E | A down
0x9E | A up
0xB6 | right shift down

If a single "shift" toggle bit is used by software, then the 0xAA scan code would clear it, returning to unshifted input, and return a lower-case "a", rather than the correct upper-case "A".

| improve this answer | |
1

I got a little carried away researching for what was just intended to be a mild elaboration on what was already said. I hope you find this interesting nonetheless:

Old Terminal Hardware

First, the ASCII section in Eric S. Raymond's "Things Every Hacker Once Knew" goes into more detail on how old terminals mapped keys, including that Shift toggles the 16 or 32 bit depending on the key, and that Ctrl would mask out the top three bits.

That's why you type Ctrl+D (Historically visualized as ^D) to exit an interactive Python session on Linux or if you're using cat > name_of_file as an equivalent to the old DOS COPY CON trick. The binary representation of D is 1000100 while 0000100 is the ASCII control character EOT (End of Transmission).

As ESR points out, DOS and Windows use Ctrl+Z (^Z) as their end-of-file character, which is not the ASCII-specified meaning but still derives from how old terminals would mask out the top three bits of the letter when you held Ctrl.

Here's the ASCII-to-binary chart he includes, generated using his ascii utility:

   0000000 NUL    0100000      1000000 @    1100000 `
   0000001 SOH    0100001 !    1000001 A    1100001 a
   0000010 STX    0100010 "    1000010 B    1100010 b
   0000011 ETX    0100011 #    1000011 C    1100011 c
   0000100 EOT    0100100 $    1000100 D    1100100 d
   0000101 ENQ    0100101 %    1000101 E    1100101 e
   0000110 ACK    0100110 &    1000110 F    1100110 f
   0000111 BEL    0100111 '    1000111 G    1100111 g
   0001000 BS     0101000 (    1001000 H    1101000 h
   0001001 HT     0101001 )    1001001 I    1101001 i
   0001010 LF     0101010 *    1001010 J    1101010 j
   0001011 VT     0101011 +    1001011 K    1101011 k
   0001100 FF     0101100 ,    1001100 L    1101100 l
   0001101 CR     0101101 -    1001101 M    1101101 m
   0001110 SO     0101110 .    1001110 N    1101110 n
   0001111 SI     0101111 /    1001111 O    1101111 o
   0010000 DLE    0110000 0    1010000 P    1110000 p
   0010001 DC1    0110001 1    1010001 Q    1110001 q
   0010010 DC2    0110010 2    1010010 R    1110010 r
   0010011 DC3    0110011 3    1010011 S    1110011 s
   0010100 DC4    0110100 4    1010100 T    1110100 t
   0010101 NAK    0110101 5    1010101 U    1110101 u
   0010110 SYN    0110110 6    1010110 V    1110110 v
   0010111 ETB    0110111 7    1010111 W    1110111 w
   0011000 CAN    0111000 8    1011000 X    1111000 x
   0011001 EM     0111001 9    1011001 Y    1111001 y
   0011010 SUB    0111010 :    1011010 Z    1111010 z
   0011011 ESC    0111011 ;    1011011 [    1111011 {
   0011100 FS     0111100 <    1011100 \    1111100 |
   0011101 GS     0111101 =    1011101 ]    1111101 }
   0011110 RS     0111110 >    1011110 ^    1111110 ~
   0011111 US     0111111 ?    1011111 _    1111111 DEL

If you'd like more information on the specific standards that established the various meanings of the ASCII control characters, I recommend Aivosto Oy's Control characters in ASCII and Unicode which I can't really meaningfully excerpt because it's mostly tabular information.

Conversely, if you'd like to know more about how key-presses on UNIX and Linux terminals (and terminal emulators) get translated into what's seen by software, Linus Åkesson's The TTY demystified is the most accessible reference I've ever found.

The "Configuring the TTY device" section at the end even provides various example commands you can play with in any environment which presents a VT100-compatible terminal emulator plus POSIX-compliant commands. (UNIX, Linux, macOS, Microsoft's WSL, etc.)

IBM PC Hardware

To step forward one ecosystem, the IBM PC keyboard puts a microcontroller in the keyboard which bundles all the matrix decoding up in a binary protocol based on key presses and releases with no concern for what role each key plays. Modifiers become modifiers on the PC side.

The easiest way to play around with this is probably to boot up an X11-based desktop (eg. on Linux) and play around with the preset key reassignments offered by the setxkbmap tool.

setxkbmap -option compose:rctrl -option ctrl:swapcaps -option shift:both_capslock_cancel

This command will...

  • Remap the right control key to Compose so you can type ™ by pressing (and not holding) Composetm
  • Swap the Ctrl and Caps Lock keys so you can type your emacs keyboard shortcuts with less awkwardness and risk of repetitive strain injuries.
  • Set up "pressing both Shift keys together enables Caps Lock, pressing one Shift key disables it"

(A selection of behaviours I chose to demonstrate both using modifier keys as ordinary keys and vice-versa.)

For further details on playing with setxkbmap, I recommend a blog post I wrote after not finding anything better, Getting your way with setxkbmap.

If you want to explore the wire protocol that IBM established and PC clone makers followed with the XT, AT, and PS/2 keyboards, The Vintage PC Pages at seasip.info have some excellent SVG diagrams and tables explaining the key mappings used by the microcontrollers in the UK versions of various standard-setting IBM PC keyboards (XT 83-key, XT 84-key, PS/2 102-key) to report key-presses over the wire.

It links to 10. Keyboard-internal scan codes from "Keyboard scancodes" by Andries Brouwer for a detailed explanation of how the scan codes are encoded as byte sequences. Because IBM defined three different modes to the protocol for backwards compatibility, each encoding a "break code" (key release event) differently, I won't go into detail here but the gist is:

  • In Set 1 (PC XT), each key is assigned an identifier consisting of one or more bytes (usually just one) using a scheme which guarantees unique prefixes and key releases are indicated by XORing the last byte with 0x80.
  • In Set 2 (PC AT), each key is again assigned a (different) byte sequence but key releases are indicated by sending a 0xf0 byte before the last byte of the key sequence.
  • In Set 3 (Terminal), key releases are indicated the same way as Set 2 but it's possible to enable or disable reporting of key releases on a per-key basis and, by default, it's only enabled for modifiers and keys which didn't exist when IBM specified the protocol, such as multimedia keys.

In both Set 1 and Set 2, the Pause/Break key is unique in generating a uniquely long 6-byte (Set 1) or 8-byte sequence.

Unless the requested otherwise, the keyboard controller on the PC side will translate Set 2 or Set 3 keycodes into Set 1 for legacy compatibility.

According to Brouwer, support for Sets 1 and 3 is either buggy or missing in most non-IBM clone keyboards and it is also the only mode supported when BIOS legacy support is exposing a USB keyboard as if it were a PS/2 device.

The IBM 6110344 Keyboard page on seasip.info points out that, as it was used for the 122-key keyboard of the IBM 5271, which predates the PC AT, it is likely that Set 3 originates in the world of IBM 3270 terminals.

If you want to go deeper, Adam Chapweske wrote PS/2 Mouse/Keyboard Protocol, which goes into the electrical details you need to build your own keyboard or hardware keyboard emulator using a microcontroller.

USB Hardware

You'd think that, because dual-mode keyboards which can speak USB and PS/2 protocol are a thing, there isn't much relevant to your question that wasn't already answered, but USB HID actually re-introduces treating modifier keys differently as a form of data compression.

Details can be found in the USB HID specification but the gist is:

USB HID defines two different protocols keyboards can speak. The fact that most keyboards only implement the boot protocol is what leads people to believe that USB HID is inherently limited to 6-key rollover.

The boot protocol is specified to fit in a single USB 1.1 Low-Speed "transaction" (I think of them as akin to TCP/IP packets), which is limited to 8 bytes.

As such, when a USB keyboard is speaking the barebones boot protocol that everything must implement for compatibility with things like BIOS menus, the PC polls for status (USB HID says interrupts are supported but optional) and receives a report that looks like this[1]:

           Bit 0   Bit 1    Bit 2   Bit 3   Bit 4   Bit 5    Bit 6   Bit 7
         ╔═══════╦════════╦═══════╦═══════╦═══════╦════════╦═══════╦═══════╗
  Byte 0 ║ LCtrl ║ LShift ║ LAlt  ║ LWin  ║ RCtrl ║ RShift ║ RAlt  ║ RWin  ║
         ╠═══════╩════════╩═══════╩═══════╩═══════╩════════╩═══════╩═══════╣
  Byte 1 ║ Reserved                                                        ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 2 ║ Keycode #1                                                      ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 3 ║ Keycode #2                                                      ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 4 ║ Keycode #3                                                      ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 5 ║ Keycode #4                                                      ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 6 ║ Keycode #5                                                      ║
         ╠═════════════════════════════════════════════════════════════════╣
  Byte 7 ║ Keycode #6                                                      ║
         ╚═════════════════════════════════════════════════════════════════╝

(Thank you, tablesgenerator.com and Vim editing commands.)

Note that this does not constrain USB HID to only 256 keycodes. (Though the X11 input event protocol did bake in such a limitation)

The USB HID Usage Tables define key codes 0xA5-0xAF and 0xE8-0xFFFF in the Keyboard table as Reserved and some devices, such as the ATi Remote Wonder II, have buttons from other tables such as Channel Down/Up which get mapped to key codes above 255 by the Linux driver.

I'm unsure whether these keys require switching away from the boot protocol to access or if there's an option I missed to switch the boot protocol into a mode which supports three 16-bit key codes rather than six 8-bit key codes.

| improve this answer | |
  • This is very interesting indeed! Thanks for the extra work! – Trevor Mershon May 4 at 13:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.