What do people want from the firmware?

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:

https://www.massdrop.com/article/introduction-to-keyboard-programming

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:

https://gist.github.com/algernon/3a71d8de3e7184fb0827fa360207dc44

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

@algernon, I’ve got a question about Akela dual-use modifiers. I’ve been toying with the idea of setting up a keyboard with the home row keys set up as the eight usual modifiers (when chorded), and I’m wondering if you’d consider that to be a terrible idea because of timing issues for a fast typist (which I’m not, but I’m asking hypothetically here). A quick glance at the code doesn’t tell me how the timer works – is it necessary to hold the key down for a minimum period in order to trigger the modifier?

Obviously, I’m thinking about this backwards; it seems that you were thinking, “I could make those modifier keys do something else, too”, whereas I’m pondering using letter keys as modifiers if held. Suppose I’ve got L set to be RControl when chorded, and S is likewise LControl – would you expect any problems to arise typing RControl + S? Would that be any different if both keys were set up to be LControl (possibly clearing the modifier despite holding down a different key mapped to the same modifier? The code is too opaque for me without spending significant time reading and understanding it all, so I thought I’d just ask directly.

2 Likes