見出し画像

Vial + Planck rev7 + Rotary Encoders 修正進捗

2024/10/28: Vialのvialブランチに修正が反映されました。よって修正作業は完了となります。数ヶ月間、ありがとうございました。
以下の文章は、いつかのために残しておきますが、QMKのmasterブランチやVialのvialブランチというリリース対象となるブランチを使うことにより、Planck rev7 にエンコーダーを搭載して快適に使えるようになっています。

Layout タブのEncodersをチェックすると、Vial画面からエンコーダーの設定を変更出来ます。

この記事は、Planck に ロータリエンコーダー を装備させたときにQMKで発生する不具合とその修正具合についてまとめていた記事である。

画像:
* Planck rev7
* DROP + THE LORD OF THE RINGS™ MT3 ELVISH KEYCAP SET(ET3プロファイル エルフ語キーキャップ)
* 2 Encoders(BOURNS PEC11R-4015F-S0024 デテント無し)
    * readme.md 上ではデテントが必要のようだが実際はデテント無しでも大丈夫そう。(ただし、反応が悪い時ある気がする。追記: 接触不良の可能性大。)
* 2 WUQUE STUDIO Zoom75 Extra knob
* アリエクの光るUSBケーブル(たまに接続不良)




進捗・まとめ

  • [済み] 最新のコードに追随できていない

  • [済み] 不具合

  • [済み] ENCODER_MAP_ENABLE関連

  • [済み] QMKレポジトリ、developブランチへのMerge

  • [済み] QMKレポジトリ、masterブランチへのMerge

    • 2024/08/26: Merge済み。0.26.0でmasterブランチ入り

  • [済み] VIAL へのPullRequestとMerge

    • 2024/10/27: Merge済み。

修正進捗

問題が多いので少しずつクリアしていく。作業時のメモを含むため本章の記載は古い可能性がある。
最新の状態は上記の「進捗・まとめ」を参照すること。

1. 最新のコードに追随できていない

keyboards/planck/rev7/matrix.c に記載されているコードを更新する。
具体的には https://github.com/qmk/qmk_firmware/blob/master/docs/ChangeLog/20240225.md#notable-core-changes-notable-core に記載のことができていない。もちろん、まだ、下位互換がまだあるようだが、そのうち使えなくなるはず。

追記: ここは既にqmk本体側で対応済みだった。vial側でも次第に対応されるはず。
追記2: Mergeされる直前にRGB関連のキーコードの修正があることに気が付いたため、対応した。

2. 不具合について

公式DiscordのForumで以下通りやりとりさせてもらい、認識はされているけど、直っていない不具合ということが分かっている。
また 9d9cdaaa2d035787b0b50c26f2975695fdbc16f4 のコミットを使う事により問題無いことが分かっている。

Issue with Rotary Encoders on Planck rev 7

Hello,

I am currently facing an issue with setting up Rotary Encoders on my Planck rev 7 keyboard. I have tried using the default Planck rev 7 rules.mk file with the ENCODER_ENABLE = yes configuration, but the encoders are not functioning as expected.

I have tried using the PEC12R-4222F-S0024 encoder from Yushakobo, as well as other may compatible encoders from Aliexpress. However, none of them seem to work properly. The encoders respond to both clockwise and counterclockwise rotations, but the values of index and clockwise passed to the encoder_update_user function are incorrect.

I have soldered the encoders to Number 0, 3, and 7, but the behavior is the same bugs. For example, when rotating the encoder connected to Number 3 clockwise, the `clockwise` value is 0 and the `index` value is 5, 7, or random (occasionally, the `clockwise` value is 1 and the correct `index` is passed).

I have checked the soldering connections multiple times, but everything seems fine. I have also confirmed that the `ENCODER_RESOLUTION` value is set to 4, which is the default.
I have checked the datesheet of PEC12R-4222F-S0024 and PEC11R-4215F-S0024.
I have included some sample output from the HID console below:

keymap.c

```
bool encoder_update_user(uint8_t index, bool clockwise) {
printf("encoder_update_user\n");
printf("+ index: %d\n", index);
printf("+ clockwise: %d\n", clockwise);
printf("+ get_highest_layer(layer_state): %d\n", get_highest_layer(layer_state));
```


HID console

```
> encoder_update_user
> + index: 6
> + clockwise: 0
> + get_highest_layer(layer_state): 0
> encoder_update_user
> + index: 2
> + clockwise: 0
> + get_highest_layer(layer_state): 0
> encoder_update_user
> + index: 5
> + clockwise: 0
> + get_highest_layer(layer_state): 0
> encoder_update_user
> + index: 1
> + clockwise: 0
> + get_highest_layer(layer_state): 0
> encoder_update_user
> + index: 5
> + clockwise: 0
> + get_highest_layer(layer_state): 0
```

