自作キーボードの話(LHP14・Lite)

キーボードの自作キットに沼り早くも5ヶ月そして4個目。

今回はジョイスティックとOLED(ちっちゃい液晶画面)付きのキーボード LHP14の制作をしてみる。

LHP14は生産終了してしまった名左手デバイス G13を入手できない人の支援も目的としたジョイスティック付きキーボード。

QMK Firmwareというキーボードにプログラミングするソフトを使用することが前提となっている作りなので以前作った物よりも多少難易度が上がっている。とはいえ1からプログラミングするのではなく用意されたプログラムを手順通り進めていくものなのでそこまで身構えずとも大丈夫だ(多少改変する必要あり)

設計者がFF14プレイヤーなのでゲームでの使用にも嬉しい設計になっている(部品の交換など、もちろんクリエイター・絵描きにもおすすめできる)

現在販売されているのは

LHP14c

LHP14Lite

がある。

前者は後者より8ボタン多く高さがありスティックはPS4と同じ形状の物で操作性が良い。

後者はかなりコンパクトで薄くスティックはSwitchの様な携帯向けの形状で手の小さい人や持ち運び操作に向いている。

制作費用(材料費)はLHP14cが約13420円だった。

製作工程は設計者さんがこちらに載せているので多くは記載しません。

LEDの難易度は高く、基板の仕様上少しチップが浮く状態でハンダ付けしなければならなかった。

1箇所をハンダ付けして多少浮いた部分はLEDの足を基板側に押し込み少し曲げた状態でハンダ付けしていった。

初めてこのチップコンデンサを見た時は驚いた。あまりにも小さい1mmほどのチップに慄いた。

しかしハードウェア面では慣れたもので順調に作業が進んだ。

問題はソフトウェア側でこちらになかなか苦戦した。

用意されたテスト用ファームウェアは問題なく実装できて安心したのだが 次に行ったQMK Firmwareでのコンパイル(.hexファイルの出力)に躓いた。

C言語などまっっっっったく知らない自分はネットの情報を読み漁りC言語を理解しようとしたがC言語とはそんな簡単な物ではなく腰を据えて学習しても何ヶ月・何年もかかるものだと悟った。結局は【動けばえぇねん】という事で同じ境遇を乗り越えた先人達の知恵を拝借してコピーペーストで乗り越える。

最初は.cなどのファイルをメモ帳で開いて改変して保存という原始的な作業を行っていたがVisiual studio codeという無料のエディター(超高機能メモ帳みたいな感じ)を使用することをおすすめする。

 

結論から言うと動かせるようになったので備忘録として記しておく。(最適解かはさておき動作した)

まずQMK Firmwareでmake LHP14c:defaultをコンパイルすると赤文字でエラーが出た。

そもそもファイル名に大文字が入っているとエラーが出るというのを海外のサイトで発見。

しかしファイル名を変えると色々な場所で参照しているので問題が出てくる。全てを書き換えればいいのだがそれも大変だ。

なので大文字も読み込めるようにQMK Firmwareの大本を書き換えるという情報を見つけた。

qmk firmware/data/schemas/definitions.jsonschemaにある86行目

                        "pattern": "^[0-9a-z][0-9a-z_/]*$"

これを

                        "pattern": "^[0-9A-Za-z][0-9A-Za-z_/]*$"

に変更しA-Zを追加して大文字を読み込めるようにした。(合っているのかはわからないが正常に読み込んだ)

 

しかし次にoled_task\userでエラーが出た。これはqmk firmware/keybords/LHP14c/keymap/defaultのdefault.c内124-127行目

void oled_task_user(void) {
    render_logo();
    render_layer();
}

これを

bool oled_task_user(void) {
    render_logo();
    render_layer();
    return false;
}

に変更した。これは大本のoled_task_userの

qmk firmware/driver/oled/oled_driver.hの290行目が

bool oled_task_user(void);

とboolで宣言されていたため出たエラーのようだ。

 

これで無事にデフォルトのキーマップをコンパイルして.hexファイルを出力→本体に書き込み成功。

無事正常に動作した。

 

そしてこれまでの経験によりキーマップの変更やOLEDの表示変更などが出来るようになった。

c言語の理解が深まり今度はジョイスティックのアナログ操作だけでなくデジタル出力やマウスの動作もさせてみたいと思い始めた。

