この記事は、【手配線で自作キーボードを作る講座】の第8回目です。 そのほかの記事はこちら
QMK Firmwareの入手
QMK Firmwareの本体はGitHubから取得できます。
また、ビルド環境の構築方法や書き込み手順などは、公式サイトおよびドキュメントに記載されています。 なにか困ったらここを確認するようにしてください。
必要なソフトウェアのインストール
QMK Firmwareのアップデートなどによって色々と変更されることもあるため、ここではあまり詳細な手順は紹介しません。 基本的には公式ドキュメントの Getting Started を見て進めてください。
公式ドキュメントが英語で少々敷居が高いですが、日本語で解説している記事なども多くありますので、 随時調べながら作業していきましょう。
Window、Mac、Linuxでそれぞれ必要なソフトが異なってきます。 ご使用の環境に合わせてセットアップしてください。
Windowsの場合の例
以下、2019/08/24 時点でのWindowsの場合の手順を記載します。 前述のとおり手順が変更されている可能性もあるため、基本的に公式ドキュメントを正として、以下は参考程度にしてください。
MSYS2をダウンロードします。環境に合わせて、32bit版か64bit版のどちらかを選んでください。 ダウンロード後、インストーラに従ってインストールします。
インストール完了後、MSYS2を起動して、以下のコマンドでGitをインストールします。
$ pacman -S git
Git を使って、QMK Firmware を取得します。
$ git clone --recurse-submodules https://github.com/qmk/qmk_firmware.git
Cloneした中に util/qmk_install.sh
というスクリプトがあるので、実行すると必要なソフトがインストールされます。
途中何度かインストール対象を選択する場面がありますが、おおよそ "All" や "Yes" を選択しておけば問題ないです。
$ git clone --recurse-submodules https://github.com/qmk/qmk_firmware.git $ cd qmk_firmware $ util/qmk_install.sh
インストールできたら、ビルドが正常にできるかテストしてみます。 以下のコマンドで試しにビルドしてみて、エラーが出なければOKです。
$ make ergo42/rev1:default
新しいキーボードの生成
QMK Firmwareは、色々な自作キーボード用の設定ファイルが大量に同梱されています。 しかし、今回作成しようとしている自作キーボードは完全なオリジナルなので、新しく設定ファイルを作成していく必要があります。
参考:QMK Firmware Building Your First Firmware
new_keyboard.sh
のスクリプトで、自分用の新しいキーボードを作成することができます。
今回は、Ergo42 と同じ配列のキーボードなので、Ergo42 のものをベースにして作成します。 そういえば、今回作っているキーボードの名前を決めていませんでしたが、Ergo42 の Clone Keyboard ということで、Ergock としました。
new_keyboard.sh
を実行すると、キーボード名などを聞かれるので、入力していきます。
Keyboard Type
については、ProMicroを使う場合は avr
のままでよいので、何も入力せずに Enter を入力してください。
$ util/new_keyboard.sh Generating a new QMK keyboard directory Keyboard Name: ergock Keyboard Type [avr]: Your Name [okayu]: Copying base template files... done Copying avr template files... done Renaming keyboard files... done Replacing %YEAR% with 2019... done Replacing %KEYBOARD% with Ergock... done Replacing %YOUR_NAME% with okayu... done Created a new keyboard called Ergock. To start working on things, cd into keyboards/Ergock, or open the directory in your favourite text editor.
成功すると、 keyboards/ergock
ディレクトリが作成され、中に設定ファイルのテンプレートがコピーされます。
$ cd keyboards/ergock $ ls config.h ergock.c ergock.h info.json keymaps readme.md rules.mk
各ファイルの説明
新しく作成したキーボード用の各ファイルの概要は以下の通りです。
<project_name>
の部分は、 new_keyboard.sh
で指定したキーボード名になります。
config.h : ピン割当、USBデバイス設定、マトリックスの行列設定など。 <project_name>.c : QMK Firmwareの機能の上書きなど。今回は使用しません。 <project_name>.h : キーレイアウト設定。 info.json : QMK API用の設定。今回は使用しません。 readme.md : このキーボードの説明文。今回は使用しません。 rules.mk : ハードウェアに関する設定、QMK Firmwareの機能のON/OFFなど。 keymaps : キーマップ設定。 └─default : デフォルトキーマップ。 ├─config.h : config.hの設定を上書き設定する場合に使用します。今回は使用しません。 ├─keymap.c : 実際のキーマップ設定を記載します。 └─readme.md : キーマップの説明文。今回は使用しません。
これらのファイルをテキストエディタで編集して、今回のキーボード用の設定を記載していきます。
ハードウェアの設定(rules.mk)
ハードウェアや、QMK Firmwareの機能を設定します。
まずブートローダーの設定を変更します。
ハードウェアとしてProMicroを使用しているので、ソースコード上のコメントに従って caterina
に変更します。
# Bootloader selection # Teensy halfkay # Pro Micro caterina # Atmel DFU atmel-dfu # LUFA DFU lufa-dfu # QMK DFU qmk-dfu # atmega32a bootloadHID BOOTLOADER = caterina
今回は左右分割キーボードを作成しているので、最終行に以下の設定を追加します。
SPLIT_KEYBOARD = yes
キーマトリックス、ピン設定(config.h)
キーマトリックス、ピンに関する設定をしていきます。
MATRIX_ROWS, MATRIX_COLS
キーマトリックスの行数、列数を指定します。
今回のキーボードは4x7分割キーボードです。
分割キーボードの場合、MATRIX_ROWS
の値を2倍の値にする必要があります。今回は4×2で8を指定します。
#define MATRIX_ROWS 8 // 4*2=8 #define MATRIX_COLS 7
2倍にする理由はこちらを参照:Rows and columns of split using 2 pro micros : olkb
MATRIX_ROW_PINS, MATRIX_COL_PINS
キーマトリックスの行列に、ProMicroのどのピンを使用するかを設定します。
今回は以下のように設定しました。
#define MATRIX_ROW_PINS { D7, E6, B4, B5 } // Printed on ProMicro 6, 7, 8, 9 #define MATRIX_COL_PINS { F5, F6, F7, B1, B3, B2, B6 } // Printed on ProMicro A2, A1, A0, 15, 14, 16, 10
この時のピン指定はProMicroに印字されている番号ではなく、データシートに記載されているPort名で指定します。 少しわかりづらいので、ソース上にはコメントでProMicroの印字との対応を記載しておきました。
Port名はsparkfunのProMicroのページで、DOCUMENTS > Graphical Datasheet のPDFを参照してください。
Pro Micro - 5V/16MHz - DEV-12640 - SparkFun Electronics Pro Micro Graphical Datasheet
SOFT_SERIAL_PIN
分割キーボードの左右の通信を行うためのピンを指定します。
今回はデフォルトの D0
(ProMicroの印字では3
)のままとします。
#define SOFT_SERIAL_PIN D0 // or D1, D2, D3, E6
その他
その他にも、USBデバイスに関する設定などは、好みに合わせて変更するとよいでしょう。
#define VENDOR_ID 0xFEED #define PRODUCT_ID 0x0523 #define DEVICE_VER 0x0001 #define MANUFACTURER okayu #define PRODUCT Ergock #define DESCRIPTION A splited keyboard for me
VENDOR_ID
は通常は 0xFEED
のままにしましょう。
PRODUCT_ID
はほかの自作キーボードと被らない値にするべきですが、
このキーボード用ファームウェアをQMK Firmwareの本体に取り込んでもらわない場合(Pull Requestを送らない場合)は自由です。
キーレイアウトの設定(<project_name>.h)
#define LAYOUT
の内容を設定します。
この設定は、2つのセクションから成っています。
/* 初期状態 */ #define LAYOUT( \ k00, k01, k02, \ k10, k11 \ ) \ { \ { k00, k01, k02 }, \ { k10, KC_NO, k11 }, \ }
上記は new_keyboard.sh
で生成した直後の状態ですが、
ここで k00, k01~
となっている部分が前半のセクション、
{ k00, k01, ~
となっている部分が後半のセクションです。
前半のセクションでは、キーボードの物理的なキーと同じ数だけの変数を指定します。ここはあくまで後半セクション用の引数になります。
後半のセクションでは、物理的なキーがキーマトリックスのどの位置に対応するかを設定します。この時に、前半で指定した変数を用います。
「習うより慣れろ」で、とりあえず今回の4x7キーボード用に作成してみます。
#define LAYOUT( \ L00, L01, L02, L03, L04, L05, L06, R00, R01, R02, R03, R04, R05, R06, \ L10, L11, L12, L13, L14, L15, L16, R10, R11, R12, R13, R14, R15, R16, \ L20, L21, L22, L23, L24, L25, L26, R20, R21, R22, R23, R24, R25, R26, \ L30, L31, L32, L33, L34, L35, L36, R30, R31, R32, R33, R34, R35, R36 \ ) \ { \ { L00, L01, L02, L03, L04, L05, L06 }, \ { L10, L11, L12, L13, L14, L15, L16 }, \ { L20, L21, L22, L23, L24, L25, L26 }, \ { L30, L31, L32, L33, L34, L35, L36 }, \ { R00, R01, R02, R03, R04, R05, R06 }, \ { R10, R11, R12, R13, R14, R15, R16 }, \ { R20, R21, R22, R23, R24, R25, R26 }, \ { R30, R31, R32, R33, R34, R35, R36 } \ }
左右のキーがわかりやすいように、左手側は L00
、右手側は R00
という命名規則で設定しました。
分割キーボードの場合、上の例のように左右のキーボードで行を分ける必要があります。
また、 MATRIX_ROWS
の設定で行数を2倍の値で設定したのも、これが理由になります。
補足:キーマトリックスに空白を作りたいとき
今回作成しているキーボードでは、完全に格子状のキーボードのため、キーマトリックスがきれいに埋まります。 しかしレイアウトによっては、キーマトリックス上に「物理的なキーのない部分」が発生する場合があります。
たとえば、Helixキーボードは、
一番内側に1~2個のキーがあり、その上にはキーがありません。
このキーのない部分を表すには、 KC_NO
キーコードを指定します。
詳細についてはQMK Firmwareの手配線ガイドに記載がありますので、参考にしてください。
QMK Firmware Quantum Hand-Wiring Guide
また、QMK Firmwareに入っているHelixキーボード用の設定ファイル keyboards/helix/rev2/rev2.h
なども参考になります。
/* keyboards/helix/rev2/rev2.h から一部抜粋 */ #define 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, R36, R30, R31, R32, R33, R34, R35 \ ) \ { \ { L00, L01, L02, L03, L04, L05, KC_NO }, \ { L10, L11, L12, L13, L14, L15, KC_NO }, \ { L20, L21, L22, L23, L24, L25, KC_NO }, \ { L30, L31, L32, L33, L34, L35, L36 }, \ { KC_NO, R00, R01, R02, R03, R04, R05 }, \ { KC_NO, R10, R11, R12, R13, R14, R15 }, \ { KC_NO, R20, R21, R22, R23, R24, R25 }, \ { R36, R30, R31, R32, R33, R34, R35 }, \ }
キーマップの設定(keymaps/default/keymap.c)
LAYOUT
で設定した物理キーに対して、キーコード(押したときに入力される文字)を設定していきます。
また、ファンクションキー(レイヤー)の処理や、モードの切り替えなどについても、キーマップで行います。
今回は、一般的なQWERTY配列をベースとします。数字キーの列が存在しないため、Let's Splitなどと同じようにレイヤーの概念を導入します。
Baseレイヤー設定
キーマップの基本となるBaseレイヤーを作成して、キーコードを設定します。
キーマップ設定のメイン部分は、以下の部分です。
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = LAYOUT( /* Base */ /* ここにキーコードを書いていく */ ), };
<project_name>.h
でも出てきた LAYOUT
マクロで、実際のキーコードを割り当てていきます。
QMK Firmwareに用意されているキーコードは、以下の公式ドキュメントページで確認できます。
今回用にキーコードを設定しました。わかりやすくなるようにコメントも残していきます。
#define BASE 0 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* Base * ,------------------------------------------------. ,------------------------------------------------. * | Tab | Q | W | E | R | T | Reset| | Reset| Y | U | I | O | P | Bksp | * |------+------+------+------+------+------+------| |------|------+------+------+------+------+------| * | LCTL | A | S | D | F | G | ( | | ) | H | J | K | L | ; |Enter | * |------+------+------+------+------+------+------| |------+------+------+------+------+------+------| * |LShift| Z | X | C | V | B | [ | | ] | N | M | , | . | / | ' | * |------+------+------+------+------+------+------+ |------+------+------+------+------+------+------| * | LGUI | Alt |LCTRL | LGUI | Lower| Space| ESC | | C-Spc| Space| Raise| Left | Down | Up |Right | * `------------------------------------------------' `------------------------------------------------' */ [BASE] = LAYOUT( KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , RESET , RESET , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_BSPC, \ KC_LCTL, KC_A , KC_S , KC_D , KC_F , KC_G , KC_LPRN, KC_RPRN, KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_ENT , \ 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, KC_QUOT, \ KC_LGUI, KC_LALT, KC_LCTL, KC_LGUI, XXXXXXX, KC_SPC , KC_ESC , LCTL(KC_SPC), KC_SPC , XXXXXXX, KC_LEFT, KC_DOWN, KC_UP , KC_RGHT \ ), };
まだ Raise/Lowerレイヤーを作っていないので、それぞれのレイヤー用のキーは XXXXXXX
にしています。
これは、押しても何も反応しないキーという意味です。
Raise/Lowerレイヤー設定
Let's Split等のように、Lower
キーや Raise
キーを押しているときのキーマップを設定します。
Baseレイヤーと同じように、キーマップを作製します。
レイヤー適用中もBaseレイヤーと同じキーでよい場合は、
キーコード KC_TRNS
または _______
を指定します。
#define BASE 0 #define LOWER 1 #define RAISE 2 const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { ... /* Lower * ,------------------------------------------------. ,------------------------------------------------. * | ~ | ! | @ | # | $ | % | | | | ^ | & | * | ( | ) | | * |------+------+------+------+------+------+------| |------|------+------+------+------+------+------| * | | | | | Del | End |PgDown| | | _ | + | { | } | | | | * |------+------+------+------+------+------+------| |------+------+------+------+------+------+------| * | F1 | F2 | F3 | F4 | F5 | F6 | | | | F7 | F8 | F9 | F10 | F11 | F12 | * |------+------+------+------+------+------+------+ |------+------+------+------+------+------+------| * | | | | | | | | | | | | | | | | * `------------------------------------------------' `------------------------------------------------' */ [LOWER] = LAYOUT( KC_TILD, KC_EXLM, KC_AT , KC_HASH, KC_DLR , KC_PERC, _______, _______, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, _______, \ _______, _______, _______, KC_DEL , KC_END, KC_PGDN, _______, _______, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, _______, \ KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , _______, _______, KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ ), /* Upper * ,------------------------------------------------. ,------------------------------------------------. * | ` | 1 | 2 | 3 | 4 | 5 | | | | 6 | 7 | 8 | 9 | 0 | | * |------+------+------+------+------+------+------| |------|------+------+------+------+------+------| * | | | |Insert| Home | PgUp | | | | - | = | [ | ] | \ | | * |------+------+------+------+------+------+------| |------+------+------+------+------+------+------| * | |PtScr |ScLock| Pause| | | | | | | | | | | | * |------+------+------+------+------+------+------+ |------+------+------+------+------+------+------| * | | | | | | | | | | | | | | | | * `------------------------------------------------' `------------------------------------------------' */ [RAISE] = LAYOUT( \ KC_GRV, KC_1 , KC_2 , KC_3 , KC_4 , KC_5 , _______, _______, KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , _______, \ _______, _______, _______, KC_INS , KC_HOME, KC_PGUP, _______, _______, KC_MINS, KC_EQL , KC_LBRC, KC_RBRC, KC_BSLS, _______, \ _______, KC_PSCR, KC_SLCK, KC_PAUS, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, \ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ \ ),
LowerレイヤーとRaiseレイヤーを作りましたが、 BaseレイヤーのLowerキーとRaiseキーに何も割り当てられてないので、動作しません。
MO(layer)
を使用して、LowerキーやRaiseキーを押下している間のみ、それぞれのレイヤーが適用されるように修正します。
先ほど仮に XXXXXXX
としていたところを MO(LOWER)
MO(RAISE)
に変更してください。
[BASE] = LAYOUT( KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , RESET , RESET , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_BSPC, \ KC_LCTL, KC_A , KC_S , KC_D , KC_F , KC_G , KC_LPRN, KC_RPRN, KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_ENT , \ 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, KC_QUOT, \ KC_LGUI, KC_LALT, KC_LCTL, KC_LGUI, MO(LOWER), KC_SPC , KC_ESC , LCTL(KC_SPC), KC_SPC , MO(RAISE), KC_LEFT, KC_DOWN, KC_UP , KC_RGHT \ ),
これでLowerキーとRaiseキーが動作するようになりました。 ひとまずこれでファームウェアの設定は完了です。
ビルドと書き込み
ファームウェアの設定ができたら、まずはビルドします。
$ make ergock:default
エラーが出た場合は、メッセージに従って修正してください。
ビルドに成功したら、書き込み先のProMicroをPCに接続して、 以下のコマンドで書き込みます。
$ make ergock:default:avrdude
コマンドを実行してしばらくすると Detecting USB port, reset your controller now.
と表示され、
avrdude
が書き込み対象のデバイスを探し始めます。
ここでProMicroをリセットすると、 avrdude
がProMicroを認識し、処理が再開されます。
ProMicroの RST
ピンと GND
ピンを短絡させることでリセットできます。ピンセットなどで一瞬だけ短絡させてください。
(すでにQMK Firmware書き込み済みのProMicroの場合は、 キーコードに RESET
を設定したキーを押下したのでもOKです。)
書き込みが正常に終われば、以下のようなメッセージが表示されているはずです。
avrdude.exe: verifying ... avrdude.exe: 24448 bytes of flash verified avrdude.exe done. Thank you.
これでファームウェアの準備が整いました。 次は、キースイッチとProMicroを配線していきます。