🎱

トラックボール付き自作キーボードをさらに使いやすくするファームウェア 【Keyball】【cocot46plus】

2022/12/03に公開約4,100字13件のコメント

この記事はキーボード #2 Advent Calendar 2022の4日目の記事です。

今年も多種多様な自作キーボードが登場しましたが、トレンド…と表現するのが適切か分かりませんが、トラックボール付きのキーボードの躍進が目覚ましかったように思えます。

https://www.youtube.com/watch?v=XyoEP3h4iB8

https://www.youtube.com/watch?v=U7nu5G_PX5Y

私もcocot46plusとKeyball44を購入して組み立て、愛用しております。
それらにまつわる小話は以下の記事に記載しておりますので宜しければ御覧ください😁
https://zenn.dev/takashicompany/articles/b18f6ec2e22030

またaki27さんが設計されたmeishi Trackball Moduleの登場で、より自作キーボードのキットにトラックボールが搭載されることが増えるのではないかと予期しております。
https://www.youtube.com/watch?v=JdEJge-yius

そんな自作キーボード・トラックボール界隈に少しでも貢献できたらと思いまして、当記事を書くに至りました。

miniZoneトラックボールファームウェア

まず、miniZoneとトラックボールファームウェアをご説明します。

miniZoneは私が設計した0.8uキーの30%キーボード]です。

小型ながら、トラックボールやOLEDやBLE Micro Proによる無線化など多機能なオプションが用意されたキーボードです。

トラックボールを搭載した際に、 レイヤーを変えずにクリックやドラッグやスクロールをしたいナァ… という欲求から試行錯誤して完成に至ったファームウェアです。

https://www.youtube.com/watch?v=CvgJOeVlwB8

  • トラックボールを一定距離動かすとマウスレイヤーが有効になる
    • 大抵は末端のレイヤーがマウスレイヤーになります
    • ソースコードを変更すれば任意のレイヤーに設定することも可能
  • マウスレイヤー内にクリックキーやスクロールキーを入れておくことでホームポジションから手を動かすことなく、クリックやスクロールが可能
  • クリック中、またはクリックしている間はマウスレイヤーが有効状態を維持する
    • ダブルクリックやドラッグ、スクロールに対応
  • スクロールキーを押し続けている間はトラックボールを動かすことでスクロール入力
  • マウスレイヤー内のクリックキーやスクロールキー"以外"のキーを押すとマウスレイヤーが解除される
  • 一定時間トラックボールを操作しない場合もマウスレイヤーが解除される

といった仕様となります。

上述のminiZoneの動画で言うと、マウスレイヤーに

Yキー: 左クリック
Uキー: スクロールキー
Iキー: 右クリック

を設定しております。

動画内では使用していませんが

Fキー: 左クリック
Dキー: スクロールキー
Sキー: 右クリック

というようなマッピングも行っており、右手でトラックボールを触りながら左手でクリック系の操作も可能になっております。

Keyball44で使ってみた

https://www.youtube.com/watch?v=1v9imqEokbQ

Keyball44では

Fキー: 左クリック
Dキー: スクロールキー
Sキー: 右クリック

というキーマッピングにしています。

普段は右手でMX Ergoというトラックボールを使っているので、Keyball44のトラックボールは左に取り付けましたね。
当ファームを使うと左手だけでトラックボールの操作とクリック・ドラッグ・スクロールができるので、利き腕をあけた状態でWebの閲覧やチャットを読むことが可能です。
(お行儀悪いけど、おやつ食べながらインターネットするのにも便利です笑)

ファームウェア

ファームウェアは以下で配布しております。

ファームウェアのファイルをダウンロードした後、Pro Micro Web Updaterから書き込むと使用可能です。

当ファームウェアを書き込んだ後に、Remapでキーマップをご自身の慣れたものに変更するとよろしいかと思います。

他のトラックボール付きのキーボードでも使いたい!

こちらの実装を参考に、以下のソースコードをkeymap.cに追加すればおおよそ動作するのではないかと思います。

変更履歴

  • 2023/01/07
    • スクロール時の方向を逆転できるキーを追加(KC_SCROLL_DIR_V, KC_SCROLL_DIR_H)
    • ignore_disable_mouse_layer_keys に追加されたキーはマウスレイヤー時に押下してもマウスレイヤーに戻らない
    • クリック中、スクロール中に通常キーを押してもマウスレイヤーに戻らないようにする

