⌨️

QMK Firmwareで自作キーボードのファームウェアをイチから書く

2024/08/19に公開

QMK Firemwareでイチからキーボード構成ファイル(※)を起こす際に最低限やればいいことをまとめたメモです。
環境構築やビルドの話は書きません。公式ドキュメントのチュートリアル参照のこと。

※ ... QMKのkeyboardsディレクトリ以下のファイル群のことを便宜上こう呼びます

QMKのバージョン

本記事執筆時点最新の0.25.22を対象としています。

なおQMKはここ最近キーボード構成ファイルに大きな変更をバシバシ入れてくるので、次のバージョンでは本記事の内容は役に立たなくなっているかもしれません。

前提

The QMK Tutorialを実施し、QMK本体にマージされている何らかのキーボードのファームウェアがビルド可能な状態になっているところからスタートです。

キーボード構成ファイルの理解

GitHubからダウンロードできるQMKのソース一式にはたくさんのディレクトリとファイルがありますが、自分のキーボード構成ファイルを足す上で大事なのはkeyboardsディレクトリだけですので、他は気にしなくていいです。

keyboardsディレクトリは概ね次のような構造になっています。ビルド時のオプションで指定するqmk compile -kb <作者名/キーボード名> -km <キーマップ名>がそれぞれ対応しています。

keyboards/
  作者名/
    キーボード名/
      keyboard.json
      readme.md
      keymaps/
        キーマップ名/
          keymap.c

自分用のキーボードのファームウェアを作成するには、これらのディレクトリとファイルを作成する必要があります。

なお、keyboardsディレクトリにはすでに大量のキーボード構成ファイルが含まれていますが、これらは過去に各作者がQMK本体に自分のキーボード構成ファイルを登録(マージ)したものです。現在ではQMK本体へのマージは受け付けていないようで、徐々に整理が進められています。

ファイルの準備

これらのファイルは一つ一つ手作りしてもいいのですが、qmk new-keyboardという便利なコマンドでテンプレートが一式作れるので使いましょう。会話形式でいろいろ聞いてきますので入力してください。

質問 説明
Keyboard Name 作者名/キーボード名の形式で入力。ディレクトリ名に使える文字だけを使うこと
Your GitHub Username GitHubユーザ名。この値で別にGitHub連携をするわけではないので、単に作者名のことだと思っていい
Your Real Name 同上
Default Layout 既存のキーボードのレイアウトをベースにする場合に選ぶが、構造がわかりづらくなるのでしない方がいい。一番下のnone of the aboveを選ぶ
MCU 採用しているMCUを選ぶと何かとプリセットされる。リストにない場合は採用しているMCU名を指定する。29. atmega32u437. RP2040など

下記は例です。私はよくWaveshare社のRP2040-Zeroというマイコンボードを使いますが、MCUのリストには含まれていないので37. RP2040を選択しています。

$ qmk new-keyboard
Ψ Generating a new QMK keyboard directory

Name Your Keyboard Project
For more infomation, see:
https://docs.qmk.fm/#/hardware_keyboard_guidelines?id=naming-your-keyboardproject

Keyboard Name? ymkn/myawesomekeeb

Attribution
Used for maintainer, copyright, etc

Your GitHub Username? ymkn

More Attribution
Used for maintainer, copyright, etc

Your Real Name?  [ymkn]

Pick Base Layout
As a starting point, one of the common layouts can be used to bootstrap the process

Default Layout?
        1. 60_abnt2
        2. 60_ansi
(略)
        61. tkl_nofrow_iso
        62. none of the above
Please enter your choice:  [62]

What Powers Your Project
For more infomation, see:
https://docs.qmk.fm/#/compatible_microcontrollers

MCU?
        1. bit_c_pro
        2. blackpill_f401
(略)
        14. promicro
        15. promicro_rp2040
(略)
        28. atmega32u2
        29. atmega32u4
(略)
        37. RP2040
(略)
Please enter your choice:  [29] 37
Ψ Created a new keyboard called ymkn/myawesomekeeb.
Ψ Build Command: qmk compile -kb ymkn/myawesomekeeb -km default.
Ψ Project Location: /home/ymkn/vial-qmk/keyboards/ymkn/myawesomekeeb,
Ψ {}Now update the config files to match the hardware!{}

Project Location記載の場所に、下記のファイルが作成されているはずです。

keyboards/
  ymkn/
    myawesomekeeb/
      keyboard.json
      readme.md
        default/
          keymap.c

