おかゆ++

IT業界の片隅で生き残るブログ

8.QMK Firmwareの設定と書き込み【手配線で自作キーボードを作る講座】

f:id:okayu-moka:20190901155543p:plain

この記事は、【手配線で自作キーボードを作る講座】の第8回目です。 そのほかの記事はこちら

QMK Firmwareの入手

QMK Firmwareの本体はGitHubから取得できます。

github.com

また、ビルド環境の構築方法や書き込み手順などは、公式サイトおよびドキュメントに記載されています。 なにか困ったらここを確認するようにしてください。

qmk.fm

docs.qmk.fm

必要なソフトウェアのインストール

QMK Firmwareのアップデートなどによって色々と変更されることもあるため、ここではあまり詳細な手順は紹介しません。 基本的には公式ドキュメントの Getting Started を見て進めてください。

公式ドキュメントが英語で少々敷居が高いですが、日本語で解説している記事なども多くありますので、 随時調べながら作業していきましょう。

Window、MacLinuxでそれぞれ必要なソフトが異なってきます。 ご使用の環境に合わせてセットアップしてください。

QMK Firmware Getting Started

Windowsの場合の例

以下、2019/08/24 時点でのWindowsの場合の手順を記載します。 前述のとおり手順が変更されている可能性もあるため、基本的に公式ドキュメントを正として、以下は参考程度にしてください。

MSYS2をダウンロードします。環境に合わせて、32bit版か64bit版のどちらかを選んでください。 ダウンロード後、インストーラに従ってインストールします。

www.msys2.org

インストール完了後、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に用意されているキーコードは、以下の公式ドキュメントページで確認できます。

QMK Firmware keycodes

今回用にキーコードを設定しました。わかりやすくなるようにコメントも残していきます。

#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を配線していきます。

次の記事:

okayu-moka.hatenablog.com