QMK の公式DiscordのForumに投稿された内容より

yeah, there is an issue with the encoder code for the rev7
git revert 9d9cdaaa2d035787b0b50c26f2975695fdbc16f4 should fix that, short term

QMK の公式DiscordのForumに投稿された内容より

yeah, that commit is adding abstraction/driver support for encoders, and changes the code for the planck rev7. Unfortunately, it looks like there is some issues with the changes, and ideally need somebody with a rev7 to do some testing/etc.
and you're not the first to have issues with this

QMK の公式DiscordのForumに投稿された内容より

めっちゃyeah yeah言いよる。中華系カナダ人の友人が、何か言うと4回ぐらいyeah言う人だったことを思い出した。中身同一人物か?ってレベル。

不具合は上記のPRで混入した。おそらく、PRを出した人はエンコーダーが複数設定されることを想定していなかったのではないか。
というのも、PRの実装では何度もPIN読み取りを初期化するような処理が走るせいで、変な挙動をする。
どのように、修正すればいいか分からないため、Jack Humbert氏が作ったものをほぼそのまま移行する形で修正した。
具体的には encoder_driver_task というドライバー側の処理を上書きする形で、その修正をした。
コードレビュー時に抽象化したコードを使えという話になったので、PINの状態読み取りを同時ではなない形で強制されることとなっている。従って、若干のラグはあるかもしれないが、他のキーボードと同じなので分からない程度だとおもう。

encoder_quadrature_read_pin の呼び出し元が、 encoder_driver_taskなので、そこから上書きをしてしまえばいいという作戦である。
もっと良い形があるならば教えてほしい。


もし、この作戦がダメでQuadratureのドライバを使うことがだめならば、自身で書いてやらないといけなくなる。大変だ…。

3-1. Planck が ENCODER_MAP_ENABLE に対応していない

これはハードウェア的な問題ではなくソフトウェア(QMK)的な問題だったはず。というのも、最新の状態ではENCODER_MAP_ENABLEに対応しているかのような状態で、encoder_mapで定義が出来た(はず)この「はず」というところがキモで、エンコーダーを0番、3番、7番でつかっていたときに問題無く動いていた気がする..。という曖昧な記憶に基づくもののため。では、実際にはどうだったかというと、ソフトウェア的な問題だった。

3-2. Planckに装備されているロータリエンコーダーにあてられるキーコードをVIALなどで変更できない

以下のコードに書いておいたが、VIALの画面で設定できる場所と、コンパイル時?に使われるものが違う。
ただ、単純に設定方法が待ちがっているだけ… という気もしている。凡ミスが原因な気もするので、時間かければ直る気がする。

const uint16_t PROGMEM encoder_map[][NUM_ENCODERS][NUM_DIRECTIONS] = {
    //  不具合: VIALの画面とコンパイラで参照する場所が違う
    [0] = { ENCODER_CCW_CW(KC_A, KC_S)/* ←VIALの画面的には3番目のエンコーダ */, ENCODER_CCW_CW(KC_D, KC_F) /* ←VIALの画面的には7番目のエンコーダ */, ENCODER_CCW_CW(KC_G, KC_H), ENCODER_CCW_CW(KC_J, KC_K)/* ←コンパイラ的には3番目のエンコーダ */, ENCODER_CCW_CW(KC_L, KC_Z), ENCODER_CCW_CW(KC_X, KC_C), ENCODER_CCW_CW(KC_V, KC_B),  ENCODER_CCW_CW(KC_N, KC_M)/*←コンパイラ的には7番目のエンコーダ */ },
    [1] = { ENCODER_CCW_CW(KC_A, KC_S), ENCODER_CCW_CW(KC_D, KC_F), ENCODER_CCW_CW(KC_G, KC_H), ENCODER_CCW_CW(KC_J, KC_K), ENCODER_CCW_CW(KC_L, KC_Z), ENCODER_CCW_CW(KC_X, KC_C), ENCODER_CCW_CW(KC_V, KC_B),  ENCODER_CCW_CW(KC_N, KC_M) },
    [2] = { ENCODER_CCW_CW(KC_A, KC_S), ENCODER_CCW_CW(KC_D, KC_F), ENCODER_CCW_CW(KC_G, KC_H), ENCODER_CCW_CW(KC_J, KC_K), ENCODER_CCW_CW(KC_L, KC_Z), ENCODER_CCW_CW(KC_X, KC_C), ENCODER_CCW_CW(KC_V, KC_B),  ENCODER_CCW_CW(KC_N, KC_M) },
    [3] = { ENCODER_CCW_CW(KC_A, KC_S), ENCODER_CCW_CW(KC_D, KC_F), ENCODER_CCW_CW(KC_G, KC_H), ENCODER_CCW_CW(KC_J, KC_K), ENCODER_CCW_CW(KC_L, KC_Z), ENCODER_CCW_CW(KC_X, KC_C), ENCODER_CCW_CW(KC_V, KC_B),  ENCODER_CCW_CW(KC_N, KC_M) },
};