さらにはレイヤーを分けてジョイスティックの動作も変えることにしたい。

 

マウスの動作

LHP14c/rules.mkの末尾に

POINTING_DEVICE_ENABLE = yes
POINTING_DEVICE_DRIVER = analog_joystick

を追加。

LHP14c/keymaps/任意のキーマップファイル/config.hの末尾に

#define ANALOG_JOYSTICK_X_AXIS_PIN D4
#define ANALOG_JOYSTICK_Y_AXIS_PIN F4

#define ANALOG_JOYSTICK_AXIS_MIN 0
#define ANALOG_JOYSTICK_AXIS_MAX 1023
#define ANALOG_JOYSTICK_SPEED_REGULATOR 20
#define ANALOG_JOYSTICK_READ_INTERVAL 10
#define ANALOG_JOYSTICK_SPEED_MAX 20

を追加。(マウスカーソルのスピードはANALOG_JOYSTICK_SPEED_MAXの数値で調整)

LHP14c/keymaps/上記のファイル内/keymap.cの末尾に

void joystick_task(){
          joystick_status.axes[0] = -(analogReadPin(D4)/4 - 128); //X軸
          joystick_status.axes[1] = analogReadPin(F4)/4 - 128; //Y軸
          joystick_status.status |= JS_UPDATED;
    send_joystick_packet(&joystick_status);
}

を追加。(analogReadPinの()内が繋がれているPinの指定。コンパイル後X軸Y軸が逆だった場合などはPinを変更して調整。変更した場合はconfig.hのANALOG_JOYSTICK_X(Y)_AXIS_PINも変更)

さらに4行目に

#include "pointing_device.h"

を追加。

これでマウスを動かす事が出来た。

 

レイヤー毎にジョイスティックの動作を変更する方法は

LHP14c元ファームウェアのkeymap.c395行目

void joystick_task(){

    joystick_status.axes[0] = analogReadPin(F4)/4 - 128;
    joystick_status.axes[1] = analogReadPin(D4)/4 - 128;
    send_joystick_packet(&joystick_status);
}

これを下記に変更。

void joystick_task(){

    switch (get_highest_layer(layer_state)) {
        case SAM:
            if (!arrows[0] && analogReadPin(F4) - 512 > actuation){
                arrows[0] = true;
                register_code16(KC_D);
            }
            else if (arrows[0] &&  analogReadPin(F4) - 512 < actuation){
                arrows[0] = false;
                unregister_code16(KC_D);
            }
            if (!arrows[1] && analogReadPin(F4) - 512 < -actuation){
                arrows[1] = true;
                register_code16(KC_A);
            }
            else if (arrows[1] && analogReadPin(F4) - 512 > -actuation){
                arrows[1] = false;
                unregister_code16(KC_A);
            }
            if (!arrows[2] && analogReadPin(D4) - 512 > actuation){
                arrows[2] = true;
                register_code16(KC_S);
            }
            else if (arrows[2] &&  analogReadPin(D4) - 512 < actuation){
                arrows[2] = false;
                unregister_code16(KC_S);
            }
            if (!arrows[3] && analogReadPin(D4) - 512 < -actuation){
                arrows[3] = true;
                register_code16(KC_W);
            }
            else if (arrows[3] && analogReadPin(D4) - 512 > -actuation){
                arrows[3] = false;
                unregister_code16(KC_W);
            }
            break;
        case SCH:
            joystick_status.axes[0] = analogReadPin(F4)/4 - 128;
            joystick_status.axes[1] = analogReadPin(D4)/4 - 128;
            send_joystick_packet(&joystick_status);
            break;
        default:
            joystick_status.axes[0] = analogReadPin(F4)/4 - 128;
            joystick_status.axes[1] = analogReadPin(D4)/4 - 128;
            send_joystick_packet(&joystick_status);
            break;
    }

}

これでレイヤーSAMの時はWASDのデジタル入力になりレイヤーSCHとその他レイヤーではアナログジョイスティック入力となる。

KC_の部分を変えれば別のキー入力に変更できる。

 

OLEDのロゴ画面変更はLHP14c直下のconfig.hの78行目

#define OLED_FONT_H "keyboards/LHP14c/glcdfont_LHP14.c"

このkeyboards/LHP14c/glcdfont_LHP14.c部分が参照元なのでここを変更すればロゴを変更できる。