2018年1月まとめ

2018年も早くも一月が過ぎた。この調子で行けば明後日当たり、正月が来そうなスピード感ある。

この1月何をやっていたか。

  • Twitterで年越し
  • ガキの使いとおもしろ荘で初笑い
  • ラミクタールを増量した
  • エビリファイを減薬した
  • コートとジャケット買った
  • パタヘネ本読み始めた
  • ロイヤル英語文法読み始めた
  • 電子工作入門以前を読み終わった
  • Biacco42さんとPekasoさんの薄い本読んだ
  • 東京グール14巻を読んだ
  • TAPL本買った
  • TRONキーボード作れなかった
  • 無線レツプリ諦めた
  • Kinesis Advantage買った
  • MinidoxとCraven作って買い取ってもらった
  • TRONキーボードリベンジするべく、アクリルプレートを発注した
  • Re-CapでCanvasルーン文字と格子型修飾キー買った
  • Helix GB参加した
  • Mod-MスイッチのGB企画した
  • ゼノブレイド2面白くなかった
  • ゼルダのDLC2できなかった
  • イカ2が嫌になってきた
  • Switchを手放した
  • 歯医者通ってる
  • LOST見終わって号泣した
  • パタヘネ本面白くなってきた
  • five new old聞き始めた
  • 久しぶりにHaskellへの好奇心を思い出したが難しさも同時に思い出し心折れそう
  • Twitter依存度を下げようと心がけている
  • Twitterの代わりにFeedlyを見るようにした

こう書き出してみると以外と多い。無を生産している自覚しか無かった


冬休み

やはり無をしている以外の記憶がないので、もう少しこまめに日記をつけると無が可視化されるかもしれない。 暇をすぎて無だった。その無を読書に使うなりすればよかったのに、やはり無は無。

オックスリー

ラミクタールを増やしたので様子見をしていた気がする。量が増えたが3錠が1錠にまとまったので飲みやすくなった。 エビリファイは副作用で睡眠に悪さをしている気がしていたので、無くしてみたが睡眠は改善されず。 無くしたデメリットの方がめだつ。鬱っぽさがかるくぶり返してきてる。 眠剤代わりにリフレックスメイラックスを飲んでいるが、これを他の眠剤で置き換えたいが、その2つの薬は不安やうつにも効果があるので、 一筋縄ではいかないだろう。セクロエルを試してみたい。セクロエルも睡眠と不安を改善させる効果がある薬なので、私のような器質性には効きそう。

オックスリーを貰いに行った帰りに服を買った。一年ぶりくらいに服屋入った。前回は発作が起きて死にかけた。 コートを買ったが完全に冬用ではなくて、秋春用だったので失敗した。ジャケットはカジュアル用途で買ったが思ったより高かったので、おっ?ってなった。

テレビ

ガキの使いを見た。はまちゃんのエディ・マーフィーのパロディはツボった。 人種差別だと言うことで炎上したらしいが、お門違いも良いところだろう。 あれを差別という人達自身の差別が露呈しているだけのことで、制作側はそのような意図はないだろう。 他にも色々正月特番をもっと見たかった気もする

読書

ひさしくまとまった読書などしていなかったが、いくつか本を買った。

パタヘネ本

まずはパタヘネ本。とても有名な本でで某大学では教科書として使われているらしい。 MIPSというシンプルに設計されたアーキテクチャを元にコンピュータの低レイヤーを説明している。 これを買ったのは、ラムダ計算がどのようにアセンブラに変換されるのか知りたかったからだ。 これについては、2章で手続き呼び出しを説明しているのでそれでだいたいわかった。 スタックフレームにリターンアドレス、呼び出し元の状態、引数、ローカル変数、などを積んで、手続きが終わったら、 それを元に呼び出し元の状態を復元してあげるだけのことだった。 まあ、知っていたと言えば知っていたのだけど、アセンブラレベルでの理解を少し深めた。 結局コンパイラが頑張ってあげる必要がある。 興味はここから、低レイヤーのセキュリティや、型推論、System F、定理証明などに移っていくと思う。 なので、TAPLで知られる、型について詳しく説明されている有名な本を買った。値段が高い。分厚い。読めんのかこれ。

英語本

次にロイヤル英語文法。私にはまだ早かった。 しかし少し読んだだけだが英語文法に対する感覚がすこし変わってきた。 もっとやさしい本から始める必要があるが、少しずつ何度も読んでみたい。 これの動機は英語力が無だから。比喩じゃなくてほんとに、学歴が無。したがって英語力も無。その他の素養も無。 プログラミングの趣味をもっと楽しみたいからで英語が必須になるので勉強しなければと、ここ10年位思っていて、ようやく最近手を付け始めたが続く気がしない。

電子工作入門以前

電子工作入門以前、これはマイコンの表面実装などができるようになりたくて、基本的な部品の仕組みや使い方を知りたく買った。 数学の素養も無なので、電子工作には数学の知識も必須なのだと思い知った。ツライ。 コンデンサ、コイル、抵抗、電子、などについて優しく説明されているので超初心者にはいい本だと思う。

漫画

東京グール:Re14巻も読んだ。前巻が読むのが辛かった。 前巻は主人公の仲間たちが追い詰められていき、そこに救世主的に登場した最強主人公も負けてしまい、読者を絶望の淵に立たせ、 さらに崖から突き落とすような展開は心えぐられる。 それと打って変わって、今回は凄惨は状況をうらはらに、死んでいたと思われていた主人公の親友がなぞの復活。 快活なキャラで、けして交わることのない敵と味方を一つにまとめあげ、新たに出現した災悪を倒すべくすべてのキャラが己のすべてを露呈させ集結する。

薄い本

薄い本も読んだ。Ergo42の作者@Biacco42さんが出したKbD本と、自作キーボード界隈の重鎮PekasoさんのBYOK本。 KdD本はフルカラーで大まかな自作キーボードの紹介と基板作りに関して記載されている。レイアウトが完全に雑誌でビアッコさんプロの方ですかって感じがした。 BYOK本は圧巻。けして薄くない。作者の豊富な自作キーボード作りのビルドログやキースイッチの仕組みやQMKファームウェアについて、などなど網羅されている。 これ一冊で自作キーボード沼に肩まで浸かれる。

キーボード

f:id:kumatoki:20180201130931j:plain

今年もまだ抜け出せないでいる。 今後製作予定の物だけで、Helix、TRON、Preonic、Plack Lightと色々あかんことになっている。助けて

TRON

