AZ1UBALLは、よっぴさん(@4py1)が開発した1Uサイズのトラックボールです。
以前設計したThumbShift5-15TBではAZ1UBALLを接続できるようにしていました。
ThumbShift5-15TBのマイコンはPro Microでしたが、次に設計したキーボードではマイコンをRP2040-Zeroにしました。するとAZ1UBALLを動作させる設定の記述にいくつか追加が必要でした。
RP2040-ZeroでAZ1UBALLを使えるようにするために参考にしたページは以下の2つです。
これらをよく読めばRP2040-ZeroでAZ1UBALLを動作させることができます。しかしせっかくなので2つのページの情報をまとめ直しました。そして追加として、Pro Microでの実装方法のほか、マウスレイヤーへの自動移動や、トラックボールでスクロールを可能にする設定方法なども紹介したいと思います。
Pro MicroでAZ1UBALLを動作させる
Pro MicroでAZ1UBALLを動作させるのは比較的簡単です。回路図では、Pro Microの2番ピン(SDA)と3番ピン(SCL)をAZ1UBALLのSDAおよびSCLにつなぎます。(回路図はThumbShift5-15TBのものです)

QMKでは「rules.mk」に以下を書き加え、コンパイルしたファームウェアをPro Microに書き込めば動作します。
POINTING_DEVICE_ENABLE = yes
POINTING_DEVICE_DRIVER = pimoroni_trackball
Pro MicroはI²Cに使えるピンが2番(SDA)および3番(SCL)と決まっているので、どのピンをI²Cとして使うかなどを指定する必要はありません。
RP2040-ZeroでAZ1UBALLを動作させる
RP2040-ZeroでAZ1UBALLを動作させる場合、回路図で考慮するところが増えます。またQMKでも追加で必要なファイルがいくつかあります。
回路図では、RP2040-Zeroの「3V3」ピンとAZ1UBALLのVCCを結びます。AZ1UBALLは3.3Vと5Vの両方で動作する一方、RP2040-Zeroの信号電圧は3.3Vだからです。
RP2040-Zeroには2つのI²Cデバイスを接続できます。RP2040-Zeroのピン配置を見てみましょう。

RP2040-Zero - Waveshare Wiki
「I2C0」と「I2C1」と書かれているピンがたくさんあります。この中からI2C0のSDAとSCL、またはI2C1のSDAとSCLを選んで任意のピンに接続します。下の回路図では、RP2040-Zeroの4番ピンと5番ピンにAZ1UBALLのSDAとSCLを接続しました。これらはI2C0として扱われます。

