Chrysalis - layout & keyboard settings editor

There’s no requirement for Keyboardio to use the cloud. Plugins for a bi-directional communication tool is an excellent idea.

I suggested IFTTT because it’s an obvious choice to integrate with as it’s something a lot of people are familiar with and gives an idea what could be done. If there’s better, more open alternatives to IFTTT, then I would like to hear about them.

A boring use case I can think of is a notification from a friend on a social media site, (maybe flashing a key matching the friend’s initial,) the Any Key turns green and clicking on it opens that app. Or another could be a notification of a failing build script and now the Any Key could open the log to the failing script.

1 Like

This should be possible, there already is a Keylogger plugin, just have to teach Chrysalis (likely via a plugin, too) to do something with that information.

The keyboard doesn’t even need to ask: Chrysalis can push it down when it starts up, and then all we have to do is make sure it starts with the OS. Kind of like an agent of some sort :slight_smile:

No need for a “spinner” theme then, either. Pushing down a LED effect is a couple of milliseconds, so your keyboard will just stay with LEDs off, until Chrysalis starts up.

The harder part of that is that currently the LED themes can’t tell the host their names, nor how they look - the former can be fixed with reasonable ease, the latter - not so. This means that if we want Chrysalis to preview built-in themes, we need to pretty much re-code them in it, too. Or at least provide a static image (this would be a reasonable compromise, in my opinion).

Oh dear.

** algernon rolls a saving throw* * - phew, crisis averted, I won’t be ranting about the 5Q!

The keyboard itself can’t connect to the internet, and there is no reasonable way to add that functionality. I don’t think anyone wants to, either. Chrysalis could act as a bridge, but by default, it will not. Anyone’s free to write a plugin to do that, of course, but you will never need to install it, if you don’t want to (I wouldn’t, either, except perhaps to prove a point).

5 Likes

To make a few things clear, here are some of my plans for Chrysalis:

  • I want it to be similar in spirit to Kaleidoscope (the firmware that powers the Model 01): a small, lean core, and a horde of plugins.
  • There will be very little that will need to be mandatory. So much so, that you will be able to disable everything, including bi-directional communication in the firmware, and use Chrysalis as a nice looking flashing application.

The plugins then, would add the bulk of the functionality:

  • Flash compiled firmware.
  • Build a firmware from sources (will need Arduino IDE installed, and a bit of configuration).
  • Provide a REPL (read-eval-print loop) for advanced users.
  • A keyboard layout editor & uploader (to be stored in EEPROM).
  • LED effect editor. With previews & whatnot.
  • One to tell the keyboard the OS of the host, so it doesn’t have to guess.
  • Tell the keyboard the active program, so it can switch layers, or do something else.
4 Likes

I could live with that for built-in themes. :slight_smile:
Or, for extra credit, they could be APNGs so the user can get a sense of what a given theme does… :stuck_out_tongue:

1 Like

Over the weekend, while finishing up the current Diablo3 season (using a Shortcut prototype, powered by Kaleidoscope; of course), my unconscious spent some time thinking about Chrysalis and its architecture, while the rest of my brain conveniently switched off while hunting demons. While I will present a number of ideas here, unfortunately, there will be no pictures, no mockups, or anything like that, so we’ll have to use our imagination. And I hope I can describe the ideas good enough to be imaginable. Mind you, some details may end up being a bit technical, this is pretty much an unedited brain dump now.

Starting up

So, we want to support different hardware with the application, so it should try to discover the device as soon as possible: it would scan the USB devices, and if it sees something it recognises, it would try to connect to it via Serial, and issue a version command to figure out the details. For the time being, until we figure out a way to do plugins, this would be built into the application, just like it all started with Kaleidoscope, too. If it finds no device, it would present a way to manually select one.

Home screen

Once we have a device, it’s time to load up the starting screen! Up until now, the user was presented with a logo, and a progress bar. With the starting screen, we’d still have the logo, the keyboard manufacturer + product under it, and then a set of boxes with which we can reach the various functions of the application. When selecting one of the functions, a new screen loads. Each of these would have a little Home (or Back) icon in the top left corner, to allow navigating back to the starting screen. I think this is a better approach than the permanent sidebar, that takes up a considerable amount of space, yet, it is unlikely to see frequent use.

