feature: add basic doc about how a keyboard works on USB
This comes from the discussion on #520
This commit is contained in:
		
							
								
								
									
										96
									
								
								doc/basic_how_keyboards_work.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								doc/basic_how_keyboards_work.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,96 @@
 | 
				
			|||||||
 | 
					# How keys are registered, and interpreted by computers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					In this file, you can will learn the concepts of how keyboards work over USB,
 | 
				
			||||||
 | 
					and you'll be able to better understand what you can expect from changing your
 | 
				
			||||||
 | 
					firmware directly.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Schematic view
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Whenever you type on 1 particular key, here is the chain of actions taking
 | 
				
			||||||
 | 
					place:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` text
 | 
				
			||||||
 | 
					+------+         +-----+       +----------+      +----------+     +----+
 | 
				
			||||||
 | 
					| User |-------->| Key |------>| Firmware |----->| USB wire |---->| OS |
 | 
				
			||||||
 | 
					+------+         +-----+       +----------+      +----------+     |----+
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This scheme is a very simple view of what's going on, and more details follow
 | 
				
			||||||
 | 
					in the next sections.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 1. You Press a Key
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Whenever you press a key, the firmware of your keyboard can register this event.
 | 
				
			||||||
 | 
					It can register when the key is pressed, held and released.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This usually happens with a [periodic scan of key presses with a frequency around 100 hz](https://github.com/benblazak/ergodox-firmware/blob/master/references.md#typical-keyboard-information).
 | 
				
			||||||
 | 
					This speed often is limited by the mechanical key response time, the protocol
 | 
				
			||||||
 | 
					to transfer those key presses (here USB HID), and by the software it is used in.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 2. What the Firmware Sends
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The [HID specification](http://www.usb.org/developers/hidpage/Hut1_12v2.pdf)
 | 
				
			||||||
 | 
					tells what a keyboard can actually send through USB to have a chance to be
 | 
				
			||||||
 | 
					properly recognised. This includes a pre-defined list of keycodes which are
 | 
				
			||||||
 | 
					simple numbers from `0x00` to `0xE7`. The firmware assigns a keycode to each
 | 
				
			||||||
 | 
					key of the keyboard.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The firmware does not send actually letters or characters, but only keycodes.
 | 
				
			||||||
 | 
					Thus, by modifying the firmware, you only can modify what keycode is sent over
 | 
				
			||||||
 | 
					USB for a given key.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 3. What the Operating System Does
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Once the keycode reaches the operating system, a piece of software has to have
 | 
				
			||||||
 | 
					it match an actual character thanks to a keyboard layout. For example, if your
 | 
				
			||||||
 | 
					layout is set to QWERTY, a sample of the matching table is as follow:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					``` text
 | 
				
			||||||
 | 
					| keycode | character |
 | 
				
			||||||
 | 
					|---------+-----------|
 | 
				
			||||||
 | 
					|    0x04 | a/A       |
 | 
				
			||||||
 | 
					|    0x05 | b/B       |
 | 
				
			||||||
 | 
					|    0x06 | c/C       |
 | 
				
			||||||
 | 
					|     ... | ...       |
 | 
				
			||||||
 | 
					|    0x1C | y/Y       |
 | 
				
			||||||
 | 
					|    0x1D | z/Z       |
 | 
				
			||||||
 | 
					|     ... | ...       |
 | 
				
			||||||
 | 
					|---------+-----------|
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Back to the firmware
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					As the layout is generally fixed (unless you create your own), the firmware can
 | 
				
			||||||
 | 
					actually call a keycode by its layout name directly to ease things for you.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This is exactly what is done here with `KC_A` actually representing `0x04` in
 | 
				
			||||||
 | 
					QWERTY. The full list can be found in `keycode.txt`.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## List of Characters You Can Send
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Putting aside shortcuts, having a limited set of keycodes mapped to a limited
 | 
				
			||||||
 | 
					layout means that **the list of characters you can assign to a given key only
 | 
				
			||||||
 | 
					is the ones present in the layout**.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					For example, this means that if you have a QWERTY US layout, and you want to
 | 
				
			||||||
 | 
					assign 1 key to produce `€` (euro currency symbol), you are unable to do so,
 | 
				
			||||||
 | 
					because the QWERTY US layout does not have such mapping. You could fix that by
 | 
				
			||||||
 | 
					using a QWERTY UK layout, or a QWERTY US International.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You may wonder why a keyboard layout containing all of Unicode is not devised
 | 
				
			||||||
 | 
					then? The limited number of keycode available through USB simply disallow such
 | 
				
			||||||
 | 
					a thing.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## How to (Maybe) Enter Unicode Characters
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					You can have the firmware send *sequences of keys* to use the [software Unicode
 | 
				
			||||||
 | 
					Input
 | 
				
			||||||
 | 
					Method](https://en.wikipedia.org/wiki/Unicode_input#Hexadecimal_code_input) of
 | 
				
			||||||
 | 
					the target operating system, thus effectively entering characters independently
 | 
				
			||||||
 | 
					of the layout defined in the OS.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Yet, it does come with multiple disadvantages:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 - Tied to a specific OS a a time (need recompilation when changing OS);
 | 
				
			||||||
 | 
					 - Within a given OS, does not work in all software;
 | 
				
			||||||
 | 
					 - Limited to a subset of Unicode on some systems.
 | 
				
			||||||
		Reference in New Issue
	
	Block a user