各ファイルの編集

readme.md

ファームウェアのソースコードを公開しないならば、不要なので削除していいです。

keyboard.json (以前info.jsonと呼ばれていたファイル)

すでに必要最低限の項目が記載されていますので、キーボードの設計に合わせた修正が必要な箇所だけを編集します。

公式ドキュメントAdding Your Keyboard to QMKに要所の説明が記載されているのでこれに従って修正してください。文中ではinfo.jsonと記載されていますが、そのままkeyboard.jsonと読み替えて結構です。

項目 説明
diode_direction キーマトリクスのダイオードの向きです。テンプレートには列から行方向を示すCOL2ROWが記載されていると思います。行から列としている場合はROW2COLに修正しましょう
matrix_pins マトリクス方式を採用している場合の行列位置とマイコンのピン番号の対応関係を定義します。マイコンのピン番号はデータシート上の名称がそのまま認識できるように配慮されています(※)
usb VIDについては頭の痛い問題があります。自分だけで使う場合は特に問題とならないので、他の製品とかぶらなさそうな番号を振りましょう
layouts 配線上のレイアウトと、物理上の配置の対応関係を示します。Keyboard Layout Editorから得られるjsonを加工して貼り付けるのが簡単です
※ピン番号に指定できる名称の定義

実体は_pin_defs.hにて定義されています。サブディレクトリに_pin_defs.hがあればそれも読みます。例えばRP2040用のピン番号はvendors/RPディレクトリ内の_pin_defs.hにて定義されています。

その他記載可能な項目の解説はinfo.jsonのリファレンスが助けになるでしょう。正確な項目定義はスキーマ定義を参照してください。

keymap.c

ここでデフォルトのキーマップを定義します。説明は公式ドキュメントのAnatomy of a keymap.cあたりに説明がありますが、少々難解なので読まなくていいです。要は行と列に対応するキーコードをカンマ区切りで並べて書いていけばよいということです。

// ↓おまじない。いじらない
#include QMK_KEYBOARD_H
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [0] = LAYOUT(
// ↑おまじない。いじらない

// 1行目
KC_ESC, KC_1,
// 2行目
KC_TAB, KC_Q,
// ...
KC_LCTL, KC_Z // 最後はカンマなし

// ↓おまじない。いじらない
    )
};
// ↑おまじない。いじらない

レイヤーを複数定義したい場合は、[0] = LAYOUT(から)までの行をコピーして、[0]の数字を1増やしてください。

下記あたりが注意ポイントになります。

  • あくまで配線上の行と列であって、物理的な配置ではないこと
  • 配線していない場所には何も書かない(KC_NOやKC_TRNSを書いたりしない。カンマを余計に打ったりもしない)
  • 一番最後はカンマ不要
  • [0] = LAYOUT()};など元々記載されているコードを消したりしない(さもないとビルドエラーになります)
細かい話

このファイルはC言語のソースコードそのもので、内容としてはkeymaps定数の定義になります。これはuint16_t型のレイヤー数×行数×列数の3次元配列です。uint16_t型は具体的にはkeycodes.hにて定義されている列挙体の値、つまりはキーコードが指定されることを想定しています。

keymaps定数の初期化はLAYOUTマクロによって行われています。このLAYOUTマクロがどのように定義されているのかまでは詳しく追っていませんが、(行数×列数)個の引数で与えられたキーコードの羅列に、C言語の多次元配列の初期化子を付与するような処理を行っているように見えます。

keyboard.jsonの"layouts"要素の直下"LAYOUT"がマクロ名として、その直下の"layout"内の要素数が引数の数として採用されているようで、これらとkeymap.c内のマクロ名や要素数が合っていないとビルドエラーになります。

ここだけC言語の香りが残っているので、ここもいずれkeyboard.jsonに集約されるんですかね?今後の動向に期待。

ビルド

以上です。keyboard.jsonに集約されたおかげで作成すべきファイルが減り、大分すっきりしましたね。

QMKのソースを配置したディレクトリ直下でqmk compile -kb <作者名/キーボード名> -km <キーマップ名>でビルドできます。

VIAについて

VIAについては私は詳しくないので割愛します。

Vialについて

公式の移植ガイド通りで特に問題なくビルド可能です。つまり、vialキーマップ用のディレクトリ内のconfig.hとrules.mkは今まで通り必要です。これもいずれkeyboard.jsonに書けるようになるといいですね。

Discussion