しまもん 

モンスターラボ島根開発拠点のブログ

[PRK Firmware Advent Calendar 2021] mutual_uart_at_my_own_riskとは何なのか

はすみきん ・2021-12-24

おはようございます。hasumikinです。2021年「PRK Firmware アドベントカレンダー」24日目の朝です。ついにあと2日でアドカレがコンプリートされますね。よくここまでがんばりました。

 

きょうはスプリット型キーボードの左右をつないでいる線について書きます。

本題の前に

QMK Firmwareの「マスター」と「スレーブ」という用語に相当するPRKの用語は、「アンカー」と「パートナー」です。

 

master/slaveの代替語としてcontroller/targetとかhost/deviceとかいろいろあるのはわかります。 しかしどれもピンとこなかったので、ほかでは使われていない言葉のペアを探しました。 2日くらい考えました。 みなさんも同じだと思いますが、名前が決まらないとコードが書けませんよね。

 

最初の有力候補は、ふたり乗りのディンギー・ヨットから着想を得た「スキッパー」と「クルー」でした。 いまでも本当はこれが一番よい言葉だと思っていますが、さすがにskipperは一般に通じなさすぎるだろうから諦めて、anchor/partnerと決めました。

PRKのUART開発経緯

PRKの初期の目標は「マイコンをPro Micro RP2040に差し替えるだけでCrkbdやClaw44を動かす」でした。 そのための要件は、以下のとおりです:

 

  • 信号線が1本で済む通信方式であること
  • アンカーとパートナーはともにGPIOの1番を通信に使用すること

 

なるべくさっさと動くものをつくりたかったので、アンカーをRX(受信)、パートナーをTX(送信)にそれぞれ役割を固定し、RXはRP2040のハードウェアUART、TXはPIOによる(ある種の)ハードウェアUARTとしました。 PIOを使用したのは、GPIOの1番にハードウェアUARTのTXを設定できないというRP2040の制限があるためです。

 

これはわりと簡単に実装できました。 しかし、光らないキーボードなら問題ないのですが、光るキーボードでは問題があります。 「アンカーでどのキーが押されたかを、パートナーに知らせる方法がない」からです。 RGBLEDの点灯モードを変更する :RGB_TOG などのキーがアンカー側にマッピングされていると、点灯モードの変更をパートナーが知る手段がありません。 ではそのキーをパートナー側に設定すればよいかというとそうでもなくて、パートナーは現在のレイヤが何であるかを知ることもできないので、パートナーは自身の「押されたスイッチの位置」しかわからず、「押されたキーコード」はわからない、というのが以前のPRKでした。

そこでMutual UARTですよ

半二重方式というのですが、アンカーがRX/パートナーがTXの状態とアンカーがTX/パートナーがRXの状態を交互に切り替えることによって、1本の信号線で双方向のデータ交換を可能にします。

 

そんなわけで、以前からやってみたかったソフトウェアUARTを組み、あわせて半二重方式を導入しました。 ソフトウェアでRX/TXを交互に切り替え、それぞれのRX動作とTX動作もソフトウェアで制御します。一方がRXのとき他方はTXになっていなければならず、逆も同様です。 GPIOの観点では、入力(RX)/出力(TX)を交互に入れ替えることになります。 この方式の問題は、「ミスると危険」な点です。 仮に以下の状態になったらどうでしょうか:

 

  • 一方のGPIOが出力に設定され、そのピンがオン(3.3V)になる
  • 他方のGPIOも出力に設定され、そのピンがオフ(0V)になる

 

これは危険です。一方から他方に向けて、全力な電流が発生してしまいます。マイコンが煙を上げて昇天してしまうかもしれません。まあ火事にはならないと思います。 実際にはマイコンの保護回路が働くなどしてすぐに壊れたりはしないかもしれませんが、そのような状態がものすごい早さで1秒間に何回もやってくると想像するとマイコンに申し訳ありません。

 

そうはならないように慎重に組んだソースコードはこちらにあります。 問題点を見つけたかたがおられましたらご報告ください。

 

仮にミスっても、信号ラインに直列に100Ωくらいの抵抗器を入れておけば全力電流を防げます。 しかし、既存の分割キーボードに対応したいという条件が必須だったので、抵抗器が入っていることは期待できません。 いまから設計するキーボードなら、直列抵抗を入れておくと安心かもしれません。 100Ωが適切な値かどうかは要テストですが、おそらくQMKにも有効な保護回路になります。

そんなわけですので、

kbd.mutual_uart_at_my_own_risk = true という物騒な書き方を強要しております(ぜひWikiも読んでください)。 筆者の手元のCrkbdはこの設定で1か月くらい電源を入れっぱなしですが、マイコンが壊れる様子はなく、正常に稼働しています。 しかしキーボードには設計上の個体差がありますし、RP2040のマイコンボードにも種類があるので、あらゆる組み合わせが絶対に大丈夫であるとは断言できません。

 

デフォルトの kbd.mutual_uart_at_my_own_risk = false であれば従前どおりの片方向ハードウェアUARTによる通信になります。

 

しかし、通信に使用するピンがRP2040のハードウェアUART(RX)を設定できない設計のキーボード(たとえばErgoDashがそうで、GPIOの3番だそうです)の場合は、物騒設定が必須です。 片方向通信のソフトウェアUARTを実装することも可能ですが、とくにそういうご要望は(∩゚д゚)アーアーきこえなーい


現場からは以上です。 相互に通信するソフトウェアUARTがちゃんと動いているかを、ツイッターでもどこでもいいので教えていただけるとうれしいです。 これに関しては、「動いてない、なんか変」の報告はもちろんのこと、「n日使ってるけど問題なさそう」という報告も助かります! キーボード名もあわせて教えてください。 んじゃまた!

| 採用情報

城下町・松江で一旗揚げたいRailsエンジニア絶賛募集中!

Blue