What do people want from the firmware?

Hehe. Well, it’s a keyboard. Under normal circumstances, you don’t need much memory on it. The ErgoDox EZ, and most other ErgoDoxes except for the Infinity, use a Teensy2.0, which has the same amount of memory. It’s not uncommon to have very little RAM in these.

But even if it would have more memory, there would be some hairy obstacles to cross before a per-layer/per-modifier heatmap could be made fully within the firmware: in general, you don’t want to allocate memory at run-time, because that’s costy (in terms of RAM needed for bookkeeping). So you’d have to preallocate enough to hold all the data. Even if you don’t use that many layers, or all eight modifiers. That’d be terribly wasteful…

Yes, it is. It emulates an USB keyboard, an USB mouse, and an USB serial device. The logs are sent on the USB serial device.

I can add the keycode to be sent to the log too, that way you may not need to recreate the layout for the analyzer. But yes, there are things that you may need to do twice, but when you change the layout, there is little to change in the analyzer: just update the layout there, too. I’ve been doing that with my heatmap generator tool, and all I need to do, is update my layout on KLE, and update the JSON for the heatmap generator. No other change necessary. And I do that update anyway, so I can print a new cheatsheet :stuck_out_tongue:

My personal experience is that having a good heatmap is an incredible asset, and writing the log parser & analyzer was well worth it. I’ll likely write something similar for the Model 01 too.

2 Likes

I just implemented this. Usage is - I hope - reasonably simple too. This last example is the symbol replacement for my number row.

2 Likes

Something to check: If some keys are configured to be shift-inverted and others are not, the user might hold down shift and type a series of keys. Typing an inverted key should not result in the following non-inverted key being unshifted, et cetera…

Yep, this is something I’m still pondering about how to do neatly. The thing I have now can only replace the shifted symbol, it does not do any shift inversion. I plan to do that separately, but making the two work nicely together is non-trivial. I’m pretty sure its doable to compose the two, I just have to find a way how.

1 Like

Also to keep in mind: One might want to configure a key with two shifted or two unshifted characters. As an example, suppose I was completely insane, and wanted all the capital letters on my left hand, and lowercase on my right hand…

From the discussion on Firmware and Booting, Jesse gave this description:

If I understand correctly, this means that the host polls the keyboard to get information on which keys are currently pressed. Or which keys have been pressed and released since the last poll? So when I press a key, the keyboard registers that key as pressed, and clears that state when it’s polled again, unless the key is still pressed. And after a key is released, the next poll generates a key release event?

That does make things trickier than if the keyboard simply sent interrupts to the host, doesn’t it? Especially for shift-inverted keys with chorded, one-shot, and sticky modifiers (just shift really) that all need to work properly.

Or have I misunderstood how it all works? I haven’t had time to look at much of the code yet.

My understanding is that the keyboard sends reports, of the current state of keys. It will not send a diff, it always sends a complete state. That makes things a lot simpler, because all the logic of how to update that state can reside in the keyboard firmware. Additionally, judging by how QMK appears to work, and what I saw in the KeyboardioFirmware code, the device itself can send a report (or queue a report, I don’t know, but it doesn’t matter much in this case) too.

For one-shots, this whole thing means that when a one-shot modifier is activated, the code will keep adding the modifier to the report, until it times out, or gets cancelled. Then it simply won’t add it anymore. This means that the modifier will appear held as long as one-shot is active, no interruptions. Same for sticky shift: the firmware will make sure the report has the modifier set.

Normal shift Just Works™, because as long as you keep pressing it, the firmware will set it in the report.

For shift-inverted, if it needs to send a code without shift pressed, it will clear shift from the report, add the code, send a report, and re-register shift if need be. For shift-needing codes, it will register shift, and the code, send a report, and un-register shift if need be. This may have some side effects, when you are holding other keys, because the report is not cleared inbetween, so the shift will appear interrupted to the host. But I expect that to be a rare case, and if it ever comes up, we’ll figure something out to make it less annoying. Worst case is an OS-side layout… in this case, that is considerably more reliable.

1 Like

Since almost all keyboards use a scan matrix they in fact don’t know the state of any key at a given time but they will scan each row/column at a certain frequency and update a “table” which is then sent to the computer.

For more information see the following doc which is a pretty good introduction to the workings of keyboards:

4 Likes

Yes, of course. If I’m holding down shift and two other keys, only one of which is inverted, there’s no way for the keyboard to send the desired data (assuming I did it on purpose) unless the host OS is configured to do the shift-inversion itself.

I would happily live with that pseudo-bugginess, as it shouldn’t affect normal typing except in some very rare cases, which I would guess will come up orders of magnitude less often than regular human-error typos.

