An introduction to hacking an open keyboard

Keyboard Remodel

© Lead Image © 3355m,

© Lead Image © 3355m,

Article from Issue 211/2018

Reprogramming the Keyboardio Model 01's firmware is limited only by its memory and your imagination.

Last month, I described the numerous features of Keyboardio's Model 01 (Figure 1) [1]. The keyboard's ergonomics, customizations, and aesthetics are joy enough for many users, but these features are just the most obvious. The Model 01 is open hardware, which means that you can program everything in the firmware to your liking, rearranging the keymap and the LED backlights and adding plugins; you are limited only by the memory of the keyboard's two ATmega32U4 Arduino microcontrollers. In the process, you can learn some of the basics of programming Arduino C for use with other devices [2], as well as some of the logic behind other open source keyboards that use some of the same code, such as those offered by Input Club.

Figure 1: The Model 01 keyboard.

Before you can reprogram the firmware, you need to set up the Arduino IDE and the Model 01 firmware [3]. Begin by downloading, uncompressing, and installing the Arduino IDE, following the instructions on the Keyboardio wiki. These instructions are lengthy, but each step is simple in itself. Note, though, that there are some special instructions for some distributions. In particular, the ones for Ubuntu also apply to Debian, and, I'm guessing, most Debian-derivatives as well.

Next, follow the instructions to download and install the source code for the Model 01 firmware [4]. The procedure places a copy of the firmware in $HOME/Arduino/Model01-Firmware called Model01-Firmware.ino – a sketch, in Arduino jargon. This file can be edited in the Arduino IDE or any other text editor. When you are finished editing, the file must be flashed on to the keyboard, just as a firmware update from Keyboardio would be. A Keyboardio firmware update would overwrite your edited file, so either change its name or back up a copy of your changes as a reference. If you run into difficulties, you can restore the default firmware and try your customizations again.

To have complete freedom to customize the firmware, you need to study Arduino C. However, Keyboardio heavily comments its source code and general instructions, and numerous macros and plugins are already available. As a result, you can become moderately adept simply by reading the code already available for the Model 01 or for third-party macros and plugins. If you start with modifying existing code, you can slowly learn to write your own by looking for specific examples in existing code. The fact that the Model 01 is a specialized case makes learning easier than it might otherwise be.

Altering Keymaps

Because the Model 01 is an ergonomic keyboard, most users take a few days to adjust to typing on it. This time can be frustrating as your typing speed slows, but it can also indicate some of the first customizations to try. For example, if you find that you often overreach the Z key and hit the Page Down key, catapulting you from your current position in an editor, you might start by repositioning the Page Down key, or else using the key for something less distracting.

When you change the position of a key or a command, you are changing a keymap. A keymap is exactly what it sounds like: a description of what happens when you strike each key. In Keyboardio's case, the map is divided into two halves, one for each part of the keyboard. For example, Figure 2 shows the keymap for the default QWERTY arrangement of keys on the Model 01.

Figure 2: The source code for the default keymap in an INO file.

To change a particular key's bindings, give it a different keycode. The Model 01 supports dozens of keycodes, available in three lists [5]: common characters, command codes, and controls for other devices, such as volume. You can also add common functions, such as copy and paste, with a series of brackets. For example you can reduce Ctrl+C (copy) to a single keystroke with the code LCTRL(Key_C) or RCTRL(Key_C) (in some applications, which Ctrl key you use can make a difference, but not here). For Ctrl+Shift+C (copy in a virtual terminal), the code would be LCTRL(Key_LeftShift(Key_C)).

Besides swapping key positions, you might try the following custom keymappings:

  • Adding a Caps Lock with the code Key_CapsLock if you frequently type uppercase letters.
  • Assigning frequently used keyboard shortcuts in commonly used applications.
  • Adding a currency character, such as the symbol for euro or yen.
  • Adding a command for such purposes as a system shutdown or opening a desktop menu.
  • Subtracting a seldom-used key or moving it to another layer (see below).

Some of these purposes may only save you a keystroke or two at a time, but in some cases, the advantage can quickly add up. For instance, if you are editing constantly, a single keystroke for each copy, paste, and save is both ergonomic and efficient over an entire day's work.

The largest limitation is the number of keys you can customize without giving up some functionality or shifting it to another layer. However, the Butterfly and Any keys are good places to assign new keybindings. So is the Prog key, although you will need to go through a special procedure to flash firmware if you assign something to it (see below). You can also use several macros to make multiple uses of keys (again, see below).

Another consideration is that you cannot always switch keycaps – the part that fingers press – to match your customizations, because many keys on the Model 01 are individually sculpted and are not always interchangeable with keys in other positions. An exception is the four control keys pressed by the thumb on each half of the keyboard, which are all the same shape. Otherwise, you might chose to contact Keyboardio for some blank keycaps to help minimize confusion. A blank keycap's purpose may not be obvious, but at least it will not display a former purpose. You might even add a label to a blank keycap, although it will likely need frequent replacements.

