Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Docs] Japanese translation of docs/understanding_qmk.md #10136

Merged
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
196 changes: 196 additions & 0 deletions docs/ja/understanding_qmk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
# QMK のコードの理解

<!---
original document: 0.9.55:docs/understanding_qmk.md
git diff 0.9.55 HEAD -- docs/understanding_qmk.md | cat
-->

このドキュメントでは、QMK ファームウェアがどのように機能するかを非常に高いレベルから説明しようとしています。基本的なプログラミングの概念を理解していることを前提としていますが、(実証する必要がある場合を除き) C に精通していることを前提にはしていません。以下のドキュメントの基本的な理解をしていることを前提としています。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

* [入門](ja/getting_started_introduction.md)
* [キーボードがどのように動作するか](ja/how_keyboards_work.md)
* [FAQ](ja/faq.md)

## スタートアップ

QMK は他のコンピュータプログラムと何ら変わりないと考えることができます。開始され、タスクを実行し、そして終了します。プログラムのエントリーポイントは、他の C プログラムと同様に、`main()` 関数です。ただし、QMK を初めて触る人は、`main()` 関数があちこちに現れるため、混乱するかもしれません。また、どれを見ればよいか分かりにくいかもしれません。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

複数ある理由は、QMK は様々なプラットフォームをサポートするからです。最も一般的なプラットフォームは `lufa` です。これは atmega32u4 のような AVR プロセッサ上で実行されます。また、`chibios` および `vusb` もサポートします。