こちら、修正完了済みである。Planckの良いところといえば、8つのエンコーダーに対応と考えている。それならば元から8つのエンコーダーに対応したvial.jsonを書いておいた方が使用者の為と考え、その形で修正をした。
(追記: この思想でPullRequestをおくってMergeされるかは分からない。)

使用している KLEファイル: ピンク色がロータリーエンコーダー関連になるところ。(もちろん、無駄が不要な方は http://www.keyboard-layout-editor.com/#/gists/f8c286f3f31edb0aa95ef9a51ab251b3 のようにしてもいいはず)
追記(2024/09/09): Planckを初めて触ったとき、エンコーダーの設定方法がサッパリ分からなかったことを記憶しています。そのため、エンコーダーを含むvial.jsonをVialのPRに反映する予定でしたが、Layoutタブにてエンコーダーの有無を選択出来るようにしました。(つまり、エンコーダーが欲しい人と欲しくない人が同じvial.jsonを利用出来るようにしたいと考えてます)
追記(2024/10/28): 一部、レイアウトをVialブランチに既にあるものを基準に修正したものをvialブランチにMergeしてもらいました。そのため、私の作業ブランチにあるレイアウトとは少々違うものとなっています。1U*2といった構成を使っている方は大丈夫だと思いますが、2U + 2U といった構成などであると不都合があるかもしれません。

8つのエンコーダーに対応したPlanckのKLE。0,1 や 1,1 といったlegendとeが大切。(index, Clockwise) といった並び順。3番と7番なら3,0 と 3,1 と7,0 と 7,1の定義が必要。

また、一番左上にて設定が1,0だったとき(エンコーダーが有効だったとき)の表示を綺麗に見せるために、decalを追加が必要。
Layoutタブに、エンコーダーの有無を選択出来るようになっている画面
Planck が ENCODER_MAP_ENABLE に対応し、encoder_mapで各ロータリエンコーダーを変更できる状態の画面

MEMO 調査方法
quantum/dynamic_keymap.c の dynamic_keymap_reset でENCODER_MAP_ENABLEが定義されているときに dynamic_keymap_set_encoderが登録されるのは分かっているが、VIAL_ENABLEが有効なときの挙動についてうまく理解できていない。
おそらく、VIALなどを使わず、QMK単体で使うなら、ここは意識しなくて良いかもしれない。

MEMO 利用価値のありそうなデバッグメッセージ

ファイル: drivers/encoder/encoder_quadrature.c

// static int8_t encoder_LUT[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};

void encoder_quadrature_handle_read(uint8_t index, uint8_t pin_a_state, uint8_t pin_b_state) {

    // 2ビットの状態を作成する bit的には ba の形になる。
    // uint8_t state = pin_a_state | (pin_b_state << 1);
    uint8_t state = (pin_a_state << 0) | (pin_b_state << 1);

    // (encoder_state[index] & 0x3) が記録されている最後の状態。stateが今の状態
    if ((encoder_state[index] & 0x3) != state) {

        //printf("<eqhr> %d is before %d, will state: %d\n", index, (encoder_state[index] & 0x3), (state & 0x3));

        // 左に2ビットシフトして、新しいのを入れられるようにする
        encoder_state[index] <<= 2;

        // 空いたところの2ビットに新しい状態を保存する
        encoder_state[index] |= state;

        // イベントを発火
        encoder_handle_state_change(index, encoder_state[index]);
    }
}

QMK/VIA、VialのPullRequestについてMEMO

次回以降のために、感じたことを書く。

QMK/VIA

  • Discordで事前に連絡をしておくと、かなりスムーズにPullRequestの確認を進めてくれる。

  • 実装がよくないため、ほぼ確実にChange requestな状態になるとおもうが、それらを踏まえるとdevelopブランチにMergeされるのが2週間から3週間かかる。

  • masterブランチにMergeされる(リリースされる)のは、おおよそ3ヶ月おき。(5月末→8月末→11月末(?))

    • その間の小さい修正は、逐次リリースされる。

  • VIA キーマップは変更しなくてもMergeされる。(たぶん)

  • PullRequestのテンプレートに書いてある文章が長い。頑張って読む必要がある。

Vial

  • QMKのmasterブランチが定期的に取り込まれる

    • QMKがリリースされると、リリースブランチのようなブランチがQMKのリリース後1週間程度で作られ、その後、数日でvialブランチにMergeされる。ただ、Mergeに1ヶ月程度掛かることもあるようだ。

    • vialブランチは、vial-qmkのmasterとなるブランチ。HEADとなるブランチ。

  • QMK側で管理するコードには手をいれるべきではない。(たとえば、defaultキーマップなど)

    • vialキーマップのみ手を入れた方が良さそう。Vialの問題ではないものは、QMKをまず修正するべき。

  • PullRequestのテンプレートに書いてある文章は大した量はない。読むしかない。

  • Mergeは非常にスムーズ、一瞬で終わる。

QMK と Vial

* だいたい、PRだしてから3ヶ月ぐらいかかる。Vialに反映されるまで。

感想・雑記

  • 2024/06/20 昼:
    本業がphp、rails、iOSという感じで、レイヤーが高い人間なので、低レイヤーの実装は久々である。Obj-Cを含めずに最後にC-lang一族とふれあったのはOpenCVのときでほぼ前世なので今世は初めて。組み込み系などのビット列を意識した実装も前世以来である。そもそもQMKを自身で使うのは初めてで、不具合が多く感じてだいぶ印象が悪い。

  • 2024/06/20 夜:
    時間をみつけて、少し触っていたらvial.jsonを間違って書いていたことに気が付く。ロータリエンコーダーを0番に設定していたときにうっすらと問題無く動いていた気がするのがきっかけで気が付けた。あとはPullRequestに向けてコードを整え、削除しすぎた箇所はもとにもどせば良いだけとなった。とても達成感がある。

  • 2024/06/21 昼:
    PullRequestを送った後、DiscordのForumにコメントを書いておいたら直ぐに対応してくれた。一部、よくない実装があったようで、どのようにすればいいかPullRequest上でやりとり中。

  • 2024/07/08 昼:

    • 今朝、developブランチへMergeされたとの通知あり。

  • 2024/07/12 昼:

    • qmk側masterブランチにMergeされていないが、developブランチにMergeされてしばらくたっているので、そのうちmasterにMergeされるだろう。また、VIAL側にqmkのdevelopにMergeされたコードをもってきて動作確認したが、問題はなさそうである。

  • 2024/08/28 昼:

    • 26日にQMKにMergeされた。あとは、Vial側対応となる。が、Vial側にQMKのmasterブランチがMergeされていない。そのため、再開できない…もどかしい。

  • 2024/09/09 深夜:

    • VialのコードをPullRequest向けに整える作業中。vial.jsonのlayoutにエンコーダーを使うか使わないか設定を含ませる修正をして、エンコーダーを使わないPlanck使いからの批判を避けたいと考えている。

  • 2024/09/10 昼:

    • VialへのPullRequest準備完了。ロータリエンコーダー有無のレイアウトを整えた。(一旦、エンコーダーがあるか、ないかだけのチェックにする)

    • PullRequest時に、個別にエンコーダーの有無を変更出来るようにしろという話があれば、そのようになるとおもうが、現状でいいのでは?と思っている。(いまのレイアウトはエンコーダーを使いたい初学者に対して厳しいから、マシになるのは絶対なはずなので)

  • 2024/09/26 夜:

    • Vialにqmkのmasterブランチ取り込みがまだされない。

    • 以前のログから考えると、変

  • 2024/10/08 昼:

    • あと少しでPR出せますが、時間を作れていないのでまだ時間かかります。

  • 2024/10/20 昼:

    • 仕事が忙しくなってしまい土日すらない状態が継続中。まだ時間かかります。

  • 2024/10/26 昼:

    • 時間が作れたのでPullRequest作りました。

  • 2024/10/28 夜:

    • 無事、Mergeされました。終わりました。

参考資料、ほか

  • ロータリエンコーダーの挙動については以下の記事がすごく勉強になった。encoder_update を使った実装は ENCODER_MAP_ENABLEを使う実装とは少し違うので、あくまで一般的なロータリエンコーダーの実装についての学習という形で役に立った。2ビットの動きで回転を表現するってのがよくわかった。

  • 猫山王 氏 の記事でいろいろやりとりさせてもらい、この修正に至っている。色々、ありがとうございました。https://note.com/nekoyamaou/n/nffc1742e6930 https://note.com/nekoyamaou/n/nef832302f7c5


いいなと思ったら応援しよう!