Phase 25c

その後もいろいろ試行錯誤した結果、NISSE はこの配列に落ち着いた。

  • 内側3個ずつ計6個の親指キーの役割は結局、ほぼ左右対称になった。左右の [Space] は両方とも単独のスペースキーで、日本語入力中は変換キーになる。左右の [Fn/Mod1] は単打でそれぞれ [英数] [かな] となり、日本語入力中に打てば確定操作とモード変更を同時に行う。
  • 左手親指に [BS] を置いていない。15年来の慣習を破った形だ。[Space] か [Fn/Mod1] の位置に [BS] を置ければそれに越したことはないのだが、この2キーは使用頻度上どうしても [Space] と [Fn/Mod1] に割り当てざるをえず、その外側に [BS] が追いやられてしまう。すると、そこまで親指を動かすよりは Fn+[ S ] の方が打ちやすいということになり、左親指に [BS] がなくてもさほど困らないということが分かった。むしろ、単独の [BS], [Enter], [Del] をすべて右手に配置したことで、左手の Fn+[ S ]=[BS], Fn+[ D ]=[Enter], Fn+[ F ]=[Del] と合わせ、どちらの手でも [BS], [Enter], [Del] を打てるようになったことのメリットが大きい。
  • 記号キーの ['"] と [\|] をこっそり入れ替えた。正規表現を手書きする(「\」を多用する)より英語口語文を書く(「'」を多用する)ことが増えたので。

Phase 25a for Keyboardio

4月発送予定(ほんまかいな)の Keyboardioマッピング案もついでに描いてみた。

  • 親指の付け根に Fn キーが独立しているとはいえ、それを含めて64キーってのはさすがにキー数の限界を下方突破してる。Alt キーを左右に置けないどころか、独立した Ctrl キーを置くことすらままならない状況だ。どうすんだこれ…

こうなったらもう、数字キーを Mod2 に追い出してしまおうか。この方がまだ健康で文化的なキー割り当てができる気がするぞ。

Phase 25a

ちょうど昨日から使い始めた ThinkPad Yoga 260 用と合わせて、NISSE, μTRON, OADG の3種類のキーボードに共通のキー配列を決めた。

要件
  • 親指にモディファイヤ Mod1 を置き、Mod1+[文字キー] ですべてのキー操作ができること。
  • Mod1+[文字キー] は片手で操作できること。つまり、左右どちらの親指でも [Mod1] が押せること。
  • 英文入力のために、左右どちらの親指でもスペースが入力できること。できれば KeyDown でスペースが入力されるよう、[Space] はワンショットモディファイヤ化しないのが望ましい。
  • マウスを左右どちらの手で持ってもいいように、マウスと併用する主な編集操作(Delete や Ctrl+C など)は左手側と右手側にそれぞれ配置したい。
  • [Ctrl], [Shift], [Alt] はマウスと併用する場合があるので、少なくとも各1個は単独の(ワンショットモディファイヤでない)キーとして配置すること。
  • [Win] はランチャーとして使うので、左右両方の押しやすい位置に配置したい。
図の凡例
  • [英数]: 日本語入力 off (変換中の場合は全文確定してから日本語入力 off)
  • [かな]: 日本語入力 on (変換中の場合は全文確定)
  • [和文]: ATOK の英語入力モード off
  • [英文]: ATOK の英語入力モード on

NISSE

  • NISSE はファームウェアを改造して [Shift] と [Fn] の位置を入れ替え、さらに [左Fn], [右Fn] が押されている間それぞれ [F14], [F13] を吐くようにしてある。これをのどかで検出してワンショットモディファイヤ Mod1 とする。
  • 英文入力のために両親指に Space を配置するが、左が普通の [Space] なのに対し、右は [Shift+Space] になっている。なぜかというと、ATOK で Shift+Space を 「全文確定」に割り当てておき、和文入力時に「左親指で変換→右親指で確定」という流れに持ち込むため。確定直後に左親指で [英数/Mod1] を押すことが多いので、この「左で変換、右で確定」という配置は理に適っている。
  • [Alt+F4] はキーボードの縁に指を添えてバシッと叩くので右上隅に存在しなければならない。このキーはめちゃめちゃ頻繁に使うので Mod1 に重ねることは不可能。
  • [Shift+Space] と [Alt+F4] を単独キーとして確保すると、それだけでキー数が限界に達してしまう*1。ファンクションキー込みで76キーという仕様はどう考えてもタイトすぎる。せめて80キーは欲しかった*2

