ESP32でPSコントローラーを読むには

ESP32-devkitcというマイコン開発ボードでプレステのコントローラをファミコンで使うアダプタを作って遊んでいた。
弾を撃つと不意にポーズがかかったりして、出来はいまいちなんだが、開発メモを書いておく。

利用できるライブラリ

ぐぐるといくつか出てくる。

これはPSコントローラを認識できなかった。

そのまま使うと動かない。
ライブラリのソースコードGPSX.cの、GPIOピン番号を適切に変更する。

#define DAT_PIN 27  // CTL1 Data
#define CMD_PIN 13  // CTL2 Command
#define AT1_PIN 26  // CTL6 Attention (PAD1)
#define CLK_PIN 14  // CTL7 Clock

ここでは左の番号がESP32のGPIO、右のCTLxがPSコントローラのピン番号。

どのGPIOピンでも動くが、17〜22ピンは使ってはいけない。(内部で使っている)
また、12ピンはDATピンにはできない。DATにはプルアップ(PSピンとESP32ピンの間に10kΩの抵抗を入れ、Vcc(5V)につなぐ)が必要だが、ESP32は12ピンをプルアップするとBASICが起動してしまう!

digitalWriteを開く

digitalWriteは遅いのでポートレジスタを直接叩いてやる高速化メソッドがある。
これをESP32でやる場合、単純にポートレジスタのアドレスにand,orしてもうまくいかなかった。

fにはHIGH/LOWにあたる1/0が入るとして、

  // digitalWrite(PIN_OUT, f); // 相当のコード
  if (f) {
    GPIO.out_w1ts |= ((uint32_t)1<<PIN_OUT);
  } else {
    GPIO.out_w1tc |= ((uint32_t)1<<PIN_OUT);
  }

IO32〜39ピンなら以下のようになる。

  // digitalWrite(pin, f); // 相当のコード(PIN=32..39)
  if (f) {
    GPIO.out1_w1ts.val = ((uint32_t)1<<(pin - 32));
  } else {
    GPIO.out1_w1tc.val = ((uint32_t)1<<(pin - 32));
  }

esp32-hal-gpio.cの_digitalWriteに全部書いてある。

ファミコンコントローラ信号

GitHub - GOROman/NESBot-mini
ファミコンのコントローラー信号をソフトウェアで作るサンプルを見たのでESP32を使ってみたが、よくよく見るとここではVSyncのタイミングを得るためファミコンのCPUからNMIを取り出している。
PS,CLKピンの割り込みだけでもそこそこ動いたが、先に述べたようにゲームにならない。

結局本物のコントローラーと同じ4021のロジックで信号作るのだったら、PSコンの読み取りはArduinoで済んじゃう。
とするとESP32を用意した意味あんまりなかったが…まあここまで遊べたので良い。
また何かの役に立つ日も来るかも。