スーパーファミコン(SFC/SNES)のコントローラーをUSBに変換するアダプタを作成したのでメモ。 ”最強”についてはあくまで主観です。異論は認める。

なお以前にもArduinoを利用してSNESコントローラーを(XInput)に変換するものを作成して使用していたのですが遅延が多少気になったのとNintendo Switchでも使いたくなったのでそのあたりを解消できるもの作ることにしました。
GP2040-CEにはSNESコントローラー・コンバーター機能がある
Raspberry Pi Pico(およびRP2040搭載の互換マイコン)を多機能・高性能USBゲームコントローラーにするOSSファームウェア GP2040-CEは、SNES(SFC)コントローラーの信号線をGPIOに接続することでコンバーターとして動作する機能を有しています。この機能を利用するとGP2040-CEの機能と性能をフルに近い*1形で享受できる高性能なSNESパッド to USBコンバーターを容易に作成することが可能になります。 ボタンのアサインは固定ですが、ごく直感的なものになっているので基本的に困ることは無いと思います*2。
GP2040-CEのSNESパッドコンバーター機能についてのオフィシャルドキュメントは以下です。 gp2040-ce.info
GP2040-CEが対応している機種は現在のv0.7.11では以下です。つまりは現行のプラットホームでUSB刺さるやつなら大体OK、という感じになります。
- XInput
- DirectInput
- Xbox One(要認証ドングル)
- Xbox 360(要認証ドングル)
- Nintendo Switch
- PS3
- PS4(PS3モードのしてレガシーコントローラーとして or 認証ドングルを使用してPS4 Native)
- PS5(認証ドングルを使用してPS4互換モード)
- NEOGEO mini
- イーグレットツー mini
- アストロシティー mini
- メガドライブmini
- PCエンジンmini
- Playstation Classic
- キーボード エミュレ―ション
任意のキーを割り付けできるキーボードエミュレーションもあるので、PC用のゲームやアプリケーションでゲームコントローラーに対応していないものでも、JoyToKey のようなソフトウェア無しでコントローラーで操作できるようになります。例えば最近だとscratchはゲームパッドに対応していませんが、GP2040-CEのキーボードモードを使用すればscratchで作成したゲームをゲームコントローラーで操作できるようになります。
またGP2040-CEは入力遅延についても現在存在するもののなかでも最低クラスですので*3、少なくともSNESコントローラーコンバーターとしては ”最強” を名乗ってもバチは当たらない筈です。
作ってみた
というわけで作ってみました。
試作1号機
ますは試作1号機(v1.0)です。

これは実は、KiCadでのPCB設計の練習と基板発注のお試し目的で作ったものでもあります。 そのため、機能面ではさほど問題はなかったのですが、下記の不満が残りました。
- 基板のフットプリントが無駄にデカい
- KiCadによる初めてのPCB設計だったので勝手もよくわからず出来上がりなどもうまく想像できてなかった
- OLEDモジュールのピン配列に柔軟性が欠ける
- 実は2台目を実装しようと思ったら手持ちのOLEDがピン配列違うのばかりだった...
- 世の中のI2C OLEDモジュールは案外ピン配列がバラバラっぽい
試作2号機
そこで次に作成したのがこちらの試作2号機(v3.0)です*4。

試作一号機での不満を解消しつつ、GP2040-CE v0.7.11で実装されたMini Menuを有効活用する方向性も狙って作成したものになります。フットプリントのサイズについては二階建てにすることで解消を考えました。OLEDのピン配置についても力技で対応しやすいようにしてみました。
これ以降は、は試作2号機についてのメモとなります。
仕様
ざっくり以下の仕様としました。
- firmware : GP2040-CE v0.7.11
- BOARD : Waveshare RP2040-Zero(互換ボード)
- SNESコントローラー用コネクタを実装
- OLEDを実装
- パススルー認証用USBコネクタを実装
- 以下のボタンをコンバーター基板上に実装
- S2(Startボタン相当/Webコンフィギュレータモード遷移用)
- A1 (Homeボタン、PSボタン相当)
- A2 (Captureボタン、タッチパッド相当)
- L2
- R2
- L3
- R3
- Turbo
- Function (主に他のボタンと組み合わせでOLEDのMiniメニューを操作するホットキーとして使用)
MCU
MCUは実装サイズを重視してWaveshare RP2040-Zeroを利用することにしました*5。