ここでは AVR プロセッサに焦点を当てます。これは `lufa` プラットフォームを使います。`main()` 関数は [tmk_core/protocol/lufa/lufa.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/protocol/lufa/lufa.c#L1028) にあります。関数にざっと目を通すと、(ホストへの USB も含めて)設定された全てのハードウェアが初期化され、プログラムのコア部分が [`while(1)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/protocol/lufa/lufa.c#L1069) で開始されることが分かります。これが[メインループ](#the-main-loop)です。

## メインループ

コードのこの部分は、同じ命令セットを永久にループ処理するため、"メインループ"と呼ばれます。ここはキーボードに必要なことを実行させる関数を QMK が割り当てる場所です。一見、多くの機能を持つように見えるかもしれませんが、大抵の場合、コードは `#define` によって無効にされます。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

```
keyboard_task();
```

ここで、全てのキーボードの固有の機能が実行されます。`keyboard_task()` のソースコードは [tmk_core/common/keyboard.c](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/keyboard.c#L216) にあり、マトリックスの変化を検知し、LED の状態をオンオフする責任があります。

`keyboard_task()` に以下を処理するコードがあります:

* [マトリックスのスキャン](#matrix-scanning)
* マウスの処理
* シリアルリンク
* Visualizer
umi-umi marked this conversation as resolved.
Show resolved Hide resolved
* キーボードの状態の LED (Caps Lock, Num Lock, Scroll Lock)

#### マトリックスのスキャン

マトリックスのスキャンはキーボードファームウェアのコアの機能です。これは今どのキーが押されているかを検知するプロセスであり、キーボードはこの機能を1秒間に複数回実行します。ファームウェアの CPU 時間の 99% はマトリックスのスキャンに費やされていると言っても過言ではありません。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

実際のマトリックスの検知には様々な方法がありますが、それはこのドキュメントのスコープ外です。マトリックスのスキャンをブラックボックスとして扱っても問題ありません。マトリックスの現在の状態を尋ねると、以下のようなデータ構造を取得します:
umi-umi marked this conversation as resolved.
Show resolved Hide resolved


```
{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
}
```

これは 4行x5列のテンキーの直接的な表現のデータ構造です。キーが押されると、マトリックス内のそのキーの位置が、 `0` ではなく `1` として返されます。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

マトリックスのスキャンは1秒間に複数回実行されます。正確なレートは様々ですが、知覚できるような遅延を避けるために、秒間に少なくとも10回実行します。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

##### マトリックスから物理的なレイアウトへのマップ

キーボード上の各スイッチの状態が分かると、それをキーコードへマップする必要があります。これは、QMK では、物理的なレイアウトの定義とキーコードの定義を分離することができる C マクロを使うことで行えます。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

キーボードレベルで、キーボードのマトリックスを物理キーにマップする C マクロ (一般的には、`LAYOUT()` という名前)を定義します。マトリックスの全ての場所にスイッチがあるわけではないことがありますが、このマクロを使って KC_NO を事前に埋め込むことができ、キーマップの定義を扱いやすくすることができます。以下は、numpad のための `LAYOUT()` マクロです:
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

```c
#define LAYOUT( \
k00, k01, k02, k03, \
k10, k11, k12, k13, \
k20, k21, k22, \
k30, k31, k32, k33, \
k40, k42 \
) { \
{ k00, k01, k02, k03, }, \
{ k10, k11, k12, k13, }, \
{ k20, k21, k22, KC_NO, }, \
{ k30, k31, k32, k33, }, \
{ k40, KC_NO, k42, KC_NO } \
}
```

`LAYOUT()` マクロの2つ目のブロックが、上記のマトリックススキャン配列とどのように一致しているかに注意してください。このマクロはマトリックスのスキャン配列をキーコードにマップするためのものです。ただし、17キーの numpad を見ると、キーが大きいために、スイッチが置けるが実際には無い箇所が3つあることが分かります。これらのスペースに `KC_NO` を設定したので、キーマップ定義に必要はありません。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

このマクロを使って通常ではないマトリックスのレイアウト、例えば [Clueboard rev 2](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/66/rev2/rev2.h) を扱うこともできます。その説明はこのドキュメントの範囲外です。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

##### キーコードの割り当て

キーマップレべルでは、上記の `LAYOUT()` マクロを使って、物理的な場所からマトリックスの場所にマッピングします。以下のようになります:

```
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
[0] = LAYOUT(
KC_NLCK, KC_PSLS, KC_PAST, KC_PMNS, \
KC_P7, KC_P8, KC_P9, KC_PPLS, \
KC_P4, KC_P5, KC_P6, \
KC_P1, KC_P2, KC_P3, KC_PENT, \
KC_P0, KC_PDOT)
}
```

これら全ての引数が、前のセクションの `LAYOUT()` マクロの前半とどのように一致しているかについて注意してください。これが、キーコードを取得して、それを前のマトリックススキャンにマップする方法です。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

##### 状態変更の検知

上記のマトリックススキャンはある時点のマトリックスの状態を伝えますが、コンピュータは変更のみを知りたいのであって、現在の状態を気にしません。QMK は最後のマトリックススキャンの結果を格納し、いつキーが押されたか放されたかを決定するために、このマトリックスから結果を比較します。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

例を見てみましょう。キーボードスキャンループの途中に移動して、前のスキャンが以下のようになっていることを確認します:
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

```
{
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
}
```

現在のスキャンが完了すると、以下のように見えます:
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

```
{
{1,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
}
```

キーマップと比較すると、押されたキーが KC_NLCK であることが分かります。ここから、関数 `process_record` セットを呼び出します。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

<!-- FIXME: Magic happens between here and process_record -->

##### Process Record

`process_record()` 関数自体は一見簡単に見えますが、その内部は QMK の様々なレベルで機能を上書きするためのゲートウェイです。キーボード/キーマップレベルの機能について調べる必要があるときは、以下に列挙した一連のイベントを手引帳として使います。`rules.mk` またはほかの場所で設定されたオプションに応じて、最終的なファームウェアに以下の関数のサブセットのみが含まれます。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

* [`void process_record(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/tmk_core/common/action.c#L172)
* [`bool process_record_quantum(keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L206)
* [このレコードをキーコードにマップする](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L226)
* [`void velocikey_accelerate(void)`](https://github.com/qmk/qmk_firmware/blob/c1c5922aae7b60b7c7d13d3769350eed9dda17ab/quantum/velocikey.c#L27)
* [`void preprocess_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L119)
* [`bool process_key_lock(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_key_lock.c#L62)
* [`bool process_clicky(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_clicky.c#L79)
* [`bool process_haptic(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/2cee371bf125a6ec541dd7c5a809573facc7c456/drivers/haptic/haptic.c#L216)
* [`bool process_record_kb(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/card.c#L20)
* [`bool process_record_user(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/keyboards/clueboard/card/keymaps/default/keymap.c#L58)
* [`bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/rgb_matrix.c#L139)
* [`bool process_midi(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_midi.c#L81)
* [`bool process_audio(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_audio.c#L19)
* [`bool process_steno(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_steno.c#L160)
* [`bool process_music(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_music.c#L114)
* [`bool process_tap_dance(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_tap_dance.c#L141)
* [`bool process_unicode_common(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicode_common.c#L169)
umi-umi marked this conversation as resolved.
Show resolved Hide resolved
以下のいずれかを呼び出します:
umi-umi marked this conversation as resolved.
Show resolved Hide resolved
* [`bool process_unicode(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicode.c#L20)
* [`bool process_unicodemap(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_unicodemap.c#L46)
* [`bool process_ucis(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_ucis.c#L95)
* [`bool process_leader(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_leader.c#L51)
* [`bool process_combo(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_combo.c#L115)
* [`bool process_printer(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_printer.c#L77)
* [`bool process_auto_shift(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_auto_shift.c#L94)
* [`bool process_terminal(uint16_t keycode, keyrecord_t *record)`](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/process_keycode/process_terminal.c#L264)
* [Identify and process Quantum-specific keycodes](https://github.com/qmk/qmk_firmware/blob/e1203a222bb12ab9733916164a000ef3ac48da93/quantum/quantum.c#L291)
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

(`process_record_kb()` のような)関数がこの一連のイベントの中の任意のステップで `false を返す`と、以降の処理を停止することができます。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

この呼び出しの後で、`post_process_record()` が呼ばれます。これはキーコードが通常処理された後に実行する必要がある追加のクリーンアップを処理するために使われるものです。
umi-umi marked this conversation as resolved.
Show resolved Hide resolved

* [`void post_process_record(keyrecord_t *record)`]()
* [`void post_process_record_quantum(keyrecord_t *record)`]()
* [このレコードをキーコードにマップする]()
* [`void post_process_clicky(uint16_t keycode, keyrecord_t *record)`]()
* [`void post_process_record_kb(uint16_t keycode, keyrecord_t *record)`]()
* [`void post_process_record_user(uint16_t keycode, keyrecord_t *record)`]()

<!--
#### Mouse Handling

FIXME: This needs to be written

#### Serial Link(s)

FIXME: This needs to be written

#### Visualizer

FIXME: This needs to be written

#### Keyboard state LEDs (Caps Lock, Num Lock, Scroll Lock)

FIXME: This needs to be written

-->