キーマップ内に以下のキーを設定しておくと動作確認がスムーズかと思います。
Keyball44でのサンプルはこちら

enum定義 一般的な機能※
KC_MY_BTN1 左クリック
KC_MY_BTN2 右クリック
KC_MY_BTN3 OSによる
KC_MY_SCR スクロール
KC_TO_CLICKABLE_INC マウスレイヤーが有効になるまでの待機時間を増やす
KC_TO_CLICKABLE_DEC マウスレイヤーが有効になるまでの待機時間を減らす

※ 動作環境によって異なる可能性があります。

キーボードやファームウェア、回路、MCUによっては動作が異なることがあるかもしれません。
その際は変数の値やしきい値を変更して使いやすい設定を探すと良いかと思います。

当ファームウェア、ソースコードは自由に使用・改変していただいて構いませんが、発生した不具合や不利益による責任は負いかねます。ご了承ください。

小話とまとめ

設計者さんにも流用頂けました。

https://twitter.com/aki27kbd/status/1596389766941282305?s=20&t=GsoLhDm9B6x6zevp7YLu-g

余談ですが、遊舎工房のフリーマーケットの参加した際に、来場者の方から「cocot46plusのファームウェア使ってます!」と言われまして、つくって良かったナァと思いました。

普段は自分のキーボードを設計することが主ですが、こういった関わり方も良いナァ…と思った2022年でした!


この記事はmiziZone・トラックボール付き・BLE Micro Pro(有線)で書きました。

Discussion

マウスでのドラッグドロップ中は以下のようなショートカットもあります。
このため、ClickLayerを維持するキーがもう少し多い方がいいような…

A.ドラッグドロップ中に、altを押しながらtab を押しつつ、altを離すことで、ドラッグドロップ先を決定。

B.ドラッグドロップ中に、ctrl+Alt+Aabを一度押し、キーを離す。
  カーソルキー、Home, End, PageDown/PageUp、Tab, Shift+Tabでドラッグドロップ先を選びつつ、
  スペースキー押下で、ドロップ先を選択。(その間クリックは押しっぱなし)

C.ドラッグドロップ中に、Win+Tabを一度押し、キーを離す。
  カーソルキー、Home, End, PageDown/PageUp、Tab, Shift+Tabでドラッグドロップ先を選びつつ、
  スペースキー押下で、ドロップ先を選択。(その間クリックは押しっぱなし)

D.サクラエディタ使用中に、Alt+マウスドラッグで矩形選択。そのまま上記A~Cのドラッグ

E.mery使用中に、Alt+Shift+マウスドラッグで矩形選択。そのまま上記A~Cのドラッグ

A~Cともに、操作中はクリックボタンが押しっぱなしである必要がありますが、
これが、altなどでクリックレイヤーでなくなると、 Btn1のホールドが解除されてしまうような。

(私がショートカットキー変態なだけなので、参考にしても仕方ないのですが)
ちなみに、「A」と「B」は、会社の仕事では、多用してます。

自信の環境では、頂いたソースをもとに応用&活用させていただいており、大変感謝しております。

コメントありがとうございます。

a. クリック中はマウスレイヤーを解除しない
b. 指定されたキーを押したときはマウスレイヤーを解除しない

という機能のいずれかがあれば、ある程度はご要望のカバーはできそうですかね。

bはどこまでカバーするか次第ですが、ファームウェアビルドできる前提とかであれば、そこまで難しくない気はしました。

aにすれば、他のキーがあったときにも困らないですね。
bだとWindowsのalt+tabを片手で押す必要がある配置を、マウスレイヤーに寄せられますね。

どっちにもメリットがあるので、私の使い方だとと両方の機能を活かしたロジックにするのが良さそうです。
(最初はbだけで考えてたので相談して良かったです😄)

ソースコード部分を改善してみました。

  • スクロール時の方向を逆転できるキーを追加(KC_SCROLL_DIR_V, KC_SCROLL_DIR_H)
  • ignore_disable_mouse_layer_keys に追加されたキーはマウスレイヤー時に押下してもマウスレイヤーに戻らない
  • クリック中、スクロール中に通常キーを押してもマウスレイヤーに戻らないようにする

