Prospector ZMK Dongleのタッチ機能を使う
背景
Prospectorは、ZMKキーボードのレイヤー情報やperipheralのバッテリー残量などをディスプレイに表示できるデバイスです。
最近、これの組み立てキット/完成品がbeekeeb.jpで手軽に入手できるようになったので、これをきっかけに筆者もProspectorを入手しました。
本家GitHubのREADMEを見ると、以下のように書いてあります。
Waveshare 1.69inch Round LCD Display Module with Touch
Non-touch version has different mounting pattern and will NOT fit
日本語訳:
Waveshare 1.69inch Round LCD Display Module タッチ付き
タッチなしのバージョンは別の取り付けパターンなので、装着できません
使っていないけどハードウェア的にはタッチ機能がついているということです。タッチができればいろいろ遊べるだろうし、底面にあるリセットボタンが押しにくいのも解決しそうです。というわけで、やってみました。
配線・はんだ付け
beekeeb.jpで販売されているProspectorの組み立てキットでは配線を簡単にするためのコネクタボードが使用されていますが、タッチパネル用のピンの配線がされていません。(使ってないピンまで配線されていれば親切だったけど、本家のビルドガイドでもこのピンの配線は切れと書いてあるので、まあしょうがない。)
なので、そのピンを自力で配線・はんだ付けをする必要があります。
以下の画像のように配線しました。
(一応、オプションのモーションセンサー(画像右側で見切れているもの)と共存できるようにピンを選んだつもりです。)

(画像は本家の組み立てマニュアル に2025/11/09に手書きで書き加えたものです。)
実際に配線した写真はこんな感じ。(だいぶはんだ付けが汚いですが許してください。)