Layout editor

One of the most used parts, and the first one we will likely develop, is the layout editor. The latest backer update showed a preview of it:

https://ksr-ugc.imgix.net/assets/015/983/708/3bb9653e3006795de1e20bb1d49c9fb5_original.gif?w=639&fit=max&v=1490319942&auto=format&gif-q=50&q=92&s=ffd901a100c8ffce0122a08e166db518

You basically click around, or otherwise navigate the keyboard, and once you found a key you want to replace, click it. Then you are presented with a menu - either a popup, or one in a fixed place on the right - where you can configure that particular key. What I’m not sure about, is how we can discover features of the firmware? Like, if one-shots are not compiled in, we likely should not present those as possible key actions, either. I was thinking, that we could have a Features plugin (or bake this into Kaleidoscope-Ranges, which sort of does something related), which would keep a set of flags, whether a particular plugin is enabled or not. Plugins could then poke their flag on when they are included and used, and Chrysalis could ask the keyboard for a list of features, and get a bit mask, which it can then translate back to actual features. This would not take much space on the keyboard, and still be reasonably useful. The downside is that we have a central registry of features now, and both the firmware-side list, and Chrysalis must be in sync for this to be useful. But then, we already have something like that with Kaleidoscope-Ranges (not going into detail what that plugin is for, feel free to ask me if you are curious).

Profiles and devices

For different keyboards, a different layout would load, and they’d be saved in different “profiles”. Question is, how do we figure out the configuration on the device? As in, if you have two Model 01s, plug one in, configure it, then unplug it and plug in the other, how will Chrysalis know it is not the same device? We could hash the EEPROM contents, I suppose. Every unconfigured keyboard would look the same then, but once you configure one, that one would be different.

And this leads to a next issue: what if multiple Kaleidoscope-powered devices are plugged in at the same time? I do that all the time: both the Model 01 and the Shortcut are plugged in. We’ll need a device chooser, I suppose. Could reuse it in the initial discovery too, when no device, or multiple devices are found.

Layout editor, take two

But, back to the layout editor! When you configure an action, it would internally store it in a structured fashion, one that is easy to work with, to export, and so on. In a format independent of the codes used under the hood. When applying the layout, Chrysalis would do so via a shared “compiler” that translates its internal format to keycodes Kaleidoscope works with. We’ll have to come up with an extensible internal representation. Doing the compiling/transformation afterwards is a walk in the park in comparison.

LED theme editor

The LED theme editor would look somewhat similar to the layout editor, except we’d have a permanent palette on the right (itself editable, of course). You click a color, then click all the keys you want to apply that color to, and done. Repeat until you have a theme you like. In the future, we may want to allow selecting a group of keys to apply colors to. But perhaps not in the initial version.

Below the palette, would be the color chooser: the selected color could be altered by selecting a different one from the chooser.

Firmware flasher

Now, this is simple. Select file, hit upload, wait, done. I don’t think we need more than that?

REPL

This is something I want to have a lot of polish too, because I will use this the most. What I have in mind, is not only a very dumb thing that I can use to send and receive data to the keyboard, by speaking its low-level protocol (though that should be an option too!), but something higher level.

It would turn the keymap.map dump (which is a series of 16-bit integers) into a proper layout, one that looks the same as if it were on the layout editor. Even better, if it could load up, and embed the editor, that would be best.

Same goes for the colormap and the palette, and possibly other things too: Chrysalis should apply as much formatting and presentation, as is needed to represent a particular thing to the user.

However, this will only work well, if we have a reasonably modular architecture, so initially, the REPL may do some formatting, but it will not embed any other parts of the application yet.

Closing thoughts

This is all I had in mind for now. In the next few days, I’ll try to come up with a few mockups, to see if those help. Other than that, I think that pondering about the plugin architecture at this point is not necessary. It would take too much time and effort to do so, and shipping something is more important. We can - and will - rewrite parts when necessary. I did that with Kaleidoscope plugins, some of them have been rewritten more than three times. While it feels sad, and perhaps a waste to do that, these things are small enough to be rewritten in a week or so. I hope Chrysalis will end up similarly.

6 Likes

@algernon,

