前説
Twitterのタイムラインに流れてきたkuriharaさんのつぶやきの3Dプリントされたキーボードケースらしき何か。
引用されていたWebページをたどっていくと、C-13Xというキーボードでした。ちっさいものが好きなんで作ってみようかなと。
URL
flurplesさんのgithub
https://github.com/flurples/C-13X
kuriharaさんのブログ (3Dプリント発注先の記事)
https://kurihara.hatenadiary.jp/entry/2022/01/04/154223
まきゃさんのC-13X制作ページ
https://machiaworx.net/?p=1312
PRK Firmware
https://github.com/picoruby/prk_firmware
下準備
- キーボードケース:flurplesさんのgithubからデータをダウンロードして、WENEXTで出力
- キースイッチ:AKKO CS Jelly SpongeをAmazonから購入
- キーキャップ:AKKO WAVE 226キーASAプロファイルをAmazonから購入
- ソケット:CHERRYMXスイッチ用 Kailh PCBソケットをTALP KEYBOARDさんから購入
- マイコン:Seeed XIAO RP2040をマルツから購入していた...
- そのた:スイッチ間の格子用に太い銅線、マイコン接続用にエナメル線、ダイオード、コンスルーは家にあったりあまりものだったり
ケース出力
中国の基板屋さんも最近は3Dプリントをやっている様ですが、WENEXTに発注したのはkuriharaさんのブログでクーポンを書いていただいてたからです。お世話になりました!
出力はクーポンの範囲内でしたが、送料と合わせるとそれなりの金額になった感じがしました。今回が初発注ですが、国内の業者さんだったらすごく高いんだろうなぁ...
しかも発注から到着までが思ってたよりも早くておおむね2週間。配達はFedExなので出荷から到着も早かったです。
到着した箱は怪しいけど、まぁこんなもんかなと思って開梱するとなぞの紙やすり。これで出力物を磨いてくださいって事なのかなと理解。
しっかり緩衝材が入っていたので、破損とか傷とかはなかった。中国から送られたとは思えない感じですね。
マイコンなに使うの問題
flurplesさんはelite-c、まきゃさんはRP2040搭載 SparkFun Pro Microを使用されてます。
さてさてどうしようかなと思って、とりあえずRaspberry Pi Picoを買ったのですが、買った後に引き出しから出てきたのがSeeed XIAO RP2040でした。そういえば職場近くのマルツに入荷した時に慌てて買いに行ったのをわすれてた😅
ピン数は少ないけどこれを使いたいなと思いつつPRKfirmwareとKMKfirmwareをみてると、PRKがDuplex-Matrixをサポートしているのが目についたのでちいさくガッツポーズ。
これでピン数問題は解決できる目処が立ったので、マイコンはSeeed XIAO RP2040に決定しました。
ケース加工
マイコンなに使うの問題が解決できたので、elite-cに合わせ込まれているケースの加工を行いました。そもそもケースを出力する段階でデータを修正しておけばいいと思うのですが、出力してからマイコンを決めるとかしているから加工が必要になります。
現物合わせでXIAOが収まる様に彫刻刀でガリガリと少しずつ加工して、頃合いがいいところで完了です。
スイッチのマトリクス配線
ハンドワイヤーだとキーキャップを入れ替える時にワイヤーが切れると困りものなので、マトリクスの配線は家にあった太い銅線を使ってPCBソケットでスイッチが取れる様にしておいて、マトリクス配線への影響が最小になる様にしました。
プレートにスイッチをはめてからPCBソケットをはめてマトリクス配線をぼちぼちハンダ付けするのですが、ダイオードはDuplex-Matrixなので列によって向きが変わるのが要注意ポイントです。PCBを作るわけではないので自分がわかるポンチ絵を描いて配線を進めました。
マイコンとスイッチのマトリクス配線の配線
ボトムケースをはずす時にマイコンの配線が邪魔になりそうなので、手持ちのコンスルーを使うピンに合わせて切断して脱着が簡単になる様にしています。
配線材はエナメル線を使ってなるべく短くなる様にスイッチのマトリクス配線へ配線しました。エナメル線が意外と硬いので取り回しはちょっとやりにくい感じですが、ボトムケースをはずすのは滅多にないと思うのでこれで手打ちにしてます。
配線チェック
通電前に配線ショートがないかとダイオードの向き確認。特にダイオードの向きは列毎で変わるので3回くらい見直すくらいでちょうどいいと思います。
目視で問題ないなら仮のキーマップを作ってスイッチのオンチェックです。
仮のキーマップ作成
XIAOの物理ピンとPRKfirmwareで記載するピン番号が異なるので、Seeedのページでピンを確認します。PRKfirmwareで使う番号は下図のMicropythonと書いてある番号です。
https://files.seeedstudio.com/wiki/XIAO-RP2040/img/xinpin.jpg
このキーマップで順番にキーを押していって、意図しているキーが入力されたらOK
kbd = Keyboard.new
# XIAO/GPIO Pin Assign
# D0 P26
# D1 P27
# D2 P28
# D3 P29
# D4 P6
# D5 P7
# D6 P0
# D7 P1
# D8 P2
# D9 P4
# D10 P3
c1 = 0
c2 = 1
c3 = 2
c4 = 4
c5 = 3
r1 = 7
r2 = 6
r3 = 29
r4 = 28
# Note that defferent from init_pins
kbd.init_matrix_pins(
[
[ [c1,r1], [r1,c2], [c3,r1], [r1,c4], [c5,r1], [r1,c5], [c4,r1], [r1,c3], [c2,r1], [r1,c1],],
[ [c1,r2], [r2,c2], [c3,r2], [r2,c4], [c5,r2], [r2,c5], [c4,r2], [r2,c3], [c2,r2], [r2,c1],],
[ [c1,r3], [r3,c2], [c3,r3], [r3,c4], [c5,r3], [r3,c5], [c4,r3], [r3,c3], [c2,r3], [r3,c1],],
[ [c1,r4], [r4,c2], [c3,r4], [r4,c4], [c5,r4], [r4,c5], [c4,r4], [r4,c3], [c2,r4], [r4,c1],],
]
)
# default layer should be added at first
kbd.add_layer :default, %i(
KC_Q KC_W KC_E KC_R KC_T KC_Y KC_U KC_I KC_O KC_P
KC_A KC_S KC_D KC_F KC_G KC_H KC_J KC_K XXXXXXX KC_L
KC_Z KC_X KC_C KC_V KC_B KC_N KC_M KC_1 KC_2 KC_3
KC_4 KC_5 XXXXXXX KC_6 XXXXXXX KC_7 XXXXXXX KC_8 XXXXXXX KC_9
)
kbd.start!
本番キーマップ
無事キー入力ができるのが確認できたら、本番のキーマップを作成します。
前に作ってたkawaiiのキーマップに似せて作ったのですが、PRKfirmwareにはTapDanceが実装されていないみたいなので、使わない様にキーマップを調整してます。
今の所のキーマップは以下な感じです。
kbd = Keyboard.new
# XIAO/GPIO Pin Assign
# D0 P26
# D1 P27
# D2 P28
# D3 P29
# D4 P6
# D5 P7
# D6 P0
# D7 P1
# D8 P2
# D9 P4
# D10 P3
c1 = 0
c2 = 1
c3 = 2
c4 = 4
c5 = 3
r1 = 7
r2 = 6
r3 = 29
r4 = 28
# Note that defferent from init_pins
kbd.init_matrix_pins(
[
[ [c1,r1], [r1,c2], [c3,r1], [r1,c4], [c5,r1], [r1,c5], [c4,r1], [r1,c3], [c2,r1], [r1,c1],],
[ [c1,r2], [r2,c2], [c3,r2], [r2,c4], [c5,r2], [r2,c5], [c4,r2], [r2,c3], [c2,r2], [r2,c1],],
[ [c1,r3], [r3,c2], [c3,r3], [r3,c4], [c5,r3], [r3,c5], [c4,r3], [r3,c3], [c2,r3], [r3,c1],],
[ [c1,r4], [r4,c2], [c3,r4], [r4,c4], [c5,r4], [r4,c5], [c4,r4], [r4,c3], [c2,r4], [r4,c1],],
]
)
# default
# ,---------------------------------------------------------------------.
# | Q | W | E | R | T | Y | U | I | O | P |
# |------+------+------+------+------+------+------+------+------+------|
# | AALT | S | D | F | G | H | J | K | ---- | LALT |
# |------+------+------+------+------+------+------+------+------+------|
# | ZSFT | X | C | V | B | N | M | . | - |ENTSFT|
# |------+------+------+------+------+------+------+------+------+------|
# |ESCCTL| CMD | ---- | BS/LOWER | SP/RAISE | , | ---- |ENTCTL|
# `---------------------------------------------------------------------'
# default layer should be added at first
kbd.add_layer :default, %i(
KC_Q KC_W KC_E KC_R KC_T KC_Y KC_U KC_I KC_O KC_P
KC_AALT KC_S KC_D KC_F KC_G KC_H KC_J KC_K KC_NO KC_L_ALT
KC_ZSFT KC_X KC_C KC_V KC_B KC_N KC_M KC_DOT KC_MINUS KC_ENTSFT
KC_ESCCTL KC_LGUI KC_NO KC_BSLO KC_NO KC_SPRZ KC_NO KC_COMM KC_NO KC_ENTCTL
)
# raize
# ,---------------------------------------------------------------------.
# | 1 | 2 | 3 | 4 | 5 | - | = | [ | ] | \ |
# |------+------+------+------+------+------+------+------+------+------|
# | 6 | 7 | 8 | 9 | 0 | , | / | UP | ---- | : |
# |------+------+------+------+------+------+------+------+------+------|
# | ` | + | - | / | = | . | LEFT | DOWN | RGHT | " |
# |------+------+------+------+------+------+------+------+------+------|
# | TAB | | ---- | | | | ---- | |
# `---------------------------------------------------------------------'
kbd.add_layer :raize, %i(
KC_1 KC_2 KC_3 KC_4 KC_5 KC_MINUS KC_EQL KC_LBRC KC_RBRC KC_BSLS
KC_6 KC_7 KC_8 KC_9 KC_0 KC_COMM KC_SLSH KC_UP KC_NO KC_COLON
KC_GRAVE KC_PLUS KC_MINUS KC_SLSH KC_EQL KC_DOT KC_LEFT KC_DOWN KC_RGHT KC_DQUO
KC_TAB KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO
)
# lower
# ,---------------------------------------------------------------------.
# | ! | @ | # | $ | % | _ | + | { | } | | |
# |------+------+------+------+------+------+------+------+------+------|
# | ^ | & | * | ( | ) | < | > | ? | ---- | ; |
# |------+------+------+------+------+------+------+------+------+------|
# | ~ | F3 | F4 | F5 | F6 | F7 | F8 | F9 | F10 | ' |
# |------+------+------+------+------+------+------+------+------+------|
# | F1 | F2 | ---- | | ADJUST | F11 | ---- | F12 |
# `---------------------------------------------------------------------'
kbd.add_layer :lower, %i(
KC_EXLM KC_AT KC_HASH KC_DLR KC_PERC KC_UNDS KC_PLUS KC_LCBR KC_RCBR KC_PIPE
KC_CIRC KC_AMPR KC_ASTER KC_LPRN KC_RPRN KC_LABK KC_RABK KC_QUES KC_NO KC_SCOLON
KC_TILD KC_F3 KC_F4 KC_F5 KC_F6 KC_F7 KC_F8 KC_F9 KC_F10 KC_QUOT
KC_F1 KC_F2 KC_NO KC_NO KC_NO ADJUST KC_NO KC_F11 KC_NO KC_F12
)
# adjust
# ,---------------------------------------------------------------------.
# | | | | | CAPS | INS | HOME | PGUP | | |
# |------+------+------+------+------+------+------+------+------+------|
# | | | | | SLCK | DEL | END | PGDN | ---- | |
# |------+------+------+------+------+------+------+------+------+------|
# | | | | | NLCK | | | | | |
# |------+------+------+------+------+------+------+------+------+------|
# | PSCR | | ---- | | | | ---- | |
# `---------------------------------------------------------------------'
kbd.add_layer :adjust, %i(
KC_NO KC_NO KC_NO KC_NO KC_CAPS KC_INS KC_HOME KC_PGUP KC_NO KC_NO
KC_NO KC_NO KC_NO KC_NO KC_SCROLLLOCK KC_DEL KC_END KC_PGDN KC_NO KC_NO
KC_NO KC_NO KC_NO KC_NO KC_NUMLOCK KC_NO KC_NO KC_NO KC_NO KC_NO
KC_PSCREEN KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO KC_NO
)
# Your custom Keycode or Keycode (only modifiers) Release time Re-push time
# key name Array of Keycode or Layer Symbol to be held threshold(ms) threshold(ms)
# or Proc or Proc which will run to consider as to consider as
# when you click while you keep press `click the key` `hold the key`
kbd.define_mode_key :KC_AALT, [ :KC_A, :KC_LALT, 150, 150 ]
kbd.define_mode_key :KC_L_ALT, [ :KC_L, :KC_RALT, 150, 150 ]
kbd.define_mode_key :KC_ZSFT, [ :KC_Z, :KC_LSFT, 150, 150 ]
kbd.define_mode_key :KC_ENTSFT, [ :KC_ENT, :KC_RSFT, 150, 150 ]
kbd.define_mode_key :KC_MINSFT, [ :KC_MINUS, :KC_RSFT, 150, 150 ]
kbd.define_mode_key :KC_ESCCTL, [ :KC_ESCAPE, :KC_LCTL, 150, 150 ]
kbd.define_mode_key :KC_BSLO, [ :KC_BSPC, :lower, 150, 150 ]
kbd.define_mode_key :KC_SPRZ, [ :KC_SPC, :raize, 150, 150 ]
kbd.define_mode_key :KC_ENTCTL, [ :KC_ENT, :KC_RCTL, 150, 150 ]
kbd.define_mode_key :ADJUST, [ nil, :adjust, nil, nil ]
kbd.start!
組み立て
一通りキーボードとして動作するのを確認できたので、お楽しみのケース組み立てとキーキャップ装着です。
ボトムケースにゴム足を貼り付けて、スイッチ群を上にのせてトップケースを重ねてネジを閉めましょう。マイコンは両面テープで貼り付けちゃいました。
予定はIDOBAOのキーキャップをつけるつもりでしたが、購入しやすかったAKKO WAVEに変更しました。セットされてるキー数が多いので迷彩みたいにキーキャップを飾れるのがいい感じです。
気が向いたらkawaiiにつけているIDOBAOとチェンジしていいかな。
あとがき
このビルドログはC-13Xで作成しました。
PRKfirmwareはキーマップの変更が簡単で良いのですが、マスストレージとして認識されるので気楽にぬいたらおこられるのが気になるところ。
キーマップが確定したらバイナリーをmakeしてマスストレージ認識されない様にしようかしら。
実際にタイプしてみて体感できたのは、QMKとの挙動の違いやLEDつけたいとかあるのでドキュメントしっかり読まないとだめっぽいです。
物理的問題でマイコンが奥にいきすぎてリセットできない問題が発覚したり、Hの左下のキーをNにしてるけどなんとなく左にずれてる感があるのもどうしようかなと...
あとがきその2
Seeed XIAO RP2040は小さくてピンが少ないけど、Duplex-Matrixを使ったら4x14もキーが使えるので夢が広がりますね😄