Creating a keyboard remapping tutorial

I am able to confirm that your instructions are not full of lies. I was able to re-flash with the unaltered firmware a couple weeks ago, before life descended into the chaos of the eclipse and back to school. The only thing that was less than straightforward was finding the fscking “prog” button on the keyboard!

I do want to make some changes to the keymap before I force myself to type on the keyboardio all the time, so am back looking at the state of things. It’s my goal to have things re-mapped by Sunday. :slight_smile:

Happy to review and assist with docs. I’ll take notes while I’m working.

1 Like

Thanks for the feedback.
What could we change to make that bit clearer?


“When the builder tells you to hit Enter to continue, hold down “Prog” on your keyboard and hit Enter. (The “prog” key is the upper left key on the left half of the keyboardio.)”

Ah, remembering more. Perhaps also add a note that the keyboard should be plugged into the computer when you build. It’s a “duh, did you plug it in?” thing, but it wasn’t obvious to me as someone with extremely limited knowledge of the Arduino platform. I assumed that building the firmware and installing the firmware would be separate operations.



I gave up on figuring out how to change the layout, and trained myself how to use the existing layout instead. It’s not optimal for me but it’s usable, and I am enjoying the feel of the keyboardio. I am assuming that as the community matures the documentation will improve and I can take another run at it.

To give more detail:

I don’t consider myself a programmer, but I can usually read code well enough to make light modifications to things. As examples of my level of competence, I have worked on 3D printers for fun, and installed and configured Jesse’s rt ticketing system at work. I keep a current build of my company’s site software and database installed on my personal computer. I’ve written some small python scripts to manage tickets in our trello backlog via the API. Professionally I was a unix sysadmin and network architect in the 80’s and 90’s, but migrated into tech pm roles, so my code skills are old and rusty.

I had assumed if I sat down with the code for a few hours at a time over a couple weekends I could find my way to change the keymap. I could not.

I enlisted the help of my housemate when I hit the end of my frustration tolerance. He’s a senior linux admin who writes IOS apps in his spare time for fun. We were able to get one of the extra LED patterns (heatmap) compiled into the firmware and loaded onto the keyboardio, but neither of us felt confident enough about the process to think we really understood what was happening, and I still couldn’t figure out where the keymap was, much less how to change it.

I’m still interested in making my changes and would be happy to guinea pig instructions when/if they are created. I would be more than happy to translate terse language into generally useable docs if someone is inclined to help me figure it out, but I’m giving up for now.

1 Like

Yikes. That’s no good.

If you were adding LED effects, you were likely editing Model01-Firmware.ino.


The keymap starts here:

If you’re up for describing in prose or a drawing how you want to change the keymap, I’d be happy to put together instructions for making the specific changes you want, which will likely be a reasonable start at a more general tutorial to help others.


Thanks! I think it will be more helpful in the long run for all concerned if you help me learn to fish rather than catching them for me. :slight_smile:

Ok, so looked at that region of the code more closely. These are the things I think I’ve puzzled out that weren’t previously apparent to me:

  • It appears that there are three layered keymaps that are defined: QWERTY, GENERIC_FN2, and NUMPAD. This is sensible.

  • I will take it on faith that there’s a reason GENERIC_FN2 gets used when “Key_Keymap1_Momentary” is held down in the QWERTY layout, and NUMPAD gets activated when “Key_ToggleNumlock” is toggled. Understanding how those are defined as the keys that activate the alternate layouts would be helpful, particularly if I wanted to add another layer myself.

  • In each keymap all keys are defined in a comma separated list starting at the upper left of the left section, scanning across each row, and then up to the upper left of the right section.

  • Keys not used in a keymap are still represented in the map as “___”

I am assuming that I can modify these maps by changing the order/locations of the key names, eg I could swap “Key_Backspace” and “Key_Spacebar” to get a layout that has Space on the left and Backspace on the right.

So I believe I have the basics of how to modify the keymap; I’ll try tomorrow, schedule willing. :slight_smile:

Things I don’t understand:

  • Why is numeral 7 called “Key_7” in “QWERTY” and “Key_Keypad7” in “NUMPAD” ?

  • How are the shifted characters defined? eg what makes “Key_Minus” represent “-” by default and “_” when one of the *Shift keys are pressed?

I strongly recommend creating a reference chart for what the key definitions mean. Some are obvious, but others, like “Key_LeftGui” are completely opaque.

Thanks again for your time helping me with this! I am happy to write docs once I understand myself. :slight_smile:


Because they are different keys, even if they end up resulting in the same symbol: Key_7 is the normal 7 key on a keyboard, Key_Keypad7 is the 7 on the numpad. The reason there are two keys for seemingly the same thing is how they behave with other modifiers present: Shift+Key_7 is typically &, while Shift+Key_Keypad7 is Home.

They aren’t defined in the keymap, this is something the operating system manages. What a shifted symbol will represent depends on what layout your operating system is configured to use. For example, Shift+4 is $ on US-QWERTY, but ! on HU-QWERTZ. Sadly we do not have complete control over this. There are workarounds and tricks to change this behaviour on the firmware side, but those are just that: workarounds.

___ represents “transparent” keys: when you press a key marked with this in the keymap, the firmware will look at all the layers below it, until it finds a non-transparent key. XXX marks a key as unused.

In other words, if on one layer you have a ___ key, and on the base layer, that key is - say - Key_A, when you press the key while on the layer, it will still result in A. If we’d mark it as XXX, it would result in no key being input. This is so that one can make partial layers. This is useful for a whole lot of things, which should be explained at some point (I’m lacking the time to do so now).

It looks like I’ll have some time this weekend, so I’ll try to put together a short intro guide, a kind of step-by-step thing, starting from the factory firmware.


Thanks! I appreciate the support!

I will repeat what I said to Jesse- I am happy to take terse statements and turn then into docs once I understand myself. Feel free to give me sketchy notes and I can turn them into a newbie primer. :slight_smile:



Understood. At the same time, I promised that remapping would be easyish. And since we don’t have the tools & docs in place to make it easy enough for everybody, I feel like I have some obligations there :wink:


‘GENERIC_FN2’ is a horrible name and a vestige of a time when we had a bunch more keymaps defined in the firmware.

Keymaps are numbered, starting from 0, in the order they’re defined here:

The numpad keymap is defined to be keymap #2 here:
We use that later to tell the numlock implementation what’s going on:

It might be better if the code could automatically figure that out somehow. Maybe.

A while back, the numpad layer code was a lot simpler, using Key_Keymap2 to switch to it, rather than the custom macro stuff. Seeing if we can get back to that some day is perhaps a topic for another thread.

@algernon - do you think it’d be plausible to move away from the custom code to toggle numlock? (Note that i’m not asking you to try to make the change, just whether you think it’s plausible :wink:

In most cases, you want Key_Keymap3 to change the active keymap to the next new keymap and “stay there” or Key_Keymap3_Momentary to change the active keymap just while the toggling key is held down.

Yes, though if you wanted the two hands worth of keys defined ‘side by side’, you can use KEYMAP instead of KEYMAP_STACKED. We used to do this. I think it looks nicer on a wide display, but it makes editing harder. is an example of this

By defining them as ___, those keys have the behavior they had before the layer was activated. In the case of Numlock, that means that most of the left hand will typically have its QWERTY behavior. This makes it a little easier to create overlay layers that change just a little bit of the keymap.

If, instead, you want to mask out the key in question, Key_NoKey or XXX will make the key a dead key on that layer

That is correct.

Yup. I think we can do that by adding comments to and letting Doxygen help us out.

(LeftGui is the HID spec name for the Windows key)

Awesome. Tell us how it goes. Keep asking lots of questions. Thank you for bearing with us and being friendly about it as you work your way through this. :slight_smile:

1 Like

It’s a custom macro-like thingy for a number of reasons, including the LED effect. Mostly the LED effect, actually. The code we had before had trouble restoring the previous effect, and couldn’t stack with it, and that ended up being more confusing than it needed to be. I don’t think it’s plausible to go back to just using Key_Keymap2, not without sacrificing something else.

Hm. I feel like with the changes we made to have the Numlock LEDs not let other modes ‘shine through’ on keys we’re not driving, there might be a way to just have the numlock LED plugin late in the plugin list and override any other LED state for display…maybe. I need to spend some time looking at the reworked LED APIs.

1 Like

That would work, if LED modes would stack - you could just override the former stuff. But they don’t, and only one can be active. So if we want NumLock to be just a LEDMode, we need to activate ourselves when numlock turns on, and deactivate when done. This is what the old code did, and it wasn’t reliable. I think it could be made more reliable, but then we’d just shift the magic elsewhere, and wouldn’t reduce it. The current solution is at least - in my opinion, anyway - a bit more explicit magic.

If it’s not a LED mode… well, then we have the current situation. We could simplify it, if we hardcoded the NumLock key position, or made it configurable instead of auto-detected. That would allow us to get rid of the macro stuff, perhaps…

Hmm… now that I’m thinking this through… the reason we use a macro is to be able to get the location of the numlock key, and the macro is what is most confusing. But we could also use an event loop hook, and catch numlock there. The downside of that is that it won’t work if any other plugin catches numlock before us (unlikely), and will only highlight one numlock key (having two is even more unlikely, so this is a reasonable compromise).

I’ll prep a patch =)