OLED
v0.7.11から搭載されたMini Menuが使えるとモード切り替えなどとても便利なのでOLEDも実装することにしました。部品代として~400円程度で入手できますし。 Mini Menuでは、Web Configを使用することなくコントローラー単体で動作モード(Xinput/PS4/Switch/DirectInput/XBOX/各種miniコンソール等々)の切り替えや十字キーの動作モード(D-PAD,L-Stick,R-Stick)切り替えもできるため利便性が上がります*6。
Mini Menuについてはこちらも参照ください。

試作一号基板で問題になった『OLEDモジュールのピン配列が製品によって一定しない』件に対しては、パターンカットとジャンパで対応し易くしてみました。私の手元にあるものだけでも三パターンありましたし*7、今後もECサイトで買う場合は写真と実際に届くもので配列が違う可能性も否めません(特にAliexpressとかAmazonのマーケットプレースとかだと)。

各種ボタン
SNESパッドには存在しない、現代コンソールゲーム機が通常備えるL2/R2/L3/R3とA1(Home/PS等相当)、A2(CaptureやTachpad等相当)ボタンを基板上に配置しました。

SNESパッドが適するようなゲームにおいて通常のゲーム操作で必要になることはあまりないかもしれませんが、ゲーム外の部分*8などで困る事が予想できるためです。また、前述のMini Menu操作にも使用できるという利点もあります。
S2ボタンは言わゆるStartボタン相当のボタンです。StartボタンはSNESパッド上に存在するのですが、ファームウェアの書き換えやリセットした直後等はSNESパッドがまた使用できない状態でWeb Configuratorに入る際にあると便利なのでえて配置しています*9 。 またこの理由から、firmwareの初期導入直後でもWeb Configモードに容易に入れるようにするためにS2ボタン対するGPIOのピンアサインは規定値のままとしています。
その他のボタンとして、連射機能のOn/Offを切り替えるTurboボタンと他のキーと組み合わせでホットキーを構成することでMini Menuの操作などを行うためのFunctionボタンを配置しています。 Functionキーを利用したホットキーのアサインは別途後述します。
USBコネクタ
パススルー認証用のUSBコネクタも実装しておくことにしました。 XBOXやPS4/5で利用する予定は現状ないのですが、USBコネクタは部品代としては安いので負担になりませんしGPIOも余裕がありまた基板上のスーペースも空いているので…という程度の理由です。将来的に使いたくなる可能性も十分ありますし。