Working with Layers

Layers are a different keymap. The default QWERTY is used automatically. Other layers, however, are activated by pressing a Command key, just as holding down the Shift key in the default layer activates uppercase letters and a small set of symbols. If you use a software-defined keyboard layout, you may also have another layout that uses a particular key to access accents, umlauts, and other diacritical marks.

The Model 01 also ships with two other layers, besides the default QWERTY. The second is the FUNCTION layer, which is activated as long as you hold down the Fn key with your palm. It gives you access to the function and arrow keys, as well as curly and square brackets. The third is NUMPAD, which activates a number pad when the Num key is toggled. Both these layers help to reduce the number of keys on the Model 01 by assigning different functions to some keys depending on which layer is currently active. Since only one layer is active at a time, any confusion is minimal, and, in any event, the Model 01 ships with a laminated sheet showing the three default layers (Figure 3).

Figure 3: Keymaps for the Model 01's default layers are included with each keyboard on a laminated sheet. You can write your own layout on the other side of the sheet.

In theory, the Model 01 can support a total of 32 layers, although in practice, it might run out of memory and keys long before reaching these numbers. These layers could be alternative keyboard layouts or collections of macros for an often-used program like Emacs or Krita, for a favorite game, or for anything else you can imagine. You could also use the existing FUNCTION or NUMPAD for adding numerous macros, since both make light use of the left-hand portion of the keymap.

To add a layer, copy and paste an existing keymap around the existing keymaps. Then add the layer name in uppercase letters to the list that appears before the default layer in the *.ino file. For example, to add a layer with Vim keybindings, the list would look like this:

enum { QWERTY, NUMPAD, FUNCTION, VIM }; // layers

The first layer in the list is the default. If you prefer an alternative keymap like Colemak rather than QWERTY, it must be placed first in the list. However, if someone else who uses the keyboard prefers a different keymap, you will probably want another layer for their preferred keymap as well.

Additionally, each layer requires a key that activates it from any other layer. One choice is to activate a layer only so long as a key is being pressed. If you look at the QWERTY layer, you will see the code snippet for activating a layer in this way illustrated in the mapping for the Fn key: ShiftToLayer(FUNCTION). Alternatively, you can designate a key to toggle a layer on until the key is pressed again. This choice is illustrated in the mapping for the Num key: LockLayer(NUMPAD). It would, of course, be inconvenient to always have to hold down a key while using a number pad.

Further access can be gained by defining a key with three underscores (___), as the Prog key is in QWERTY. When a key with this definition is pressed, it produces the character or command in the last active layer, which can be handy for accessing something quickly. You can also use XXX to block a key from being used on a layer, as the NUMPAD layer blocks the LED key from being used; since the NUMPAD layer uses red backlights to indicate which keys compose the number pad, you do not want this arrangement interrupted by the cycling through default light arrangements, as the LED key does on the QWERTY layer.

Editing LED Effects

The Model 01's LEDs are as programmable as the keys themselves. The LEDs are useful in dim light, but even when you touch-type, they are detected on your vision's periphery and make for more accurate typing. Some LED modes signal an event, such as connecting the keyboard or flashing the firmware. Others are accessibility aids, such as Kaleidoscope-LED-AlphaSquare.h, which uses the keys around the one pressed to produce the same character using all three banks of the character keys, or Kaleidoscope-LED-Stalker.h, which lights up a key for several seconds after it is pressed, allowing you to confirm which key was pressed. Others treat the keyboard as a light organ of rippling effects and are simply eye candy.

When you press the LED key, you can toggle through the dozen default modes. The code for each mode is stored in


and made available by an #include statement at the start of the Model01-Firmware.ino file.

The code for these modes provide concrete examples of how to write your own code for the Model 01. However, after you have cycled through the default modes a few times, your first customization of the LEDs might be to comment out the modes you no longer want, so you can toggle more quickly to the ones you actually use. If you decide on just one preferred mode, you might also search for support for an "LED off mode" and comment out #include "LED-Off.h" below it; then, replace the line LEDOff.activate(); with the mode of your choice, such as solidRed.activate();.

Another simple customization is to edit the default solid color definitions used by other LED effects. Each value occupies a single line and includes a name for easy reference, followed by the color definition, such as:

static kaleidoscope::LEDSolidColor solidRed(160, 0, 0);

You can change the existing color definitions, deleting unwanted values or adding new ones to the list. You can get a color definition by opening Gimp, but remember that while Gimp uses an RGB color definition, the firmware uses a BGR definition, listing values for Blue, Green, and Red.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

comments powered by Disqus