次にQMKです。2つの新しいファイルを作成します。以下はI2C0を使う場合の記述内容です。
- halconf.h
#pragma once
#define HAL_USE_I2C TRUE
#include_next <halconf.h>
- mcuconf.h
#pragma once
#include_next <mcuconf.h>
#undef RP_I2C_USE_I2C0
#define RP_I2C_USE_I2C0 TRUE
#undef RP_I2C_USE_I2C1
#define RP_I2C_USE_I2C1 FALSE
「mcuconf.h」はI2C0を使用するときのみ必要で、I2C1を使用するときは不要かもしれません。(未確認です)
「rules.mk」にはPro Microと同様、以下の記述を追加します。
POINTING_DEVICE_ENABLE = yes
POINTING_DEVICE_DRIVER = pimoroni_trackball
「config.h」ではI2C0とI2C1のどちらを利用するのか、またどのピンをI²Cとして使うかを記述します。SDAは4番ピン、SCLは5番ピン(I2C0)なので以下のようになります。
#define I2C_DRIVER I2CD0
#define I2C1_SDA_PIN GP4
#define I2C1_SCL_PIN GP5
ここで使っているI²CはI2C0ですが、2行目と3行目は「I2C0」ではなく「I2C1」が正しいようです。
これでRP2040-ZeroでAZ1UBALLを使えるようになります。
(ここから先は、Pro MicroとRP2040-Zeroで共通のカスタマイズとなります)
これはThumbShift5-15TBのユーザーさん(いるんですよこれが)に教えてもらいました。
自分の場合、AZ1UBALLのトラックボールを上へ転がすとマウスポインタが右へ移動していきました。こういったときは「config.h」に以下の記述を追加します。
#define POINTING_DEVICE_ROTATION_90
トラックボールの回転方向とマウスポインタの移動方向の違いによっては、「90」の部分は「180」や「270」と書くのがよいかもしれません。
トラックボールを動かすと自動的にレイヤーを移動する設定
最近のQMK Firmwareは、トラックボールを動かすと特定のレイヤーへ移動するよう設定できます。QMKの現在のドキュメントでは以下で解説されています。
自動レイヤー移動をオンにするには、「config.h」に以下のように記述します。
#define POINTING_DEVICE_AUTO_MOUSE_ENABLE
#define AUTO_MOUSE_TIME 1000
「AUTO_MOUSE_TIME」はトラックボールの操作を終えてから何ミリ秒後に元のレイヤーに戻るかを指定します。1,000は1秒後で、デフォルトは650(ミリ秒)です。
次に「keymap.c」に以下を追記します。
void pointing_device_init_user(void) {
set_auto_mouse_layer(4);
set_auto_mouse_enable(true);
}
「set_auto_mouse_layer(4);」をkeymap.cに記述する代わりに、config.hに「#define AUTO_MOUSE_DEFAULT_LAYER 4」と記述する方法もあります。レイヤーの管理はkeymap.cで行うので、ここではどこをマウスレイヤーにするかの指定もkeymap.cで行うようにしました。
これでトラックボールの操作時に自動的にレイヤー4へ移動するようになりました。
ここはSelf-Made Keyboards in JapanのDiscordで教えてもらいました。
通常のマウスでは、マウスホイールの回転で画面をスクロールさせることができます。AZ1UBALLはボールが一つしかありませんので、トラックボールでマウスポインタを移動するモードから画面をスクロールするモードに切り替える方式で実装します。QMKの現在のドキュメントでは以下で解説されています。
以下を「keymap.c」に記述します。
enum custom_keycodes {
DRAG_SCROLL = SAFE_RANGE,
};
bool set_scrolling = false;
report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
if (set_scrolling) {
mouse_report.h = mouse_report.x / 3;
mouse_report.v = -mouse_report.y / 3;
mouse_report.x = 0;
mouse_report.y = 0;
}
return mouse_report;
}
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (keycode == DRAG_SCROLL && record->event.pressed) {
set_scrolling = !set_scrolling;
}
return true;
}
これによって、カスタムキーコード「DRAG_SCROLL」が定義されました。keymap.cのキー定義で、任意のキーに「DRAG_SCROLL」を割り当ててください。「DRAG_SCROLL」が入力されるたびに、マウスポインタを移動するモードと画面をスクロールするモードが切り替わります。
ついでに、左クリックするキーコードは「MS_BTN1」、右クリックは「MS_BTN2」、ホイールの押し込みは「MS_BTN3」です。
「DRAG_SCROLL」に割り当てたキーを押している間だけスクロールモードに切り替える実装方法もあり、以下で解説されています。
個人的には、キーを押している間だけスクロールモードにするよりは、モードをトグルで切り替えつつ使う方が便利だと感じました。
スクロールモードでは、トラックボール操作時の自動レイヤー移動が行われません。スクロールモード中にクリックしたいときは「MS_BTN1」を割り当てたキーを押す以外に、AZ1UBALLのボールを押し込む方法もあります。(ボールの押し込みによるクリック操作はマウスポインタを移動するモードでも有効です)
AZ1UBALLはマウスを併用しつつ利用中
AZ1UBALLは便利ですが、これでマウスいらずになるかというとなかなか厳しいとも感じています。トラックボールに触れたり指を離したりする際のわずかな動きが入力され、マウスポインタが動いてしまいがちだからです。クリックしたい場所が小さいと、マウスポインタをその上へピタリと置くのが難しいのです。
これはAZ1UBALLのせいではなく、おそらくQMK Firmwareのマウスポインタを動かす部分のできがもう一つだからでしょう。たとえば、ある範囲の加速度でわずかな距離の移動は無視するようにするなどでより高精度に操作できるようになる気がします。といっても自分にはそのようなプログラミングはとても無理なのですが。
現在はマウスをメインに使いつつ、スクロールモードにしたAZ1UBALLを併用するという使い方になっています。手をホームポジションからマウスへ移動することなく親指でスクロールできるので、ウィンドウを切り替えながらスクロールしたいときなどに重宝です。
参考になるかもしれないページ
このページでは、マウスポインタを一気に遠くまで動かせる「加速度モード」や、マウスポインタの移動量を動的に変化させる関数が解説されています。このへんをなんかうまいことやって、マウスポインタの動きを高精度にできたらいいなあ。