μTRON

  • μTRON はファンクションキー抜きで76キーあり、左下と右下の10個*3を除いても NISSE より2キー多い。おかげで [Alt] と [BS] を左右に配置できた。

ThinkPad

  • ThinkPad はファンクションキー込みで89キー。しかし親指領域で常用できるキーは4個しかない。
  • 左右両方の親指で打てるのは [Space] だけなので、[Mod1] は [Space] にワンショットモディファイヤとして重ねるしかない。KeyDown でスペースが入力されなくなって英文入力速度が落ちるが、やむを得ない*4
  • [変換] の位置に [かな] を、[ひらがな] の位置に [英数] を配置した。確定は [かな] または [英数] で行う。
    • 今まで [変換] の位置に単独の [Shift+Space] を配置して KeyDown でスペースを入力できるようにしていたのは廃止。結局あまり使わなかったのと、[英数] が [左Alt] の位置まで追いやられてキーボードによっては*5誤打多発してたので。
  • 右手親指の [かな] と [英数] を両方ともワンショットモディファイヤ化して [Ctrl] と [Shift] を重ねてみた。
    • 今まで [ : ] の位置に単独の [Shift] を、[\] の位置にワンショットの [Ctrl] を配置してたのは廃止。文字キーをワンショットモディファイヤ化するのは意外なほど弊害が大きかったので。
  • 白いキーは割り当て未定。右側に [BS] が欲いんだよね…。

ダウンロード

OADG キーボード用が欲しい人はコメントください。

*1:Fn キーのワンショットモディファイヤ化改造後でこの有様なので、改造前はキー数の余裕が本当にゼロだったということ。

*2:[ 1 ] の左と [ 0 ] の右に2キーずつ追加するだけでいい。基板のスペースには余裕がある。

*3:[Fn], [Home], [End], [PgUp], [PgDn], [←], [→], [↑], [↓], [TRON]

*4:[無変換] と [ひらがな] の位置まで [Mod1] を引っ込めるのは論外。

*5:特に Microsoft Surface のキーボードとか

エスリル NISSE ファームウェア改造ガイド (4)

エスリル ニューキーボード − NISSEファームウェアを自分用に改造するメモ。

6. Fn キーをワンショットモディファイヤ化する

ワンショットモディファイヤとは、単独で押して放すと放したタイミングで自身のキーコードを送出するが、他のキーと同時に押すとモディファイヤとして振る舞う(自身のキーコードを送出しない)もの。普通のキーとモディファイヤキーを重ね合わせることで、少ない物理キーに多くの機能を割り当てる常套手段である。いわゆる SandS もワンショットモディファイヤの一種だ。
NISSE は親指領域にキーが10個もあるように見えるが、いちばん外側は遠すぎてホームポジションからは常用できず、いちばん内側も親指の移動にかなり時間がかかるので頻繁には使えない。常用できるのは残る6個(デフォルトの配列だと [Fn], [LShift], [Backspace], [Space], [RShift], [Fn])だが、そのうち2個が [Fn] に占有されるので、ドライバ側で検出できる(のどかでカスタマイズできる)のはわずか4個。えっ、4個? そんなん普通の OADG 109 キーボードと変わらんやないか!! 常用可能な親指キーには1個1万円の価値があるのだから*1、6万円の NISSE を買ったら親指キーが6個は常用できないと割に合わんのだよ!!!
というわけで、NISSE の Fn キーをワンショットモディファイヤ化して、単独で押して放したときは別のキーとして働くようにしたい。具体的には、[左Fn] の単打を [F14] に、[右Fn] の単打を [F13] にしたい。これを実現する作戦は2つ考えられる。

  1. 外部モディファイ作戦。キーボード側からはモディファイヤキーも普通のキーと同様に送出する。つまり、[右Fn] が押されている間、他の同時に押されているキーコードに加えて [F13] を送出しつづける。ワンショットモディファイヤ化はドライバ側で(のどかを使って)行う。
  2. 内部モディファイ作戦。キーボード側でワンショットモディファイヤ化を行う。つまり、[右Fn] が単独で押して放されたときに限り、放されたタイミングで [F13] を一度だけ送出する。

簡単なのはどちらかと言えば外部モディファイ作戦だろう。Fn 面のマッピングをキーボード側ではなくドライバ側で定義するので、NISSE を使っていない他のマシンとの配列共通化も容易にできる。内部モディファイ作戦は、もし NISSE が携帯性に優れた製品で、ドライバをいじれない出先のマシンに接続して使うようなものだったら意味があると思う。というわけで、手始めに外部モディファイ作戦を採用しよう。

外部モディファイ作戦

