Juicy technical updates from the engineers at Input Club.
by Input Club
Here at Input Club we tend to do a lot more than what gets publicized in our product and Kickstarter updates. And while all our code and designs are opensource and up on GitHub it can be overwhelming (even for engineers!) to figure out what we’ve actually been working on. So the engineering team here at Input Club is going to start publishing monthly updates on what we’ve been working on!
First off, introductions of the team are in order.
Before turning this into a biography, let’s just say HaaTa has too many projects . He works on a bit of everything at Input Club. Inventor of KLL, main firmware engineer for Input Club, keyboard collector, measurer of force curves, Hako/Halo switch inventor and designer of keyboards at Input Club. He’s been in the keyboard community since 2009 and is always excited to talk about keyboards.
At Input Club, Parak is responsible for PCB design and all-around KiCad wizard. He keeps PCB fabs on their toes with his stringent manufacturing checklist (we’ve qualified a lot more pcb fabs than we’d care to admit here at Input Club ). Parak, the ebay master responsible for most of HaaTa’s keyboard collection, is a proficient collector in tools of great quality (such as IBM keyboards) in his own right.
Ever wonder how Input Club makes their simple, but beautiful, cases. By going Over^Kill, that’s how . Over^Kill deftly designs the cases, not just to look good (as an engineer), but designed to be manufactured to keep the quality high and the failures low (because he’s a manufacturing wizard). Lately he’s been really into using IronCAD. Over^Kill also helped turn HaaTa’s proposed force curve in the final Hako and Halo switches.
Master of the configurator and all things related to the web, jbondeson is a connoisseur of keycaps. He has all sorts of cool things planned out for the desktop configurator all in the name of R, G and B. In his quest for quality, he rewrites code about just as much as HaaTa does .
While the most recent addition to the Input Club team, smasher816 has been helping out since before the Infinity 60% first shipped out in 2015 . Proficient in both PCB and firmware design.
Next up, git repos! Open Source is very important to Input Club . It likens back to a day where you got a service manual with your keyboard (1970s IBM) and you could just lookup the part that was not working correctly. Or better yet, figure out how to build your own!
Unless otherwise specified, we use GPLv3 for software and the CERN OHL v1.2 for things we work on. Or if we’re contributing back to another project, we maintain that license (and usually try to upstream changes).
All the Input Club git repos can be found on GitHub.
The controller git repo contains all the code that goes onto the keyboard as firmware. For those that are not familiar, firmware is compiled software that is stored on a non-volatile device (like inside a keyboard’s flash storage). This repo contains both the driver code for various keyboard MCUs (microcontrollers) as well as the implementation of KLL. This is the repo you should be watching if you’re interested in new keyboard features and bug-fixes.
The code here is mainly written in C with a CMake build system.
Both Travis-CI and Appveyor are used to make sure the firmware can be compiled for Windows (Cygwin/Bash), Linux and macOS. The recommended way to compile the firmware manually is through Docker.
TMK (where QMK was derived from late 2014) was started back in 2010 by hasu and the kiibohd controller firmware, by HaaTa, early 2011. Both were designed as protocol converters, and both started with the PJRC Teensy 2.0. Soarer, hasu and dfj all conspired on the GeekHack IRC channel (#geekhack@irc.freenode.net) to develop what we know today as USB NKRO that works across Windows, Linux and macOS.
Soarer developed his own protocol converter for XT/AT/PS2/Terminal keyboards to USB (using a Teensy 2.0 or 2.0++). dfj, while not well known, developed one of the first custom Model F capacitive sense controllers a couple years before xwhatsit. You can find the schematic for one of the later versions of the capsense controller on our GitHub (was originally hosted on Gitorious which closed) which was named DPH for dfj, parak and HaaTa.
The Input Club Infinity 60%, which shipped in early 2015, was likely the first production keyboard to support USB NKRO on Windows, Linux and macOS out of the box with no extra drivers or configuration necessary .
The Infinity Ergodox interconnect runs at 4.5 megabaud. With a symbol size of 8 bits, that would put the link at a 562 500 Hz polling rate . USB 2.0 FS is only polls for new data at 1000 Hz and even USB 3.1 Gen 2 at 8000 Hz . For reference, a standard USB 2.0 LS keyboard only polls data at 125 Hz .
Work on the K-Type started (at least the KLL portion) started even before the Infinity 60% launched (just a few days prior) back in October 2014 while HaaTa was flying to Japan (to go drinking with hasu again ).
While the firmware was originally based on the Teensy 2.0 and 3.0 codebases the original schematics and bootloader were forked from the McHCK project.
The K-Type animations run at 100 fps. The original goal was 30 fps . Both the WhiteFox and Infinity Ergodox hardware also support 100 fps animations.
The LEDs in any Input Club keyboard will not turn on until USB has been fully negotiated. This means if the LEDs turn on, the firmware is doing something .
This repo contains the KLL compiler source code.
KLL is the DSL that HaaTa wrote to define keyboard functionality in a distinct and widely compatible way.
It uses a powerful Trigger:Result
mapping idiom design to smoothly compile down into code that can be compiled for a microcontroller.
The compiler is written in Python and is based on funcparserlib.
The KLL compiler supports multiple emitters, so while it currently supports kiibohd, KLL (yes it can regenerate back to a KLL file) and none (syntax checking), it is possible to add KLL support to other keyboard firmwares just by adding a new emitter.
Travis-CI is used to test the KLL compiler against a variety of Python 3 versions.
The KLL compiler supports multiple emitters. Therefore it’s possible to add KLL support to other keyboard firmwares or anything that supports key mapping.
For the K-Type (and LED support) the KLL compiler was entirely rewritten as a multi-staged parsing compiler. Parsing rules first determine what kind of expression before extracting detailed information. This makes it much easier to write parsing rules and not break unrelated rules.
The Python funcparserlib parsing expressions resemble xBNF grammars.
The KLL compiler was started in the summer of 2014 while the KLL spec has origins all the way back to 2011 .
The kll-spec repo contains the KLL spec (written in LaTex). If you’re interested in seriously understanding KLL you’ll definitely want to read the spec. So far only 0.3d is fully implemented; however, much of 0.5 has been added (i.e. LED support). The major feature left to implement in KLL 0.5 is state-scheduling (e.g. tap-keys, short/long presses).
Overleaf was used to compile/maintain the docs in the past. Unfortunately there have been some issues lately so all compilation hosting is done on GitHub now (using Travis-CI).
KLL (0.2c) was first unveiled at the 7th Kiibohd Bay Area keyboard meetup (in San Francisco) on May 31st, 2014, hosted by keyboard.io. The KLL spec already had provisions for analog keyboards.
No compiler was made for KLL 0.2 and lower.
This is the awesome desktop app that jbondeson has been working on. It was designed to handle both layout mapping as well as LED configuration for you keyboard. Rather than attempting to bundle a compilation environment, the configurator uses a KiiConf server to handle firmware generation.
Written mainly in Clojure.
Both Travis-CI and Appveyor are used to automate the release generation. All of the releases (including release notes) can be found on GitHub.
Originally started by matt3o for the WhiteFox keyboard, KiiConf is the web-based configuration utility for our keyboards. Using your configuration it generates a KLL file. Which the configurator backend then uses to generate a firmware bundle.
Written mainly in JavaScript but also contains quite a bit of PHP and Shell code as well.
Travis-CI is used, in combination with docker, to make sure releases keep on working!
This is a relatively new repo forked from libwdi by smasher816. It contains the code for the upcoming automated Zadig driver installation (no more messing with Zadig!).
Appveyor is used to generated automated builds.
Do remember that for drivers Win32 vs. x64 really does matter.
The cases of Input Club are designed by Over^Kill using IronCAD. We generally opensource (CERN OHL) the design around 30 days (usually because we’re really busy trying to ship the keyboard, haha) after the first units of a design ships. There are a few reasons for this, though the most important is to make sure we release files that are the same as what ships.
The files can be opened using any 3d model/cad program that can work with .step files (e.g. FreeCAD).
Input Club’s pcb are designed by Parak using KiCad. We opensource (CERN OHL) the schematic, layout, BOM (bill of materials) as well as the gerbers used to manufacture the pcbs. These are generally released around the same time as the case. Historically we generally revise the pcb between runs more often than the case.
KiCad can be used to view the schematics, layout and gerbers (though we recommend gerbv on Windows and Linux for viewing gerbers).
A small fork of dfu-util to maintain a macOS binary release of dfu-util.
Written in C.
Uses Travis-CI to publish releases.
This is the old Windows GUI front-end for dfu-util. It has been long deprecated, please use the configurator instead. While it also works for macOS and Linux it is tricky to package correctly for all distributions.
This repository contains both some scripts used in keyboard manufacturing (bootloader flashing) as well as a detailed wiki on the tools and processes needed to flash and validate shipping keyboards. The wiki also has details on how to build a bootloader flashing adapter which is useful if you’re trying to manufacture your own pcb.
If you’re interested in how we manufacture keyboards, definitely reach out to HaaTa on Discord.
A fork of the McHCK SWD flashing utility for the BusPirate. Contains some small updates for the Kinetis mk20dx256vlh7 MCU as well as some additional debugging used in manufacturing.
This isn’t needed unless you’re looking at flashing the bootloader on your keyboard with a BusPirate in SWD mode. Also, don’t worry, you don’t need a bootloader update (you’re not missing out on any keyboard features).
Written in Ruby.
This is a small fork of OpenOCD which contains patches for using openocd with a BusPirate and the SWD protocol. The BusPirate and OpenOCD are used in manufacturing, though we use JTAG if possible (same cable, much faster but is not supported by all MCUs).
While not particularly useful for most of you, this repo contains the firmware source as well as algorithms used for HaaTa’s force gauge.
It also contains the code which publishes the graph data onto Plotly.
Written mainly in C (firmware) and Python (algorithms and web interaction).
This is a relatively new repository fork. BOSSA is a tool used to flash MCUs with the SAM-BA integrated bootloader which will be used for manufacturing of SAM4S keyboards. It has GUI and command line releases for Windows, Linux and macOS.
Written mainly in C++.
The latest version of the configurator (it’s auto-updating! ) can always be found on GitHub. Our most recent release is v0.4.1.
The configurator is comprised of two parts, the UI (the configurator download) and the KiiConf server (which handles generating the firmware image). We update these two pieces separately as we qualify stable firmware for the configurator rather than just releasing the latest (and possibly unstable) firmware.
Manufacturing before Chinese Lunar New Year has put a damper on configurator development, but it should start to ramp-up again soon. The next two new features to help simplify firmware downloading.
The first would be, auto-downloading of dfu-util binaries. Not all computers have a working version of dfu-util available so if the configurator can’t find one on the system the configurator will download a known working dfu-util for your system. This is particularly helpful for both Windows and macOS.
The second is automating the Zadig driver installation. Using the new kiidrv project by smasher816, we can automatically determine whether you need to install the Zadig driver and handle it for you. No more accidentally installing the driver on the wrong interfaces!
We’ve been hard at work on the keyboard firmware since the K-Type launched working on bugs and adding new features.
One of the major improvements to the firmware was moving from a single execution loop to two concurrent threads. Prior to the K-Type, the only heavy lifting the MCU had to do was scan keys, send updates to USB and occasionally update some peripherals (e.g. LCD screen, change LED brightness, etc.). However, to fully utilize the RGB’ness of the K-Type a high frame rate required using the majority of the CPU time servicing animations…instead of scanning for keypresses.
After thinking about the problem for a while, HaaTa decided to rewrite a large portion of the firmware and split execution into two different paths. You can think of it as two different threads: one that runs consistently and reliably for key scanning and the other as fast as it can to deal with animations. Periodic and polling, respectively.
To prevent flickering, each LED frame must be serviced as quickly as possible. Which means you need to spend as little time away from the LED processing as possible. And, instead of scanning all the keys, then processing all the LEDs, just process one strobe (matrix column) of keys at a time. Then process one frame of LEDs, then onto the next strobe.
For those that are curious, the periodic
cli command will let you adjust, in real time, how many cycles to wait between periodic scans.
Work has been done to fix issues with KLL macros as well as some offset errors which were causing some keyboards to reset (yep, off by 1 bug). These were all fixed using the new the Self-Testing KLL build feature.
The other large project going on right now is preparing the firmware for Kira. This will be the first keyboard design since 2015 to use a new MCU! More SRAM for code, more flash for animations, more Hz for spamming USB packets over the interwebs. All-in-all, just better. However, we’re moving away from NXP’s (originally Freescale’s) Kinetis K20 line and onto Microchip’s (originally Atmel’s) SAM4S line of MCUs. Also, before you say anything , no, this isn’t an AVR, it’s a full blown ARM Cortex-M4, just like the Kinetis K20 series.
Recently there have been a lot of changes in the KLL compiler in regards to JSON output.
JSON is used by both the configurator/KiiConf as well as host-side KLL to gather more information that is available to the KLL compiler, but not the final output generated by the KLL compiler.
This includes things such as all defined KLL capabilities, per-layer trigger:result
pairs and physical keymapping.
Another recent change was classifying some capabilities as thread-safe. With the recent change in the controller firmware to use 2 threads of execution (periodic and poll) some capabilities may need to access resources that are not thread-safe. Capabilities that are thread-safe may be called immediately inside the periodic thread, while non-thread-safe capabilities must be queued up for the polling thread.
As we’re still trying to catch-up and finish the KLL 0.5 support, there hasn’t been a lot of action on the KLL spec. However, there are a few things that will likely sneak into the KLL 0.5 spec before it is complete. Something that will make it for KLL 0.5 are lock LED triggers. These are useful for triggering off of things such as CapsLock and NumLock.
If you use one of our keyboards on Windows, you probably recognize this.
And if you’ve been unlucky , you’ve probably messed up and had to uninstall the driver as well (which is a bit tricky). Zadig is a great tool, but why can’t it just be done for you (like on macOS and Linux) and just work. That’s the goal of kiidrv, to make flashing your keyboard on Windows more seamless.
smasher816 integrated both libwdi, the library used to create Zadig and devcon, an API to work with the Device Manager, to create kiidrv. This means we can not only install the correct driver for your keyboard, but also validate that you’ve only installed it correctly (in case you used Zadig on the wrong device by mistake; really easy to do btw).
Feel free to use kiidrv in your own projects as it’s fully opensource under GPLv3 and LGPLv3, and just a useful tool in general. Make sure to download the correct architecture for your version of Windows.
For a long time HaaTa has had a difficult time testing KLL. By design, KLL supports an enormous number of configurations multiplied by the number of keyboards that support it. Sadly, this means it’s also impossible to test every configuration ahead of time.
But, KLL has a very interesting design aspect to it.
The trigger:result
pairs that define what you pressed and what should happen when you press.
Or said a different way, both input and outputs are known ahead of time !
This means KLL defines what we’re expecting to happen, which for those software engineers out there means that this is actually a constrained problem that can be unit tested.
So, back in 2016 HaaTa began his port of the KLL firmware to x86.
Instead of setting up a complicated hardware setup, the KLL firmware implementation relies entirely on CPU instructions, so no emulation is required for the trigger:result
macro logic.
Then, to support all of the hardware specific calls, Python callbacks were implemented with Scan and Output.
The goal of this shared library (kiibohd.so
) was to be able to control the KLL processing cycle-by-cycle in order to construct any sort of situation that may occur on a keyboard.
Even the ones that are basically impossible to trigger on a physical keyboard (e.g. press 10 keys in a row exactly 10 us apart for 3 ms each).
The tests not only require interaction with the newly generated kiibohd.so
, but also what the input and outputs of trigger:result
pairs are.
Instead of re-parsing the KLL files, the KLL compiler generates a kll.json
file which contains detailed information about the compiled KLL layout.
With this information a test can be generated for each possible key combination on each layer and what the result of each test should be.
Inputting trigger information is fairly straightforward as each trigger currently defines a scancode. This scancode is then sent as a pressed scancode. Next, the library is indicated it may process a single loop. Before checking the result, the trigger cleanup must begin. The trigger scancode is released, as to simulate an extremely quick press/release on a keyboard.
Validating the result is a bit trickier as results are actually KLL capabilities (i.e. C functions).
Some of these functions, such as USB, will output a USB code that is easy to validate as a press/release event.
However, some capabilities trigger hardware that is not available to the shared library.
In this case a capability history buffer is maintained.
This history buffer is compared to what was expected, using the kll.json
information.
While this is only a start, self-testing KLL should be working for all macros (sequence and combo) currently supported by the firmware.
Now, it’s possible to self-test your own KLL files. While this functionality is currently limited to compiling the firmware yourself, it will be added to the configurator as well in the future. Not only does it give you an indication on which expressions are having issues, it also provides developers with more information on what the problem actually is (the trickiest part when reporting a bug is providing enough relevant and detailed information to actually solve the issue).
Really though, all this work was done in order to prepare for state scheduling testing (also known as short/long press or tap keys). State scheduling provides so many customization options and timing options that are just not possible to test reliably on a physical keyboard. So we’re now one more step closer to achieving full KLL 0.5 support.
If you’re curious as to what the output looks like, take a look at this Travis-CI job.
We’re hard-at-work on both the next prototype case and pcb revisions (with big news in less than a week!). Much of the work on the case has been figuring out how to injection mold the bottom foot. The pcb has so many components on it that it has been tricky to place posts for screw holes. This is extra tricky due to the hotswap pcb needing to be braced against the steel plate without having any switches inserted.
The pcb is our first design using the SAM4S so we’re using all the experience we gained designing the K-Type and Type C WhiteFox to make the Kira even better. Something that people tend to forget, is why old keyboards had bezels. Keyboards used to have big bezels because you could place your keyboard controller chips in those areas. It was a simpler time then. But now, with our sleek and streamlined keyboards, with no arrow cluster or spaced function row, there are very few places to put components on the pcb that won’t interfere with the keyboard switches. Fortunately, there’s a lot of room under the spacebar and a bit near the shift keys.
One cool feature of the SAM4S is the built-in bootloader SAM-BA. While we’ll still be using a custom dfu bootloader to handle layout flashing, this built-in bootloader means that we’ll no longer need an external tool to update to bootloader. But don’t worry, you’ll have to fully open up the case and follow some special instructions (won’t be labeled) in order to activate the built-in bootloader.
And to finish off, some things to look forward to in the coming months.
And that’s it for this update! We’re going to try and put out at least one update ever 1-2 months (though maybe not quite this long ).
tags: update - engineering - keyboards - firmware - case - pcb - configurator - fun