Software
08/01/2024
software, qmk, mechanical keyboard, keychron
So I recently bought the Keychron v1 and noticed that Rtings lists it as having 20ms of input delay. For reference some 'gaming' keyboards advertise having a 1ms input delay and a good value seems to be less than 10ms. It's not that noticeable during normal use but it definitely feels a bit sluggish when playing games like Street Fighter where the responsiveness matters. Luckily I was able to reduce the input delay to a point where it doesn't bother me at all, here's how. The general gist is that the Keychron v1 runs with a software known as QMK, an open source firmware that controls microcontrollers on keyboards. With some research I was able to find a pull request that modifies the code to reduce input delay and after that I simply compiled the new firmware locally and used it to flash the keyboard. The instructions below will be tailored for Windows though the technique itself should be possible on Mac and Linux.
The modification is based on this article by Michael Stapelberg which concludes input lag can be reduced by a faster debouncing algorithm and a lower USB polling interval. This is the example pull request stated in the article which I'll be replicating in the V1. It seems the defaults were chosen as conservative values but having used the modified firmware to write this post, I can safely say that the improved code works fine on the V1 without any erroneous input.
I followed the official documentation to edit, compile and flash the firmware. First I downloaded and installed the latest QMK_MSYS which seems to be an easy executable that prepares the CLI environment. I then forked the qmk repository to my own github account and then cloned it to my local machine.
$ git clone --recurse-submodules https://github.com/<my_username>/qmk_firmware.git
Then I executed the setup command
$ qmk setup
Then I made a new branch, navigated to /keyboards/keychron/v1/ansi_encoder
and edited config.h
and rules.mk
according to the example pull request in the article. The encoder
in the directory name refers to the knob variant of the v1; the same edits can be made in the ansi
folder if you have the knobless v1.
// rules.mk DEBOUNCE_TYPE = sym_eager_pk // additionally enable VIA support if you use it to remap keys VIA_ENABLE = yes
Some mechanical key switches exhibit something known as contact bounce where due to a flaw in hardware, a single key press sends multiple repeating signals which results in duplicate characters being registered. You won't usually notice this at all because the QMK software has a debounce feature by default which mitigates this.
The default debounce algorithm is sym_defer_g
which works by waiting until a set amount of time has passed where no changed has occurred, after a key is pressed. Once any potential contact bounced has settled, the input is pushed. This gets rid of the noise but it means every key press is delayed at minimum by the given debounce interval which is 5ms by default.
QMK provides alternate debounce algorithms and I went with was sym_eager_pk
. This algorithm immediately sends the signal when a key is pressed, and ignores any subsequent bounce signals that happen afterwards within the debounce interval. This means that sym_eager_pk
is faster by 5ms but the problem is that any contact bounces that happen after 5ms of the key press don't get filtered out (Which is usually the case). To counter this I increased the debounce interval to 50ms which completely eliminates any noise whilst retaining immediate responsiveness. The catch is that this prevents repeated key presses that are faster than 50ms but that's 20 individual inputs per second (without holding down the key) which doesn't happen unless you're rolling on an NES controller for Tetris.
// config.h #define USB_POLLING_INTERVAL_MS 1 #define DEBOUNCE 50
Finally I ran the compile command which builds the customized firmware as a .bin
file in the root directory
$ qmk compile -kb keychron/v1/ansi_encoder -km default
Now all I had to do was install the new firmware into the keyboard. First I installed QMK Toolbox then loaded the keychron_v1_ansi_encoder_default.bin
firmware into it. Then I followed the Keychron documentation to flashing the keyboard which was basically as follows.
fn + J + Z
for 4 seconds to factory reset the keyboard then unplug the power.DFU device connected
is displayed in QMK Toolbox in yellow. (You can release the reset button once connected)fn + J + Z
for 4 seconds again and factory reset for good measure.And that's it, with the new firmware the v1 is noticeably more responsive. Though I don't have exact numbers to back this claim, it feels comparable to the Epomaker E84 I was using before so I'm guessing it's somewhere between 10ms and the original 20ms. If you experience any instability you can simply reflash the firmware with the original firmware.
Lastly the official site gives the following disclaimer so I'm obligated to say that there's a small but inherent risk to overriding the firmware if you feel like trying this mod out for yourself.
Note: If everything works fine with your keyboard. Please don’t flash the firmware. There is a chance it can damage your keyboard.