 So hi, I'm Scott, and I'm going to talk about keyboards. So keyboards are everywhere. We use them all the time. Probably a bunch of us in the room are touching a keyboard right now, but how do they work? I started building a keyboard because I wanted to learn more about them, and I also wanted to have an ergonomic one that fit my hands. And so what I have currently looks like this. And aside from the shape, it's pretty similar to most of the other keyboards on the inside. So most keyboards have the same parts. There's a bunch of keys and switches that are underneath them, and then there's a key matrix that ties all of those switches together, and then there's some sort of microcontroller that just reads the state of all those switches and then communicates what's being typed. So there's many, many kinds of key switches. People have really strong opinions about liking keys that are clicky or things like that, but from an electrical standpoint, they're all pretty similar. And so here's a slide of a Cherry MX key, which is one popular brand of switch. Essentially what it does, though, is when you push on the top, those two wires on the bottom connect, and that's the most important thing. And more abstractly, the circuit symbol for this kind of switch is just two wires that end, and then they have a little thing that pushes down and connects them. It's called a momentary switch because it only momentarily connects stuff. And on my oscilloscope, the switch activity looks like this, so the voltage level is low, and then when you press it, it jumps up high really suddenly, and that's just because the switch closes and current can float through it. But if you zoom in time-wise into hundreds of nanoseconds, what we actually see is that the switch is kind of flickering as it changes because the switch has a spring and it has mechanical moving parts, and so it's not instantaneous. And so a keyboard needs to control for this. This is called debouncing. So the keyboard just needs to wait for things to settle down before it actually considers some sort of event who have happened. And then also, most microcontrollers can't actually have a input pin dedicated to every single key on the keyboard because if you look at a keyboard here, it might have 100 keys on it, and this is not going to have like a really big powerful CPU in it. It's gonna have a little microcontroller. So instead, the keys are set up in a key matrix, and that way, instead of having a wire and an IO pin dedicated to every single key, it can just have one for every row and every column and multiplex them, and that's the difference between multiplying and adding for the total. And so what that looks like is there's a grid here, these are all switches, there's column wires, there's row wires, and it just cycles through reading those. So let's say that we have that key in the fifth column, the third row is currently being pressed down so it's electrically connected, and then it puts power on the first row and then the second row and then the third row and the third row connects to that column because the switch is closed and so it's able to read power on that column and then it keeps sweeping through and it's just doing this hundreds of times a second, maybe thousands depending on the keyboard. But if the switch is closed, it will consistently allow power to go through so then it can read that as being a key that's being pressed. And then also there's the microcontroller inside the keyboard which will be running some sort of firmware that can actually read this and communicate it to the operating system that your keyboard is typing for. So my keyboard also looks like this, which is just a whole bunch of wires. That's a development board for an STM32F0 chip. It's a 32 bit ARM microcontroller, something that gets used in embedded systems a lot. It's kind of like an Arduino but it's got some more resources to work with and in particular this one supports USB which is pretty critical here. And in that breadboard on the left, the wires are grouped into a couple different sections. On the top there are the left hand columns. On the bottom are the right hand columns and then in the middle there are the rows that go all the way across the keyboard and that purple wire there that's connecting the left hand first row over or the first column over to that row is effectively the firmware thinks that I'm typing A. That's just connecting those so it's holding down A. And my firmware is broken up into a couple passes. So first it scans the key matrix and then it does the debouncing. It has some counts to keep track of what has been changing and then if it gets any events out of the debouncing it hands that off to the layout and looks up what that particular key being pressed means in that context. And then anything that comes out of the layout updates a report for saying what the current state of the keyboard is and then that gets reported over USB. But this architecture is really deliberate. I've been very careful to put seams around those because everything except for reading the raw state of the key switches and producing the USB report can be tested completely independently off of the hardware and I can have a whole set of scripted test data to run against it. I can use property-based testing to generate input to it and see if it can find any bugs and simplify the bugs to minimal failing cases. And I can also factor time out of the system which is something that I have never regretted doing in setting up libraries like this because if you don't need to deal with time everything becomes quite a lot simpler to test to be confident about that it works. But that's kind of another talk so I'll move on. So back to USB. It's called the universal serial bus. So you know it's going to be a little bit complicated. When you plug in a USB device it goes through a process called enumeration which is because you're speaking in enums. It's doing a bunch of registration of what sort of device it is and a bunch of different descriptors. So there's a whole descriptor tree that's requested and a physical keyboard might configure itself as being a keyboard but it also might have LEDs that you can light up or it might have a touch pad or something built into it and devices can also register as different things depending on how they're being powered. So this tree of descriptors, I remember it as dice. The letters are sort of out of order but there is the device layer, the configuration layer, the interfaces and the endpoints and the device says what version of USB and how many different configurations are there and also like the vendor and product ID. Configuration will say how much power it needs and whether say typing a key on the keyboard should wake up the OS if it's asleep and then the interface says what kind of what class of interface it is. It might be a keyboard, it might be a mouse, it might be some other sort of control panel or something and how many endpoints it has and the endpoints are sort of the different data buffers specifying how often and how much data is being read or can be written to it and that those are all like IO pipes connected to it and there's an awful lot of details in terms of how of all that stuff fits together, the different IDs that are used for specifying that stuff and so on. So ultimately I have to refer you to this book which is very, very good and gets into all of that stuff in great detail. The book USB Complete by Jan Axelson and she also has a lot of info about working with USB on her website. And specifically in this talk I'm talking about HID, human interface device, class devices, which they don't need any custom device driver because it's something that it's assumed that you can just plug in and work with its common input devices like keyboards and mice and stuff. And they are specified, they have a report for how they send their data specified in like a weird little stack language that's completely different from everything else in USB. It took me some time to figure out why that was structured the way that it was. But so that's used for a bunch of common stuff. There's keyboards, mice, joysticks, track pads, barcode readers, magic carpet simulation devices which are in the USB HID standards. So if you ever wanna write a really cool Easter egg into something, and I don't know, maybe there's already like a little mini game with a magic carpet in Excel or something if you just have it plugged in, who knows. But so the HID reports are once everything's configured it just sends a report periodically and it's pretty simple. So a keyboard looks like this, it's gonna be sending typically eight bytes. This is in hexadecimal. And the first byte there is a set of bit flags representing shift, control, alt, and GUI which is either the Windows key or command key for the left hand or the right hand. And then the next byte is just always zero, it's reserved. And then the rest is a set of up to six different keys that are being pressed or zeros or error codes. That's also how cool steno keyboards like Mirabai is using work. So they can keep track of a combination of keys other than just individual keys that are being pushed. And in this case, it's typing left shift and the one key or a bang. So I have about a minute left to thank some quick tips if you wanna make a USB human interface device. First of all, it's really helpful to be able to record and decode USB protocol messages. If you have access to a Beagle protocol analyzer that's really helpful, but they're also several hundred dollars so you can also use a Linux kernel extension and then turn USB into a network interface and use Wireshark, which is great. And I read through, I don't expect this to be all that readable, just sort of the tree structure of it. I read through a bunch of those descriptors and all of a sudden the USB complete book made so much more sense because I recognized what a lot of the individual codes meant and where they fit in there. And then also use a hub and be able to disconnect your whole USB stack if you can because if you have a USB device firmware that hits a break point or something and it freezes everything else on the USB connection is also going to hiccup and it's a huge pain. I have a USB to Thunderbolt adapter that apparently when I unplug that and plug that back in it resets everything. And if you want an open source keyboard firmware there's something called TMK that works on a lot of platforms. And if you're intrigued by the idea of a mechanical keyboard, there's also kits such as Technomancy's Atreus kit. I have mine with me and it's designed so that it doesn't really need very much advanced soldering, so that's a nice keyboard. And thanks.