TAP THE FIRST SHOW

左右分離型のキーボードを使う夢があった。
ご多聞に漏れず、遅ればせながらErgoDoxEZを購入した。
しかし、購入して終わりではない。
夢見るのは、これからだ。


#TAP THE FIRST SHOW
ある程度C言語が出来る方が望ましい。
しかし、勘がありさえすれば、プログラミング知識は不要だ。

では、タップの世界へ、レッツらゴー。

##ワンタップで通常キー
タップしただけでは、通常のキー押下として扱い、押しっぱなしをControl Keys(Control・Shift・Alt・GUI)にしたい場合に、以下の設定を行う。

通常キーとは、アルファベットなどのことで、**Control Keys** 以外のキーを指す。

###Controlキー
`CTL_T(通常キー)`を使えば、タップは通常キーだが、長押しでコントロールキーに変貌する。
例えば、

```ErgoDox:keymap.c
CTL_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、コントロールキーになる。
あまりにも有名な変換方法で今更だろうが、一応紹介した。
これは、標準のキーマップで備わっているからな。
タップしたときは'Z'キーで、押しっぱなしは、コントロールキーになる。
　[ErgoDox EZ Default Layout - v1.3.4](https://configure.ergodox-ez.com/keyboard_layouts/new "ErgoDox EZ Default Layout")

`CTL_T(通常キー)`は、エイリアスで、本来は`LCTL_T(通常キー)`が正式になる。
要は、左コントロールキーを使う。
右コントロールキーは、`RCTL_T(kc)`になる。

これ以降、`kc`を使うかも知れないが、これは**通常キー**と思って欲しい。

※この関数の独自作成は不可能だと思ったが、挑戦して、そして[挫折](#ctl_t関数の自前作成)した。

###Shiftキー
`SFT_T(通常キー)`を使えば、タップは通常キーだが、長押しでシフトキーに豹変する。
例えば、

```ErgoDox:keymap.c
SFT_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、シフトキーになる。
`SFT_T(通常キー)`は、エイリアスなので、本来は`LSFT_T(kc)`(左シフトキー)になる。
右シフトキーは`RSFT_T(kc)`を使う。

###Altキー
`ALT_T(通常キー)`を使えば、タップは通常キーだが、長押しでAltキーに変形する。
例えば、

```ErgoDox:keymap.c
ALT_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、Altキーになる。
`ALT_T(通常キー)`は、エイリアスなので、本来は`LALT_T(kc)`(左アルトキー)になる。
右アルトキーは`RALT_T(kc)`を使う。なぜか、右側にもエイリアスがあり`ALGR_T(kc)`を使える。

###GUIキー
`GUI_T(通常キー)`を使えば、タップは通常キーだが、長押しでGuiキーに変体する。
例えば、

```ErgoDox:keymap.c
GUI_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、Guiキーになる。
ちなみに、GUIキーとは、WindowsOSであれば、Windowsキーのこと。
そして、MacOSであれば、Commandキーのこと。

`GUI_T(通常キー)`は、エイリアスなので、本来は`LGUI_T(kc)`(左GUIキー)になる。OSに合わせるためか、他にもエイリアスがあり,`LCMD_T(kc)`・`RWIN_T(kc)`を使える。
右GUIキーは`RGUI_T(kc)`を使う。当然のように右側にもエイリアスがあり`RCMD_T(kc)`・`RWIN_T(kc)`を使える。

####コマンドキー(GUIキーのエイリアス)
GUIキーのどこに不満があるのか分からないが、コマンドキーも存在する。
`CMD_T(通常キー)`を使えば、タップは通常キーだが、長押しでコマンド(Gui)キーに変化する。
例えば、

```ErgoDox:keymap.c
CMD_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、コマンド(Gui)キーになる。

####Winキー(GUIキーのエイリアス)
GUIキーのどこに不満があるのか分からないが、Windowsキーも存在する。
`WIN_T(通常キー)`を使えば、タップは通常キーだが、長押しでWindows(Gui)キーに変化する。
例えば、

```ErgoDox:keymap.c
WIN_T(KC_A)
```

これで、タップしたときは'A'キーになり、押しっぱなしであれば、Windows(Gui)キーになる。
コマンドキーとの違いが分からない。
一応MacOSとWindowsOSで使ってみたが、どれも(Gui・Cmd・Win)Guiキーとして動いてくれた(エイリアスなので当たり前)。

#TAP THE LAST SHOW
~~上記のソースコード(と言うか不明)は、左右に影響されない。
分けたい場合は、左は"L"を付け、右は"R"を先頭に付ければ区別されるようになるはず。~~

基本的に接頭辞に何も付いていない場合は、左側になる。
右側のコントロールキーやシフトキーにエイリアスはないようだが、用意されている場合もあるようだ。

```ErgoDox:keymap.c
 CTL_T(KC_A)