1 Like

I opened this window to post a success message, but discovered when I started typing that something was wrong. Here is what I tried:

jennifer$ diff Model01-Firmware.ino Model01-Firmware.ino.broken2
<     Key_LeftControl, Key_Backspace, Key_LeftGui, Key_LeftShift,         \
<                           Key_Keymap1_Momentary,     \
>     Key_LeftControl, Key_Keymap1_Momentary, Key_LeftGui, Key_LeftShift,         \
>                           Key_Backspace,     \
<     Key_RightShift, Key_LeftAlt, Key_Spacebar, Key_RightControl,                   \
<     Key_Keymap1_Momentary \
>     Key_RightShift, Key_LeftAlt, Key_Keymap1_Momentary, Key_RightControl,                   \
>     Key_Spacebar \

Basically I am not finding the thumb buttons comfortable to use a lot, so wanted to swap space and backspace for the fn palm keys.

Light testing suggested it was working, but when I started typing more it seemed like the keymap was offset, and changing with more or less every keypress.

Are the palm keys or “Key_Keymap1_Momentary” exceptional in some way, or did I muck something up?

Thanks for all your help!


I vote for keeping the LED magic. It helped a lot when I was first using the keyboard and hit NUM when reaching for ENTER, and the keyboard switched unexpectedly.

The magic we’re talking about getting rid of is the special macro and some of the visible code complexity. The actual LED effect isn’t being discarded. You’d asked about why the layer-switching code for Numlock and FN2 looked so different. And the rough answer is “it shouldn’t. we can make that easier to understand.”

1 Like

Ok.That’s just weird. The problem sounds like the keymap not having the right number of entries. The only thing I see off the top of my head is that you have a missing \ on line 74 in your new code. That /might/ be the cause.

There’s nothing inherently special about the Fn keys. The only key that has some extra specialness is Prog – it’s also hooked up to the main controller chip, but that’s neither here nor there.

If fixing the \ doesn’t repair things, I’d recommend starting with the default Model01-Firmware and doing something really trivial, like swapping the A and S keys. If that works, then back it out and

The “” at the end of 74 is there in the file, as is the one at the end of 81 that I accidentally deleted from the diff when formatting it above.

The A S key awsp worka juat fine!

Time for me to sign off for the evening, but I’ll keep poking at it tomorrow.

@Jennigma - Algernon points out that you might be running into issues with having changed the QWERTY map, but not the FN2 map to match it. That wouldn’t precisely match the symptoms you describe, but it’s worth checking.

Wondered about that.

My plan is to archive the problematic “Model01-Firmware.ino” file versions, wipe my entire repository and clone a clean one, and try again. This repo potentially has traces of my earlier blundering about, so I’d like to eliminate that factor from the equation.

If I can repro the issue on a clean install, then I’ll try re-mapping on both layers (or should I try making the relevant keys transparent?) If it’s still behaving badly when both are re-mapped then I can start characterizing exactly what is happening when the keyboard responses go wonky, and we can take it from there.

I wasn’t paying attention to exactly what triggered the behavior before; as I mentioned I tested enough to see that all four remapped keys were behaving as expected then opened a reply to you, but when I tried to start typing it became increasingly bizarre. It’s kind of a wild ride when it gets going; at first it’s odd alpha characters, but then it starts shifting window focus and opening menus and the like, so I think the function layer may be getting triggered somehow.

I actually have two versions of the file that produce the behavior. In the first I also commented out a bunch of the LED modes I didn’t like, and then when that worked I added the keymap changes. When it acted bizarre I saved off that file, made a copy of the original, and made only the key binding changes. The behavior was substantially similar.

I then made a third copy and made the A/S key binding swap, which worked normally. I typed with it active for a while and used the FN keys for arrowing around and some mouse events with no trouble. It’s now got the original loaded.


1 Like

Before you wipe the versions with the bad behavior, can you send a copy of one or both of 'em to I’d love to figure out what caused it so that we can try to bullet-proof the code to save others these kinds of headaches in the future.