ファームウェアの書き換え
今回はProspector Scannerという、Prospectorを独立したデバイスとして簡単に使用できるようにしたファームウェアを用います。
Prospector Scannerの使用方法については、以下の記事を参照してください。
以下で紹介している変更はこちらのリポジトリのaea61ddコミット時点のものに全て反映されています。
自分で書き換えるのが面倒くさい人はこれをビルドすればそのまま使用できます。
既存のI2Cの設定の削除
config/boards/seeeduino_xiao_ble.overlayにI2Cの設定がありますが、これは本家Prospectorにはないもので、使われているのかどうか・動作するのかどうかよく分からない、削除しても問題ないように見えたので、ファイルごと削除しました。
タッチセンサーのドライバーの設定
Waveshare 1.69inch Round LCD Display Moduleは、タッチコントローラーにHynitron CST816Sを用いています。幸いなことに、ZephyrにCST816Sのドライバーが用意されているので、これを使用します。
&i2c0 {
status = "okay";
touch_sensor: cst816s@15 {
compatible = "hynitron,cst816s";
reg = <0x15>;
status = "okay";
rst-gpios = <&gpio0 2 GPIO_ACTIVE_LOW>; // D0 = P0.02
irq-gpios = <&gpio0 3 GPIO_ACTIVE_LOW>; // D1 = P0.03
};
};
/ {
touch_listener: touch_listener {
status = "okay";
compatible = "zmk,input-listener";
device = <&touch_sensor>;
};
};
CONFIG_INPUT=y
CONFIG_ZMK_POINTING=y
CONFIG_INPUT_CST816S=y
CONFIG_INPUT_CST816S_INTERRUPT=y
これで、タッチセンサーの入力が読み取られ、入力イベントが発行されます。ZephyrのCST816Sドライバーのソースコードを見ると、具体的には以下のInput Eventを発行していることがわかります。
-
INPUT_BTN_TOUCH: 画面のタッチ -
INPUT_ABS_X: タッチしたxの絶対座標 -
INPUT_ABS_Y: タッチしたyの絶対座標
これらはZMKの標準機能で直接扱えないので、何かしら変換をかますなどする必要があります。
マウスカーソル移動ができるようにする
以下のモジュールに含まれている、INPUT_ABS_X・INPUT_ABS_Y(絶対座標)をINPUT_REL_X・INPUT_REL_Y(相対座標)に変換するInput Processorを用います。これによって、ZMKでマウスカーソル移動として使えるようになります。
カーソル移動している様子
remotes:
- name: halfdane
url-base: https://github.com/halfdane
projects:
# https://github.com/halfdane/zmk-input-processors
- name: zmk-input-processors
remote: halfdane
revision: main
path: modules/zmk-input-processors
#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <behaviors/input_processor_gestures.dtsi>
#include <behaviors/input_processor_absolute_to_relative.dtsi>
&touch_listener {
input-processors = <
&zip_absolute_to_relative
&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_Y_INVERT)
&zip_xy_scaler 4 1
>;
};
Prospectorはディスプレイを90°回転して使用しているので、&zip_xy_transformで補正しています。また、CPIが小さかったので、&zip_xy_scalerで4倍にしています。
この辺については、以下の記事を参考にしてください。
タップでクリックする
zmk-input-gesturesモジュールを用います。
このモジュールは、INPUT_ABS_X・INPUT_ABS_Y(絶対座標)を読み取って、タップでクリックする、カーソル移動に慣性をつけるなどのトラックパッド向けのジェスチャーを行ってくれます。
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_INPUT_THREAD_STACK_SIZE=4096
projects:
# https://github.com/halfdane/zmk-input-gestures
- name: zmk-input-gestures
remote: halfdane
revision: main
path: modules/zmk-input-gestures
#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <behaviors/input_processor_gestures.dtsi>
#include <behaviors/input_processor_absolute_to_relative.dtsi>
#include <behaviors/input_processor_gestures.dtsi>
// Alias &touch_sensor to &glidepoint for input gestures module
glidepoint: &touch_sensor {};
&zip_gestures {
tap-detection;
tap-timout-ms = <150>;
prevent_movement_during_tap;
};
&touch_listener {
input-processors = <
&zip_gestures
&zip_absolute_to_relative
&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_Y_INVERT)
&zip_xy_scaler 4 1
>;
};
元々はCirque GlidePointというトラックパッド向けに作られたモジュールで、&glidepointというラベルがデバイスについていないとビルドできませんでした。なので、&touch_sensorに&glidepointというエイリアスをつけてあります。
これでタップするとクリックが入力されるようになります。ダブルタップも可能です。左クリック・中央クリックや、ドラッグ&ドロップはできません。
マウスジェスチャーを導入する
zmk-mouse-gestureモジュールを用います。
このモジュールは、4方向のカーソル移動の組み合わせをジェスチャーとして認識し、設定したキーバインドを発行してくれます。
これを使用することで、Prospectorの押しにくい位置にあるリセットボタンの代わりに、タッチ画面のジェスチャーでbootloaderを起動するといったことができるようになります。
なお、Prospectorにはキーがないので、キーを押さなくてもジェスチャーを有効化できるようにする必要があります。このために、オートマウスレイヤーとzmk-listenersを組み合わせます。具体的には、
- レイヤー1を追加する
- オートマウスレイヤー(
&zip_temp_layer)で、カーソル移動が始まったら自動的にレイヤー1を有効にし、200ms後に無効にする - zmk-listenersを使って、レイヤー1が有効になったときに
&mouse_gesture_on、無効になったときに&mouse_gesture_offを実行する
というように設定します。
remotes:
- name: ssbb
url-base: https://github.com/ssbb
- name: kot149
url-base: https://github.com/kot149
projects:
# https://github.com/ssbb/zmk-listeners
- name: zmk-listeners
remote: ssbb
revision: v1
path: modules/zmk-listeners
# https://github.com/kot149/zmk-mouse-gesture
- name: zmk-mouse-gesture
remote: kot149
revision: v1
path: modules/zmk-mouse-gesture
#include <behaviors.dtsi>
#include <dt-bindings/zmk/keys.h>
#include <dt-bindings/zmk/bt.h>
#include <dt-bindings/zmk/outputs.h>
#include <dt-bindings/zmk/pointing.h>
/ {
keymap {
compatible = "zmk,keymap";
default_layer {
bindings = <&none>;
};
mouse_layer {
bindings = <&none>;
};
};
layer_listeners {
compatible = "zmk,layer-listeners";
mouse_gesture {
layers = <1>;
bindings = <&mouse_gesture_on &mouse_gesture_off>;
};
};
};
#include <input/processors.dtsi>
#include <dt-bindings/zmk/input_transform.h>
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <behaviors/input_processor_absolute_to_relative.dtsi>
#include <mouse-gesture.dtsi>
&zip_mouse_gesture {
stroke-size = <150>;
enable-eager-mode;
idle-timeout-ms = <200>;
bootloader {
pattern = <GESTURE_DOWN GESTURE_RIGHT GESTURE_UP>;
bindings = <&bootloader>;
};
};
&touch_listener {
input-processors = <
&zip_absolute_to_relative
&zip_xy_transform (INPUT_TRANSFORM_XY_SWAP | INPUT_TRANSFORM_Y_INVERT)
&zip_xy_scaler 4 1
&zip_temp_layer 1 200
&zip_mouse_gesture
>;
};
↓, →, ↑の順でスワイプしたらbootloaderを起動するようにしました。
今後の展望
- 左クリック・中央クリック
- スクロール
- ドラッグ&ドロップ
- タップでキー入力
- ダブルタップ
- CST816S側で実装されているジェスチャー機能の活用
- タッチまたはジェスチャーでProspector ScannerのGUI操作
などなど、色々やれることは多そうです。気が向いたらやってみようと思います。やったらこの記事に追記します。
Discussion