LCTL_T(KC_B)
RCTL_T(KC_C)

 SFT_T(KC_D)
LSFT_T(KC_E)
RSFT_T(KC_F)

 ALT_T(KC_G)
LALT_T(KC_H)
RALT_T(KC_I)

 GUI_T(KC_J)
LGUI_T(KC_K)
RGUI_T(KC_L)

 CMD_T(KC_M)
LCMD_T(KC_N)
RCMD_T(KC_O)

 WIN_T(KC_P)
LWIN_T(KC_Q)
RWIN_T(KC_R)
```

また、Altキーの場合は、`ALGR_T(通常キー)`と言う物があるようだ。
日本におけるキーボードでは見かけない記号だ。
AltGRキーのようだが、これが何か分からない。

##その他
私は興味がわかず、調べる気も無いのでよく分かっていないが、一応紹介ぐらいはしておこう。
（間違っている可能性があると言うことなので、自分で調べるように）
※押しっぱなしで、右側の組合せとして押された状態のキーになる。タップだけでは'通常キー'押下になる。

`C_S_T(通常キー)`：左側コントロールキー+Shift
`MEH_T(通常キー)`：左側コントロールキー+Shift+Alt
`LCAG_T(通常キー)`：コントロールキー+Alt+Gui（全て左側のようだ）
`RCAG_T(通常キー)`：コントロールキー+Alt+Gui（全て右側のようだ）
`ALL_T(通常キー)`：左側コントロールキー+Shift+Alt+Gui
`SGUI_T(通常キー)`：GUI+Shift（全て左側のようだ）
`SCMD_T(通常キー)`：上記`SGUI_T(通常キー)`の別名
`SWIN_T(通常キー)`：上記`SGUI_T(通常キー)`の別名
`LCA_T(通常キー)`：コントロールキー+Alt（全て左側のようだ）

興味は無いが、`C_S_T(KC_S)`の動作確認はできた。
（タップで'S'キーになり、押しっぱなしで、"コントロールキーとShiftキー"が押された状態になった）

##プログラミングの勘所
基本的なキーマッピング変更であれば、勘だけで行ける。
どれほどの勘が必要なのかの具体例は、`MO(SYMB)`がレイヤー1に切り替わるのは間違っていると解釈できるかだ。
実際は、レイヤー1に切り替わるのだが、語弊があるため、信じない方が良い。

```ErgoDox:keymap.c
#define BASE 0
#define SYMB 1
　　　・
　　　・
　　　・
```

に、SYMBに1が設定されているため、レイヤーが1に変わるだけであって、ここの値を変更してしまえば、当然のようにレイヤーはその値を基準に変わるだろう。

###締め
やっぱり、Happy Hacking Keyboard(HHKB)最高だと思った。
自分で考えるのはそれなりに楽しいのだが、既製品でここまで考えられているキーボードは他に無いと思う。
何より、この打ち心地は何物にも代えがたい。
2万円ポッチのHHKBが左右分離型になるまでの繋ぎとして、4万円近くするErgoDoxEZを今後仕方なしに使っていこうと思う。
調子に乗って色々追加購入したら4万円近くの出費になったのは痛い。
HHKBが左右分離型になってくれさえすれば、4万円近くしても買うかな。
要望としては、Bluetoothが切り替えやすくなったり、スペースバーが短くなって、その左右にボタンが追加されれば、言うことなし。
そもそもBluetoothは要らないかな。筐体がでかいので、据え置きが当たり前だろうからな。
（新人の頃は、頑張って毎日持ち歩いていたが^^）

ErgoDoxEZを使ううちに、HHKBのスペースバーの左右のキーが遠いと感じるようになってしまった。
HHKBをMacOSで使っており、それをコマンドキーに設定しているため、頻繁に使うキーになる。
もう少し何とかならないかと・・・。
他に驚いたのは、碁盤のマス目のようなキー配列になっていること。
網状(?)のキー配列は古いね。
今後出すとしたら互い違いではなく、格子状にして欲しい。指の動かす距離が短いのは、楽だということに気づいた。
触って初めて快適に気づく、この快感。

####HHKBの救世主？
今回は、ErgoDoxEZのキーマップを変更していたが、HHKBはそれが出来ない。
しかし、物理的な筐体に手を加えれば、それが出来るようだ。
　[Alternative Controller for HHKBのススメ](https://qiita.com/shela/items/62324752ff703bae3e74 "Alternative Controller for HHKBのススメ")

後日、YouTubeで一応交換結果を写している動画を見つけた(英語なので、本当にそうなのかは判断付けられない・・・無責任でごめんね)。
[WIRELESS HHKB PRO 2! Hasu Bluetooth controller install guide](https://www.youtube.com/watch?v=LQftwRu6yzQ "Tech Intakeによるコントローラー交換")
[Happy Hacking Professional 2 Keyboard - Unboxing & Review](﻿﻿https://www.youtube.com/watch?v=h4vadFrs2Jo&feature=youtu.be&t=9m18s "TaeKeyboardsによる開封動画")
[TMK Bluetooth HHKB Controller Replacement](https://www.youtube.com/watch?v=0WqgdKpMxUw "clickity Clackityによるブルートゥース化")
[HHKB Mod: USB 12KRO](https://www.youtube.com/watch?v=sDYSJ1pWf9M " tmk4kbdによるキーロールオーバー")は、同時押し検証動画なのかな。

日本人は動画が苦手なのか、普通にブログで改造紹介していました。
[Alternative Controller for HHKB を組み込んだ](https://toooybooox.blogspot.com/2017/03/alternative-controller-for-hhkb.html "おもちゃ箱")
[HHKB Hacking会を開催しました](http://40balmung.hatenablog.com/entry/2016/12/30/164450 "えんじにゃーず・ハイ")

###終わりに...
ErgoDoxEZを手に入れて5日ほどしか経っていないが、毎日キーマップを変更している。
キーコードがよく分からず、四苦八苦しているが、なかなか楽しい毎日だ。
(目処として、5日目に投稿したかったため急いだが、一応満足する内容になった。一応ね。）
























# CTL_T関数の自前作成
個人的なコントールキーは、親指に配置している。
そして、コンパクトキーボードの場合は、キー数が少ないため、1つのキーに複数の機能を持たせている。
そのため、押し続けることでコントールキーとして機能し、タップでエンターキーとして使いたいと思っている。
如何せん、プログラム知識がないため、それを実現させられない。

シフトキーとエンターキーの[組み合わせ](cf740e2e8b2b6879c798)ならあるが、やはり挙動に納得できず、使えなかった。

## 単純な組み合わせ
押し続ける：コントールキー
タップ：エンターキー
実装：CTL_T(KC_ENTER)

コントールキーを押しながらマウスクリックすることで、例えば複数のしかも任意のファイル選択ができるようになる。
その操作時間は1秒もかかっていないと思っている。
しかし、上記の組み合わせでは、認識せずにマウスクリックだけが働き、キーボード操作は無視されてしまう。
それは、時間設定の変更で対応できる。ようは解決なのだが、キーボード操作は、それ以外のキーが存在するため、単純に解決とは至らない。

具体的な時間変更は`TAPPING_TERM`を使う。
時間設定を多くすれば、押し続ける時間を長くしなければエンターキーが機能しない。
短い時間設定であれば、一瞬のタップで、エンターキーが機能する。
その時間設定は、他に組み合わせているキーマップにも作用する(当たり前のこと)。
私以外にも[指摘](https://www.reddit.com/r/olkb/comments/a5ujx6/can_i_make_qmks_modtap_behave_like_easyavrs_tap/)しているのだが、他で組み合わせているキーマップでは設定時間を長くしたい。
今回の設定のみ、設定時間を短くしたい。
これができない。
（質問している人曰く、EasyAVR'sではそれができて当たり前だそうだ。そして、QMKでは実現不可能とのことで、自前で用意したそうだ）

仕方ないため、独自の関数を作るしかない。
その人は満足できる自作関数を作ったようだが、、、

## process_record_user
[過去に投稿](e1b311eb37950cfb4896#既存キーコードの書き換え)している通り、ここでキーの挙動を決めるしかないようだ。

<details><summary>すべてを自前で用意するつもりでコーディング実施</summary><div>

```c:keymap.c
static int tapEnter_Counter_ctrlPressed = 0;
static uint16_t my_hash_timer;


