あぁ、ようやくできたわ
なんか途中で超遠回りしてカーネルをどうにかしようとしてみたりしてたら一週間ぐらい過ぎちゃった気がするよ。
というわけで、簡単に書いておきます
必要なもの
必要ではないもの
- ニンテンドークラシックミニ内蔵LinuxのUARTコンソール
- ニンテンドークラシックミニをFELモードにして動かすためのu-boot.bin
- zImage
- Linuxに関する知識
- っていうかまじで脱線しすぎた
すでにi2cでWiiコントローラと互換だという解析記事が上がっていますが
ここではとにかく、旧ファミコンのコントローラを接続することを目標にします。
まあとりあえず、ミニコントローラを分解して
i2cの部分をちょっともらって解析します。
ZEROPLUSのUSBロジックアナライザ(LAP-C 16128)を使っています。
コントローラのi2cデバイスIDは0x52です。
0x52 Write [ 0xF0 0x55 ]
0x52 Write [ 0xFB 0x00 ]
0x52 Write [ 0xFE 0x03 ]
起動直後に上記パケットの読み書きがありました。
まず前半について検証してみます。
NintendoのOSSソース提供からコントローラ部分を読むと
(#define DATA_FORMAT 3)
まさに、このままでした。さらに、コントローラ情報を読み出し、
DATA_FORMATとして書き込んだ値が反映されているかどうかをチェックしているようです。
その後、一定周期で 00 の書き込み(キースキャン命令なのかな?)が送られ、
その後Read発行で21バイト読み取りを行っています。
21バイトの内容もソースコードにばっちり書いてありました。
クソ楽勝でした。
ちょっと面白いのが以下のコメント
どうやら、8バイトより後のパケットは、i2cバスのノイズ検出として使い、
すべてのビットが0でなかった場合はこの読み取りを無効とする、としているようです。
っていうか、Wii って書いてあるけどなこれ。おもしろい。
さて、何となくプロトコルがわかったので実装します。
手持ちの中で、部品箱で眠っていた Sparkfun Arduino Pro Micro 3.3Vが一番小さかったため採用します。
っていうか、以前に使おうとしていろいろぶっ壊したっぽく、
ArudinoUnoをISP化してファームを書き直して直すとか無駄足を踏んだり。
20年前ぐらいにゴミ捨て場で拾い、アンテナ化改造を施された後長らくしまわれていたオンボロファミコンからコントローラを提供してもらいます。
各ボタンをArduinoにつないで、というのはさすがに間抜けなので、コントローラの信号をちゃんと受け取って変換することにします。
制御ICは、TC4021というシフトレジスタICが乗っていて、旧ファミコンでは5Vが供給されていましたが、データシートを見たところ、ミニファミコンでの3.3Vでも動きそうなため、全体を3.3Vで動かすことができています。
この辺の記事が参考になります。http://www.taylorbooth.com/NESController.htm
また、今回は直接配線を繋ぎましたが、前面拡張端子に繋ぐタイプのコントローラでも行ける気がします。(が、連射パッド系とか、5V必須かもしれないやつは中身によっては動かないかも…)
Arduinoで扱うライブラリがあったのでそれをそのまま使います。
元のケーブルのコネクタを外し、間にArduinoを入れます。
i2c側のプルアップ抵抗は、ミニコントローラでで測ったところ1.8k程度が出てたので、
適当に転がっていた1.6kをつけています。
先端にはマルツで買ってきたコネクタ(JST ZH 1.5mmピッチ)もつけて
一応すぐ戻せるようにしてあります。
大きさの比較
あんまり違和感ないかもしれん。
でも、ミニコントローラは使ってみると明らかに小さくて、結構手が痛くなりますよね。
さて、実際に動かした証拠動画はこちらです。
#ニンテンドークラシックミニ に ファミコンコントローラつながったよ〜 pic.twitter.com/3jbuXOB0UL
— ひろみつ(85.1kg) (@bakueikozo) 2016年11月18日
が、夜中に一人で動かしたんでなんかいまいち伝わらないですねw
でも、まぁつながったな、っていうのはわかるかな。
とりあえず、ちょっと嫁に使ってもらって違和感がないかどうか試してもらいます。