CTRL配列 - v.3.0

## はじめに

こんにちは、Ctrlです。

https://qiita.com/hiyoctrl/items/70885ee39938b72dd657

https://qiita.com/hiyoctrl/items/11ea9d917f2716408944

今回はCTRL配列のメジャーアップデートになります。

### 主な変更点

- 子音のレイヤーを左手人差し指から左手親指に変更 
- 右手でも利用できるようにスワップハンドを導入
- スワップハンド時、アローキーの左右が逆になるのを解消
- スワップハンド時、Vimiumの [ . ] 左のタブに移動、 [ , ] 右のタブに移動のズレを解消
- IMEをトグルだけでなく、直接入力、日本語入力で切り替えできるようにした

### 解決していない課題や問題(自分用メモ)

- アルファベットが逆に配置されるのと比べて、数字キーが覚えにくい
- 両手入力用レイヤーのレイヤー、トグル、ホールドの設定
- 両手入力用のファームウェアの作成の可否判断
- 未使用のタップダンスやマクロの整理
- コンボの導入の可否判断


## 使用しているPCB：物理キーボード

使用している物理キーボードは[@takashicompany](https://twitter.com/takashicompany)さんのWorm Eatenです。

https://github.com/takashicompany/worm_eaten/tree/master

普段は左手にWorm Eaten、右手にKensingtonのスリムブレード、ディスプレイの下に無指向性マイクを設置して作業しています。

## 全体のサンプルコード

<details><summary>keymap.c</summary>

```c

#include QMK_KEYBOARD_H
enum layer_number {
    _BASE = 0,_MOD1,_MOD2,_MOD3,_NUM4,_AAA5,_ENG6,_KKK7,
};
enum custom_keycodes {
    LSHB = SAFE_RANGE,
    LSHC,
    LSEC,
    PRN,
    BRC,
    TAE,
    KEY,
    GYOC,
    GYOV,
    LBS,
    CAA,
    CAC,
    CAV,
    CCC,
    CCV,
    PPRN,
};
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    switch (keycode) {
    case LSHB:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("b"));
        } else {
        }
        break;
    case LSHC:
        if (record->event.pressed) {
        SEND_STRING(SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("c"));
        } else {
        }
        break;
    case LSEC:
        if (record->event.pressed) {
        SEND_STRING(SS_LSFT(SS_TAP(X_END)) SS_LCTL("c"));
        } else {
        }
        break;
    case PPRN:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("x") SS_DELAY(100) "(" SS_DELAY(100) SS_LCTL("v") SS_DELAY(100) ")");
        } else {
        }
        break;
    case PRN:
        if (record->event.pressed) {
        SEND_STRING("()");
        } else {
        }
        break;
    case BRC:
        if (record->event.pressed) {
        SEND_STRING("[]");
        } else {
        }
        break;
    case TAE:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("t") SS_DELAY(1200) SS_TAP(X_TAB) SS_TAP(X_ENT));
        } else {
        }
        break;
    case KEY:
        if (record->event.pressed) {
        SEND_STRING(SS_LCTL("c") SS_TAP(X_ESC) "_");
        } else {
        }
        break;
    case GYOC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("c"));
        } else {
        }
        break;
    case GYOV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_END) SS_LSFT(SS_TAP(X_HOME)) SS_LCTL("v"));
        } else {
        }
        break;
    case LBS:
        if (record->event.pressed) {
        SEND_STRING("l" SS_TAP(X_BSPC));
        } else {
        }
        break;
    case CAA:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a"));
        } else {
        }
        break;
    case CAC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("c"));
        } else {
        }
        break;
    case CAV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_LCTL("a") SS_LCTL("v"));
        } else {
        }
    case CCC:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_BTN1) SS_LCTL("c"));
        } else {
        }
    case CCV:
        if (record->event.pressed) {
        SEND_STRING(SS_TAP(X_BTN1) SS_TAP(X_BTN1) SS_LCTL("v"));
        } else {
        }
        break;
    }
    return true;
};
enum {
    TD_A,TD_B,TD_C,TD_D,TD_E,TD_F,TD_G,TD_H,TD_I,TD_J,TD_K,TD_L,TD_M,
    TD_N,TD_O,TD_P,TD_Q,TD_R,TD_S,TD_T,TD_U,TD_V,TD_W,TD_X,TD_Y,TD_Z,
    TD_VVV,
    TD_CCC,
    TD_HSH,
    TD_ESE,
    TD_ZAY,
    TD_HAF,
    TD_AAF,
    TD_CAL,
    TD_SAR,
    TD_HAC,
    TD_2CA,
    TD_3CA,
    TD_0CA,
    TD_WAT,
    TD_EAU,
    TD_QAD,
    TD_CAX,
    TD_CAA,
    TD_LPA,
    TD_RPA,
    TD_LBC,
    TD_RBC,
    TD_VAH,
    TD_USU,
    TD_DSD,
    TD_CSC,
    TD_DSQ,
    TD_SBS,
    TD_ASA,
    TD_GAC,
    TD_HAD,
    TD_DDD,
    TD_PPC,
    TD_EAA,
    TD_LWL,
    TD_RWR,
};
tap_dance_action_t tap_dance_actions[] = {
    [TD_A] = ACTION_TAP_DANCE_DOUBLE(KC_A, LSFT(KC_A)),
    [TD_B] = ACTION_TAP_DANCE_DOUBLE(KC_B, LSFT(KC_B)),
    [TD_C] = ACTION_TAP_DANCE_DOUBLE(KC_C, LSFT(KC_C)),
    [TD_D] = ACTION_TAP_DANCE_DOUBLE(KC_D, LSFT(KC_D)),
    [TD_E] = ACTION_TAP_DANCE_DOUBLE(KC_E, LSFT(KC_E)),
    [TD_F] = ACTION_TAP_DANCE_DOUBLE(KC_F, LSFT(KC_F)),
    [TD_G] = ACTION_TAP_DANCE_DOUBLE(KC_G, LSFT(KC_G)),
    [TD_H] = ACTION_TAP_DANCE_DOUBLE(KC_H, LSFT(KC_H)),
    [TD_I] = ACTION_TAP_DANCE_DOUBLE(KC_I, LSFT(KC_I)),
    [TD_J] = ACTION_TAP_DANCE_DOUBLE(KC_J, LSFT(KC_J)),
    [TD_K] = ACTION_TAP_DANCE_DOUBLE(KC_K, LSFT(KC_K)),
    [TD_L] = ACTION_TAP_DANCE_DOUBLE(KC_L, LSFT(KC_L)),
    [TD_M] = ACTION_TAP_DANCE_DOUBLE(KC_M, LSFT(KC_M)),
    [TD_N] = ACTION_TAP_DANCE_DOUBLE(KC_N, LSFT(KC_N)),
    [TD_O] = ACTION_TAP_DANCE_DOUBLE(KC_O, LSFT(KC_O)),
    [TD_P] = ACTION_TAP_DANCE_DOUBLE(KC_P, LSFT(KC_P)),
    [TD_Q] = ACTION_TAP_DANCE_DOUBLE(KC_Q, LSFT(KC_Q)),
    [TD_R] = ACTION_TAP_DANCE_DOUBLE(KC_R, LSFT(KC_R)),
    [TD_S] = ACTION_TAP_DANCE_DOUBLE(KC_S, LSFT(KC_S)),
    [TD_T] = ACTION_TAP_DANCE_DOUBLE(KC_T, LSFT(KC_T)),
    [TD_U] = ACTION_TAP_DANCE_DOUBLE(KC_U, LSFT(KC_U)),
    [TD_V] = ACTION_TAP_DANCE_DOUBLE(KC_V, LSFT(KC_V)),
    [TD_W] = ACTION_TAP_DANCE_DOUBLE(KC_W, LSFT(KC_W)),
    [TD_X] = ACTION_TAP_DANCE_DOUBLE(KC_X, LSFT(KC_X)),
    [TD_Y] = ACTION_TAP_DANCE_DOUBLE(KC_Y, LSFT(KC_Y)),
    [TD_Z] = ACTION_TAP_DANCE_DOUBLE(KC_Z, LSFT(KC_Z)),
    [TD_VVV] = ACTION_TAP_DANCE_DOUBLE(RCS(KC_V),    LCTL(KC_V)),
    [TD_VAH] = ACTION_TAP_DANCE_DOUBLE(RCS(KC_V),    LCTL(KC_H)),
    [TD_CCC] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_C),   RCS(KC_C)),
    [TD_HSH] = ACTION_TAP_DANCE_DOUBLE(KC_HOME,      LSFT(KC_HOME)),
    [TD_ESE] = ACTION_TAP_DANCE_DOUBLE(KC_END,       LSFT(KC_END)),
    [TD_ZAY] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_Z),   LCTL(KC_Y)),
    [TD_HAF] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_H),   LCTL(KC_F)),
    [TD_AAF] = ACTION_TAP_DANCE_DOUBLE(KC_ASTR,      LGUI(KC_UP)),
    [TD_CAL] = ACTION_TAP_DANCE_DOUBLE(KC_COLN,      LGUI(KC_LEFT)),
    [TD_SAR] = ACTION_TAP_DANCE_DOUBLE(KC_SLSH,      LGUI(KC_RGHT)),
    [TD_HAC] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_SPC), KC_CAPS),
    [TD_2CA] = ACTION_TAP_DANCE_DOUBLE(KC_2,         LCA(KC_2)),
    [TD_3CA] = ACTION_TAP_DANCE_DOUBLE(KC_3,         LCA(KC_3)),
    [TD_0CA] = ACTION_TAP_DANCE_DOUBLE(KC_0,         LCA(KC_0)),
    [TD_WAT] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_W),   RCS(KC_T)),
    [TD_EAU] = ACTION_TAP_DANCE_DOUBLE(KC_EXLM,      RCS(KC_PGUP)),
    [TD_QAD] = ACTION_TAP_DANCE_DOUBLE(KC_QUES,      RCS(KC_PGDN)),
    [TD_CAX] = ACTION_TAP_DANCE_DOUBLE(LCTL(KC_C),   LCTL(KC_X)),
    [TD_CAA] = ACTION_TAP_DANCE_DOUBLE(LALT(KC_TAB), LCA(KC_TAB)),
    [TD_LPA] = ACTION_TAP_DANCE_DOUBLE(KC_LPRN,      KC_LABK),
    [TD_RPA] = ACTION_TAP_DANCE_DOUBLE(KC_RPRN,      KC_RABK),
    [TD_LBC] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC,      KC_LABK),
    [TD_RBC] = ACTION_TAP_DANCE_DOUBLE(KC_RBRC,      KC_RABK),
    [TD_USU] = ACTION_TAP_DANCE_DOUBLE(KC_UP,        LSFT(KC_UP)),
    [TD_DSD] = ACTION_TAP_DANCE_DOUBLE(KC_DOWN,      LSFT(KC_DOWN)),
    [TD_CSC] = ACTION_TAP_DANCE_DOUBLE(KC_COLN,      KC_SCLN),
    [TD_DSQ] = ACTION_TAP_DANCE_DOUBLE(KC_DQUO,      KC_QUOT),
    [TD_SBS] = ACTION_TAP_DANCE_DOUBLE(KC_SLSH,      KC_BSLS),
    [TD_ASA] = ACTION_TAP_DANCE_DOUBLE(KC_ASTR,      KC_AT),
    [TD_GAC] = ACTION_TAP_DANCE_DOUBLE(KC_GRV,       KC_CIRC),
    [TD_HAD] = ACTION_TAP_DANCE_DOUBLE(KC_HASH,      KC_DLR),
    [TD_DDD] = ACTION_TAP_DANCE_DOUBLE(KC_DEL,       LSFT(KC_DEL)),
    [TD_PPC] = ACTION_TAP_DANCE_DOUBLE(KC_PLUS,      KC_PERC),
    [TD_EAA] = ACTION_TAP_DANCE_DOUBLE(KC_EQL,       KC_AMPR),
    [TD_LWL] = ACTION_TAP_DANCE_DOUBLE(KC_LEFT,      LGUI(KC_LEFT)),
    [TD_RWR] = ACTION_TAP_DANCE_DOUBLE(KC_RGHT,      LGUI(KC_RGHT)),
};

const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
    {{4, 0}, {3, 0}, {3, 4}, {4, 4}, {0, 0}},
    {{4, 1}, {3, 1}, {1, 4}, {2, 4}, {0, 1}},
    {{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
    {{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
    {{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    [_BASE] = LAYOUT(
    TD(TD_HAC),   LT(7,KC_DOT), LT(3,KC_COMM),TD(TD_USU),   TD(TD_VVV),
    LT(4,KC_ESC), KC_LEFT,      KC_RGHT,      LT(1,KC_BTN1),TD(TD_CCC),
    KC_TAB,       XXXXXXX,      XXXXXXX,      TD(TD_DSD),   LT(2,KC_SPC),
    SH_TG,        XXXXXXX,      XXXXXXX,      LT(5,KC_BSPC),LT(6,KC_ENT),
    XXXXXXX,      KC_LEFT,      KC_RGHT,      LT(3,KC_DOT), LT(7,KC_COMM)),
    [_MOD1] = LAYOUT(
    TD(TD_DSQ),   TD(TD_CSC),   TD(TD_SBS),   XXXXXXX,      XXXXXXX,
    KC_UNDS,      LGUI(KC_LEFT),LGUI(KC_RGHT),XXXXXXX,      XXXXXXX,
    TD(TD_ASA),   XXXXXXX,      XXXXXXX,      TD(TD_HAF),   XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_DDD),   TD(TD_WAT),
    XXXXXXX,      LGUI(KC_LEFT),LGUI(KC_RGHT),TD(TD_SBS),   TD(TD_CSC)),
    [_MOD2] = LAYOUT(
    KC_PIPE,      KC_EXLM,      KC_QUES,      TD(TD_HSH),   CAA,
    TD(TD_HAD),   LSFT(KC_LEFT),LSFT(KC_RGHT),TD(TD_ZAY),   LCTL(KC_X),
    TD(TD_GAC),   XXXXXXX,      XXXXXXX,      TD(TD_ESE),   XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      LSHB,
    XXXXXXX,      LSFT(KC_LEFT),LSFT(KC_RGHT),KC_QUES,      KC_EXLM),
    [_MOD3] = LAYOUT(
    XXXXXXX,      TD(TD_PPC),   XXXXXXX,      LCTL(KC_S),   XXXXXXX,
    TD(TD_EAA),   XXXXXXX,      XXXXXXX,      RCS(KC_S),    XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LBC),   TD(TD_RBC),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LPA),   TD(TD_RPA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_PPC)),
    [_NUM4] = LAYOUT(
    SH_TG,        KC_1,         TD(TD_2CA),   TD(TD_3CA),   KC_4,
    XXXXXXX,      KC_5,         KC_6,         KC_7,         KC_8,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_9,         TD(TD_0CA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_LNG1,      KC_LNG2,
    XXXXXXX,      KC_6,         KC_5,         TD(TD_2CA),   KC_1),
    [_AAA5] = LAYOUT(
    TD(TD_X),     TD(TD_O),     TD(TD_E),     TD(TD_Y),     TD(TD_W),
    TD(TD_A),     TD(TD_J),     TD(TD_C),     TD(TD_I),     TD(TD_V),
    TD(TD_Q),     XXXXXXX,      XXXXXXX,      TD(TD_U),     TD(TD_F),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      TD(TD_C),     TD(TD_J),     TD(TD_E),     TD(TD_O)),
    [_ENG6] = LAYOUT(
    TD(TD_L),     TD(TD_S),     TD(TD_T),     TD(TD_R),     TD(TD_P),
    TD(TD_K),     TD(TD_Z),     TD(TD_D),     TD(TD_N),     TD(TD_H),
    TD(TD_G),     XXXXXXX,      XXXXXXX,      TD(TD_M),     TD(TD_B),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      TD(TD_D),     TD(TD_Z),     TD(TD_T),      TD(TD_S)),
    [_KKK7] = LAYOUT(
    XXXXXXX,      XXXXXXX,      LGUI(KC_UP),  XXXXXXX,      XXXXXXX,
    KC_TILD,      XXXXXXX,      XXXXXXX,      KC_MINS,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      LGUI(KC_UP),  XXXXXXX),
};

```

</details>

以上が今回の全体のサンプルコードになります。

マクロやタップダンスについては、キーボードレイアウトに組み込まれていないものもあります。また、想定していたような挙動をしないものについても、微調整中のため記載しておりますので、サンプルコードの取り扱いについては自己責任でお願いします。

## スワップハンド

``` c

const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = {
    {{4, 0}, {3, 0}, {3, 4}, {4, 4}, {0, 0}},
    {{4, 1}, {3, 1}, {1, 4}, {2, 4}, {0, 1}},
    {{4, 2}, {3, 2}, {2, 2}, {1, 2}, {0, 2}},
    {{4, 3}, {3, 3}, {2, 3}, {1, 3}, {0, 3}},
    {{4, 4}, {3, 4}, {2, 4}, {1, 4}, {0, 4}}
};

``` 

まずは今回の主な変更点の一つである スワップハンドについて解説します。

普段は左手、片手キーボード、右手、トラックボールマウスで作業しているのですが、ある時「同じキーボードで右手で使えるようになったらいいのに...」と感じ始めました。もちろん 配列を覚えているので、同じ配列のまま右手で操作すれば良いのですが、やはり片手かつ左手用に作成したキーボード配列のため、しっくりきません。

前々からスワップハンドに興味があったので、頭の体操と思いスワップハンドの導入を決意しました。しかし、スワップハンドには大きな課題があったのです。

- 左右反転すると、アローキーの左右も反転するため逆になる
- 薬指、小指など右左で操作するようなショートカットなどが逆になる
- 数字キーが押しやすく、覚えやすいテンキー配列ではなくなる

解決するために考えたのが、ファームウェア上では存在するものの、物理キーのないキーの設定と、スワップハンドの設定を組み合わせることです。

スワップハンドの設定の5段目にスワップハンド時のキー設定をしておき、スワップハンドの配列に設定したキー配置を読み込ませることで、左右の反転にも対応できるようになりました。

ポイントとしては、全てのレイヤーにスワップハンドの配列変更が適用されてしまうため、左右が反転する箇所と判定しない箇所もしっかりと設定した点です。左右反転というとても単純なことでしたが、最初はうまくいかず、非常に良い頭の体操になりました。

同様に [ . ] と[ , ]の配置はそのまま、レイヤーのホールドの左右反転させ得ることで、Vimiumの [ . ] 左のタブに移動、 [ , ] 右のタブに移動のズレの解消も実現しています。

## タップダンス (一部抜粋)

```c 

    [TD_LPA] = ACTION_TAP_DANCE_DOUBLE(KC_LPRN,      KC_LABK),
    [TD_RPA] = ACTION_TAP_DANCE_DOUBLE(KC_RPRN,      KC_RABK),
    [TD_LBC] = ACTION_TAP_DANCE_DOUBLE(KC_LBRC,      KC_LABK),
    [TD_RBC] = ACTION_TAP_DANCE_DOUBLE(KC_RBRC,      KC_RABK),
    [TD_USU] = ACTION_TAP_DANCE_DOUBLE(KC_UP,        LSFT(KC_UP)),
    [TD_DSD] = ACTION_TAP_DANCE_DOUBLE(KC_DOWN,      LSFT(KC_DOWN)),
    [TD_CSC] = ACTION_TAP_DANCE_DOUBLE(KC_COLN,      KC_SCLN),
    [TD_DSQ] = ACTION_TAP_DANCE_DOUBLE(KC_DQUO,      KC_QUOT),
    [TD_SBS] = ACTION_TAP_DANCE_DOUBLE(KC_SLSH,      KC_BSLS),
    [TD_ASA] = ACTION_TAP_DANCE_DOUBLE(KC_ASTR,      KC_AT),
    [TD_GAC] = ACTION_TAP_DANCE_DOUBLE(KC_GRV,       KC_CIRC),
    [TD_HAD] = ACTION_TAP_DANCE_DOUBLE(KC_HASH,      KC_DLR),
    [TD_DDD] = ACTION_TAP_DANCE_DOUBLE(KC_DEL,       LSFT(KC_DEL)),
    [TD_PPC] = ACTION_TAP_DANCE_DOUBLE(KC_PLUS,      KC_PERC),
    [TD_EAA] = ACTION_TAP_DANCE_DOUBLE(KC_EQL,       KC_AMPR),

``` 

タップダンスについては、記号キーをいくつかまとめるようにしました。「使うか使わないかわからない記号」「使用頻度が低すぎる記号」をタップダンスの2連打に入れてあります。

かっこ記号についてもある程度まとめて、現時点では使わないかっこについても、いつでも押せるようにしました。

また、タップダンスの挙動で「ホールドと違い長押しすることで、設定したキーが連打される」という点に気がついたため、アローキーの上を2回タップするとLSFT(KC_UP)、同じく下を2回タップすると、LSFT(KC_DOWN)という形に設定しました。使用頻度は低いものの、もう1行だけ文字列を選択したいといったような時に役立っています。

## キー配列：キーボードレイアウト

### _BASE

```c 

    [_BASE] = LAYOUT(
    TD(TD_HAC),   LT(7,KC_DOT), LT(3,KC_COMM),TD(TD_USU),   TD(TD_VVV),
    LT(4,KC_ESC), KC_LEFT,      KC_RGHT,      LT(1,KC_BTN1),TD(TD_CCC),
    KC_TAB,       XXXXXXX,      XXXXXXX,      TD(TD_DSD),   LT(2,KC_SPC),
    SH_TG,        XXXXXXX,      XXXXXXX,      LT(5,KC_BSPC),LT(6,KC_ENT),
    XXXXXXX,      KC_LEFT,      KC_RGHT,      LT(3,KC_DOT), LT(7,KC_COMM)),

``` 

デフォルトのレイヤーについては、左手の人差し指と親指のレイヤーのホールドを変更したのが今回の一番大きな変更点です。元々は子音を人差し指、母音を親指に任せることで、指単位での交互打鍵をしたいと考えていましたが、いずれスプリットにして、両手で入力することも考えた場合において配列が微妙だったために変更しました。

また、左下にスワップハンドのトグルである、SH_TG を配置することで、右手側に置いて右手の親指でタップすれば、自然と右手用キーボードに切り替えられるようになっているのも工夫した点です。

### _MOD1

```c 

    [_MOD1] = LAYOUT(
    TD(TD_DSQ),   TD(TD_CSC),   TD(TD_SBS),   XXXXXXX,      XXXXXXX,
    KC_UNDS,      LGUI(KC_LEFT),LGUI(KC_RGHT),XXXXXXX,      XXXXXXX,
    TD(TD_ASA),   XXXXXXX,      XXXXXXX,      TD(TD_HAF),   XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_DDD),   TD(TD_WAT),
    XXXXXXX,      LGUI(KC_LEFT),LGUI(KC_RGHT),TD(TD_SBS),   TD(TD_CSC)),

``` 

_MOD1は左手人差し指でホールドするレイヤーです。人差し指のホールドの最大の弱点は、人差し指の上、右斜め上、右のキーが押しにくい点にあります。そのため、子音のアルファベットの配列に苦慮していましたが、親指に任せることで大幅に解除されました。

記号キーとショートカットが混在しているため、まだまだ改善の余地があるレイヤーでもあります。

### _MOD2

```c 

    [_MOD2] = LAYOUT(
    KC_PIPE,      KC_EXLM,      KC_QUES,      TD(TD_HSH),   CAA,
    TD(TD_HAD),   LSFT(KC_LEFT),LSFT(KC_RGHT),TD(TD_ZAY),   LCTL(KC_X),
    TD(TD_GAC),   XXXXXXX,      XXXXXXX,      TD(TD_ESE),   XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      LSHB,
    XXXXXXX,      LSFT(KC_LEFT),LSFT(KC_RGHT),KC_QUES,      KC_EXLM),

``` 

_MOD2は左手親指を少し上に伸ばしてホールドするレイヤーです。基本的には文字列の選択を行う レイヤーになっています。地味に便利なのがホームとエンドのタップダンスで、それぞれ2回タップすると文頭及び文末までの文字列選択できるため、ブラウザでの閲覧と編集作業の両方に欠かせない キーになりました。

### _MOD3

```c 

    [_MOD3] = LAYOUT(
    XXXXXXX,      TD(TD_PPC),   XXXXXXX,      LCTL(KC_S),   XXXXXXX,
    TD(TD_EAA),   XXXXXXX,      XXXXXXX,      RCS(KC_S),    XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LBC),   TD(TD_RBC),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_LPA),   TD(TD_RPA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      TD(TD_PPC)),

``` 

_MOD3は左手の中指でホールドするレイヤーです。このレイヤーは主にマイク入力のオンオフ、そしてかっこ記号を入力するためにあります。中指と人差し指を伸ばしてタップする保存、LCTL(KC_S)も地味に便利です。

### _NUM4

```c 

    [_NUM4] = LAYOUT(
    SH_TG,        KC_1,         TD(TD_2CA),   TD(TD_3CA),   KC_4,
    XXXXXXX,      KC_5,         KC_6,         KC_7,         KC_8,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_9,         TD(TD_0CA),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      KC_LNG1,      KC_LNG2,
    XXXXXXX,      KC_6,         KC_5,         TD(TD_2CA),   KC_1),

``` 

_NUM4は左手の小指でホールドするレイヤーです。 IMEをKC_LNG1、KC_LNG2といった形で、直接入力とローマ字入力が意識的に選択できるようになったので、どちらの状態かわからないというストレスが減りました。ただし、まだ不慣れでデフォルトのIMEを使っている方が多いのが現状です。

### _AAA5

```c 

    [_AAA5] = LAYOUT(
    TD(TD_X),     TD(TD_O),     TD(TD_E),     TD(TD_Y),     TD(TD_W),
    TD(TD_A),     TD(TD_J),     TD(TD_C),     TD(TD_I),     TD(TD_V),
    TD(TD_Q),     XXXXXXX,      XXXXXXX,      TD(TD_U),     TD(TD_F),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      TD(TD_C),     TD(TD_J),     TD(TD_E),     TD(TD_O)),

``` 

_AAA5は親指を少し内側に曲げてホールドするレイヤーです。主に母音を担当する レイヤーであり、今回は大幅な変更はありませんでした。

### _ENG6

```c 

    [_ENG6] = LAYOUT(
    TD(TD_L),     TD(TD_S),     TD(TD_T),     TD(TD_R),     TD(TD_P),
    TD(TD_K),     TD(TD_Z),     TD(TD_D),     TD(TD_N),     TD(TD_H),
    TD(TD_G),     XXXXXXX,      XXXXXXX,      TD(TD_M),     TD(TD_B),
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      TD(TD_D),     TD(TD_Z),     TD(TD_T),     TD(TD_S)),

``` 

_ENG6は親指を右に少しずらしてホールドするレイヤーです。以前は人差し指のレイヤーでしたが、親指に変更することでキーボードの右斜めを使えるようになりました。そのため、キーボードを両方に設置する場合において、配列が綺麗になったこと、左手と右手の両方の親指の2つのキーに何か割り当てるようになったことが大きな利点です。

現時点では両手で4つのキーに何を配置するか悩んでおり、同時にどのようなレイヤー及びホールドの配置にするのかを模索しています。 

### _KKK7

```c 

    [_KKK7] = LAYOUT(
    XXXXXXX,      XXXXXXX,      LGUI(KC_UP),  XXXXXXX,      XXXXXXX,
    KC_TILD,      XXXXXXX,      XXXXXXX,      KC_MINS,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,      XXXXXXX,
    XXXXXXX,      XXXXXXX,      XXXXXXX,      LGUI(KC_UP),  XXXXXXX),

``` 

_KKK7は左手の薬指でホールドするレイヤーです。以前はかっこ記号をまとめたレイヤーでしたが、現在は持て余しており改善するべきレイヤーでもあります。基本的に小指と薬指でホールドすることは避けたいため、将来的には廃止したいレイヤーです。

## まとめと告知

スワップハンドを導入したのは、左手の薬指でアローキーの左をタップするのがストレスになってたのが最初のきっかけです。ごろ寝している時など、右手側に既存のキーボードを置いて、左のアロー キーをタップしていたものの、どうせなら左右反転した方が良いと思い実現してみました。

![worm_eaten.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608727/7f884848-d73a-b9a0-4742-021653e538ab.png)

ただし、現時点においては片手かつ左手のキーボードでの作業が基本であること、同時に画像のような形で物理キー、キースイッチを配置してあるのは15キーのみのものが多いため、物理キーを追加するか悩んでいます。

左手の左下はほぼ届かないので、キースイッチやキーキャップを配置するのがもったいないと考えているのが理由です。全部のキーに配置してあるキーボードもありますが、やはり使わないキーに物理キーを割り当てるというのは、はんだ付けする時間も含めて微妙に思っています。

![worm_eaten_000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608727/fe976502-484d-c938-0076-67d551f32e46.png)

そのため、画像のような形で将来的に両手で作業することも考えて、反転した右手の物理キーボードも作りました。

レイヤーをトグルで切り替えて、完全にキーボードとして入力できるような配列を考えています。片手ではなく両手での入力を意識し始めたのは、音声入力が基軸だと、外で作業ができないのが理由です。

とはいえ、現時点においては、15キーの片手キーボード、右側にスリムブレード、そして マイクのみで仕事が進められているため、両手による入力に必要性を感じていないことから、あくまでも頭の体操、スキルや知識のアップのために妄想してるような段階と言えます。

何か面白いアイディアがありましたら、是非とも教えてください！ 

最後までお読みいただきありがとうございました。

年度の変わり目で少々バタバタしておりますが、コンテンツマーケティング関連や執筆 関連のお仕事があれば、お気軽にご相談いただけると幸いです。

https://crowdworks.jp/public/employees/1089210

https://www.lancers.jp/profile/Ctrl

https://coconala.com/users/448062