目次
QMKの環境構築
※この記事ではQMK Toolboxを使いません。コマンドライン操作でコンパイルやProMicroへの書き込みができるようになることを目標とします。また、Windowsでの環境構築の解説なので、macOSの場合適宜読み替えてください。
1. ともあれ、QMK FirmwareをForkする
2. QMK MSYSのインストールとセットアップ
QMK MSYSの最新バージョンをダウンロード&インストール。
インストールしたQMK MSYSを開き、
$ qmk setup <github_username>/qmk_firmware --home C:\<path>\qmk_firmware
でセットアップを行う。
--home
でQMK Firmwareをcloneしたパスを指定して初期設定が完了。途中いくつかの確認項目は基本的にY
で進める。
単に
$ qmk setup
を行うと本家リポジトリをクローンして環境構築する。
3. 構築した環境をテストしてみよう
手元のキーボード用のデフォルトキーマップをコンパイルしてみる。
$ qmk compile -kb <keyboard> -km default
<keyboard>
の部分にはファームウェアを書き込む対象のキーボード名が入る。QMKに登録されたキーボードのリストはここから確認できる。
例えば、crkbdのデフォルトキーマップをコンパイルする場合、
$ qmk compile -kb crkbd/rev1 -km default
とすればOK。
長いログの後、特にエラーを吐かず * The firmware size is fine - *****/***** (**** bytes free)
とメッセージが表示されたらコンパイルは無事に完了。QMK MSYSは無事にセットアップできたといえる。
デフォルトのキーボードとキーマップを設定ファイルに書き込んでおく
$ qmk config user.keyboard=<keyboard>
$ qmk config user.keymap=<github_username>
とすることで~\AppData\Local\QMK.EXE\qmk.exe\qmk.exe.ini
内に上で指定した<keyboard>
と<github_username>
が記述され、コンパイルなどの際に都度-kb
や-km
でキーボードやキーマップを指定する必要がなくなる。
自分用keymapの作成
以下、qmk config
で設定したキーボード、キーマップをそれぞれ使用するため-kb
-km
オプションの記述は省略する。
$ qmk new-keymap
をすると、Ψ <github_username> keymap directory created in: <path>/qmk_firmware/keyboards/crkbd/keymaps/<github_username>
と表示され、自分のGithubユーザー名のkeymapを含むディレクトリがが新規作成される。
ファームウェアのコンパイルと書き込み
1. コンパイル
自分用のkeymapの作成が完了したところで一度コンパイルをしてみよう。
$ qmk compile
うまくいけば先ほどと同様 * The firmware size is fine - *****/***** (**** bytes free)
と表示され、新しく作ったkeymapでPro Micro用のファームウェアがコンパイルされた。おめでとうございます。
2. 書き込み
続けて、
$ qmk flash
でコンパイルしたファームウェアをPro Microに書き込む。
Waiting for USB serial port - reset your controller now (Ctrl+C to cancel)...
と表示され書き込み待機状態になったらPro Microのリセットスイッチを押す。
一通りの読み出し/書き込みの後、一番最後にThank you.
と表示されれば書き込みは成功。
自分用keymapの編集
ここからが本番。先程作成したキーマップを好みのエディタで開く。
場所は<path>/qmk_firmware/keyboards/<keyboard>/keymaps/<github_username>/keymap.c
。
以下はLily58キーボードの例である。
#include QMK_KEYBOARD_H
enum layer_number {
_QWERTY = 0,
_LWR,
_RSE,
_ADJ,
};
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[_QWERTY] = LAYOUT(
// ,-----------------------------------------------------. ,-----------------------------------------------------.
KC_GESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_EQL,
// |--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_MINS,
// |--------+--------+--------+--------+--------+--------| |--------+--------+--------+--------+--------+--------|
KC_LCTL, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT,
// |--------+--------+--------+--------+--------+--------+--------. ,--------+--------+--------+--------+--------+--------+--------|
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_LBRC, KC_RBRC, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, SFT_T(KC_BSLS),
// `--------------------------+--------+--------+--------+--------| |--------+--------+--------+--------+--------------------------'
KC_LALT, KC_LCTL,C(KC_SPC), KC_SPC, KC_ENT, KC_BSPC,MO(_LWR), KC_RGUI
// `-----------------------------------' `-----------------------------------'
),
[_LWR] = LAYOUT(
… // 省略
キーマップはuint16_t
型の配列になっており、レイヤーごとにキーマップを好みに設定できる。
KC_
から始まるキーコードが一般的なアルファベットや記号、数字から音量の調節、マウスキーまで多様に割り振られており、実際のキーボードの配列を模したものの中に自由に記述してゆく。使用可能なキーコード一覧はQMK公式ドキュメントを参照。
レイヤーの移動にはMO(layer)
(押している間のみレイヤーを移動)やTO(layer)
(押すたびにレイヤーをトグル)などを使う。MO(layer)
を使用する場合は、移動先のレイヤーの同じキーにKC_TRNS
あるいは_______
を指定する。
マウスキーやメディア音量の調節を割り当てる場合、rules.mk
内でMOUSEKEY_ENABLE = yes
やEXTRAKEY_ENABLE = yes
として機能を有効化する必要があるので注意。
レイヤー毎のRGBLEDの設定
viaやRemapに対応したキーマップではプリセットとして幾つかのLEDアニメーションを切り替えることができるようになっているが、ここでは自分が今どのレイヤーにいるのか判別しやすくするために、レイヤーと同時に切り替わるLEDのマッピングを解説する。
1. キーボードに実装したLEDの個数などの定義
#define RGBLIGHT_LAYERS // 機能の有効化
#define RGBLED_NUM 50 // LEDの個数
#define RGBLED_SPLIT { 25, 25 } // (分割キーボードの場合)左右それぞれに実装したLEDの個数
#define RGBLIGHT_MAX_LAYERS 8 // (最大32)
2. 各LEDの位置を判別しやすくするために番号を振る
多くのキーボードではPro Microから始まり数珠繋ぎになったLEDがS字、あるいはZ字に並んでいる。これは電気回路的な配置の話であり、任意のLEDの位置を指定してその光り方をカスタムするには分かりづらく不都合である。そこで、例えば1行目から各行ごとに左→右となるようにLEDの番号を振り直す。
config.h
を開き、#define LED_LAYOUT()
マクロを作成する。以下に示すのはHelixキーボードの例である。
#define LED_LAYOUT( \
L00, L01, L02, L03, L04, L05, R00, R01, R02, R03, R04, R05, \
L10, L11, L12, L13, L14, L15, R10, R11, R12, R13, R14, R15, \
L20, L21, L22, L23, L24, L25, R20, R21, R22, R23, R24, R25, \
L30, L31, L32, L33, L34, L35, L36 R30, R31, R32, R33, R34, R35, R36 )
{ \
L05, L04, L03, L02, L01, L00, \
L10, L11, L12, L13, L14, L15, \
L25, L24, L23, L22, L21, L20, \
L30, L31, L32, L33, L34, L35, L36, \
\
R00, R01, R02, R03, R04, R05, \
R15, R14, R13, R12, R11, R10, \
R20, R21, R22, R23, R24, R25, \
R36, R35, R34, R33, R32, R31, R30 }
前方()
で囲まれた部分には物理的なキーそのもののレイアウトが入り、例えばL13
なら左手1行3列のキーであることを示す。ここで注意するのは行列のインデックスが1ではなく0から始まっているということ。L13
は、左から数えて4つ目、上から数えて2つ目のキーである。
後方{}
で囲まれた部分にはLEDの電気回路的な並び順が入る。HelixキーボードではLEDがZ字に並んでいるため、それに対応した順を記述する。
次に、それぞれのLEDに任意の番号を振るためにRGBLIGHT_LED_MAP
マクロを定義する。
#define RGBLIGHT_LED_MAP LED_LAYOUT( \
0, 1, 2, 3, 4, 5, 19, 20, 21, 22, 23, 24, \
6, 7, 8, 9, 10, 11, 25, 26, 27, 28, 29, 30, \
12, 13, 14, 15, 16, 17, 18, 31, 32, 33, 34, 35, 36, 37 )
これでconfig.h
の編集は完了。ここで振った0
~37
までの番号をLEDのインデックスとしてkeymap.c
内で使用する。
3. レイヤ毎のLEDの光り方を指定する
keymap.c
に記述する。
rgblight_segment_t
型の配列を宣言し、先ほど割り振ったインデックスの順に必要な個数ずつ色を指定してゆく。
なお、config.h
内で定義したRGBLED_NUM
マクロで指定したものと同数を割り当てないとコンパイルエラーが出るので注意すること。
#ifdef RGBLIGHT_LAYERS
const rgblight_segment_t PROGMEM rgb_layer_1st[] = RGBLIGHT_LAYER_SEGMENTS(
{0, 1, HSV_RED}, // 開始LEDインデックス, 連続する個数, 光らせる色(ここではプリセットを使用)
{1, 5, HSV_GREEN}, {6, 3, HSV_OFF}, … // 省略
);
const rgblight_segment_t PROGMEM rgb_layer_2nd[] = RGBLIGHT_LAYER_SEGMENTS(
// 省略
);
const rgblight_segment_t PROGMEM rgb_layer_3rd[] = RGBLIGHT_LAYER_SEGMENTS
// 省略
);
const rgblight_segment_t PROGMEM rgb_layer_4th[] = RGBLIGHT_LAYER_SEGMENTS
// 省略
);
必要なレイヤーの数だけ配列を宣言し、LEDのマッピングをする。
続けて、上で用意したLEDのレイヤーとキーマップのレイヤーを対応づけるために以下を記述する。
const rgblight_segment_t* const PROGMEM rgb_layers[] = RGBLIGHT_LAYERS_LIST(
rgb_layer_1st,
rgb_layer_2nd,
rgb_layer_3rd,
rgb_layer_4th
);
void keyboard_post_init_user(void) {
rgblight_layers = rgb_layers;
}
layer_state_t layer_state_set_user(layer_state_t state) {
rgblight_set_layer_state(0, layer_state_cmp(state, _QWERTY));
rgblight_set_layer_state(1, layer_state_cmp(state, _LWR));
rgblight_set_layer_state(2, layer_state_cmp(state, _RSE));
rgblight_set_layer_state(3, layer_state_cmp(state, _ADJ));
return state;
}
#endif // RGBLIGHT_LAYERS
ここで注意するべきは、キーボード毎のファームウェアによって配列の名前が異なっている場合が多いということ。コンパイルに失敗する場合は、上のコードでのrgb_layer_xxx
, _QWERTY
, _LWR
に当たる部分などを今一度見直してみてほしい。
おまけ: 左右問わずUSB接続を可能にする
分割型のキーボードではUSBケーブルを挿したPro Microをマスター、TRRSケーブルで接続されたPro Microがスレーブと呼ぶ。
大抵の分割型キーボードではデフォルトの状態で常にマスター側を左手と認識している。
つまり右手のPro MicroにUSBを挿してしまうと、分割されたキーボードが左右反転して認識されてしまい、キーボードとして使うことができない。デスク上のケーブルの取り回しの問題で右手側にUSBケーブルを接続、あるいは状況によって左右どちらのPro MicroにUSB接続してもそれぞれの手を正しく認識するように設定してみよう。
これにはいくつかの方法があるが、ここではPro Micro上のEEPROMに右手側であること、左手側であることをそれぞれ書き込む方法を記述する。
作成した自分のキーマップ内のconfig.h
には以下の項目がある。
/* Select hand configuration */
#define MASTER_LEFT
// #define MASTER_RIGHT
// #define EE_HANDS
常にマスターを左側として認識するのは#define MASTER_LEFT
とされているからである。
3つ目の#define EE_HANDS
を有効にするために以下のように書き換える。
/* Select hand configuration */
// #define MASTER_LEFT
// #define MASTER_RIGHT
#define EE_HANDS
これでコンパイル、書き込みを行う。
次に、それぞれのPro Microに搭載されたEEPROMに左手 右手の情報を書き込む。
左手 C:\<path>\qmk_firmware\quantum\split_common\eeprom-lefthand.eep
右手 C:\<path>\qmk_firmware\quantum\split_common\eeprom-righthand.eep
QMK MSYS上であらかじめC:\<path>\qmk_firmware\quantum\split_common
に移動しておく。
$ cd C:\<path>\qmk_firmware\quantum\split_common
$ avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-lefthand.eep
ここでEnterキーを押す直前にPro Microのリセットスイッチを押して待機状態にする。
うまくいけば右手も同様に
$ avrdude -p atmega32u4 -P $(COM_PORT) -c avr109 -U eeprom:w:eeprom-righthand.eep
これで左右どちらのポートにケーブルを接続しても正しく左右を認識するようになった。