348 lines
22 KiB
Markdown
348 lines
22 KiB
Markdown
|
+++
|
||
|
title = "QMK Firmware"
|
||
|
author = ["Elia el Lazkani"]
|
||
|
date = 2021-09-23
|
||
|
lastmod = 2021-09-23
|
||
|
tags = ["qmk", "firmware", "mechanical-keyboard", "qmk-firmware"]
|
||
|
categories = ["misc"]
|
||
|
draft = false
|
||
|
+++
|
||
|
|
||
|
Over the years, I have owned a few mechanical keyboards. I'm quite fond of them.
|
||
|
I've also built my own keyboard from scratch years ago. Hot-swappable back then
|
||
|
was still in its easy stages and the sockets weren't that good. Alas, we're in
|
||
|
2021 and I've recently purchased the **Keychron Q1** keyboard.
|
||
|
|
||
|
I've chosen this keyboard for many reasons, but the one you most care about is
|
||
|
the topic that brought you here. It's a **QMK Firmware** compatible keyboards. Do
|
||
|
you know what that means ?
|
||
|
|
||
|
That means that we're going to be digging into `qmk_firmware`. Tag along !
|
||
|
|
||
|
<!--more-->
|
||
|
|
||
|
|
||
|
## Quantum Mechanical Keyboard Firmware {#quantum-mechanical-keyboard-firmware}
|
||
|
|
||
|
The [**QMK Firmware**](https://github.com/qmk/qmk%5Ffirmware) is
|
||
|
|
||
|
> a keyboard firmware based on the tmk\_keyboard firmware with some useful features
|
||
|
> for Atmel AVR and ARM controllers, and more specifically, the OLKB product line,
|
||
|
> the ErgoDox EZ keyboard, and the Clueboard product line.
|
||
|
|
||
|
It goes beyond saying, the **QMK Firmware** is open sourced. So let's hack it.
|
||
|
|
||
|
|
||
|
## Building QMK Firmware {#building-qmk-firmware}
|
||
|
|
||
|
The first step to flashing your keyboard starts here. We need to get the source
|
||
|
code of `qmk_firmware` from Github.
|
||
|
|
||
|
```shell
|
||
|
$ git clone https://github.com/qmk/qmk_firmware.git
|
||
|
# Wait a while...
|
||
|
# Yup, I know !
|
||
|
# Okay finally...
|
||
|
Cloning into 'qmk_firmware'...
|
||
|
remote: Enumerating objects: 295442, done.
|
||
|
remote: Counting objects: 100% (34/34), done.
|
||
|
remote: Compressing objects: 100% (27/27), done.
|
||
|
remote: Total 295442 (delta 13), reused 17 (delta 5), pack-reused 295408
|
||
|
Receiving objects: 100% (295442/295442), 178.92 MiB | 7.10 MiB/s, done.
|
||
|
Resolving deltas: 100% (178414/178414), done.
|
||
|
Updating files: 100% (27916/27916), done.
|
||
|
|
||
|
$ cd qmk_firmware
|
||
|
```
|
||
|
|
||
|
Once the repository is clone, we can start with installing the dependencies to
|
||
|
build `qmk`.
|
||
|
|
||
|
I'm not a big fan of auto-installers or installers scripts
|
||
|
(`util/install/arch.sh`), and here's why.
|
||
|
|
||
|
```bash
|
||
|
python3 -m pip install --user -r $QMK_FIRMWARE_DIR/requirements.txt
|
||
|
```
|
||
|
|
||
|
This is how the installer of the `qmk_firmware` concludes the round. I would
|
||
|
hate to use pip to install willy nilly like that.
|
||
|
|
||
|
Otherwise, I don't have objections to what it does on `arch` at least.
|
||
|
|
||
|
It does the following, I see no reason not to follow it.
|
||
|
|
||
|
```shell
|
||
|
$ sudo pacman -S \
|
||
|
base-devel clang diffutils gcc git unzip wget zip python-pip \
|
||
|
avr-binutils arm-none-eabi-binutils arm-none-eabi-gcc \
|
||
|
arm-none-eabi-newlib avrdude dfu-programmer dfu-util
|
||
|
$ sudo pacman -U https://archive.archlinux.org/packages/a/avr-gcc/avr-gcc-8.3.0-1-x86_64.pkg.tar.xz
|
||
|
$ sudo pacman -S avr-libc # Must be installed after the above, or it will bring in the latest avr-gcc instead
|
||
|
$ sudo pacman -S hidapi # This will fail if the community repo isn't enabled
|
||
|
```
|
||
|
|
||
|
Now that all the dependencies required by the system are installed, let's
|
||
|
install the `python` dependencies.
|
||
|
|
||
|
```shell
|
||
|
$ git checkout 0.14.9 # Checkout the latest version
|
||
|
$ vf new qmk_firmware # Create a new python virtualenv and activate it
|
||
|
$ pip install -r requirements.txt # Install python requirements
|
||
|
$ pip install qmk
|
||
|
$ make git-submodule
|
||
|
```
|
||
|
|
||
|
Finally, we can build our keyboard firmware.
|
||
|
|
||
|
```bash
|
||
|
$ qmk compile -kb keychron/q1/rev_0100 -km default
|
||
|
Ψ Compiling keymap with make --jobs=1 keychron/q1/rev_0100:default [31/494]
|
||
|
|
||
|
|
||
|
QMK Firmware 0.14.16
|
||
|
Making keychron/q1/rev_0100 with keymap default
|
||
|
|
||
|
avr-gcc (GCC) 11.2.0
|
||
|
Copyright (C) 2021 Free Software Foundation, Inc.
|
||
|
This is free software; see the source for copying conditions. There is NO
|
||
|
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||
|
|
||
|
Compiling: keyboards/keychron/q1/q1.c [OK]
|
||
|
Compiling: keyboards/keychron/q1/rev_0100/rev_0100.c [OK]
|
||
|
Compiling: keyboards/keychron/q1/rev_0100/keymaps/default/keymap.c [OK]
|
||
|
Compiling: quantum/quantum.c [OK]
|
||
|
Compiling: quantum/send_string.c [OK]
|
||
|
Compiling: quantum/bitwise.c [OK]
|
||
|
Compiling: quantum/led.c [OK]
|
||
|
Compiling: quantum/action.c [OK]
|
||
|
Compiling: quantum/action_layer.c [OK]
|
||
|
Compiling: quantum/action_macro.c [OK]
|
||
|
Compiling: quantum/action_tapping.c [OK]
|
||
|
Compiling: quantum/action_util.c [OK]
|
||
|
Compiling: quantum/eeconfig.c [OK]
|
||
|
Compiling: quantum/keyboard.c [OK]
|
||
|
Compiling: quantum/keymap_common.c [OK]
|
||
|
Compiling: quantum/keycode_config.c [OK]
|
||
|
Compiling: quantum/logging/debug.c [OK]
|
||
|
Compiling: quantum/logging/sendchar.c [OK]
|
||
|
Compiling: quantum/bootmagic/bootmagic_lite.c [OK]
|
||
|
Compiling: quantum/bootmagic/magic.c [OK]
|
||
|
Compiling: quantum/matrix_common.c [OK]
|
||
|
Compiling: quantum/matrix.c [OK]
|
||
|
Compiling: quantum/debounce/sym_defer_g.c [OK]
|
||
|
Compiling: quantum/main.c [OK]
|
||
|
Compiling: quantum/color.c [OK]
|
||
|
Compiling: quantum/rgb_matrix/rgb_matrix.c [OK]
|
||
|
Compiling: quantum/rgb_matrix/rgb_matrix_drivers.c [OK]
|
||
|
Compiling: lib/lib8tion/lib8tion.c [OK]
|
||
|
Compiling: drivers/led/issi/is31fl3733.c [OK]
|
||
|
Compiling: quantum/process_keycode/process_rgb.c [OK]
|
||
|
Compiling: quantum/led_tables.c [OK]
|
||
|
Compiling: quantum/dip_switch.c [OK]
|
||
|
Compiling: quantum/process_keycode/process_space_cadet.c [OK]
|
||
|
Compiling: quantum/process_keycode/process_magic.c [OK]
|
||
|
Compiling: quantum/process_keycode/process_grave_esc.c [OK]
|
||
|
Compiling: platforms/avr/drivers/i2c_master.c [OK]
|
||
|
Archiving: .build/obj_keychron_q1_rev_0100_default/i2c_master.o [OK]
|
||
|
Compiling: tmk_core/common/host.c [OK]
|
||
|
Compiling: tmk_core/common/report.c [OK]
|
||
|
Compiling: tmk_core/common/sync_timer.c [OK]
|
||
|
Compiling: tmk_core/common/usb_util.c [OK]
|
||
|
Compiling: tmk_core/common/avr/platform.c [OK]
|
||
|
Compiling: tmk_core/common/avr/suspend.c [OK]
|
||
|
Compiling: tmk_core/common/avr/timer.c [OK]
|
||
|
Compiling: tmk_core/common/avr/bootloader.c [OK]
|
||
|
Assembling: tmk_core/common/avr/xprintf.S [OK]
|
||
|
Compiling: tmk_core/common/avr/printf.c [OK]
|
||
|
Compiling: tmk_core/protocol/lufa/lufa.c [OK]
|
||
|
Compiling: tmk_core/protocol/usb_descriptor.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Class/Common/HIDParser.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Device_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/EndpointStream_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Endpoint_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Host_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/PipeStream_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/Pipe_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/USBController_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/AVR8/USBInterrupt_AVR8.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/ConfigDescriptors.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/DeviceStandardReq.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/Events.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/HostStandardReq.c [OK]
|
||
|
Compiling: lib/lufa/LUFA/Drivers/USB/Core/USBTask.c [OK]
|
||
|
Compiling: tmk_core/protocol/lufa/usb_util.c [OK]
|
||
|
Linking: .build/keychron_q1_rev_0100_default.elf [OK]
|
||
|
Creating load file for flashing: .build/keychron_q1_rev_0100_default.hex [OK]
|
||
|
Copying keychron_q1_rev_0100_default.hex to qmk_firmware folder [OK]
|
||
|
Checking file size of keychron_q1_rev_0100_default.hex [OK]
|
||
|
* The firmware size is fine - 23302/28672 (81%, 5370 bytes free)
|
||
|
```
|
||
|
|
||
|
Look at tha, easy as pie ! You got yourself a compiled firmware.
|
||
|
|
||
|
Before we move on, let's look at the command again and figure out what the hell
|
||
|
I did, just in case you're running a different keyboard.
|
||
|
|
||
|
If you look into the `keyboards/`, you'll be able to find a big list of
|
||
|
keyboards supported. The `keychron/q1/rev_0100` is simply a directory in there
|
||
|
that matches my keyboard. Inside that directory, we can find the `keymaps/`
|
||
|
directory. This is where all the keymaps live. We chose the `default` keymap
|
||
|
which is a directory in there as well.
|
||
|
|
||
|
|
||
|
## Remapping the keyboard {#remapping-the-keyboard}
|
||
|
|
||
|
At this stage, we were able to succesfully compile the keyboard firmware. But
|
||
|
the whole point of this is to modify the layout of the keyboard so let's go
|
||
|
right ahead.
|
||
|
|
||
|
There are commands suggested on the `QMK` docs but I didn't go that far, I
|
||
|
simply copied the `default` directory and went down to business. For the sake of
|
||
|
this blog post, I'll assume I called the directory `functions`.
|
||
|
|
||
|
The `keymap.c` file looks as follows.
|
||
|
|
||
|
```c
|
||
|
#include QMK_KEYBOARD_H
|
||
|
|
||
|
enum layers{
|
||
|
MAC_BASE,
|
||
|
MAC_FN,
|
||
|
WIN_BASE,
|
||
|
WIN_FN
|
||
|
};
|
||
|
|
||
|
#define KC_TASK LGUI(KC_TAB)
|
||
|
#define KC_FLXP LGUI(KC_E)
|
||
|
|
||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||
|
|
||
|
[MAC_BASE] = LAYOUT_ansi_82(
|
||
|
KC_ESC, KC_BRID, KC_BRIU, KC_F3, KC_F4, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, KC_INS,
|
||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_PGUP,
|
||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN,
|
||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_HOME,
|
||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||
|
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(MAC_FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||
|
|
||
|
[MAC_FN] = LAYOUT_ansi_82(
|
||
|
KC_TRNS, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
|
||
|
|
||
|
[WIN_BASE] = LAYOUT_ansi_82(
|
||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_INS,
|
||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_PGUP,
|
||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN,
|
||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_HOME,
|
||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||
|
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(WIN_FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||
|
|
||
|
[WIN_FN] = LAYOUT_ansi_82(
|
||
|
KC_TRNS, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)
|
||
|
|
||
|
};
|
||
|
```
|
||
|
|
||
|
If you read this you will understand that the keyboard originally comes with 4
|
||
|
layers. Two for windows and two for Mac. The `0` and `1` layers are toggled
|
||
|
using a physical switch. The rest are toggled with the `Fn` key.
|
||
|
|
||
|
Now let's change the Mac layout to have the `Function` keys to be on the main
|
||
|
layer while the media keys to be toggled with the `Fn` key. The final version
|
||
|
should look like the following.
|
||
|
|
||
|
```c
|
||
|
#include QMK_KEYBOARD_H
|
||
|
|
||
|
enum layers{
|
||
|
MAC_BASE,
|
||
|
MAC_FN,
|
||
|
WIN_BASE,
|
||
|
WIN_FN
|
||
|
};
|
||
|
|
||
|
#define KC_TASK LGUI(KC_TAB)
|
||
|
#define KC_FLXP LGUI(KC_E)
|
||
|
|
||
|
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
|
||
|
|
||
|
[MAC_BASE] = LAYOUT_ansi_82(
|
||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_TRNS, KC_TRNS,
|
||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_PGUP,
|
||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN,
|
||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_HOME,
|
||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||
|
KC_LCTL, KC_LALT, KC_LGUI, KC_SPC, KC_RGUI, MO(MAC_FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||
|
|
||
|
[MAC_FN] = LAYOUT_ansi_82(
|
||
|
KC_TRNS, KC_BRID, KC_BRIU, KC_F3, KC_F4, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_DEL, KC_INS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS),
|
||
|
|
||
|
[WIN_BASE] = LAYOUT_ansi_82(
|
||
|
KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_DEL, KC_INS,
|
||
|
KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC, KC_PGUP,
|
||
|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS, KC_PGDN,
|
||
|
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT, KC_HOME,
|
||
|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_RSFT, KC_UP,
|
||
|
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, MO(WIN_FN),KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT),
|
||
|
|
||
|
[WIN_FN] = LAYOUT_ansi_82(
|
||
|
KC_TRNS, KC_BRID, KC_BRIU, KC_TASK, KC_FLXP, RGB_VAD, RGB_VAI, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE, KC_VOLD, KC_VOLU, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
RGB_TOG, RGB_MOD, RGB_VAI, RGB_HUI, RGB_SAI, RGB_SPI, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, RGB_RMOD, RGB_VAD, RGB_HUD, RGB_SAD, RGB_SPD, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS,
|
||
|
KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS, KC_TRNS)
|
||
|
|
||
|
};
|
||
|
```
|
||
|
|
||
|
Now that that's done, we need to compile to check that we didn't forget
|
||
|
anything.
|
||
|
|
||
|
```shell
|
||
|
$ qmk compile -kb keychron/q1/rev_0100 -km functions
|
||
|
```
|
||
|
|
||
|
We seem to have successfully compiled our now keyboard layout.
|
||
|
|
||
|
|
||
|
## Flashing your keyboard {#flashing-your-keyboard}
|
||
|
|
||
|
If you're reached this stage, you'll need to locate the `reset` button on your
|
||
|
keyboard. Once located, follow your keyboard's manual on how to **reset** the
|
||
|
board and getting ready it for flashing.
|
||
|
|
||
|
Once the keyboard is ready to be flashed, you basically change one thing in your
|
||
|
previous command.
|
||
|
|
||
|
```shell
|
||
|
$ qmk flash -kb keychron/q1/rev_0100 -km functions
|
||
|
```
|
||
|
|
||
|
If this step succeeds, your keyboard should be ready to use in the newly
|
||
|
configured layout. Check it out !
|
||
|
|
||
|
|
||
|
## Conclusion {#conclusion}
|
||
|
|
||
|
It's pretty awesome to see keyboards like these hit the market. Whether you're
|
||
|
fan of the mechanical switches they come with or not, one thing is certain. You
|
||
|
cannot deny the fact that they are very customisable. If you don't like
|
||
|
something with your keyboard, simply change it. The beauty of it all is that the
|
||
|
firmware is open sourced. The community delivers, yet again !
|