How does a MIDI keyboard work?

You press a key, and sound comes out. Or at least that’s how its supposed to work. But what’s going on inside to make that happen? We’ve taken apart an old MIDI keyboard and looked at their design decisions, just to see what the Pro’s do. And, as it turns out, it’s pretty much in line with our lowest cost matrix scanning option.

Figure 1 – Internals of a MIDI keyboard

As shown in Figure 1, there isn’t much to the keyboard. Inside there is an array of keys (the white and black things) which press down on buttons (the grey things). The buttons are all mounted on a green PCB which runs the full length of the keyboard. Underneath the keyboard, in the upper left, you can see a brown PCB. This has the microcontroller and various bits of support circuitry, like the MIDI jacks and power supply.

Figure 2 – Close-up of keyboard buttons.

A PCB is used for the switches as it is much easier to make a PCB than it is to individually wire up all those buttons. To further save on cost, the buttons are molded rubber with conductive ink printed on them. A close up of these buttons is shown in Figure 3. The switch PCB also has conductive ink printed on it, but in 2 half-moons which face each other. These form the contacts of the switch, and when the rubber presses against them, they short together and activate.

Figure 3 – internals of keyboard buttons.

So why are there 2 buttons for each key? This is how they measure note ‘velocity’, or how quickly you pressed the key. With most synthesizers, the faster (i.e. harder) you hit a key, the louder or brighter a note will sound. This gives another mode of expression. In older keyboard there were two switches, one of which was above the key, and the other below. When a key was pressed, the top button would release and the microcontroller would begin counting. Once the bottom button was hit, the microcontroller would stop counting. This would give the time it took for the key to be fully depressed – the velocity value.

Rather than install a second PCB with buttons on top, this keyboard uses a less expensive method. The single PCB houses dual buttons under each key, with one button molded into the rubber at a larger distance from the PCB. The other button is molded such that it is almost touching. So when the key is pressed, one button touches first, and then you can count how long it takes for the second button to come into contact. This gives similar velocity readings for far fewer components.

This keyboard has 49 keys (4 octaves + 1), and two buttons per key, summing to 98 buttons. All of the buttons are arranged in a simple switch matrix, with a diode per switch (some of these are shown in Figure 4). There are 14 columns and 8 rows, with only 2 switches on the last 2 columns. Each of the row lines has a 22k pull-up resistor.

Figure 4 – Backside of switch PCB showing diodes and connector.

It’s interesting to note that they use 14 + 8 = 22 scan lines to do 98 buttons, rather than the minimal compliment of a 10 x 10 array which would allow for 100 buttons. There are a number of factors at play here. First off, there are 3 more buttons on the keyboard case which are not shown (data entry keys), so the total is actually 101, requiring a 11 x 10 matrix minimally. Secondly, and more importantly, it is faster to read in data 8 bits at a time into a microcontroller. If you only wanted a few bits off an 8 bit bus, you would have to read in the whole bus and then perform a second masking operation. In this case its worth the extra pin to speed up the read time.

The microcontroller in this device is a Toshiba TMP87C447U; an 8 bit processor, running at 8MHz. It has 44 pins and a 0.5us minimum instruction execution time. It scans the keyboard every 1.26ms (a MIDI message time period), with the columns being addressed for 6us and 12us for the up and down buttons, respectively. The total scanning time takes 300us, with the data most likely being processed as it arrives. This is usually a good method, as it lets scanned columns settle out after each transition, and fills this otherwise dead time with useful processing. Generally, the longer you can let the lines settle before reading them, the better.

All in all, it’s a good, low cost design. The only confusing aspect is the 74LS244 (3-state bus driver) on the column bus. Although the column bus is multiplexed with a 7 segment LED display (not shown), the resultant row data can easily be ignored when it’s not addressed, so there is no need to HI-Z the line. For a rework of this design using the Atmel XMEM interface, giving a 500ns (per column) read time, check out our XMEM scanning tutorial.