aとbの両方を実装してみた感じです。
よろしかったらお使いください。
まだ、私の手元で試しただけですので、感想など頂けますと幸いです。

マウスレイヤーにあるときにcontrol キーや、Shiftキーをholdして複数ファイル選択するときいつもマウスレイヤー解除されるのが気になっていたので、まさにこのファームウェアが解決すると思ったのですが(ちょっと構文例のstate == clicking のところclickableに変えて使ってみました)、ignore_disable_mouse_layer_keysで設定したmodifier キーを押下してもマウスレイヤー維持は成功したのですが、今度は肝心のmodifier キーの方が入力されませんでした。何故でしょう?

早速ありがとうございます!問題なくモディファイアキーの入力が反映されるようになりました。マウスレイヤー解除を回避したいキーの設定や組み合わせ色々試してみます!

良かったです!

私はそういった操作はあまりしないので、ためになるご意見頂けて助かります。
もしよろしければSNSなどにファームウェアの作例など載せていただけますと他の方の参考になるかと思います。
よろしければなにとぞ🙏

書き込みに慣れていないので、すいませんベタ打ちでの記載となりますが。。
takashicompanyさんのソースコードを例にしますと、

//////変更点/////

59行目:

const uint16_t ignore_disable_mouse_layer_keys[] = {KC_LSFT, KC_LCTL, KC_LALT};

// 対象のModifierキーをショートカットで使用したいものに変更。Ctrl、Shift、Altキーを入れておけば大体のマウス操作時のショートカットがカバーされると思います。

194~210行目:

        if  (record->event.pressed) {
            if (state == CLICKABLE)
          {
            for (int i = 0; i < sizeof(ignore_disable_mouse_layer_keys) / sizeof(ignore_disable_mouse_layer_keys[0]); i++)
            {
                if (keycode == ignore_disable_mouse_layer_keys[i])
                {
                    enable_click_layer();
                    return true;
                }
            }
          }
            disable_click_layer();
        }

// 194行目のstate確認の条件式をCLICKING// SCROLLINGからCLICKABLEへ変更。これでマウスを操作している間(マウスボタンを離し、click_timer中の次のマウスボタン操作待機中も含め)の指定のModifierキー押下によるマウスレイヤ解除を避けることができた。

// 196~198行目までの3行分を無効にし208行目に”}”を追記して、for文のreturn true;までをif文の中に納めた。もとのソースコードだと他のLayerにいても指定のModifierキーを押下するとマウスレイヤに移動してしまったための変更。これでマウスレイヤにいるときのみ適用になる条件文とした。

//////以上/////

tnさんが書かれたA~Eのショートカットも試してみましたが、上記コード変更でドラッグ解除されることなく実行できました。また、私がしたかった、マウスレイヤの待機時間中にショートカットで使用するModifierキーを押下してもマウスレイヤが解除されることもなくなりました。

私の仕事環境ではパワポやエクセルにて、CtrlやShiftを押しながらクリックすることで複数のオブジェクト・セルを選択する操作を行うことが多いです。Modifierキーをおすとマウスレイヤが解除されてしまうとマウスボタンを押したつもりがレイヤ0の通常キーが間違って押されてしまうという誤爆が度々あったため、今回のこのModifierキー除外を適用することで解決しました。

ご丁寧にありがとうございます。
なるほど、自分とは必要な操作が異なるのでためになりました…!

上記、実用レベルの調整までは考えずに書いているのですが。

いろいろとありがとうございます。以下、長いコメントになりますこと、お許しください。

実は、この1か月、今回、ご相談したこと以外にも、cocotのファームウェア改造については、いろいろ試行錯誤していました。
(ここで、相談した機能以外にもいろいろ手を入れてしまっていたので、よけいな遊びを一旦消さないと、ここには出せないのですが・・)

さて、今回ご相談した件ですが、自分で試行錯誤してみた限りですと、最初にお伝えしたこと以外にも必要なことが見えてきました。

具体的には、以下の通りです。

・ctrl , shiftなどを「レイヤーから脱しないキー」に追加するだけではダメで、mod-tapキーの制御も必要。
具体的には、以下のの3つに対して制御がないと実用的にならない。
A.「hold-tapキー」などのDual Rollのキーで、[alt(macのoption?), shift, ctrl]のbitが立っているとき。
B.単独の、[alt, shift, ctrl]を押されたとき。
C.キーマップで、ALT+?などの、[alt, shift, ctrl]の「modified tap」キーを押されたとき