TRONキーボードはキーピッチを16mmとしているのでそれを模範すべく小さいキースイッチを探したが無かったので、仕方がなく12mmのタクトスイッチを採用した。 それをマウントする基板も設計したがタクトスイッチではキーボードのスイッチとしては無理があったので完成させることなく放置してしまった。 基板作る前にタクトスイッチがどのような感触なのか確認すべきだったが12mmならだいぶましだろうと、 安易な考えで見切り発車してしまったので、さすがに馬鹿なことをした。 ちゃんとしたCherry MX系スイッチでリベンジするべくデザインし直して、アクリルプレートを発注した。今回は空中配線で作る。 PCBマウントにして、キースイッチの間隔を最大まで小さくすれば16mmピッチで作れるはずなんだけど、それに合うキーキャプが無い。 普通のキーキャプは19mm角だが、16mm角のキーキャプを見つけたのでキーピッチを17mmでデザインすることができた。 今回はPCBマウントではなく、プレートマウントなので、いつもは3mm厚のアクリルを使っているが、強度不足を補うため5mm厚の物にした。 まあ、結局は実験的な物になると思うので実用性は二の次だ。

f:id:kumatoki:20180201131105p:plain

無線レツプリ

無線レツプリ諦めた。ESP32のライブラリがいい感じに整備されてきているので行ける感じがしていたが、消費電力の問題や、 nRF52を使って実装しようとしてる方がいたのであきらめです。nRF52に対してESP32の有利な点は値段です。しかし消費電力では負けます。 正確に計測しているわけではないのでなんとも言えないけど、かなり不利な気がする。

Minidox

Minidoxも作った。作り方はレツプリとほぼいっしょなので、10個位レツプリを作った私が失敗などするはずがなかったがやらかした。シット。 Pro Micro裏のスイッチが効かなかったのだ。これはPro Microを外してから治す必要があるのだけど、これはかなり頑張らないと外れない。 かなり時間と根拠を費やし、Pro Microを外す技術を習得したのが救いだったが、結局ダイオードがハンダ不良だっただけのことで、Pro Microは外す必要がなかったのだ。