bool process_record_user(uint16_t keycode, keyrecord_t *record) {
	switch (keycode) {
	case CTRLENTER:
		// タップでエンターキー
		// 押し続けることでコントールキー

		if (record->event.pressed) {
			tapEnter_Counter_ctrlPressed++;
			my_hash_timer = timer_read();
		
			if ( timer_elapsed(my_hash_timer) < TAPPING_TERM && tapEnter_Counter_ctrlPressed >= 2 ) {
				// 設定時間より短く、コントールキーが連続2回押下されたときに限り、コントールキーを無効化し、エンターキーとして機能させる。
				tapEnter_Counter_ctrlPressed = 0;
				register_code(KC_ENTER);

			}
			else if ( timer_elapsed(my_hash_timer) >= TAPPING_TERM) {
				// 設定時間を超えた場合、コントールキーのまま動くようになる。
				tapEnter_Counter_ctrlPressed = 0;

			}
			else if ( timer_elapsed(my_hash_timer) < TAPPING_TERM ) {
				// ここに無条件で入ってくるため、どこかでクリアしたいが、連続タップでエンタキーを押し続けることも有効にしたいため、その処理の実装は私には無理だというのが分かった20190514
				register_code(KC_LCTRL);

			}
		
		}
		else {
			// キーを離したときの挙動

			if ( timer_elapsed(my_hash_timer) >= TAPPING_TERM && tapEnter_Counter_ctrlPressed < 2) {
				// 設定時間を超える場合、コントールキーが無効化される(エンターキーは無効化済み)。
				unregister_code(KC_LCTRL);

				tapEnter_Counter_ctrlPressed = 0;
			}
			else if ( timer_elapsed(my_hash_timer) >= TAPPING_TERM && tapEnter_Counter_ctrlPressed >= 2) {
				unregister_code(KC_ENTER);

				tapEnter_Counter_ctrlPressed = 0;
			}
			else if ( timer_elapsed(my_hash_timer) >= TAPPING_TERM ) {
				unregister_code(KC_LCTRL);

			}
			else if ( timer_elapsed(my_hash_timer) < TAPPING_TERM ) {
				unregister_code(KC_LCTRL);

				register_code(KC_ENTER);
				unregister_code(KC_ENTER);

			}
			else {
				// 無条件でエンターキーを無効化する。
			}
			if ( tapEnter_Counter_ctrlPressed >= 2 ) {
				// エンターキーとして動いていたため、無効化する。
			}
		}
		return false;
		break;
	  }
	return true;
}
```

</div></details>

結論は、途中で断念した。
　タップでエンターキー
　押し続けでコントールキー
は、可能だった。
しかし、やりたい本当の目的は、タッピングターム時間未満で2回連続のタップで、エンターキーを押し続けることだった。
そして、私の技術力ではそれを実装できず、断念に至った。
どうしてもフラグ制御に頼ってしまったため、タップ後の時間経過でフラグクリアしたいが、そうした場合、2回連続タップのエンターキーもご破算になる。


## 再挑戦
[過去に投稿](ce2883ad0a0c6c27c8de#register_codeunregister_code)した関数を用いながら上記の掲示板を参考にしながら新たに挑戦した。

<details><summary>先人の成功例を基準に改良</summary><div>

```c:keymap.c
static int tapEnter_Counter_ctrlPressed = 0;
static uint16_t my_hash_timer;