Appreciate the raw brain dump. Very nicely done. A few of my thoughts:

Layout Editor: How many different layouts can we save? Or none?

Profiles and Devices: Good thinking about plugging in multiple M01s.

LED Theme Editor: Will we have color palettes only? Or a field(s) for RGB/hex? Will there be a mechanism to save a theme and be able to choose a specific one later? Switching? Like say, normal usage/coding/specific game - D3, etc.

Firmware Flasher: Progress bar would be a nice to have (since I’m impatient). Can we have it write to a log file as well? or onscreen diags in verbose, if writing to stdout, then I can live w/o a progress bar.

Great work…

And thanks.

2 Likes

Hey @fishheadsoup, I’m working on the UI side of Chrysalis. It will feature means to import and export layouts as text-files, so you could save as many as you want that way. Having a default folder for layout-files loaded automatically and accessible via a dropdown menu or the like shouldn’t be a problem and is likely a good idea. Does that make sense?

2 Likes

Layouts: one to the keyboard (with limited number of layers, due to EEPROM being only 1k), as many as you like on the host. As @Simon-Claudius said, import/export is something we plan to do, and could be used here too. Or we could just save the extra layouts in the same profile file we save everything else in, and offer a way in the UI to select which one to put on the keyboard.

The palette is necessary, otherwise the theme would not fit in EEPROM, not together with the keymap. For RGB, it would be 3 bytes per color. With a palette, at most one. If we went with RGB, a theme would need 192 bytes, which is one and a half layer. Waaay too much. Right now, it only needs 64 (half a layer), and I’ll be cutting that back to 32 soonish. Plus the palette, of course, because that IS editable.

If there is enough demand, it’s easy to write a plugin for Kaleidoscope that allows using more colors, or even full RGB, at the cost of less layers. Supporting that in Chrysalis should be easy too. But this is not something I plan to do just yet.

The progress bar will depend on the library we use for flashing. If that can provide callbacks we can use to display a progress bar, then yeah, we’ll display one. Otherwise a hourglass or some other indication of work being done will surely be used.

1 Like

One idea I’ve had is using Chrysalis as an aid for learning new layouts.

It could work like this:

  1. I forget a key and hit a few trying to find it,
  2. Give up and press the ‘forgotten key’ key,
  3. That foregrounds Chrysalis with the current layout selected.
  4. Use the ‘train new key’ plugin that invents a key sequence I have to type a few times to background Chrysalis
4 Likes

@algernon: What are we going to call a set of device-specific features, i.e. home screen branding, layout editor GUI, etc?

Not quite sure. In Kaleidoscope, most of these are the Kaleidoscope-Hardware-* plugins. If the homepage, layout editor, etc, could be made so that there is no hardware knowledge hardwired in, but expects a “Hardware” plugin to supply those, that would be grand.

Something like, have a Device singleton object, which the plugins would implicitly depend upon. The object would be supplied by the hardware plugin, and that one would ship the SVGs, home-page branding, and so on. Coupling would be a little tight, because the hardware plugin will have to explicitly support the other plugins. Not sure if that’s the best idea, but it’s the best I see right now.

In the short term, we’ll just hardcode Device to mean the Model01.

Does this sound sane to you?

1 Like

Ideally I’d be able to maintain a branch or fork for the shortcut without too much modification. So happy with hard coding as long as it’s all in one place.

As I’m also working on Shortcut keyboard support I’ve been thinking about this in particular: I mentioned different “distributions” of Chrysalis at some point, e.g. one for the Model 01, one for the Shortcut, etc. that companies/organisations/maintainers would provide in their own fork.

Thinking about it seems neater to have one version that supports all devices and just applies the correct branding and hardware-specific features as the device is detected/selected. This way interested parties would have the option to send us pull requests with their hardware integrations and their hardware would be supported going forward and maintenance requirements for them and us would be kept minimal.

Considering that we’re aiming for a modular structure I think that downloading things as required would be a potential extension of this (similar to what text editors like emacs, Sublime Text and Atom do), i.e. only download/install what’s required.

If this is something that makes sense for us, moving to a hardware-agnostic structure without hardcoding as early as possible would be sensible.

