ErgoDox BT の設計・実装に試行錯誤した話あらため試行錯誤している話

__大変申し訳ありませんが、ErgoDox 無線化は 2016/12/25 現在未完成です。現在までの検討事項と進捗をまとめた記事になります。ご了承ください。__

しかも遅刻してごめんなさい。

# この記事が扱う内容

- ErgoDox の設計解析
- ErgoDox の無線化設計
- BLE nano の開発環境構築(RAM 32 kb 対応)

# ErgoDox を持ち歩きたい

ErgoDox を利用し始めると「外でも ErgoDox 使いたいな…」と感じるのは必定かと思います。思ってください。

しかし、ErgoDox を持ち運ぶにはいくつかの関門があります。

1. でかい・おもい
1. ノート PC or Tablet に有線でつなぎたくない

でかい・おもい については、[変わり種ErgoDox紹介 + IME話](http://qiita.com/miyaoka/items/e3f7242b4767cd599364#%E3%83%9F%E3%83%8B%E3%83%9E%E3%83%AB%E5%8C%96--%E8%A6%AA%E6%8C%87mod) でも触れられている通り、小型化・軽量化されたカスタマイズモデルを買う、__自分でつくる__ 等のアプローチが考えられますが、ちょっと難易度とお財布への負担が激しすぎるので、ここでは __我慢する__ という解決策で行きたいと思います。

実際 ErgoDox は __高々 1 kg 程度しかない__ ので、この問題は瑣末であるといえます。

ということで、2. の ErgoDox をノート PC or Tablet に有線でつなぎたくない にフォーカスして問題を解決していきたいと思います。

# ErgoDox を無線化

一回無線接続キーボードに慣れてしまうと、いちいち有線で接続するなんてやってられなくなります。そういった小さな不満で ErgoDox を持ち歩かないのはもったいないので、ErgoDox の無線化について検討していきます。

## 無線化に必要な技術

普通に考えれば、身近な周辺デバイス系の無線接続形式は Bluetooth 一択かと思います。Bluetooth でも、BLE と呼ばれる Bluetooth 4.0 以降のデバイスと、BR/EDR という Bluetooth 3 系以前で大きく別れます。

今回は

- 技適通ってる
- 消費電力が非常に少ない
- 入手性がよく、開発が容易
- ~~新しいものに触りたい~~

という理由で、Bluetooth LE の [BLE nano](http://redbearlab.com/blenano/) を採用しました。

## BLE nano とは

ARM-M0 コアを採用し、BLE モジュールを内包した Nordic NRF51822 を使用した mbed 開発ボードです。mbed についての詳しい解説については他の記事に譲りますが、AVR の Arduino のような組み込み開発がお手軽にできるボードの ARM 版です。

500 円玉より小さいぐらいの大きさで mbed オンラインコンパイラでお手軽に BLE 開発ができ、お値段も 2700 円程度と安価、その上技適取得済みということでいい事ずくめですね。インターフェースとしては、GPIO/シリアル通信(UART)/I2C-master/ADC/PWM と、だいたい乗ってる感じです。

これを前提に ErgoDox の設計を紐解いて、無線化の検討をしていきます。

## ErgoDox の設計解析と無線化設計

ErgoDox の無線化設計をする前に、そもそも ErgoDox の設計を知る必要があります。ErgoDox を構成するモジュールと ErgoDox のメジャーなファームウェア [qmk_firmware](https://github.com/jackhumbert/qmk_firmware) について確認していきます。

### ErgoDox の構成モジュール

ErgoDox のモジュール概略図を以下に示します。

![rect4346.png](https://qiita-image-store.s3.amazonaws.com/0/77727/c35cd3ac-d0ae-4919-c293-4268df624418.png)

ErgoDox をつくると必ずお世話になるあのオーディオケーブルっぽいアレ(TRRS)は、4線で I2C のためだったんですね。Teensy が MCP23018 を I2C 経由で制御して、それぞれ比較的高速な周期でそれぞれ左右の手のキーマトリックスを走査しています。

I2C はチップ間インターコネクト用のバス規格で、オープンドレインであり、I2C の親(Master)に対して、複数の子(Slave)を同一線に接続することができます。そのため今回の目論見は以下のような設計で達成できそうです。

![描画2.png](https://qiita-image-store.s3.amazonaws.com/0/77727/f97d27fa-f131-b415-f472-f4f809f89910.png)

突然現れた Attiny85 は、BLE nano が I2C の Slave に直接なれないことに起因しています…厳しい…

何はともあれ、これで無線化は実現できそうです。

### qmk_firmware

続いてはファームウェアを見ていきます。ものすごく端折りますが、qmk_firmware は tmk_core というプロジェクト・ライブラリに依存しており、この tmk_core は大きく分けて、ハードウェアを抽象化するドライバ層と、抽象的なキーマトリックス走査・キーコード変換を行う層に別れています。

今回は、このドライバ層を改造して、通信相手を USB ではなく、I2C の先につながれた BLE nano にすることで最小限の変更で無線化できそうです。

## 実装

さて、実現可能そうなことがわかったので早速実装していくのですが、ここからが本当の地獄だ…

やりたいことは以下の 4 つです。

- BLE nano を BLE host(PC等) から無線キーボードとして認識させる
- BLE nano でシリアルから送られてくるキーを送信する
- Attiny85 で I2C から Serial に載せ替える
- qmk_firmware のドライバを改造して I2C にキーコードを送らせる

### BLE nano を BLE host(PC等) から無線キーボードとして認識させる

まず、BLE nano を無線キーボードとして認識してもらわなければいけません。BLE での無線キーボードは、HID-over-GATT プロファイルとして規定されており、BLE nano にこのプロファイルを実装すればとりあえず認識はしてくれるはずです。

#### BLE nano を mbed オンラインコンパイラで実装する(失敗)

前述の通り、BLE nano は mbed コンパチな開発ボードのため、手元で開発環境を用意しなくても mbed 公式サイトのオンラインコンパイラで簡単に開発を始めることができます。また、ドキュメントも豊富で、ARM mbed による高度なハードウェアの抽象化も魅力です。

ただ、mbed オンラインコンパイラの BLE nano は初期リビジョンの RAM 16 kb のメモリマップのままになっており、実装メモリが 32 kb あるにも関わらず、16 kb しかアクセスできません…

そのため、すぐにメモリが枯渇し、パニックになるかヒープにメモリが確保できずに停止します。しばらく頑張ってみましたが、あまりにも厳しく、せっかく 32 kb の RAM があるのに苦労するのもアレで断念しました…

#### BLE nano を Arduino で開発する(失敗)

実は、BLE nano は Arduino としても振る舞うことができるようになっており、Arduino の開発環境が利用できます。しかも、Arduino では BLE nano の RAM 32 kb にも対応しており、実装メモリをフル活用できます。

ただ、Arduino の BLE nano 向けのライブラリが 2 年前から更新されておらず、セキュリティ関連の API も未実装だったため、こちらも断念となりました…

#### BLE nano を mbed として GCC でローカルビルドする

前述の通り、mbed オンラインコンパイラでは BLE の最新のライブラリが使えるものの、RAM が 16 kb しか使えず宝の持ち腐れでした。

一方、Arduino だと RAM は 32 kb 使えるものの、BLE 関連ライブラリが古く、実用には厳しい状態でした。

そこで、両者の折衷案が、mbed の スタックに乗りつつローカルで gcc を使ってビルドする方法です。この方法では mbed オンラインコンパイラの手軽さは失うものの、mbed のハードウェア抽象化の恩恵を受けつつ、よりカスタマイズしたビルドを行うことが出来ます。当然、メモリマップも書き換え放題です！

1. GCC のインストール
[GCC ARM](https://launchpad.net/gcc-arm-embedded) から取得します。
インストールディレクトリにパスを通すようにしておいてください。
※Windows のインストーラであれば、最後のパスを通すオプションにチェックをつけると楽です。

1. make のインストール
Linux のひとは適当に。Windows の人は [GNU MAKE](https://sourceforge.net/projects/gnuwin32/files/make/3.81/) から ```make-3.81-bin.zip``` と ```make-3.81-dep.zip``` ダウンロードして展開して、中身のバイナリを適当にパスの通ったところに展開します。(前述の GCC のインストールパスとかに置いちゃうと楽)

1. SRecord のインストール
make でバイナリ操作のために [SRecord](http://srecord.sourceforge.net/) をダウンロードしてパス通ってるところに展開。

1. mbed から GCC ARM Embedded プロジェクトのエクスポート
mbed オンラインコンパイラから GCC ARM 用にエクスポートします。
<img width="956" alt="export.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/77727/50eda746-edd2-24a2-4392-88a59eb5961a.jpeg">

1. リンカのスクリプトを修正して RAM を 32 kb 使えるようにする
```<Project root>/mbed/TARGET_RBLAB_BLENANO/TOOLCHAIN_GCC_ARM/NRF51822.ld``` を適当なテキストエディタで編集します。
一番最初のセクションの MEMORY の RAM の LENGTH を修正します。

```
MEMORY
{
  FLASH (rx) : ORIGIN = 0x0001C000, LENGTH = 0x24000
  RAM (rwx) :  ORIGIN = 0x20002800, LENGTH = 0x5800 // ここを 1800 から 5800 に修正
}
```

これで、0x2800 + 0x5800 = 0x8000 で 32 kb の RAM をフル活用できます。

あとは、ターミナルで root ディレクトリに移動して make すれば BLE nano を mbed として 32 kb RAM フル活用でローカル GCC ビルドが出来ます！

とりあえず、mbed の BLE API を使って、BLE nano を HID-over-GATT Profile デバイスとして[認識させることは出来ました](https://github.com/Biacco42/BLE_nano_BT_HID)。

詳細はリポジトリのソースを読んで下さい…(力尽きた)

# ErgoDox を持ち歩く

とりあえず有線での持ち歩きを実践してみました。

![P_20161105_173001.jpg](https://qiita-image-store.s3.amazonaws.com/0/77727/2bf296e5-ea96-f565-68b3-065636d45cc4.jpeg)

- めっちゃ重い
- めっちゃでかい(意外と大きくてカバンに入らない)
- めっちゃ机のスペースをつかう
- でも体験はよい

でした。でかいカバン必須です。

# おまけ - DCS or DSA -
上記の写真の通り ErgoDox EZ の無刻印は DCS なんですが、家用の Falbatech の方は DSA で、比較してみたところ個人的には DSA おすすめです。

![IMG_20161221_122834100.jpg](https://qiita-image-store.s3.amazonaws.com/0/77727/8a7dcfb2-7133-9667-0ed2-ac2fee3de823.jpeg)
_こうなった_

おしまい