bool process_record_user(uint16_t keycode, keyrecord_t *record) {
	switch (keycode) {

	case CTRLENTER:
		if(record->event.pressed) {
			my_hash_timer = timer_read();
			register_code(KC_LCTL); // Change the key to be held here

			if (timer_elapsed(my_hash_timer) < TAPPING_TERM && tapEnter_Counter_ctrlPressed == 1) {
				unregister_code(KC_LCTL);
				SEND_STRING(SS_DOWN(X_ENTER));
			}
		} else {
			unregister_code(KC_LCTL); // Change the key that was held here, too!

			if (timer_elapsed(my_hash_timer) >= TAPPING_TERM && tapEnter_Counter_ctrlPressed == 1) {
				SEND_STRING(SS_UP(X_ENTER));
				tapEnter_Counter_ctrlPressed = 0;
			}
			else if (timer_elapsed(my_hash_timer) < TAPPING_TERM) {
				tapEnter_Counter_ctrlPressed = 0;	// エンターキーをタップした後に、何時間経過しても値を保持しているため、押し続けたときにエンターキーが入力されることになる。それを回避させた場合、タッピングターム未満での連続タップで、エンターキーを押し続けることができなくなる。
				tapEnter_Counter_ctrlPressed++;
				SEND_STRING(SS_TAP(X_ENTER)); // Change the character(s) to be sent on tap here
			}
		}
		return false; // We didn't handle other keypresses
		break;
	  }
	return true;
}
```

</div></details>


結論は、途中で断念した。
　タップでエンターキー
　押し続けでコントールキー
は、可能だった。
しかし、やりたい本当の目的は・・・以下略。

同じ壁にぶち当たった。
先人が成功したのは、Escキーだからだろう。





## [タップダンス](990b2209656babac3b61)なら解決？
しかし、当時実装したときは、受け入れがたい挙動だったようなきがする。
これは、見なかった関数としよう。



## [レイヤー移動](https://github.com/qmk/qmk_firmware/blob/master/users/mechmerlin/mechmerlin.c)で解決？
よく分からないのだが、どういうこと？

他にも[独自関数](https://thomasbaart.nl/2018/12/09/qmk-basics-tap-and-hold-actions/#a-workaround-for-mod-tap)でやりたいことを実現しているようだが、私のやりたいこととは異なる。































#追記
[githubのqmkによるMod-Tap](https://github.com/qmk/qmk_firmware/blob/ce3ccd3f4a5e8ff8ac391887f3357dd8e985a452/docs/feature_advanced_keycodes.md#mod-tap "githubのqmkによるモッド-タップ")を基準に、記事を少し修正した。

以上。