I definitely want to go the route where one distribution can support many devices, because I expect there will be users who have multiple devices running Kaleidoscope, and installing N variants of the same app would be a pain in the backside.

So, yeah - moving the hardware-specific bits to its own place early on is something worth pursuing. The initial device detector could then load the appropriate plugins, and do the dance necessary to set up the Device singleton for the rest of the application.

Initially, the hardware bits could live in the same repo, too, if @matt & @Simon-Claudius find that easier to work with.

2 Likes

Wouldn’t that be the general idea going forward, anyway? Or would you want to split it up somehow?

I’d split it up, like we did with Kaleidoscope too, because that makes it easier to introduce and maintain a new device easier: you don’t have to get the code merged anywhere, which makes it easier to do faster iterations in the beginning, while still not inconveniencing users.

For example, lets say I want to add support for a custom keyboard, nicknamed Twins (for no particular reason at all, no, definitely no reason). This is a custom keyboard no-one else has, and no-one is likely to build one either, let alone mass-produce. For Kaleidoscope, this means I’ll create a Kaleidoscope-Hardware-Twins plugin, that contains the necessary bits. I don’t have to merge it into any master repo, and I can use stubs from day one, for parts that are not implemented yet. It’s convenient to develop, straightforward to work with, and so on. There is also no reason this should be merged anywhere, because this is a one-of-a-kind thing.

Obviously, I’d want Chrysalis to support this keyboard too. For similar reasons (being a one-of-a-kind keyboard), having explicit support for it in the main repo does not make much sense. No-one but me can test it, no-one else is interested in maintaining it. It would just be a burden for everyone else to carry mostly unused code around.

This is why pushing hardware stuff to plugins is sweet. Makes it easier to add and maintain device support. From a user perspective, initially, this may mean some extra work of installing the plugins (though we can do what we for Kaleidoscope with the Arduino-Boards repo, and include some of the hardware bits in a collection of “recommended default set of available plugins”), but later on, we can move towards a way to install plugins on-demand. Along with their dependencies, and so on. (That would be useful for Kaleidoscope too, by the way.)

I hope the intent is clear from this description :slight_smile:

2 Likes

Great. The end goal of this is pretty much what I’d consider idea.

Hey @fishheadsoup, I’m working on the UI side of Chrysalis. It will feature means to import and export layouts as text-files, so you could save as many as you want that way. Having a default folder for layout-files loaded automatically and accessible via a dropdown menu or the like shouldn’t be a problem and is likely a good idea. Does that make sense?

perfect. works for me. thanks.

It could work like this:

I forget a key and hit a few trying to find it,
Give up and press the ‘forgotten key’ key,
That foregrounds Chrysalis with the current layout selected.
Use the ‘train new key’ plugin that invents a key sequence I have to type a few times to background Chrysalis

This is a slick idea.

A short update, until I sum things up in a blog post: a lot of things have been happening around Chrysalis, it can go as far as detecting any number of Kaleidoscope-powered devices, connect to any of them (only one at a time, a limitation that will remain for the foreseeable future), and issue custom commands. This may not seem much, but this is the foundation we can build the rest on. And it is looking sweet.

There are also plans to ship the Chrysalis plugins together with the respective Kaleidoscope plugin, which makes it easier to keep them in sync, provide assets, and so on and so forth.

And while talking plugins: while Chrysalis is not yet set up to use plugins in a convenient way, we can - technically - split plugins out by turning them into NodeJS packages, and adding them as dependencies for Chrysalis. This is what I’ll be going with in the short term, until we figure out a better way. But the plugins being NodeJS packages is something that’ll likely remain so.

In short: lots of low-level, architectural work has been done on Chrysalis in the past week, and we are making very good progress. There is a reasonable chance that we’ll have something usable by the time PVTs ship.

Mind you, the factory firmware will likely not come with all the plugins required for Chrysalis compiled in, so we’ll ship Chrysalis with a custom firmware HEX you can flash on the keyboard. That firmware will behave exactly as the factory one, but will have a number of other plugins enabled. Okay, there may be less LED effects, we’ll see how big it will grow. The goal here is that once you unbox your Model 01, you download Chrysalis, hit a button, hold your PROG key, and have a new firmware flashed. And from that point on, you can use all of Chrysalis’ features.

4 Likes