ピンアサイン
想定するGPIOのアサインは以下の通りです。
| GPIO | Assign | GPIO | Assign |
|---|---|---|---|
| 00 | Function | 11 | SNES Data |
| 01 | S2 | 12 | SNES Latch |
| 02 | Turbo | 13 | SNEC Clock |
| 03 | Turbo LED | 14 | A1 |
| 04 | OLED SDA | 15 | A2 |
| 05 | OLED SCL | 16 | (on board RGB LED) |
| 06 | [N/A] | 17-25 | [N/A] |
| 07 | [N/A] | 26 | L3 |
| 08 | R2 | 27 | R3 |
| 09 | L2 | 28 | USB D+ |
| 10 | [N/A] | 29 | USB D- |
RP2040-ZEROではGP16はオンボードのRGB LEDに接続されているので今回使用しません。 またGP17~25は裏面の小さなパッドでアクセスできますが今回は足りていることもあって使用しません。
なおUSBコネクタへの配線ですが、詳細は後述しますが少なくとも現時点のv0.7.11とRP2040-ZEROの組み合わせでは、 GP28 -> D-、GP29 -> D+ の組み合わせは設定できませんでした。留意が必要かと思います。
GP2040-CE Configuration
GP2040-CE のWeb Configurationで設定した内容のメモです。
- RP2040-ZERO用のfirmwareを書き込んだあと、'S2'でWeb Configuratorモードに入って設定
- 各ページで都度都度
Saveすること(重要)
Pin Mapping
- ピンアサイン通りにマッピングする
- SFCコントローラー関連、USB関連、OLED関連、TURBO LEDは別のところで設定する
Peripheral Mapping
- I2C0を有効、SDAを
4SCLを5に設定 - USBを有効、D+を
28に設定(Pin Orderは規定値のまま)
Display Configuration
- Enabledに設定
Add-Ons Configuration : Turbo
- Enabledに設定
- Trubo Led Pin を
03に
SNES Input
- Enabledに設定
- Clock Pin :
13 - Latch Pin :
12 - Data Pin :
11
Settings : Hotkey Settings
- 既存の設定を全削除
- 以下の表のとおりの設定
| キー | 機能 | 意味 |
|---|---|---|
| Fn + S2 | Mini Menu Toggle | OLEDでMini Menuを表示 |
| Fn + R2 | Mini Menu Up | Mini Menuで上キー操作 |
| Fn + R3 | Mini Menu Down | Mini Menuで下キー操作 |
| Fn + L2 | Mini Menu Right | Mini Menuで右キー操作 |
| Fn + L3 | Mini Menu Left | Mini Menuで左キー操作 |
| Fn + A1 | Mini Menu Select | Mini Menuで選択操作 |
| Fn + A2 | Mini Menu Back | Mini Menuで戻る操作 |
Settings : Input Mode Settings : Additional PS4 Settings
- Input Mode Settings で
Current ModeにPS4を選択 - Authentication Settings で
USB HOSTを選択 Saveすること
Settings : Input Mode Settings : Additional PS5 Settings
- Input Mode Settings で
Current ModeにPS5を選択 - Authentication Settings で
USB HOSTを選択 Saveすること
PCBの設計と実装
基板は、マイコン基板・SFCコントローラーコネクタ・OLED・ボタン類をなるべく無駄なく最小のフットプリントにするために、基板を二階建てにすることにしました。 二枚の基板をスペーサーを挟んでビスで固定する方式です。
ただしOLEDや追加ボタンが不要な場合や、それらをこれらを別途ケースに取り付けて配置して利用するような組み込み方も考ええ、
- 1枚目(下段):MCUとSNESコントローラーコネクタ、USBコネクタを1階に配置
- 2枚目(上代):ボタン類とOLED、ターボLED
として下段だけでも機能する設計にしました。 (ケースにボタンやOLEDを組み込む場合はピンヘッダからそれぞれに必要な配線は取れる)
また1枚のみで使用する場合、Turbo用のLEDインジケータとしてRP2040-ZEROのオンボードLEDを利用するのもありかもしれません*10。
P2040-ZEROを実装するパターンは、ピンヘッダ等の足無しで直接基板にはんだ付けできるよう設計しました。単純な長方形以外のPCBを発注してみるテストも兼ねて。
OLEDの項でも書きましたが、上段のOLEDの配線はパターンカットとジャンパで色んな配列に対応できるようにしています。
PCBの設計はKiCad 9を使用しました。 製造はJLCPCBを利用しました。KiCadにJLCPCB用のアドオンを入れると必要な出力を勝手に生成してくれるのですごく楽ですね。
また初回限定クーポンなどもあったので、おそらく今回に限ってになるとは思いますがすごく安く発注出来ました。 レジストの色は無駄に紫とか選んでみましたが、なかなかいい色で気に入っています。
使用部品
以前購入して在庫している手持ちの部品の利用がおおいので、正確ではないですが概ね以下です。
- MCU:Waveshare RP2040-Zero互換ボード(Aliexpressで以前まとめて購入。1枚あたり換算すると250円程度?)
- OLED:128*96 I2C OLED(Aliexpressで以前まとめて購入。1枚あたり換算すると250円程度?)
- SFCコントローラーコネクタ:(Aliexpressで購入。200円程度)
- USB TYPE-A雌コネクタ:(秋月電子で購入。5075AR-04-WH、1個50円)
- タクトスイッチ:6mm*6mm(秋月電子で以前購入。ボタン部分が直径4mmくらいで長さが10mmくらいのやつ。30円くらい?)
- LED(Turbo用):3.3v前後で動作する適当なLED
- 抵抗(Turbo用LED保護抵抗):LEDに合わせて適当に
- スペーサーとビス類:適当に手持ちのもの
- ケーブル:14芯フラットケーブル 10cm、2*7ピンのメスヘッダ圧着済み(1本150円程度?)
- 保護用アクリル板:3mm厚のものをカット販売しているサイトに発注
仕上げとして保護目的で3mm厚の透明アクリルで挟んでみました。 アクリルは穴あけを頼むとそこそこコストが上がるので(穴一個につき100円とかになることも)、今回は自分であけました。地味に面倒でしたし適当にやったので精度が微妙ですが、まあ自分で使うためのDIYだし問題ない範囲に仕上がったと思っています。
反省点
全体的にPCB設計のノウハウが無さ過ぎるので、わかってる人から見るとおそらくよくない実装になっているのでないかと思います。が、そもそもユニバーサル基板で雑に実装しても実用上全く支障がないようなレベルの回路ですし、とりあえず気にしないことにします。趣味の自作ですし。
ただそんな中でも2点だけ、もう少し考えればよかった&実験してから決めればよかったな……となった点があります。
反省点その1
USBパススルー端子のアサインにfirmwareの制限?問題?があり*11、予定していたアサインにできない という事象が発生しました。
実はPCBの設計時点では、USB端子のD+をGP29、D-をGP28に振る設計にしていました。

