分割キーボードでデータの同期やデータ間通信をする
Data synchronization and communication for QMK split keyboard
これまでのQMKでは、分割キーボード間の同期のサポートが限定的で、データの取得ができなかったため、USBが繋がっていない方のキーボードのOLED画面には、常にロゴが表示されるような設計がほとんどでした。最新のQMKファームウェアでは、分割キーボード間の通信が標準でサポートされるようになったため、QMKのソースコードを改修することなくデータの同期ができるようになっています。
基本的な同期であれば、[config.h]にこれらの宣言を追加することで、両方のキーボードで変数が共有されるようになります。頻繁に同期通信を行うと、入力処理に影響するため、必要最低限の宣言だけにするのが望ましいでしょう。
config.h
#define SPLIT_TRANSPORT_MIRROR // マスターのマトリックス接続状況
#define SPLIT_LAYER_STATE_ENABLE // レイヤー状態
#define SPLIT_LED_STATE_ENABLE // CapsLockなどのLED点灯状態
#define SPLIT_MODS_ENABLE // シフトキーなどのMODキーの状態
#define SPLIT_WPM_ENABLE // キーボードWPMの状態
#define SPLIT_OLED_ENABLE // OLEDのオン、オフの状態
これらに該当しない、独自の値を同期することもできます。データはトランザクションIDごとに設定でき、32byte(RPC_M2S_BUFFER_SIZE / RPC_S2M_BUFFER_SIZEの値を変更することで調整可)までの情報を送受信できます。
ユーザー定義によるトランザクションIDの宣言は[config.h]にて行います。
config_user.h
// この定義はコンパイラによって適時処理される
#define SPLIT_TRANSACTION_IDS_USER USER_DATA_SYNC
// 複数のIDを宣言したいときはカンマで区切る
#define SPLIT_TRANSACTION_IDS_USER USER_DATA_SYNC1, USER_DATA_SYNC2
QMKによって自動で気に呼び出されるkeyboard_post_init_user()関数内にて、このIDを実行プログラムへ登録します。
init.c
// キーボード初期化後に呼ばれる
void keyboard_post_init_user(void)
{
transaction_register_rpc(USER_DATA_SYNC1, user_sync_sub1_handler);
}
データの更新が発生するなどで、データ通信を実行する必要が生じたなら、「transaction_rpc_send()」で、相手側のキーボードへデータを送ります。もう一方のキーボードでデータを受け取ると、登録したハンドラが呼び出されるので、ここで必要な同期処理を行います。
sync.c
// サブキーボードに同期したいデータ
typedef union {
uint8_t raw;
struct {
bool swap_gui:1;
bool mod_gui:1;
bool caps_lock:1;
bool num_lock:1;
bool sc_lock:1;
};
} key_state_r_t;
key_state_r_t key_state_r;
// サブ側で呼び出される同期ハンドラ
void user_sync_sub1_handler(uint8_t in_buflen, const void* in_data, uint8_t out_buflen, void* out_data)
{
// データの同期処理
const key_state_r_t *ks = (const key_state_r_t*)in_data;
key_state_r.raw = ks->raw;
}
// メイン側から同期の実行
void sync(){
if(is_keyboard_master()) {
transaction_rpc_send(USER_DATA_SYNC1, 1, &key_state_r.raw);
}
}
実行結果などの返り値が欲しいのであれば、transaction_rpc_send()の代わりにtransaction_rpc_exec()を使い、コールバックハンドラで参照されている「out_data」に送り返す情報を格納させます。
2021/10/04