これらを全部、除外キーに入れても「hold tapキー」のマッピングを変えるとファームも変えないといけなくなるので、keycodeの配列より、対象のビットで判断した方がよさそうです。

・現在のCLICKINGレイヤーに移動する条件に、「ALT+CLICK」などのmodifiedなクリックも加えた方がよさそう。(alt + clickなどを1キーでマッピングされていた場合の対処)


・Clickable_Layer中に、ALTを押されたときは、 マウスの移動量がほとんどなくても、
Clickable_Layerから脱しないよう、レイヤーをロックした方が、修飾キー+左ドラッグがやりやすい。
(「修飾キー押下中」のようなフラグが必要)

しかし、上記のように、ctrlを「レイヤーから脱するキー」から除外してしまうと、コピーなどの操作がすぐにできなくなります。

エディター上でのクリック、ダブルクリック、トリプルクリック、またはファイラーでのクリックをした場合、直後の操作は、CTRL+Cが多いのですよね。
ですが、ファイルドラッグのために、CTRLを除外してしまうと、Clickable_Layerが終わるまで、コピーが出来ずに支障が出ます。

このため、他に以下の調整を加えました。
・ステータスのenumにCLICKED(click直後)というのを追加し、CLICKEDの場合は、マウスを動かさなければ、200ミリ秒で、 Clickable_Layerを脱する。
・ただし、CLICKED(click直後)の期間中(200ミリ秒)には、、ほんの僅かでも、マウスを動かしたら、CLICKABLEに戻す。
(連続で出てきたポップアップをclickすることもあるため、)

また、「臺おじ」のような、マウス用のアクションゲームをcocotで行うときは、手動でマウスレイヤーに遷移しているので、以下の機能を追加しました。

・手動でマウスレイヤーに移動したときは、自動で戻す機能を実行しない。。


また、もともとのレイヤー1、レイヤー2でスクロールモードになる機能は、そのまま残した方が、すぐにスクロールに遷移できることが便利なので、
・ <キーボード名>.cの制御で、すでにスクロールモードになっているときは、自動遷移は無効にした方がよさそう。


一方で、既存のtakashicompanyさんのコードで、cocot*plusやkeyballに適用する際は、削ってもよいかなと思ったものもありました。

・cocotの場合、もともと、ボールの角度が15度単位で微調整できています。つまり・・
スクロールは、<キーボード名>.cのpointing_device_task_kbに任せれば、takashicompanyさんの「スクロール時に、横回転の感度を抑える制御」は、使わなくても大丈夫そう・・・。
まったく同じ理由で、状態変化の「SCROLLING」も、なくても良さそう
(ごめんなさい)

・cocotやkeyballの場合は、ボールを押し込むことはないので、「1Uトラックボール」のようなクリックでボールがずれることはありません。
このため、「after_click_lock_movement」の制御は要らなさそうです。
(ごめんなさい)


cocot46plusのように、単独のマウスボタンもある機種の場合、clickで、「layer_on」が呼ばれると、クリックボタンを離したことにされてしまい、びっくりすることがあります。このため、

・enable_click_layer内では、レイヤーがclickable_layerのときは、layer_onは呼ばない方がよさそうです。

ーーーーー
上記の機能を試行錯誤中です。
一方で、公式のもう少し要領を節約したいですね。以下の2つで要領を削ってから、

多分ですが、takashicompanyさんのmy_absという発想はMATH.Hを取り込まずに要領を節約するためですよね?
これを見習って要領を節約して、改造にいそしんでいますww。

※現在のcocot46plus.cは、角度調整のためにmath.hが取り込まれており、pro microには少し重荷です。
これについては、角度調整用のsinとcos関数の結果として、固定の配列を持たせてあげることと、my_absを 使うことで、公式の機能を残したまま、math.hをcocot46plus.cから除外できました。

また、oled_writeとかoled_write_pを分解して使えば、sprintfを使わずに済みました。

その辺を組み合わせて、zenと、gitに載せようかと。

プレビューせず、投降してしまったこともあり、意図しないマークダウンが入りました。
太字部分は、何の意味もございません。ごめんなさい。

ログインするとコメントできます