所が実際にそのように設定してみると、firmwareがフリーズすることがわかりました。いくつか実験をしてみましたがどうも解消しそうにないので、基板をパターンカットしてGP28をD+にGP29をD-にジャンパで配線しなおすことで対応することにしました。

反省点その2
上側の基板上の、基板と基板を接続するためのケーブルを配線がちょっと面倒でした。 手癖でなんとなく2.54mmのピンヘッダ用のフットプリントを適用したのですが、接続に市販の2*4の14ピンコネクタが圧着されたフラットケーブルを使用するであれば1mmピッチにしておいた方が多少配線が楽だったように思います。
もしくは、フレキで接続するように両端ともフレキ用のコネクタにするべきだったかもしれません。 これについては次回なにか作るときに活かせられるといいなと思ってます。
雑感
使用感は最高で、自分の中では決定版と言えるSNES to USBコンバーターが出来上がったと思っています(自画自賛)。 アスキーグリップを使用して、左手でゲーム操作&右手でマッピング のスタイルでダンジョンRPGのプレイも大変捗ります。最高。

*1:SNESパッド上のボタンがHOTKEYに使用できないとかOLEDの表示に一部対応していない等細かいところはあるものの実用上問題はないレベル
*2:どうしてもアサインを変更したい場合はソースコードを修正して自分でビルドする方法もある
*3:https://github.com/OpenStickCommunity/GP2040-CE?tab=readme-ov-file#performance
*4:v2.0は机上の設計案の時点で没になりv3.0に移行したためこの世に試作機は存在してません
*5:実際には手元にダブついていた互換ボードを使用
*6:正直なところショートカットを覚えてられないというのもある
*7:左から『VCC/GND/SCL/SDA』と『GND/VCC/SCL/SDA』と『GND/VCC/SDA/SCL』があった
*8:例えばNitendo Switchの場合Homeボタンが無いとゲームを終了し難いです。
*9:ジャンパ線などでショートさせるなど他にもやりようはありますが
*10:RP2040-ZEROのオンボードLEDはRGB LEDだが、v0.7.11以降ではTurbo LEDとしてRGB LEDも使用できるようになっている
*11:一応githubにissueを作成しましたが現時点ではレスポンスなどないので詳細は不明