いきなり自作キーボードを作る

この記事は、[キーボードとマウスとコーヒーとAdventCalendar2018 - Qiita](https://qiita.com/advent-calendar/2018/keyboard_mouse) の10日目の記事です。

![asceension001.jpg](https://qiita-image-store.s3.amazonaws.com/0/30474/57ded733-2801-4706-2b0a-1536b4a2a5d9.jpeg)

頭痛が痛い的なタイトルで恐縮ですが、いきなりメカニカルやります！

# 始まり

ふだん使いのキーボードは[ThinkPad USB トラックポイントキーボード US (55Y9003)](https://support.lenovo.com/us/ja/solutions/migr-73183) です。

でももう10年くらい使ってて、かなりヘタってきました。
明らかに買い替え時ですが、すでに生産終了してますし、オークションにも新品はめったに出品されないし、おまけに[後継モデル](https://www.lenovo.com/jp/ja/landingpage/accessories/thinkaccessories/thinkpad/02/02/)はあまりにお粗末な代物でした。

次はどうしようかとウェブを徘徊していると、いつの間にか自作系のサイトに誘われていきます。

redditを延々眺めていると、[QMK Firmware](https://qmk.fm/) というフレームワークを使っている人が多い模様。

へー、このフレームワークって昔X68000のキーボードコンバータ作ってたバブルボブルの人の後継なんや。懐かしいなぁ。じゃあオレもいっちょやってみよか、という感じです。

# やりたいこと

まあ最初ということで **いきなり変態チックなのを作らずに、ぱっと見フツーなのを** というコンセプトでいきたいと思います。

あえて言わせていただきたいのですが、これは世間一般で言われる「むっつり」とは異なります。
強いて言うなら、そう、ギャップというやつです。
賢明なる諸兄姉におかれましては、どうかそこをお間違えなく。キーマップなんて後でどうにでも出来ますんで。

というわけでコンサバ寄りにやりたいことを並べてみます。

- 基本はフツーにQWERTY
- 基板配線がめんどくさそうなので、Underglow などの光りモノは無しの方向で
- エディタが Emacs + Evil なので **Ctrl** と **Meta** キーは親指にしたい
- **ESC** と **Shift** キーも親指付近にしたいかな
- 矢印キーはVimっぽく横一列に
- 職場は Windowsで **F5** とか結構押すし、こいつらはレイヤー切替えなしでいきたい
- **Home**, **End**, **PageUP**, **PageDown** とかも念のため置いとこうかな

とか言ってると、なんやかんやで **81キー** となり、大きめになってしまいました。
スプリット的なのはまた改めてやるつもりなので今は許してください。

ちょっと前のものですが、初期検討時のキーマップを貼っておきます。

![1-key-layout.png](https://qiita-image-store.s3.amazonaws.com/0/30474/849e6848-d158-e2ab-05f0-055eb08d4d5b.png)

あと、どうせ自作するならポインティングデバイス欲しいよねということで、アナログジョイパッドをつけました。

# とりあえず部品など

とりあえず試作と割り切って、部品はDIP品だけで構成したい気分です。
家でSMDをはんだ付けするのしんどいので。

あと、マイコン周りは横着して Arduino 互換ボードで済ませます。ただ、ATMEGA328Pのものではなく USBコントローラ内蔵のAVR（ATMEGA32U4など）が載っているものを選ぶのが無難な感じ。

QMK Firmware のソースを見てると、[Pro Micro](https://www.sparkfun.com/products/12640)とか[Teensy](https://www.pjrc.com/store/teensy.html) を使ってる人が多いですが、今回は adafruit の [ItsyBitsy 32u4](https://www.adafruit.com/product/3677)を使ってみました。

マウスポインタとスクロール用のアナログジョイパッドにはPSP的な[これ](https://www.adafruit.com/product/2765)を。
ジョイパッドはホームポジションのまま親指で動かしたいので、別基板にしてキーボードの手前に垂直に立てる算段です。

キーキャップは[こんなの](https://www.banggood.com/ja/Dolch-Color-104-Keys-DSA-Profile-PBT-Big-Legend-Printed-Keycaps-Key-Caps-for-Mechanical-Keyboard-p-1213236.html?utm_design=41&utm_source=emarsys&utm_medium=Neworder171109&utm_campaign=trigger-emarsys&utm_content=Winna&sc_src=email_2675773&sc_eh=7072405b3b420aa91&sc_llid=4121607&sc_lid=105229698&sc_uid=wr5pwfrlnr&cur_warehouse=CN)を選んでみました。DSAプロファイルでPBT素材。**F** と **J** のキートップにはふつうは横棒のエンボス加工がしてありますが、これはその代わりに深く凹んでいるもの(Deep Dish)です。

キースイッチには定番の Cherry MX を使います。
キーの個数は81個なので、これをそのまま全部読むと81本ものデジタル入力が必要になってしまいます。

いい年してそんなアホなことをしてると社会的信用を失いますので、ここは素直にキーマトリクスを考えます。（QMK Firmware はキーマトリクス前提なので心配無用です）

今回のキー配列をマトリクスにすると 7rows/14cols という構成になり、必要なデジタルIOピンは 7 + 14 = 21ピンと、かなり少なくなりました。
対して、使うマイコンボード ItsyBitsy 32u4 はデジタルIOとしては計23ピン使えます。

なんとか収まりそうですが、そうは問屋が卸しません。
今回はジョイパッドのアナログ入力が別途4本必要なので、必要なピン数は 21 + 4 = 計25ピンとなり、このままでは 2ピン足らないです。

というわけでI2C接続のIOエキスパンダを使って、14colsぶんのデジタル入力を I2CのSCL, SDAの2本でまかなうことにします。 QMK Firmware のソースを見ると MCP23018 を使っている人がいますが、ここは秋月で買える下位互換品(?)の[MCP23017](http://akizukidenshi.com/catalog/g/gI-09486/)を使うことにします[^6]。

[^6]: データシートをざっと見た感じ、MCP23018 と MCP23017 の違いはI2Cの上限速度だけっぽいですし、今回のI2Cは400kHz程度と問題ないので。

その他の細かな部品は適当に選びました。参考までに[BOM](https://docs.google.com/spreadsheets/d/e/2PACX-1vQxIO_zkPiEfhVi219sfc5qDN3oJ3B2FrtImMeb-iPsALxcW_jJAPMTqnw8400emrfJPChO8t61jF9z/pubhtml?gid=1216591520&single=true)を置いときます。

# まずは回路から

キーマトリクスは、ROW側をマイコンボード（というかAVRマイコン）の PB1〜PB7の出力に割りつけ、COL側をMCP23017のGPA0〜GPB5の入力に割りつけています。

MCP23017のGPA0〜GPB5の入力は、マイコンからプルアップに設定しておき、**アクティブロー**でキー入力を判定することにします。

次にジョイパッド入力です。
回路的には1つのジョイパッドは X,Y 2本の可変抵抗と等価なので、左右で計4本のAD入力が必要となります。

|ジョイパッド|用途|X軸|Y軸|
|:----------:|:--------------|:--------------|:--------------|
|右|マウスポインタ用|PF4 (ADC4)|PF5 (ADC5)|
|左|スクロール用|PF6 (ADC6)|PF7 (ADC7)|

こんな感じに割りつけました。

あと、ポートが余ったので設定変更用のDIPスイッチもつけてみました。
実は QMK Firmware にはすでに [Bootmagic](https://docs.qmk.fm/#/feature_bootmagic) というソフト的な設定変更機能が実装されています。
なのでまったく不要なのですが、ハード的なのも趣があっていいかなと。

![2-sch-main.png](https://qiita-image-store.s3.amazonaws.com/0/30474/95b8e1b2-db9b-27d6-9f82-c784588de190.png)
![3-sch-left.png](https://qiita-image-store.s3.amazonaws.com/0/30474/de727a05-dace-c5be-f92d-7a82a8bb26b3.png)
![4-sch-right.png](https://qiita-image-store.s3.amazonaws.com/0/30474/8189878e-541d-ba3f-e77e-43f8e106179f.png)

この手の仕事を家でするときは10年以上[Eagle](https://www.autodesk.co.jp/products/eagle/overview)を使ってきましたが、今回は流行りの[KiCAD](http://kicad-pcb.org/)を使ってみました。

~~KiCAD、正直ダルいです^^;~~
ただ、Eagleもautodeskに買収されてからログインを要求したりウザい仕様が増えてきたので、しばらくKiCADを使っていきたいです。

# 次に基板を

アートワークもKiCADでやりました。

<img width="608" alt="pcb2.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/30474/d2f285d7-c10f-c903-9bab-14e6b9c63b6b.jpeg">

今回は一次試作ということもあり、

- キースイッチをはめるトッププレート
- 筐体となるベース板

を基板材料(T=1.6mm, FR-4)で済ませるべく[^8]、同じ板面に面付けしています。

[^8]: トッププレートは真鍮板で、筐体は3Dプリントか亜鉛鋼板でやりたかったですが。

基板が描けたら一晩寝かせて[^9]ガーバーデータを出力し、基板を発注します。
基板の製造は [Elecrow](https://www.elecrow.com/pcb-manufacturing.html)さんにお願いしました。
この面付け5枚に黒レジスト指定で価格は1.4万円くらい[^10]、
到着は（サイズが大きかったので難儀したとかで）10日程度でした。

[^9]: 一晩寝かせると失敗や改善点が見えてくるので。
[^10]: 工場の歩留まりがよかったのか、6枚届きました。

仕上がりについては、レジストのノリやシルクもわりと綺麗でしたし、ドリル精度も申し分ない出来でした。

# いよいよ実装を

基板が届いたら、電源ライン周りをチェックしたあと、部品を一つずつはんだ付けしていきます。

こういうのは背の低い部品から実装していくものなので、それに沿って寡黙に続けます。

まずメイン基板にダイオード、抵抗、コンデンサ。次にIC、DIPスイッチときて最後にマイコンボードをつけます。
ジョイパッドは別基板に付けておき、あとでL字のピンヘッダでメイン基板につなぎます。

キースイッチはまず、トッププレートに全部挿し込んでおき、それを裏返した上にメイン基板を載せます。

あとは、足を一本づつはんだ付けしていきますが、基板の反りや部品の浮きを避けるため、まず基板中央付近の１つをメイン基板に押さえながらはんだ付け→次にその半分の中央付近→外端という感じで、内→外に向かってつけていきます。

# 最後はソフト

まず、ビルドに必要な環境を[この辺り](https://docs.qmk.fm/#/newbs_getting_started?id=getting-started)を見て作ります。

次に本家の [QMK Firmware](https://github.com/qmk/qmk_firmware)をforkして、さらにそれをローカルにcloneし、そこに自分用のブランチを作成します。

今回はキーボードの名前を asceension [^11]として、それをブランチ名にしています。本家にプルリクする気はありませんけど。

[^11]: タイポしてます。キーボードだけに -_-;

次にベースとするキーボードを選びます。

[keyboardsフォルダ配下](https://github.com/qmk/qmk_firmware/tree/master/keyboards)には膨大な数の派生キーボードのソースがあるので、その中から自分のしたいことに近いものを選びます。

手頃のなものを見つけたら、`make`してみます。

```
cd /どこか/qmk_firmware
make ベースのフォルダ名:default
```

とかするとだいたいOKなはず。
もし手元に Arduino 互換ボードがあれば、USBケーブルつないで書き込みもやってみます。[^12]

[^12]: 最後に指定する`avrdude`などは、使う基板ごとに異なるので、[ここ](https://docs.qmk.fm/#/newbs_flashing?id=flash-your-keyboard-from-the-command-line)とか確認です。あと、書き込み時にブートローダに入れる操作も若干異なります。

```
make ベースのフォルダ名:default:avrdude
```

ちゃんとmakeが通ったら、そのフォルダをコピって自分のソースフォルダを用意します。

 `cp -a base-dir handwired/asceension`とかしてパクりました[^13]。

[^13]: 今回は試作なので[keyboards/handwiredフォルダ](https://github.com/qmk/qmk_firmware/tree/master/keyboards/handwired)の下に作りました。

あとは、ひたすら ソース変更 → make → テスト を繰り返していきます。

下記は主な変更/作成ファイルです。

|ファイル|内容|
|:-----------------------|:------------|
|keymaps/default/keymap.c|自分的なキーマップ変更|
|rules.mk|自分的な`make`の設定。デバッグ出力の有効/無効などもここ|
|readme.md|自分的なREADME|
|asceension.c|自分的なメインっぽい処理|
|analogpad.c|ジョイパッド処理 …ですが実用的にはちょっと難あり|
|dipsw.c|DIPスイッチ処理|
|config.h|ホストに返す VID, PIDの設定はここ|

アナログジョイパッド処理は、[promethium](https://promethium.keyboard.id/)というキーボード（電池電圧読んでる？）と[dichotemy](https://imgur.com/gallery/GWvwg)というキーボード（シリアル経由でロータリーエンコーダ？？）を参考にさせてもらいました。

AVRは10年ぶりくらいだったので、いろいろ忘れてて大変でした。

CADデータとかソースコードは [GitHub](https://github.com/hidsh/qmk_firmware/tree/asceension/keyboards/handwired/asceension) に置いときます。

# 振り返りとか

実際作ってみると、いろんな問題があるもんです。

- アナログジョイパッドはやっぱりちょっと実用性に欠ける
- 矢印キーをホームポジション以外でVim配列にしても脳が受け付けてくれない
- 長いキー（**Enter** など）にはスタビライザーをつけるべきだったかも
- 回路や基板の誤りもいくつか[^15]
- DIP品でもはんだ付けはダルい
- micro USB ソケットがモゲやすいので、次は Type-C にしたい
- AVR マイコンはもうコスパ的につらいので、そのうち ARM Cortex M4 とかにしたい
- ソフトは深いところがまだよくわかってない（レポート送信等）

イケてなかったところはこんなところです。

[^15]: ダイオードが逆とか、USBコネクタのピン配列が逆とか、アナログジョイパッドの足が入らなかったとかとか

# 感想など

そういえば昔、HHK のキーマップを変えたくてキーボードコントローラを自作したことがありました。

そのときは Cypress の EZ-USB を使って基板を起こし、USB や HIDクラスなんかを勉強しながら実装していったので、かなり時間かかった記憶があります。

それを思うと、マイコン周りはArduino互換品を買ってくればいいですし、ソフトのフレームワークは QMK Firmware を使えば、ブレッドボードでも確認できるので、かなり楽になったと思います。

そういえば、QMK Firmware 自体は C言語と 一部 C++ で書かれているようです。
組込みで実用的に C++ を試すにはいい材料だと思いました。

さて、いろいろ失敗したので今年中に次の基板を描きたいところですが、その前にまずはまともなケースを作らなければと思っています。

少しだけ概要を書くつもりが、長くなってしまいました。
コーヒーについてはまたそのうち書かせていただけたらと思います。

それでは良いお年を。