[左Fn] と [右Fn] に異なる機能を持たせるために、まずは両者を区別できるようにする。Keyboard.h の

#define KEY_FN          0xF0

#define KEY_LEFTFN      0xF0
#define KEY_RIGHTFN     0xF1

とし、KeyboardCommon.c の onPressed 関数にある

    if (KEY_FN == key) {

    if (KEY_LEFTFN == key || KEY_RIGHTFN == key) {

とすればよい。あとは KeybaordUS.c にある配列 matrixQwerty, matrixDvorak, matrixColemak, matrixJIS, matrixNicolaF に含まれる KEY_FN を KEY_LEFTFN または KEY_RIGHTFN に置き換えれば OK。
次に、Fn キーがキーコードを発生するようにする。今いじった KeyboardCommon.c の onPressed 関数にある

    if (KEY_LEFTFN == key || KEY_RIGHTFN == key) {
        current[1] |= MOD_FN;
        return; // ←これを削除
    }

この return; を削除する。それから、KeyboarCommon.c にある配列 matrixFn の [左Fn] と [右Fn] にあたる位置に、それぞれ押下時に送出したいキーを書く。たとえば [F14] と [F13] を送出したければ、matrixFn の最下行をこうする*2

{{0}, {0}, {KEY_F14}, {0}, {KEY_LEFTCONTROL, KEY_BACKSPACE}, {0}, {0}, {KEY_LEFTCONTROL, KEY_SPACEBAR}, {0}, {KEY_F13}, {0}, {0}}

これで [左Fn] を押している間は [F14] が、[右Fn] を押している間は [F13] が送出され、ドライバで検出できるようになった。
ここまで来れば Fn 面のマッピングはドライバ側で(のどかを使って)自由に定義できる。だから、もはやキーボード側で苦労して Fn 面をリマップする必要はないのだ。いっそ matrixFn の中身を matrixJIS と同じ並びにしちゃってもいい。こんなふうに。

static uint8_t const matrixFn[8][12][3] =
{
    {{KEY_RIGHT_BRACKET}, {KEY_F2}, {KEY_F3}, {KEY_F4}, {KEY_F5}, {KEY_F6}, {KEY_F7}, {KEY_F8}, {KEY_F9}, {KEY_F10}, {KEY_F11}, {KEY_EQUAL}},
    {{KEY_INTERNATIONAL3}, {KEY_F1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_F12}, {KEY_LEFT_BRACKET}},
    {{KEY_NON_US_HASH}, {KEY_1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_0}, {KEY_MINUS}},
    {{KEY_CAPS_LOCK}, {KEY_2}, {KEY_3}, {KEY_4}, {KEY_5}, {0}, {0}, {KEY_6}, {KEY_7}, {KEY_8}, {KEY_9}, {KEY_QUOTE}},
    {{KEY_Q}, {KEY_W}, {KEY_E}, {KEY_R}, {KEY_T}, {0}, {0}, {KEY_Y}, {KEY_U}, {KEY_I}, {KEY_O}, {KEY_P}},
    {{KEY_A}, {KEY_S}, {KEY_D}, {KEY_F}, {KEY_G}, {KEY_ESCAPE}, {KEY_APPLICATION}, {KEY_H}, {KEY_J}, {KEY_K}, {KEY_L}, {KEY_SEMICOLON}},
    {{KEY_Z}, {KEY_X}, {KEY_C}, {KEY_V}, {KEY_B}, {KEY_TAB}, {KEY_ENTER}, {KEY_N}, {KEY_M}, {KEY_COMMA}, {KEY_PERIOD}, {KEY_SLASH}},
    {{0}, {0}, {KEY_F14}, {0}, {KEY_BACKSPACE}, {0}, {0}, {KEY_SPACEBAR}, {0}, {KEY_F13}, {0}, {0}}
};

こうすれば、のどかの設定を他のマシンとほとんど共通化できるはずだ。
次回は(気が向いたら)内部モディファイ作戦を試してみるよ。

ダウンロード

筆者がカスタマイズしたファームウェアソースコードはここからダウンロードできる。

Hex ファイルが欲しい人はコメントください。

*1:5万円の μTRON キーボードは6個、2.5万円の Truly Ergonomic Keyboard は2個の親指キーが常用できることから逆算。

*2:[Fn] が標準の位置にある場合。筆者のカスタマイズ例では [Fn] と [Shift] を入れ替えたので {{0}, {0}, {0}, {KEY_F14}, {KEY_BACKSPACE}, {0}, {0}, {KEY_SPACEBAR}, {KEY_F13}, {0}, {0}, {0}} となる。

エスリル NISSE ファームウェア改造ガイド (3)

エスリル ニューキーボード − NISSEファームウェアを自分用に改造するメモ。

5. Fn 面のマッピングを変える

Fn キーを押しているときのキー割り当てを定義しているのは KeyboardCommon.c にある3次元配列 matrixFn だ。

static uint8_t const matrixFn[8][12][3] =
{
    {{KEY_INSERT}, {KEY_F2}, {KEY_F3}, {KEY_F4}, {KEY_F5}, {KEY_F6}, {KEY_F7}, {KEY_F8}, {KEY_F9}, {KEY_MUTE}, {KEY_VOLUME_DOWN}, {KEY_PAUSE}},
    {{KEY_LEFTCONTROL, KEY_DELETE}, {KEY_F1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_VOLUME_UP}, {KEY_SCROLL_LOCK}},
    {{KEY_LEFTCONTROL, KEY_LEFTSHIFT, KEY_Z}, {KEY_LEFTCONTROL, KEY_1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_LEFTCONTROL, KEY_0}, {KEY_PRINTSCREEN}},
    {{KEY_DELETE}, {KEY_LEFTCONTROL, KEY_2}, {KEY_LEFTCONTROL, KEY_3}, {KEY_LEFTCONTROL, KEY_4}, {KEY_LEFTCONTROL, KEY_5}, {0}, {0}, {KEY_LEFTCONTROL, KEY_6}, {KEY_LEFTCONTROL, KEY_LEFTSHIFT, KEY_LEFTARROW}, {KEY_LEFTSHIFT, KEY_UPARROW}, {KEY_LEFTCONTROL, KEY_LEFTSHIFT, KEY_RIGHTARROW}, {KEYPAD_NUM_LOCK}},
    {{KEY_LEFTCONTROL, KEY_Q}, {KEY_LEFTCONTROL, KEY_W}, {KEY_PAGEUP}, {KEY_LEFTCONTROL, KEY_R}, {KEY_LEFTCONTROL, KEY_T}, {0}, {0}, {KEY_LEFTCONTROL, KEY_HOME}, {KEY_LEFTCONTROL, KEY_LEFTARROW}, {KEY_UPARROW}, {KEY_LEFTCONTROL, KEY_RIGHTARROW}, {KEY_LEFTCONTROL, KEY_END}},
    {{KEY_LEFTCONTROL, KEY_A}, {KEY_LEFTCONTROL, KEY_S}, {KEY_PAGEDOWN}, {KEY_LEFTCONTROL, KEY_F}, {KEY_LEFTCONTROL, KEY_G}, {KEY_ESCAPE}, {KEY_CAPS_LOCK}, {KEY_HOME}, {KEY_LEFTARROW}, {KEY_DOWNARROW}, {KEY_RIGHTARROW}, {KEY_END}},
    {{KEY_LEFTCONTROL, KEY_Z}, {KEY_LEFTCONTROL, KEY_X}, {KEY_LEFTCONTROL, KEY_C}, {KEY_LEFTCONTROL, KEY_V}, {KEY_LANG2}, {KEY_TAB}, {KEY_ENTER}, {KEY_LANG1}, {KEY_LEFTSHIFT, KEY_LEFTARROW}, {KEY_LEFTSHIFT, KEY_DOWNARROW}, {KEY_LEFTSHIFT, KEY_RIGHTARROW}, {KEY_LEFTSHIFT, KEY_END}},
    {{0}, {0}, {0}, {0}, {KEY_LEFTCONTROL, KEY_BACKSPACE}, {0}, {0}, {KEY_LEFTCONTROL, KEY_SPACEBAR}, {0}, {0}, {0}, {0}}
};

この並び順も前出のキーマトリクスに対応している。各要素が配列になっていて3キーまでの同時押しが可能。キーの名前は Keyboard.h に定義されている。"KEY" まで打って Ctrl+Space で補完すれば間違えない。
この matrixFn を好きなように書き換えれば Fn 押下時のキーマップを変更できるが、いくつか罠がある。
罠その1。Fn+F2 (OS) の設定が 109a または 109b の場合、Fn+[M], Fn+[<], Fn+[>], Fn+[/] がそれぞれ [無変換], [変換], [ひらがな], [全角] になるようにハードコーディングされている。これを止めるには KeyboardCommon.c の getKeyFn 関数の次のコードを削除する。

    if (is109()) {
        if (12 * 6 + 8 <= code && code <= 12 * 6 + 11)
            return matrixFn109[code - (12 * 6 + 8)];
    }

罠その2。3キーまでの同時押しが可能と書いたが、モディファイヤとしては Ctrl と Shift しか使えない。Alt と Win も使えるようにするには KeyboardCommon.c の processKeys 関数の case 文に次の分岐を追加する。

case KEY_LEFTALT:
    modifiers |= MOD_LEFTALT;
    break;
case KEY_RIGHTALT:
    modifiers |= MOD_RIGHTALT;
    break;
case KEY_LEFT_GUI:
    modifiers |= MOD_LEFTGUI;
    break;
case KEY_RIGHT_GUI:
    modifiers |= MOD_RIGHTGUI;
    break;

罠その3。[変換] (KEY_INTERNATIONAL4) と [無変換] (KEY_INTERNATIONAL5) がスペースキーに化ける。[変換] と [無変換] がそのまま入力されるようにするには KeyboardCommon.c の processOSMode 関数の次のコード(4か所ある)をすべて削除する。

case KEY_INTERNATIONAL4:
case KEY_INTERNATIONAL5:
    report[i] = KEY_SPACEBAR;
    break;

罠その4。Fn+F3 (LAYOUT) の設定が jp または jp-n の場合、Shift+[0] でアンダースコア(Shift+[\])が入力されるが、この処理もハードコーディングされている。Fn 面に [\] を割り当てたときバッティングするので、KeyboardJP.c にある次のコードを削除する。

case KEY_0:
    if ((mod & MOD_SHIFT) && isJP())
        key = KEY_INTERNATIONAL1;
    break;

KeyboardJP.c にはこの他にも怪しげなハードコーディングがたくさんある。日本語レイアウトを使う人は一通り検証したほうがいい。

筆者のカスタマイズ例

最終的な割り当ては OS 側で(のどかを使って)別途カスタマイズする。ファームウェア上のマッピングは、そのままの状態での実用性を求めるのではなく、カスタマイズの自由度を最大化することを目指す。つまり、単独で存在しないキーを(実際の使用頻度にかかわらず)できるだけたくさん Fn 面に割り当てる。とはいえ、109 キーボードドライバで拾えるキーはそんなに多くないので、全部を単独キーと異なるキーにすることはできない。

  • 下段の16進数はのどかで調べたスキャンコード(Keyboard.h で定義されている値とは異なる)。
  • 小指外側のキー([全角], [英数], [:], []])は、のどかでモディファイヤ化する可能性を考えて、元のキーと同じにしてある。
  • OS のキーボードドライバは、日本語 109 キーボード用の標準ドライバを使う。
  • NISSE は次の設定で使う。(ファームウェア書き込み直後のデフォルト設定。[\] と [¥] が存在しない)
f2 pc
f3 us
f4 roma
f5 d0
f6 c
f7 ms
f8 c-c
f9 off

ソースコード:

static uint8_t const matrixFn[8][12][3] =
{
    {{KEY_PRINTSCREEN}, {KEY_F2}, {KEY_F3}, {KEY_F4}, {KEY_F5}, {KEY_F6}, {KEY_F7}, {KEY_F8}, {KEY_F9}, {KEY_MUTE}, {KEY_VOLUME_DOWN}, {KEY_PAUSE}},
    {{KEY_GRAVE_ACCENT}, {KEY_F1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_VOLUME_UP}, {KEY_BACKSLASH}},
    {{KEY_SCROLL_LOCK}, {KEY_LEFTALT, KEY_1}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {0}, {KEY_LEFTALT, KEY_0}, {KEYPAD_NUM_LOCK}},
    {{KEY_CAPS_LOCK}, {KEY_LEFTALT, KEY_2}, {KEY_LEFTALT, KEY_3}, {KEY_LEFTALT, KEY_4}, {KEY_LEFTALT, KEY_5}, {0}, {0}, {KEY_LEFTALT, KEY_6}, {KEY_LEFTALT, KEY_7}, {KEY_LEFTALT, KEY_8}, {KEY_LEFTALT, KEY_9}, {KEY_QUOTE}},
    {{KEY_INTERNATIONAL2}, {KEY_INTERNATIONAL4}, {KEY_PAGEUP}, {KEY_INTERNATIONAL5}, {KEY_INTERNATIONAL6}, {0}, {0}, {KEY_LANG3}, {KEY_NON_US_BACKSLASH}, {KEY_UPARROW}, {KEYPAD_EQUAL}, {KEYPAD_COMMA}},
    {{KEY_INTERNATIONAL1}, {KEY_INSERT}, {KEY_PAGEDOWN}, {KEY_DELETE}, {KEY_INTERNATIONAL3}, {KEY_ESCAPE}, {KEY_APPLICATION}, {KEY_HOME}, {KEY_LEFTARROW}, {KEY_DOWNARROW}, {KEY_RIGHTARROW}, {KEY_END}},
    {{KEY_F15}, {KEY_F16}, {KEY_F17}, {KEY_F18}, {KEY_F19}, {KEY_TAB}, {KEY_ENTER}, {KEY_F20}, {KEY_F21}, {KEY_F22}, {KEY_F23}, {KEY_F24}},
    {{0}, {0}, {0}, {0}, {KEY_BACKSPACE}, {0}, {0}, {KEY_SPACEBAR}, {0}, {0}, {0}, {0}}
};

次回は Fn キーのワンショットモディファイヤ化に挑戦するよ。

参考資料

エスリル NISSE ファームウェア改造ガイド (2)

エスリル ニューキーボード − NISSEファームウェアを自分用に改造するメモ。

4. Fn キーと Shift キーを入れ替えてみる

MPLAB X IDE を起動。前回終了時に開いていたプロジェクト「USB Device - HID - Keyboard」が自動的に開く。
Projects ツリーで Header Files と Source Files を眺める。関係しそうなのは Keyboard.h, KeyboardCommon.c, KeyboardJP.c, KeyboardUS.c あたりか。
ソースコードの識別子(変数名や関数名)の上で右クリック → Navigate - Go to Declaration/Definition で、その変数/関数の宣言/実装にジャンプできる。あと右クリック → Find Usages (Alt+[F7]) でその識別子の使用箇所一覧が出てくる。
app/main.c に main 関数がある。そこから app/app_device_keyboard.c の APP_KeyboardTasks 関数を経て、押されているキーごとに KeyboardCommon.c の onPressed 関数が呼ばれる。
そこから KeyboardUS.c の getKeyBase 関数が呼ばれ、同じ KeyboardUS.c に定義されている配列 matrixQwerty, matrixDvorak, matrixColemak, matrixJIS, matrixNicolaF を参照して、押されているキーのマトリクス上の行番号と列番号である row, column が key に変換される。
単純にキーを入れ替えるだけなら、これらの配列 matrix* を書き換えればよさそう。

static uint8_t const matrixQwerty[8][12] =
{
    KEY_LEFT_BRACKET, KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, KEY_F10, KEY_F11, KEY_EQUAL,
    KEY_GRAVE_ACCENT, KEY_F1, 0, 0, 0, 0, 0, 0, 0, 0, KEY_F12, KEY_BACKSLASH,
    KEY_RIGHT_BRACKET, KEY_1, 0, 0, 0, 0, 0, 0, 0, 0, KEY_0, KEY_MINUS,
    KEY_CAPS_LOCK, KEY_2, KEY_3, KEY_4, KEY_5, 0, 0, KEY_6, KEY_7, KEY_8, KEY_9, KEY_QUOTE,
    KEY_Q, KEY_W, KEY_E, KEY_R, KEY_T, 0, 0, KEY_Y, KEY_U, KEY_I, KEY_O, KEY_P,
    KEY_A, KEY_S, KEY_D, KEY_F, KEY_G, KEY_ESCAPE, KEY_APPLICATION, KEY_H, KEY_J, KEY_K, KEY_L, KEY_SEMICOLON,
    KEY_Z, KEY_X, KEY_C, KEY_V, KEY_B, KEY_TAB, KEY_ENTER, KEY_N, KEY_M, KEY_COMMA, KEY_PERIOD, KEY_SLASH,
    KEY_LEFTCONTROL, KEY_LEFT_GUI, KEY_FN, KEY_LEFTSHIFT, KEY_BACKSPACE, KEY_LEFTALT, KEY_RIGHTALT, KEY_SPACEBAR, KEY_RIGHTSHIFT, KEY_FN, KEY_RIGHT_GUI, KEY_RIGHTCONTROL
};

この並び順は https://www.esrille.com/keyboard/ja-jp/support.html の一番下に書いてあるキーマトリクスに対応している。絵で描くとこう。

とりあえず QWERTY 配列の左手だけ、KEY_FN と KEY_LEFTSHIFT を入れ替えてみよう。

    KEY_LEFTCONTROL, KEY_LEFT_GUI, KEY_LEFTSHIFT, KEY_FN, KEY_BACKSPACE, KEY_LEFTALT, KEY_RIGHTALT, KEY_SPACEBAR, KEY_RIGHTSHIFT, KEY_FN, KEY_RIGHT_GUI, KEY_RIGHTCONTROL

Ctrl+[S] で保存し、Run - Build Project でビルドする。
HIDBootloader.exe を起動。firmware/third_party/mla_v2013_12_20/apps/usb/device/hid_keyboard/firmware/MPLAB.X/dist/Esrille_New_Keyboard_with_Mouse/production/MPLAB.X.production.hex を NISSE キーボードに書き込む。
のどかを使ってスキャンコードを調査。新しい左 Fn キーが Fn キーとして働いていることを確認。Fn+[F1]〜[F9] の機能もちゃんと働いてることを確認。*1
よっしゃ!
うまくいったようなので、右手の KEY_RIGHTSHIFT と KEY_FN も入れ替える。他の matrix* も同様に書き換えて Fn キーの位置を全マトリクスで統一しておこう。
あと NumLock 時のマトリクスも、右 Fn キーを [0] として使っているので修正したほうがいい。

static uint8_t const matrixNumLock[8][5] =
{
    0, 0, 0, 0, 0,
    0, 0, 0, 0, 0,
    0, 0, 0, KEYPAD_MULTIPLY, 0,
    KEY_CALC, 0, KEYPAD_EQUAL, KEYPAD_DIVIDE, 0,
    0, KEYPAD_7, KEYPAD_8, KEYPAD_9, KEYPAD_SUBTRACT,
    0, KEYPAD_4, KEYPAD_5, KEYPAD_6, KEYPAD_ADD,
    0, KEYPAD_1, KEYPAD_2, KEYPAD_3, KEY_ENTER,
//  0, KEYPAD_0, 0, KEYPAD_DOT, 0,
    0, 0, KEYPAD_0, KEYPAD_DOT, 0,
};

次回は Fn 面のマッピングを変えるよ。

*1:Fn+[F3] で QWERTY 以外の配列にすると Fn キーの位置が元に戻る。忘れると焦る。

エスリル NISSE ファームウェア改造ガイド (1)

エスリル ニューキーボード − NISSE の Fn キーの位置が使いにくい。設定では Fn キーの位置は変更できないので、ファームウェアを自分用に改造する。開発環境は Windows 7 (64 bit)。

1. 開発環境のセットアップ

Microchip 社の MPLAB X IDE と MPLAB XC8 Compiler を使う。あと Microchip Libraries for Applications も必要。

罠注意!

インストール作業はディスプレイのスケーリングを 100% にして行うこと! 高解像度ディスプレイ利用者は特に注意。

これを忘れるとインストーラが固まる。うちの環境でディスプレイスケーリングの問題が起きたのは XC8 Compiler だけだったが、この会社のインストーラは信用できないので、最初から最後までディスプレイスケーリング 100% の環境でインストールした方がよさそう。

MPLAB X IDE
  1. https://www.microchip.com/pagehandler/en-us/family/mplabx/ の Downloads タブから MPLAB® X IDE v3.20 をダウンロード。
  2. MPLABX-v3.20-windows-installer.exe を実行。
  3. C:\Program Files (x86)\Microchip\MPLABX\v3.20\ にインストール。
MPLAB XC8 Compiler
  1. https://www.microchip.com/pagehandler/en-us/devtools/mplabxc/ の Downloads Archive タブから MPLAB XC8 Compiler v1.34 をダウンロード。
    • 執筆時点では最新版 v1.35 が最新版だが、v1.35 を使うと問題がある(後述)。今のところ v1.34 を使っておいた方が無難。
  2. xc8-v1.34-full-install-windows-installer.exe を実行。
  3. インストール先は C:\Program Files (x86)\Microchip\xc8\v1.34 で OK。
  4. Compiler Settings で Update MPLAB IDE to use the XC8 compiler for all existing C18 (mcc18) projects と Use XC8 for the C18 Linker, Librarian and Assembler にチェック。
    • Compiler Settings 画面で文字がちらついてたらアウト! ディスプレイのスケーリングを 100% にすること。このまま進めると次の Installing 画面でインストーラが固まる。
  5. PRO ライセンスは不要。Next をクリック。
Microchip Libraries for Applications
  1. http://www.microchip.com/pagehandler/en-us/devtools/mla/ の Current MLA タブから Microchip Libraries for Applications をダウンロード。
  2. mla_v2015_08_10_windows_installer.exe を実行。
  3. インストール先は C:\Program Files (x86)\Microchip\mla\v2015_08_10 で OK。
設定確認
  1. MPLAB X IDE を起動。
  2. Tools - Options - Embedded - Build Tools に XC8 が登録されてることを確認。
XC8 Compiler v1.35 を使う場合

XC8 v1.35 から Peripheral Libraries (plib) が同梱されなくなった*1ので、これを別途インストールする必要がある。

  1. https://www.microchip.com/pagehandler/en-us/devtools/mplabxc/ の Downloads タブの下の方から PIC18F Legacy Peripheral Libraries v1.0 をダウンロード。
  2. peripheral-libraries-for-pic18-v2.00rc3-windows-installer.exe を実行。
  3. インストール先を C:\Program Files (x86)\Microchip\xc8\v1.35 に修正してインストール。

2. ソースコードの取得とコンパイル

ファームウェアソースコードhttps://github.com/esrille/new-keyboard にある。

  1. GitHub にログインしてソースコードを Fork する。GitHub のアカウントを作りたくない人は Zip でダウンロードしてもいいけど。
  2. MPLAB X IDE を起動。
  3. File - Open Project で、ダウンロードしたソースツリーの firmware\third_party\mla_v2013_12_20\apps\usb\device\hid_keyboard\firmware\MPLAB.X を開く。
  4. 通常型とポインティングデバイス内蔵型は、同じプロジェクトだが異なるコンフィグレーションになっている。コンフィグレーションの切り替えはツールバーのドロップダウンリストで行う。ビルドはコンフィグレーション別に行う必要がある。
  5. Projects ツリーの USB Device - HID - Keyboard を右クリック → Build でビルドする。
  6. BUILD SUCCESSFUL (total time: 43s) とか表示されたら成功。ソースツリーの次の場所にファームウェアの .hex ファイルが生成されている。
    • 通常型は firmware\third_party\mla_v2013_12_20\apps\usb\device\hid_keyboard\firmware\MPLAB.X\dist\Esrille_New_Keyboard\production\MPLAB.X.production.hex
    • ポインティングデバイス内蔵型は firmware\third_party\mla_v2013_12_20\apps\usb\device\hid_keyboard\firmware\MPLAB.X\dist\Esrille_New_Keyboard_with_Mouse\production\MPLAB.X.production.hex
XC8 Compiler v1.35 を使った場合
  • ビルド時に ../src/system_config/esrille_new_keyboard/system.c:57: error: (141) can't open include file "plib/usart.h": No such file or directory というエラーが出て失敗したら、Legacy Peripheral Libraries をインストールし忘れている。C:\Program Files (x86)\Microchip\xc8\v1.34\include\plib フォルダの中に .h ファイルが存在することを確認。あと一応、File - Project Properties の XC8 linker の Link in Peripheral Library にチェックが入っていることも確認。
  • なんか Warning が出てるのが気になる。特に後者は気になる。
../../../../../../../../src/KeyboardUS.c:115: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardUS.c:130: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:397: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:401: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:405: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:420: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:434: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardJP.c:448: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/Mouse.c:85: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/Mouse.c:103: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:181: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:184: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:187: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:190: warning: (1404) unsupported: The Read_b_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:207: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:221: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:235: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
../../../../../../../../src/KeyboardCommon.c:249: warning: (1404) unsupported: The Busy_eep routine is no longer supported. Please use the MPLAB X MCC.
Warning: firmware/third_party/mla_v2013_12_20/apps/usb/device/hid_keyboard/firmware/MPLAB.X/dist/Esrille_New_Keyboard_with_Mouse/debug/MPLAB.X.debug.elf contains code that is located at addresses that do not exist on the PIC18F4550.
Code incompletely loaded.
  • .hex ファイルの中身も v1.34 でビルドしたものとは異なる。NISSE キーボードにロードしてみたら、とりあえず動いているようだけど…?

3. ファームウェアの書き込み

https://www.esrille.com/keyboard/ja-jp/support.html の一番下に書いてあるとおり。

  1. NISSE キーボードの USB ケーブルを抜き、Esc キーを押しながらケーブルを挿し直す。赤ランプが点滅する。
    • USB ハブを介するとダメみたい。PC 本体の USB ポートに直結すること。
  2. C:\Program Files (x86)\Microchip\mla\v2015_08_10\apps\usb\device\bootloaders\utilities\bin\win\HIDBootloader.exe を実行。
    • Device not detected. Verify device is attached and in firmware update mode. と表示されたらダメ。NISSE キーボードを接続し直す。
  3. File - Import Firmware Image で、さっきビルドしたファームウェアの .hex ファイルを開く。
  4. Program - Erase/Program/Verify Device でファームウェアを NISSE キーボードに書き込む。
  5. Program - Reset Device で NISSE キーボードをリセットする。


これでようやくスタートラインに立った。次回からいよいよソースコードをいじるよ。