If I decide I want to use my Model 01 as a game controller, though, I’d want to switch it to a different mode without any shift-inversion. But I’d want a completely different keymap in that case, regardless.

I want to be clear that this isn’t a design decision we made. This is just how USB devices work.

2 Likes

Oh, yes, of course! The inconvenient legacy of nineteenth-century typewriters runs very deep, doesn’t it?

Over the past few days, I’ve had something in the back of my mind: application- and window-switching. I frequently switch between Linux (Alt+Tab) and MacOS (Command+Tab). It’s not so terrible having to do that context switch in my head, but I’d like the keyboard to do it for me. I’ve already got plans to have separate Linux & Mac modes in order to get consistent cut/copy/paste/undo keys, but the application switcher is more complicated, because holding down the modifier and tapping Tab twice doesn’t give the same result as if one releases the modifier in between presses. I want to be able to hold down the palm key and tap a “next app” key to get the same behavior as I’m used to, but I think this requires more than anything we’ve already discussed.

I think the behavior I want is for a key (on some layer) to set e.g. “mod-down”, then “tab-down”, then “tab-up” (when released), but leave the modifier registered, and only clear it when that layer is switched off, or until some other (particular) key is pressed to clear that state (perhaps a “clear all sticky modifiers” function — for that matter, I’d also like a “clear all sticky (non-base) layers” function). Note that it’s got to stay registered for other subsequent keypresses, such as arrow keys on MacOS.

I’d also like to map a other keys to provide the “previous app/window” functions (i.e. Alt+Shift+Tab).

Hmm. This doesn’t sound too hard, and sounds entirely doable with macros! So all we need, is the macro, which may look something like this:

This creates two macros, one that does the Alt+Tab stuff, and the other that cancels the Alt. Bind these to whatever keys you like. This doesn’t have the Linux/MacOS logic yet, but that’s fairly easy to add later. I’ll use something like this as an example for my plugin library. Thanks!

I have a “clear all one-shot mods” function, but will add one for sticky mods too.

This is in the works too. As in, a pull request exists, I just need to iron out a few bugs.

Just hold shift at the same time as the macro keys outlined above? :slight_smile:

1 Like

@algernon is awesome.

What would work best for me would be a “clear all mods”, regardless of one-shot or sticky status. I can’t think of any situation where I’d want to separate the two.

That would work, but I actually want to try having separate keys, one for left and one for right. I’m sure the implementation is simple for this part.

All my ideas are already listed ! Well done, y’all.

Not sure if that’s firmware-relevant, but a way for the keyboard to receive innocuous instructions from third party programs, such as “light this LED”. To make games (such as keyboard hero), or to be able to script LED lighting in the language of my choosing.

Also, when typing unicode characters with Fn+u, a form of LED-oriented suggestion, lighting up the only characters that make sense given what I started to type. Might be pretty hard, and unbearably slow, but hey, you said no limits !

3 Likes

This is in the planning stage, at the moment, we are thinking of a textual protocol one can use over USB Serial, for bidirectional communication between keyboard and host.

This is a good idea, thanks!

I’ve read the whole thread and I’m not entirely sure this has been covered, but I’d like some basic hardware text expansion. e.g. when I type ;m;ph, they keyboard would type my phone number; when I type ;m;em, it would type my main email address, and so on. I’m not entirely sure whether this is feasible, but it would be neat.

2 Likes

That’ll be doable with a leader key + macro combo, except that instead of ;m, you’d press the leader key, and then type ph or em. Is that good enough for you, or you’d want to stick with ;m? That’s possible too, but a bit harder. I will be able to provide some example code to do that, but not sure if it is worth putting it into a plugin.

With ;m, the keyboard would have to delay inputting both symbols until it is certain it will not be part of the text expansion (or delete back, and that’s not the most reliable thing). With a leader key, it has to do a lot less magic, and the experience is considerably better, in my opinion.

1 Like

The ;m was just an example. I didn’t explain properly. What I meant was that text expands automatically after a user defined macro (without leader key). However, that would imply constant keylogging, which probably isn’t a good idea. However, I think the leader key + macro combo solution you outlined is great and a perfectly fine replacement for what I described. In fact, I think it’s superior for a number of reasons. It’s certainly going to be more robust across systems.

3 Likes

It may be interesting to some people here, who don’t follow me on twitter, that I finally finished a long blog post about what I’ve been up to recently, with regards to the KeyboardioFirmware and Akela projects.

The post also contains the code for a LED effect yet unseen, and for a set of powerful macros (thanks @merlin for the idea!), to show how easy it is to extend the firmware, and how sharing code can be made easy too.

6 Likes