(´・_・`)

Minidoxはやっぱり私では使いこなせないと判断し、売りに出した。レツプリを2台も買っていただいているお得意さんが今回も買ってくれることになった。 お世話になっているので、おまけを付けることにした。

Craven

ブログ記事にはしていなかったがCravenというキーボードをオリジナルで作っていたのでそれをおまけとした。 CravenはKailhのロープロスイッチ専用でAdafruitのFeatherというBluetoothに対応したマイコンとProMicroの2つに対応している、薄型、一体分離型、40%キーボードだ。 一応、無線化に成功したがマイコン側のピンアサインを理解してなくて、ジャンパが必要になってしまったり、自分でファームウェアを書く羽目になったりで面倒だった。 ProMicroは問題なく動いた動作しQMKにも対応した。 基板が薄いのでボディがよじれていて、がたつきがあるので実用に耐えなかったが、基板を二枚の間にスペーサーを大量に噛ませ、サンドイッチプレートとした。 なんとかそれで収まった気がするが、はやりよじれが残っているので、力任せにボディを捻って歪みを調整する必要がある。

Kinesis

Kinesis Advantageを買った。安く売りに出していた方がいたので譲っていただいた。 正直破格値ではないかと思う。ありがたい。 これを買った動機としては、40%が辛くなってきたことだ。キー数の少なさをレイヤーで補うやり方は脳に負担がかかる。 人によっては苦にならない方も居るようだが、自分には違和感が残り続け60%に手を出したくなった。 しかし、40%を使っていた理由としては、それ以上のキーに手首を固定した状態では指がとどかないからだ。 Kinesisではそれをお椀型にキー配列を湾曲させることで解決している。 その意味においては素晴らしいが、少しこの湾曲と自分の手が合っていないような気も最初はしていたが次第の慣れてきた。 とここまで文章を書いてきて腕が痛くなってきたので、うーん。。。

展望

TRONキーボードを作ろうと思ったのも同じ動機で、60%かつ指が届く。このことをキーピッチと放射状に広がる配列で実現しようとしているからだ。

「エルゴノミクスキーボードはKinesisの様なお椀型と、TRONの様な傾きを上と内側に10度、左右で分割されたキーの内角が25度になるようにしている一体型分離式、 のふたつに分類できる」と言う趣旨のツイートをNISSEのShiki先生がされていた。

Ergodox以降流行りの完全分離式は一体型分離式より劣ると言う研究結果があるそうだ。その点において次は一体型分離型が流行るかもしれないが、 完全分離式のErogdox -> Let's split -> Helixで大盛り上がりの自作キーボード界隈にそのことを周知する必要があるし、 Helixのようにかっこよく、値段も抑えめで、お祭りのようなイベントが行われる必要もある。 そこを私は開拓できる可能性があると考えるが、モチベーションが無い。無いこと無いんだけど、技術力、企画力、プレゼン力などなど足りない物が多すぎる。 とは思いつつ、ぐだぐだいってないで、魅力あふれる商品を作り上げ、コミュニティーに提示することができればある程度ニーズを掘り起こせるかも知れない。

Mod-M GB

Mod-M GBを勢いでやることになった。スイッチは届いたので後は、請求と発送。 結局、2500円位安く上がっただけなので、GBの手間を考えれば、仕事をする当事者としてはあまりいいGBでは無かった。 まあ、参加してくれた方にメリットは有ったことは確かなのでそれはそれで。

ゲーム

ゼルダ

Nintendo Switchを半年くらい前に買った。ゼルダがやりたくて我慢できなかった。 オープンワールドアクションをゼルダの世界観でプレイできるのはもう最高に最高。 150時間近くプレイした気がする。とても良い時間だった。 DLC1は覇者の試練だけやった。今まで手に入れてきた装備全部剥ぎ取られて、裸で敵の前に放り出され続ける。 頭をフルに使い、限りある資源や武器を使い攻略していく。最高に最高。 DLC2はもう飽きてしまった頃に降ってきたので、まあいいやとなってしまった。

イカとゼノブレイド

ゼルダ以外では、マリオカート、なんか腕が伸びるやつ、ストリートファイターII、マリオオデッセイ、スプラトゥーン2ゼノブレイド2などを買った。 イカ2以外個人的には外れだった。しかしイカにかなりハマった。これも150時間位プレイしてそう。 結局SとA+を行ったり来たりしている程度の実力しか身につかなかったが、最高に最高。 オンラインゲームなのでやはり不快な思いもする。コミュニケーション手段が最低限に絞られているが、イカ状態と人状態を繰り返す、煽り行為が最高に不快。 あと病気のせいもあり、プレイしていると心臓が張り裂けそうになるし、震えが止まらない。ノルアドレナリン過多によるある種の発作状態だと思う。 それがなければもっと楽しくプレイできていたし、それがあっても死にそうになりながらプレイしてたので完全に最高に最高。 ゼノブレイド2については、ゲスの極みなおやさんが人生で最高のゲームの一つだとRebuildで言っていたし、たなこふ先生も絶賛だったのでかなり期待をしていた。 だが期待はずれだった。テンポが遅い。アニメーションがつまらない。バトルが作業感。 プレイを進めていけばある程度面白くもなっていくのだろうけど、そこまでもたなかった。

Switchドナドナ

まだやりたいゲームが有ったが、それ以外に時間も使いたいためSwitchを手放すことにした。 その趣旨のことをつぶやいたら、それにリアクションしてくれた方がいたので売りに出してみると速攻で売買成立となった。 その間わずか一時間である。そのへんのゲーム屋に持っていけばもっと高く買い取りしてくれたかもしれないが、 Twitterでお世話になっていた先生に買っていただけることになったので良いところに嫁に出したと思う。

その他

歯医者に通っている。体を壊していこう行けなかったので3年ぶり位の歯医者だ。 神経取る必要があったり、銀歯被せる必要があったりで散々だったし、発作が起きかける。これが一番つらい。

LOSTを全シーズンようやく見終わった。10年ぶり位の視聴になる。 もうね。最高に最高。 現在と過去。現在と未来。一話の中で交互にフラッシュバックして描いている。 「島」に選ばれた人たちがひとつの飛行機に導かれ、その飛行機は「島」へと墜落する。 その島から生還すべく、主人公達は奔走するが、あるものは島を特別な聖地であること体験し、あるものはそんなものは幻想で無意味であると言う。 島に巣食う謎の黒い煙、世界を救い続ける番号を入力しなければならないハッチ、先住民たち。 そして「島」。過去、未来、現在、運命が交錯し巧みに物語は盛り上がりを続ける。 もうね。最高に最高。細かい所はまあいろいろ回収されてないけど十分です。

なかなかパタヘネ本読む続けられなかったが、読み進め面白くなってきた。 しかし浮動小数点の実装についてはわかりみがわからん。

five new old。最高に最高です。 エモ、ロック、パンク、シュゲイザー、ジャズ、ダンス。融合しまくってる。 最高に最高。

Haskell難しいです。ただ使うだけならなんとかなる。革新的なライブラリとかちょこちょこでてくるのでそれらを理解しようと思うとつらい。 無駄に抽象化されていて実装が追いづらい。type familyとかGADTsとか多用されると頭が追いつけないので終わりです。 ただそれだけ勉強しがいがある所でもあるので、気が向いたらやっていきたい。

Twitter依存を下げようとしている。Twitterしてる時間を読書にあてたい。無理みたいです。

2017年まとめ

年末。病気とキーボードの一年だった。 病気の話は前回したから置いておいて、キーボードを振り返る。


1月、Ergodox EZを買った。その理由は首への負担軽減。 結局病気と関連してる話になるんだけど、病気になってPCもろくに触れないような時期が続いていた。 しかし1月ごろから症状が好転。またプログラミングに向かことができた。 それと同時に肩こり、首の疼痛、頭痛、眼精疲労などの症状がPCを触っていると出た。 それを少しでも緩和しようとPC環境の改善にラップトップスタンドとErgodoxを買ったのでした。

Ergodoxになれるまで数ヶ月を要しその間毎日のようにタイピング練習していた。 ある程度使えるようになり、Ergodoxに愛着が湧いてきた。 一方で打鍵音が気になるようになり、O-ringやZealencio Slient Clipなど買ったりした。 そんなこんな調べているうちに深遠なるキーボード沼の岸辺に立っていた。

岸辺でじゃぶじゃぶと遊んでいる程度だったが、Twitterをキッカケに沼の奥へと足を進めていった。 Twitterにはごろごろとすごい人達がいる。毎日のようにキーボードに関する情報が飛び交っていて、それを肴にワイワイしてる方々が目に入ってきた。 キーボードその物の魅力もそうだし、それを取り囲む方々の魅力も相まって、そこに近づいて行きたくなった。 そうしてるうちに自分もキーボードに関する知識を蓄え、技術を養い、キーボードを自作するようにまでなった。 さらにそれを売り出し、普通では関われないような方ともコミュニケーションをとれたり、縁が出来たりした。 それらの活動から得たなかで大きな自慢があるとすれば、完全オリジナルのキーボードを作れるようになったことと、RubyのMatzにフォローしてもらったことだろうか。 「MatzにTwitterでフォローされてます」の一言で転職できそうなトロフィーかもしれない。

f:id:kumatoki:20171229230449j:plain


そういえばQiitaにしょうもない記事書いてたっけな。ただ2つほどリアクションが貰えたのがあった。 RustでテトリスとSECDマシンを実装した記事。 テトリスは皆さんご存知テトリス。フロントエンドのエモい人がブクマしてくれたお陰で幾つかブクマが付いた。

qiita.com

SECDマシンは古い関数言語向けのVM。これをつかってLISPインタープリターを作った。 HaskellとRustで実装したのだが、とくに性能はでなくて、一度書いたっきりで終わりかとおもいきや、 Rustのマッチョな人がコメントとコードをくれたり、Rustの紳士な方がプルリクくれたりと、拙いコードに手を入れてくれて嬉し恥ずかしだった。

qiita.com


仕事のことについては語ることもない。 抽象的に言えば、身体が壊れたので量をこなすために質を落とした。 しかしそれではだめだと、病状が回復するに連れ思うようになった。 質と量を両立できれば一人前というか一流だろうと思う。 どちらかを取れば、どちらかが落ちる。自分はまだこのようなレベルを行ったり来たりしている。 今の仕事は自分の身体を考えれば続けられるかとても不安があるが、どのような仕事も病気の前ではそんなもんだろうとも思うが、 その考えこそ病気に支配されているといえるのかもしれない。


さて、来年はどうするか。 目の前の目標があるとすれば、完全無線レツプリの開発。 これに関しては12月後半からファームウェアの開発の下調べをしているが順調に難航している。 esp32を使えばBLE開発基板が700円くらいで買えるのでそれを採用できるようコードを読んでいるが、 初心者むけの高レベルな抽象化レイヤーが無いのでBluetoothの基礎のから学ばねばならないし、APIも実際のコードレベルになるとレイヤーが入り乱れ、かなり難しい。 ただ、もう一つ良いBLEモジュールがあって、nRF52という物でモジュール自体は1000円ほど。これに関してはAdafruitという会社が作っているArduino向けのAPIがあり、 それを使えば容易にBLEキーボードを実装できる。しかしモジュール自体はそう高くはないが、 これを実際に使いやすいように色々実装したAdafruitの開発基板となると5000円近くする。 レツプリだと2つ必要なのでそれだけ一万円とかなり値が張る。 金で開発難易度を下げるか、努力で原価を下げるか、現状では後者を実現するべく取り組んでいる。 ファームウェアさえできてしまえば、基板もケースも設計できるので見通しが立つ。 これが完成した暁にはGroupBayなどもやってみたいところだがクリティカルなディスパッチは苦手なのでたぶんやらない。 ハードの知識があれば自分でnRF52の開発基盤を作ることができ、開発費も下げれそうな物なので、esp32での開発が完了したらそちらの知識を勉強したりもしたい。 年末のコミケでは自作キーボードの手引となる薄くない本がたくさん売れたらしいので来年の界隈はもっともりあがるのだろうね


はたして、来年はキーボード沼から這い上がることができるのだろうか。 とは言え、沼から抜けた所で何すんのってなる。 何しようか。うーん。勉強したい。病気に子供の時から支配されていたので教養がなく、色々困ったりする。 何を勉強しようか。うーん。英語かな。英語はハードとソフトの開発に必須なのでこれができるかできないかで、やれることがまるで違ってくる。 どのように学べば良いかもよくわからんけど、少しずつやっていければ良いんじゃないかな。 あとは、そうだなー。うーん。セキュリティかな。CTFにすこし興味が出てきた。ジェイルブレイクとかっこいいじゃん。子供っぽいけど、実際はとても地味で芸術的。 そしてそして、うーん。筋トレか。体と心のメンテナンスを怠らないようにしなければ、また病状が悪化しかねない。病気の本質的にまた悪化するのは確定的なんだけど それでもできることはあるはず。


最後に今年はSpecial Favorite Musicというバンドを知った。 もうね、最高。目覚ましにもしてるし、寝る前にも聞いてるし、ほんと最高。 語彙がないので最高しか言えないが、今年はこの音楽が私の人生を大きく色づけた。 www.youtube.com

まぁ、今年も生き抜いただけで御の字でしょう。良いお年を。

NISSE mini 作ったよ!

自作キーボード Advent Calendar 2017の二日目の記事です。

NISSEを小型化したキーボードを自作したので今日はそのお話。 おこがましいですが便宜上NISSE miniと名付けました。 NISSEについてはサイトを見てください。

NISSEを作られているshikiさんのblogにこのような記事があります。

エルゴノミック キーボードの簡単な歴史

この記事で説明されている通りNISSEは長いキーボード研究を参考に作られているのがわかります。 最近自作キーボードをチョットダケデキルようになったので作ってみようと思い立ったわけです。

コンセプト

そのまんまNISSEでは私の好みに合わないところがあります。 まずは大きさ。ファンクションキーなどはほぼ使わないので削除。 さらに数字行、これは私の手の大きさでは届かない行なのでこれも削除。 両サイドの記号列も手がとどかないので削除。

さて、減らした数字や記号、時々たまに使うかもしれないFNキーなどはどうするの? そう思われる方もいるかもしれませんが、ちゃんと入力できるので後述。

キー数も減らしたら、ボディのサイズも小さくできるので余分な所は削除。

さてさて、つまりはNISSEを小さくしたNISSE miniが私の作りたい物のようです。 コンセプトが決まった所で形をつくっていきましょう。

デザイン

私が使えるのはfusion360という3dcadソフトなのでそれでスケッチを書いていきます。

まずはキースイッチ。 スイッチ自体の大きさは14x14mmくらいです。 そこに乗るキーキャプのサイズが18x18mmです。 さらにキーキャプどうしが干渉しないようにスペースが必要ですね。それを1mm。 キースイッチの上蓋をあとから外せるようにするためのスキマもあけて。 それらをひとまとめにしたのがこちら。

f:id:kumatoki:20171027203600p:plain

これをパターンとコピペを駆使してならべていくわけです。 キー配置はNISSEをざっくりモデリングしました。 具体的にはNISSEの画像を先程のスケッチに寸法を合わせるように拡大して、手でポチポチならべます。 必要分並べたら外枠もトレース。 できあがりがこれ。

f:id:kumatoki:20171027203610p:plain

外枠が大きいままです。 NISSEでは上方向と内側方向に傾斜がついています。 この傾斜はとても重要で、エルゴノミクスの一部です。 斜め下の辺を基準に傾斜をつけているのではないかと思います。 なのでできるだけ斜め下の辺をイジらないように最小化できないかと考えましたが、今回アクリル加工をしてもらったサービスの都合上、寸法に制限があったのでなかなか都合良くはいかず。 ネジ穴など開けて、最終的なスケッチがこれ。

f:id:kumatoki:20171027203622p:plain

これの5枚制作。5枚っていうのもサービスの都合上。 できあがったアクリルプレートがこれ。

f:id:kumatoki:20171027204017j:plain

形が見えてきました。

キースイッチはんだ付け

今回はGateron BlueにJSpacersというスイッチ内部に仕込むO-Ring的な物を付けました。 これの取り付け作業がとてもたいへん。

f:id:kumatoki:20171027204315j:plain

プレートにスイッチをはめ込んでいきましょう。ポチポチと。 はめ込んだらはんだ付けです。 キーマトリックスダイオードなどについて説明しません。

横と縦と配線を張り巡らせていきます。

f:id:kumatoki:20171028172712j:plain

Pro Micro

キーボードの脳となるのがPro Microとよばれるマイコン。 ほかのマイコンを使ってもよいのでしょうが、値段的にも、後述するファームウェア的にもこれが手軽です。ピン数が少ないので対応できるキー数が少ないのが傷。IO Expanderなどでカバーしましょう。

f:id:kumatoki:20171028172729j:plain

今回はこれをプレート裏にエポキシ樹脂接着剤で固定して、これに配線をしていきます。

f:id:kumatoki:20171028172753j:plain

QMK Firmware

からっぽの脳に知性を宿しましょう。QMK Firmwareです。 簡単なファームウェアなら自作もそう難しくはないのですが、すでに私はErgodoxやLet's splitなどでqmk firmwareの便利さを知っていたので、今回もこれを採用。

QMK対応のやり方は別記事

さて、上記の削除されていったキー達。ちゃんと入力する方法があるんです。 LayerとよばれるQMKの機能を多用して入力できます。 簡単に言えば修飾キーみたいなもんです。 あるキーを押しながら別のキーを押すと、入力できる文字がある。それだけのことです。 具体的にはLowerキーを押しながら「q」を押すと「!」が。Raiseキーを押しながら「q」を押すと「1」が。 こんな具合に削除されていったキーを入力することができます。 もちろんキーマップも書き換え可能なのでそれらのパターンは自分で無数に定義できるわけです。

出来上がったキーマップはこちら。 記号はplanckのdefaultの配列が秀逸だと気がついたのでそれを採用。 MISCレイヤーに矢印や音量調整、音楽再生、マウスカーソル移動などの雑多なキーを配置。 真ん中4つにはよく使うショートカット、タブ移動とアプリ移動。 あれ、ファンクションキーが結局いらない子でしたね。。。

#define XXXX KC_NO
#define ____ KC_TRNS

// for MacOS
#define NEXTTAB ACTION_MODS_KEY(MOD_LGUI, KC_RCBR)
#define PREVTAB ACTION_MODS_KEY(MOD_LGUI, KC_LCBR)
#define NEXTAPP ACTION_MODS_KEY(MOD_LCTL, KC_RGHT)
#define PREVAPP ACTION_MODS_KEY(MOD_LCTL, KC_LEFT)

enum Layer {
  TOP,
  LOWER,
  RAISE,
  MISC,
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [TOP] = {
    {KC_TAB,        KC_Q,             KC_W,    KC_E,      KC_R,   KC_T,    PREVTAB,  NEXTTAB,  KC_Y,    KC_U,   KC_I,      KC_O,    KC_P,              KC_BSPC},
    {CTL_T(KC_ESC), LT(MISC, KC_A),   KC_S,    KC_D,      KC_F,   KC_G,    PREVAPP,  NEXTAPP,  KC_H,    KC_J,   KC_K,      KC_L,    LT(MISC, KC_SCLN), KC_QUOT},
    {KC_EQL,        KC_Z,             KC_X,    KC_C,      KC_V,   KC_B,    XXXX,     XXXX,     KC_N,    KC_M,   KC_COMM,   KC_DOT,  KC_SLSH,           KC_MINS},
    {XXXX,    XXXX,     KC_LGUI,       MO(LOWER), SFT_T(KC_SPC), KC_LANG2, KC_LALT,
     KC_RALT, KC_LANG1, SFT_T(KC_ENT), MO(RAISE), KC_RGUI,       XXXX,     XXXX}
  },

  [LOWER] = {
    {____, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, ____, ____, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, ____},
    {____, ____,    ____,  ____,    ____,   ____,    ____, ____, ____,    KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, ____},
    {____, ____,    ____,  ____,    ____,   ____,    XXXX, XXXX, ____,    KC_TILD, KC_PIPE, KC_QUOT, ____,    ____},
    {XXXX, XXXX,    ____,  ____,    ____,   ____,    ____, ____, ____,    ____,    ____,    ____,    XXXX,    XXXX},
 
  },

  [RAISE] = {
    {____, KC_1, KC_2, KC_3, KC_4, KC_5, ____, ____, KC_6, KC_7,    KC_8,    KC_9,    KC_0,    ____},
    {____, ____, ____, ____, ____, ____, ____, ____, ____, KC_MINS, KC_EQL,  KC_LBRC, KC_RBRC, ____},
    {____, ____, ____, ____, ____, ____, XXXX, XXXX, ____, KC_GRV,  KC_BSLS, KC_DQT,  ____,    ____},
    {XXXX, XXXX, ____, ____, ____, ____, ____, ____, ____, ____,    ____,    ____,    XXXX,    XXXX},
  },

  [MISC] = {
    {RESET, ____, KC_WH_U, KC_MS_U, KC_WH_D, KC_PAUS, ____, ____, KC_HOME, KC_PGDN, KC_UP,   KC_PGUP,  ____,    ____},
    {____,  ____, KC_MS_L, KC_MS_D, KC_MS_R, KC_INS,  ____, ____, KC_END,  KC_LEFT, KC_DOWN, KC_RIGHT, ____,    ____},
    {____,  ____, ____,    ____,    ____,    ____,    XXXX, XXXX, KC_MPRV, KC_MPLY, KC_MNXT, KC_MUTE,  KC_VOLD, KC_VOLU},
    {XXXX,  XXXX, ____,    ____,    KC_BTN1, KC_BTN2, ____, ____, PREVTAB, NEXTTAB, ____,    ____,     XXXX,    XXXX}
  }
};

仕上げ

Pro MicroにQMKを書き込み一通りテストを終えたら、ボディを組み立て。 ボトムプレートはあまったトッププレートを流用するというだいぶかっこ悪い感じですが、妥協です。 二枚を接着。接着面がわずかなので強度ゼロですが、これも妥協。 持ち運ばないし、まぁいいよね。必要になったら補強します。

f:id:kumatoki:20171028173316j:plain

fusion360上でスペーサーの寸法出しておいたので、スペーサーを噛ませて傾斜をつけてネジを締めれば完成。できあがりです。やったね!

f:id:kumatoki:20171027204409j:plain

感想

楽しく作れました。とくにCAD上での設計は楽しい。 砂場で遊ぶ子供のように無邪気に作っては壊しを繰り返して少しずつ要領を掴んでいきました。 そのまま3Dプリントでボディを作ろうかと思いましたが値段がかなり掛かるので今回はアクリルとスペーサーを使いましたが複雑な造形を作ろうとすれば3Dプリントが必須になるでしょう。

傾斜のつき方が上方向には十分取れたのですが、内側方向には不十分となってしまいました。 プレートの設計を妥協したのでしょうがないね。

まぁ、そんな具合に仕上がりました。次はPCBの設計にでもチャレンジしてみようかな。

(この記事はMacbookのキーボードで書かれました)

自作キーボードをQMK Firmwareに対応させる

pro microとUnix系OSの使用を前提として話をすすめる。

まずはcloneしてnew_project.shでテンプレートを作る。

❯ git clone https://github.com/qmk/qmk_firmware
❯ cd qmk_firmware
❯ util/new_project.sh your_keyboard_name
❯ cd keyboard/your_keyboard_name

次にconfig.hを編集。 MATRIX_ROWSMATRIX_COLSをそれぞれ数合わせ。

#define CATERINA_BOOTLOADERを追加しておくとRESETキーが使えるようになる。 BOOTLOADER = caterinaもrule.mk ファイルに追加しましょう。

MATRIX_ROW_PINSMATRIX_COL_PINSは以下の画像の紫色の背景のP〇〇がポート番号なのでそれらを列挙。

f:id:kumatoki:20171030180002p:plain

次はお好きにkeymaps/default/keymap.cを定義。

たぶんpro microではピンの数が足りないのでIO Expanderを使ったり、pro microを2つ使ったりして、その2つを通信する必要があるわけです。それらがめんどくさいという方はteensyを使うといいかもしれない。ピン数が多くて事足りるかもしれない。

IO Expanderを使うのであればまずはi2cかSPIの実装が必要です。 さらに使用するIO Expanderの使い方を覚えなくてはいけません。 MCP23017と言うIO Expanderを使うのであれば、こちらの実装を借りると良いかもです。

alter

pro microを2つ使うのであればlet's splitの実装が参考になるかもしれません。

lets_split

❯ cd ../..
❯ make your_keyboard_name:default:avrdude

qmk_firmwareディレクトリトップに戻ってmakeします。

書き込みが成功したらとりあえずQMKに対応です

自作キーボードができるまで

f:id:kumatoki:20170925120214j:plain 他の写真

ババーン

これ、私が作りました。すごいでしょ。 batmanっぽいのでbatkeysと名付けました。

デザイン的にはkeyboardioとnisseを模範している。 それらをさらにコンパクトかつ高さを低く抑えた形となった。

使い勝手としては、タイピング速度測定サイトで記録を更新することができたのでいい方と言ってもいいだろう。気になると思うのは親指キー周り。率直なところ親指に役割を持たせすぎると辛い。自分では3キーくらいがベストだと思う。がキーを少なくしすぎたのでどうしても親指をフル活用せざる追えない。まぁそのうち慣れてくるでしょう。

回顧録

さて自作キーボードという世界がある。世の中に普及しているキーボードは人間工学的に好ましくないものが多い。そこで流行ったのがErgodox、最近ではlet's split。しかしこれでも満足しない人たちがいる。そういう人たちが足を踏み入れるのが自作キーボードという世界。

私もその一人だ。と言いたいがそうでもなく、ただ作って見たかったというだけでそもそもプログラマですらなければデスクワーカーでもない。本当に趣味で、好奇心で、作りたかっただけなのでした。

始まりは、twitterでキーボードを作り始めている方を見かけたから。その方はないんさんと言う方でキーボードのモックアップを最初に作られていた。そのキーボードは当時自分が使っていたergodoxと比べてとても小さく、さらに左右分離式で、親指をうまく活用できるようキーを配置してあった。それはとてもかっこよくてSNS引きこもりな自分がついコメントしてしまうほど魅力的だった。しかしその方は、さらに基盤やケース、ファームウェアも自分で作られていて、とても自分が真似できるようなことでは無いとも思った。

とは思いつつも電子工作に子供の頃から漠然とした興味があったので、少しずつ初めてみることにした。 まずはArduino unoを買って簡単なプログラムを動かした。highとlow、vccやgnd、抵抗やLEDやタクトスイッチ。とても簡単なところから一つずつ試していってゆっくり体で覚えて言った。正直なところ、それがなぜそうなるのか、もっと根本的な原理はなんなのか、までは知らない。ただそうすればそう動くと覚えていった。

少しずつ慣れていき、次第にキーボードに焦点を当てていった。キーボードの根本はキーマトリックスというものとそれをPC側へキー入力として伝えるマイコン。この二つを覚えればキーボードの仕組みはほぼ覚えたようなものだった。

あとは具体的にどのように実用的な形にしていくか。ここが自分にとっては難しいところだった。 デザインはどうすればいいのか。デザインをどう形にすればいいのか。イマイチ踏み出せないでいた。

そんなこんなしてる間に、他の方のキーボードが出てき始めていた。 ゆかりさんhrhgさん言った方々のとてもかっこ良いものがさらに自分を刺激した。 このお二人に共通しているのは3DPrinterを使って媒体を作られていること。 これで簡単にケースが作れると知って、fusion360という3DCadソフトを覚えることにした。 このソフトとても高機能ではあるがそのぶん難しい。しかし自分のデザインが形となっている様はとても楽しく、それに身を任せてすぐに使い方を覚えることができた。

デザインをする上で参考としていたのがesrilleのnisse。それを作られている方のブログ。 Shiki's Weblog この方のブログを読み、左右分離型を前提としていた考えを変え、一体型にすることにした。 まあ、技術的にも一体型の方が楽だというのもある。

dmm.makeで3DPrintしてもらうことができたのでそこに注文した。値段は4k~5k。まあ、40キーしかないこのサイズだからこの値段で済んでるとも言える。あとはスイッチやキーキャプ、マイコンなどを用意しケースの出来上がりを待つだけ。届いたらあとは根気よく半田付け。これで出来上がり。 今回配線に使ったポリウレタン銅線は少し半田付けにコツがいるようで、最初は苦労したがtwitterでゆかりさんにコツを教えていただいたら、すぐにできるようになったのでありがたい。

ハードが出来上がればあとはソフト。キーマトリックスを読み、それを元にキーコードを発行していく。 コンパクトなキーボードに欠かせないのがレイヤー。これもすんなり実装できた。もう一つ必要な機能があってそれはqmk firmwareではmod tapと呼ばれる機能で一つのキーに修飾キーと普通の文字キーの二つを役割を与える機能。これの実装に手間取った。というかすぐに諦めた。そこで大人しくqmk firmwareに対応させることにした。これも前述のないんさんが記事にされているのでそれにしたがって進めて言った。途中わからないところがあったがすぐにないんさんにフォローしていただいた。おかげでqmk対応もすんなりできたのでキーボードとして満足に機能させることができた。

@matsPodさんにRedditにポストしていただいので海外の方からの反応もいただくことができた。英語わかんないので雰囲気だけだけどね。 reddit

先人たちのアドバイスのおかげで自分もキーボードというものを作り上げることができた。 感謝したい。

elmでライフゲーム

elm

リアクティブプログラミングを軸にした関数型言語であり、Javascriptへ変換されるいわゆるAltJS。 破壊的な操作も関数的に扱える仕組みはモナドではない新しいタイプの操作体系で、Elm Architectureと呼ばれる。

そんなelmに入門。個人的に新しい言語を覚えるときはHello worldの代わりにLifegameを書いているので、例によってelmでもライフゲームから始める。

ライフゲーム

お堅い呼び名はセルオートマトン。実態は単細胞シミュレーション。 あるセルの状態とその周囲の状態からルールを元に次の状態を決定していく。 そのルールは、

  • あるセルの状態1であり、周囲に2つの状態1があれば、次のセルの状態は1。
  • あるセルの状態1であり、周囲に3つの状態1があれば、次のセルの状態は1。
  • あるセルの状態0であり、周囲に3つの状態1があれば、次のセルの状態は1。
  • それ以外は、セルの状態は0となる。

コード

https://github.com/kmtoki/lifegame-elm

レコードと呼ばれる、JSのオブジェクトのようなものでまとめて状態管理。 セルの実態はArray (Array Bool)と2次元配列。

module Lifegame exposing (..)

import Array exposing (Array)


type alias Lifegame =
    { size : { y : Int, x : Int }
    , count : Int
    , isContiune : Bool
    , cells : Array (Array Bool)
    }

init : Int -> Int -> Lifegame
init y x =
    { size = { y = y, x = x }
    , count = 0
    , isContiune = False
    , cells = Array.repeat y <| Array.repeat x False
    }

上記のルールを関数化したものがこれ。

rule : Bool -> Int -> Bool
rule b n =
    case ( b, n ) of
        ( True, 2 ) ->
            True

        ( True, 3 ) ->
            True

        ( False, 3 ) ->
            True

        _ ->
            False

周囲の状態を調べるのがenv。 ルールと周囲の状態を元にセルを更新するのがnext。

env : Int -> Int -> Lifegame -> Int
env y x lg =
    let
        arounds =
            [ ( y - 1, x - 1 )
            , ( y - 1, x )
            , ( y - 1, x + 1 )
            , ( y, x - 1 )
            , ( y, x + 1 )
            , ( y + 1, x - 1 )
            , ( y + 1, x )
            , ( y + 1, x + 1 )
            ]

        f ( y, x ) =
            case Array.get y lg.cells of
                Nothing ->
                    0

                Just xs ->
                    case Array.get x xs of
                        Nothing ->
                            0

                        Just b ->
                            if b then
                                1
                            else
                                0
    in
        List.sum <| List.map f arounds


next : Lifegame -> Lifegame
next lg =
    let
        cells =
            Array.indexedMap
                (\y xs ->
                    Array.indexedMap
                        (\x b -> rule b <| env y x lg)
                        xs
                )
                lg.cells
    in
        { lg
            | count = lg.count + 1
            , cells = cells
        }

ライフゲームの実態は以上のコードで済む。 そのライフゲームをブラウザ上でアニメーションすることがelmでは簡単にできる。 Model Update Viewを基本とし、Subscriptionsでタイマーなどの副作用のある操作などをすることができる。

Modelを各関数で引き回し、それを元にViewがHtmlを生成し、ブラウザ上のイベントをMsgという形でupdateへ送信し、各操作へ振り分けていく。

面白いのが副作用の扱い方。副作用をSub/Cmdで包み関数の返り値として返すとElm Architectureが裏側でよしなにしてくれる。OCamlHaskellとも違うながらも純粋関数的な程を保っている。

今回のコードではランダムとタイマーしか使っていないが、この仕組みでWebsocketなども扱える豊かな表現力ある。

module Main exposing (..)

import Html as H
import Html.Attributes as HA
import Html.Events as HE
import Svg as S
import Svg.Attributes as SA
import Array exposing (Array)
import Time
import List
import String
import Random
import Lifegame


main =
    H.program
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }


type alias Model =
    Lifegame.Lifegame

type Msg
    = New
    | SetY String
    | SetX String
    | Start
    | Next
    | Stop
    | Random
    | RandomSet (Array (Array Bool))


init : ( Model, Cmd Msg )
init =
    ( Lifegame.init 0 0, Cmd.none )


subscriptions : Model -> Sub Msg
subscriptions model =
    if model.isContiune then
        Time.every (Time.millisecond * 100) <| always Next
    else
        Sub.map (always Stop) Sub.none


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        New ->
            ( Lifegame.init model.size.y model.size.x, Cmd.none )

        SetY s ->
            case String.toInt s of
                Ok n ->
                    ( { model | size = { x = model.size.x, y = n } }, Cmd.none )

                Err _ ->
                    ( model, Cmd.none )

        SetX s ->
            case String.toInt s of
                Ok n ->
                    ( { model | size = { y = model.size.y, x = n } }, Cmd.none )

                Err _ ->
                    ( model, Cmd.none )

        Start ->
            ( { model | isContiune = True }, Cmd.none )

        Next ->
            ( Lifegame.next model, Cmd.none )

        Stop ->
            ( { model | isContiune = False }, Cmd.none )

        RandomSet cells ->
            ( { model | cells = cells }, Cmd.none )

        Random ->
            let
                gen =
                    Random.map Array.fromList <|
                        Random.list model.size.y <|
                            Random.map Array.fromList <|
                                Random.list model.size.x Random.bool
            in
                ( model, Random.generate RandomSet gen )


view : Model -> H.Html Msg
view model =
    H.div []
        [ H.div []
            [ H.input [ HA.type_ "number", HA.placeholder "y", HE.onInput SetY ] []
            , H.input [ HA.type_ "number", HA.placeholder "x", HE.onInput SetX ] []
            , H.button [ HE.onClick New ] [ H.text "New" ]
            , H.button [ HE.onClick Start ] [ H.text "Start" ]
            , H.button [ HE.onClick Stop ] [ H.text "Stop" ]
            , H.button [ HE.onClick Random ] [ H.text "Random" ]
            ]
        , H.div [] [ H.text (toString model.count) ]
        , H.div [] [ viewLifegame model ]
        ]


viewLifegame : Model -> H.Html Msg
viewLifegame model =
    S.svg
        [ SA.width (toString <| model.size.x * 50)
        , SA.height (toString <| model.size.y * 50)
        ]
        (List.concat <|
            Array.toList <|
                Array.indexedMap
                    (\y xs ->
                        Array.toList <|
                            Array.indexedMap
                                (\x b ->
                                    S.rect
                                        [ SA.x (toString <| x * 5)
                                        , SA.y (toString <| y * 5)
                                        , SA.width "5"
                                        , SA.height "5"
                                        , SA.fill
                                            (if b then
                                                "green"
                                             else
                                                "black"
                                            )
                                        , SA.stroke "black"
                                        ]
                                        []
                                )
                                xs
                    )
                    model.cells
        )

出来上がり

f:id:kumatoki:20170731172704g:plain

所感

元々はFRPベースだったらしく、小難しい概念で副作用を取り扱っていようだがElm Architectureとやらのおかげでずいぶん簡単に入門できた。パターンマッチばかりで関数合成が少なくなってしまったが語彙の問題なので覚えればすぐ簡潔にかけるようになるだろう。elm-formatにはちょっと趣味と合わない部分があるが、まあ人様に見やすく編集しやすいコード書式という意味でelm-formatで統一的に合わせていくのは良いと思う。
HTMLイベントの発火の分、Msgを追加していかないといけないのは面倒なのでどうにかまとめたいが方法がまだよくわからない。あとTaskという概念もあるらしく、非同期通信などを使う場合は必要になってくるらしい。Haskellで関数型の思考には慣れているので書き味は程よく気持ちのいいものであったが、Haskellと比べ、型安全なライブラリ設計なので冗長的な部分も多々ある。型クラスの導入も議論されているらしいがHaskellの標準ライブラリの型クラス化などを見ている限り、なかなか型クラスも面倒なところがありそうなので、無いなら無いで良いのかもしれない。データ操作が明示的なのも、書くときは面倒だが、読むときに楽できるので良い部分もある。
フロントエンドの知識はまるでないので、これを機会に少し覚えていけたらと思うだけで特に勉強しない結末。

let's split キーマップ

  /* Qwerty
   * ,-------------------------------------------, ,------------------------------------------,
   * | Tab   |   Q  |   W  |   E  |   R   |   T  | |   Y   |   U  |   I  |   O  |   P  |  BS  |
   * |-------+------+------+------+-------+------| |-------+------+------+------+------+------|
   * |Esc/Ctl| A/Md |   S  |   D  |   F   |   G  | |   H   |   J  |   K  |   L  |;:/Md |'"/Ctl|
   * |-------+------+------+------+-------+------| |-------+------+------+------+------+------|
   * |  =+   |   Z  |   X  |   C  |   V   |   B  | |   N   |   M  |  ,<  |  .>  |  /?  |  -_  |
   * |-------+------+------+------+-------+------| |-------+------+------+------+------+------|
   * |   `~  | Raise| Alt  | GUI  | Lower |Sp/Sft| |Ent/Sft| Lower| GUI  | ALT  | Raise|  \|  |
   * `-------------------------------------------' `------------------------------------------'
   */

  /* Lower 
   * ,-----------------------------------------, ,-----------------------------------------,
   * |      |   1  |   2  |   3  |   4  |   5  | |   6  |   7  |   8  |   9  |   0  |      |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * | PREV |   !  |   @  |   #  |   $  |   %  | |   ^  |   &  |   *  |   (  |   )  | NEXT |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |   ~  |   `  |   |  |   \  |      | |      |   [  |   ]  |   {  |   }  |      |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      | Eisu |      | |      | Kana |      |      |      |      |
   * `-----------------------------------------' `-----------------------------------------'
   */

  /* Raise 
   * ,-----------------------------------------, ,-----------------------------------------.
   * |  F1  |  F2  |  F3  |  F4  |  F5  |  F6  | |  F7  |  F8  |  F9  |  F10 |  F11 |  F12 |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      |      |      | |      |      |      |      |      |      |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      |      |      | |      |      |      |      |      |      |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      |      |      | |      |      |      |      |      |      |
   * `-----------------------------------------' `-----------------------------------------'
   */

  /* Media 
   * ,-----------------------------------------, ,-----------------------------------------.
   * |      |      | WhUp | MsUp | WhDn |      | |  End | PgDn |  Up  | PgUp | Home |      |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |Reset |      | MsLf | MsDn | MsRg |      | |      | Left | Down | Right|      |Reset |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      |      |      | | Prev |StpPly| Next |Mute  |VolDn |VolUp |
   * |------+------+------+------+------+------| |------+------+------+------+------+------|
   * |      |      |      |      |Click2|Click1| |      |      |      |      |      |      |
   * `-----------------------------------------' `-----------------------------------------'
   */

keymap.c

最初に

qmk_firmwareとは多様なキーボードに対応するための汎用ファームウェアであり、自分でキーマップを変えることができる。さらに普通のキーボードにはない機能があり、レイヤー、タップ/ホールド、タップダンス、マクロなどがある。

私のレツプリキーマップ

レツプリことlet’s split、48のキーをどう効率よく使えるか、は悩ましく楽しい問題。 48キーで十分と言えるのは一重に「レイヤー」と呼ばれる機能のおかげ。このレイヤーをうまく使い各々のキーマップを作り上げていける。 私の場合、4つのレイヤーを作っている。アルファベットやスペース、エンターなどの基本キーを配置したトップレイヤー、記号を散りばめたLowerレイヤー、ほぼ使われないFnキーのRaiseレイヤー、マウスカーソルやクリック、アローキーや音楽再生と音量調整ができるMediaレイヤー。

Qwerty

トップレイヤーはコード上ではQwertyレイヤーと読んでいる。今時わざわざQwerty配列なんぞ使わんでもよかろうと言う気もしなくはないが、新しい配列を覚えるコストは非常に高く、さらに既存のQwerty配列を前提に設計されたソフトウェアを多用する身としてはなかなか抜け出せない。

Qwertyレイヤーの肝は親指にある。親指スペースは当たり前だが、さらにエンターを持ってきた。さらにこの2キーはスペースとエンターとして機能すると同時にシフトとしても機能する。 どう言うことかと言う これはキーをタップした場合とホールドした場合で挙動を分けられる機能。 これによって一つのキーに二つの役割を与えることができる。よって親指シフトを実現することができている。

英数とかなの位置はなかなか難しく、当初はQwertyレイヤーに置いていたが誤入力した場合に非常に煩わしいのでLowerレイヤーに置くことにした。しかし多用するキーを入力するのに2つのキーを押さなければならないと言うのは少し納得が行かない面もある。

WindowsでのIME切り替えはAlt + `で全角/半角ができる

Lower

次にLowerレイヤーについて。プログラミングするので記号は全て多用する。その中でもさらによく使う記号を良い位置に置いておきたいがある程度既存の配列と互換性を持たせて置くと、配列を覚えやすいのでそれを優先した結果が上記の配列になっている。defaultの配列ではLowerとRaiseに記号を分けているので少々覚えるのにコストがかかるのではないかと思い、Lowerのみに記号を詰め込んだ。

NEXTTABとPREVTABとは、文字どうりタブ移動を一つのキーにまとめたもの。 MacOSでしか使えないショートカットだと思うのでWindowsではCtrl+Tab / Ctrl+Tab+Shiftで同様のことができる(多分。

// MacOS only
#define NEXTTAB ACTION_MODS_KEY(MOD_LGUI, KC_RCBR)
#define PREVTAB ACTION_MODS_KEY(MOD_LGUI, KC_LCBR)

Raise

Raiseレイヤーはファンクションキーを割り当てている。 そもそもレイヤー切り替えは脳に負担がかかるものだと思うので、少ないほど良いと思う。

Media

Aか;をホールドすると使える、 Mediaレイヤーはなかなか便利なもので、ホームポジションから手を動かさずマウス操作ができるのでかなり便利。キーボードからマウス操作もできるのもqmk_firmwareの機能。ただ矢印上と右か左を同時押しででカーソルがロックと言うか動かなくなるのでどうにかならないかな。