The mysterious 60% mechanical keyboard returns. I had attempted to flash the firmware of several other keyboards in the hopes of enabling more functionality, and had varying degrees of success before finally finding a method for flashing QMK.
Since getting QMK on the keyboard, i've modified the configuration extensively for my own personal use. This write-up will serve as a point-in-time walkthrough of my configuration, as well as the methodology behind it.
A public release of my QMK configuration can be found at niallr/qmk-firmware-public.
Keyboard Aspirations
- Reduction in hand movements, particularly to reduce the dependency on moving to a pointing device for all positioning interactions.
- Reduction in finger movements and to keep default position close to the home row.
- Ability to maintain macros in code and store them on the keyboard.
- Ability to add "random delay" steps within macros (as found in Logitech Gaming Software). This allows for humanisation of macros, particularly when creating automated procedures for sensitive environments (i.e. anti-cheats).
Configuration Items
Reset To Bootloader shortcut
RESET
is used to put your keyboard into DFU mode so you can flash firmware without physically pressing the reset button usually found in the underside of the keyboard / grounding the BOOT pin.
Space Cadet Shift
I type parentheses ("(" & ")") frequently, and holding Shift while moving my right hand to the correct keys can reduce WPM. Space Cadet Shift is a useful function for adding additional functionality to the 2 Shift keys. Tapping Left Shift gives an open parenthesis. If the key is held and another key is then pressed, the Shift key works as usual and gives a capital letter. Right Shift functions the same way, but with a closing parenthesis. I can then use my pinky fingers to tap the Shift keys when required.
Layers
QMK enables the definition of multiple key layers. As my keyboard is 60%, it makes sense to at least have the arrow and functional keys available on another layer, as well as any macros that I have coded. The modifiers for the different layers are Fn, Caps Lock hold and Tab hold.
Mouse Keys (config.h)
I added mouse keys to the Tab hold layer so that I could easily use my left pinky finger to hold the key. I adopted the mouse key configuration from the Miryoku QMK layout with no changes. I then bound the following: - Mouse movement to WASD - Scroll up/down to Q/E - Mouse clicks to JKL (left, middle, right)
Arrow Keys
I added arrow keys to the Caps Lock hold layer so that I could easily use my left pinky finger to hold the key. I then bound the arrow keys to WASD.
Enabling Granular RGB Matrix Control
Alongside OPENRGB_ENABLE = yes
in rules.mk (see my previous write-up regarding OpenRGB), I added RGB_MATRIX_ENABLE = yes
and RGB_MATRIX_DRIVER = SN32F24xB
for granular control of the RGB matrix within functions.
Random Number Generation
There is a built-in function that can send a random character to the host device, though my requirement was to be able to dynamically generate a random number which can then be used in another function (i.e. a macro or to then map that number to a alphabetic character). I also wanted to be able to provide a range for the generation too.
My approach was to utilise the srand()
function, which takes a seed number to generate pseudorandom numbers. I used a timer value as the seed number to make the generation as "random" as possible. I finally wrapped this with upper and lower bound range parameters, and used a nifty formula to constrain the pseudorandom number to the given range.
Random Number Generation Applications In Macros
Random Alphabetic Character Generation
I used the "random number in range" function to create a "random letter" function by constraining the generated number to upper bound of 26. I can then use register_code (KC_A + number)
and unregister_code (KC_A + number)
to send a pseudorandom alphabetic character.
Random Delays in Macros
I used the "random number in range" function as an input for a while loop that checks for timer_elapsed(some_timer)
to reach the given number input and waits 10ms if not met. In combination with the "random number in range" function, random delays can be then be added between macro steps (i.e. between key presses and for defining key hold duration).
Press Multiple Keys Simultaneously
Typically you can use register_code(key)
commands in series for each key to be held, then unregister_code(key)
afterwards to release, so 2 lines of code per key hold. The small utility function reduces these scenarios to one line regardless of the number of keys.
String Macro
I used SEND_STRING
to send characters for a given string on keypress, such as my email address.
Customising RGB
I wrote an override for rgb_matrix_indicators_user()
with a switch statement on get_highest_layer(layer_state)
to check when each layer was active. I then set the modifier key for the active layer to glow green.
Conclusion & Future Work
QMK is a fantastic addition to any keyboard. With the additions listed above, my keyboard aspirations have been mostly fulfiled at a budget pricepoint. I will continue to refine this configuration as I use it more.