スーパーファミコン コントローラーの無線化プロジェクト:コントローラー状態の読み取り



 スーパーファミコンのコントローラーは、本体からP/Sのパルスと、CLKの供給を受けて、そのタイミング事に、ボタンの押している状態を返す。

無線化する際に、本体側のP/Sなりを子機にあたるコントローラー側に無線で飛ばしてやる事も考えられるが、無線の遅延を考えるとあまり得策ではないだろうと考えた。

基本ボタンの状態だけを本体側は受信して、本体クロックにあわせて、本体にDATの信号を返すで動かす。完全に非同期。1秒に60回、16.6msec、本来の入力状態から遅延する事が考えられるが、m秒を争うゲームをする訳でもないので。

コントローラー(ゲームパッド)に向かって、本体からではなく、マイコンで生成したP/SとCLKの偽物データを送りつけて状態を読みとることをテストとして行う。

とは言え、16.6ms間隔でデータを生成したいので、これだけはTimerを使って時間をできるだけ正確にとることにする。

ESP8266TimerInterruptと先人の方々らライブラリーを用意してくれているのありがたく使う。
#include "ESP8266TimerInterrupt.h"

#define PS_PIN 4  //D1
#define DAT_PIN 14   //D5
#define CLK_PIN 5 //D2

ESP8266Timer ITimer;
void timertask() {
  int status=0b0;
    digitalWrite(PS_PIN, HIGH);
    delayMicroseconds(12);
    digitalWrite(PS_PIN, LOW);
    delayMicroseconds(6);
    for (int i=0;i<16;i++){
    digitalWrite(CLK_PIN, LOW);
    if(digitalRead(DAT_PIN)==LOW){
      bitWrite(status,15-i,0);
    }else{
      bitWrite(status,15-i,1);
    };
    delayMicroseconds(6);
    digitalWrite(CLK_PIN, HIGH);
    delayMicroseconds(6);
    }
    Serial.println(status, BIN);
}
void setup() {
  // put your setup code here, to run once:

  Serial.begin(115200);

  pinMode(PS_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(DAT_PIN, INPUT);
  digitalWrite(PS_PIN, LOW); //normal state of PS pin
  digitalWrite(CLK_PIN, HIGH);  //nomal state of CLK pin
   
  ITimer.attachInterruptInterval(16666, timertask);
}

void loop() {

}


回路の方は、

電源は現時点ではUSBからの給電。5V系は、ESPのVinから供給。
コントローラー側の5本については
茶色:GND(マイコンのGND)
赤色:DAT(レベルコンバーターを介してマイコンのGPIO15へ)
橙色:P/S(レベルコンバーターを介してマイコンのGPIO4へ)
黄色:CLK(レベルコンバーターを介してマイコンのGPIO5へ)
白色:+5V

それぞれをロジアナで観測してみる

  digitalWrite(PS_PIN, HIGH);
    delayMicroseconds(12);
    digitalWrite(PS_PIN, LOW);
でPSを12usecだけHIGHにしにいくが(真ん中のオレンジのライン)、実際は13.75usとやや長い。これきっちり12usecに調整してもよいが、状態を読めればよいので、このまま。
6usecあけてクロックが立ち下がり、それを16回繰り返す。これも本来12usec周期だが、16.125usecと長い。これも調整してもよいがこのまま。
上の例の場合は、”上”キーを押してキャプチャーした場合。しっかりコントローラー内のICはそのタイミングでLOWレベルにしている。

各状態をLOWになるタイミングで読んで16ビットの整数として記憶する。
シリアルポートに16ビットの整数をBIN形式で出力しているので、ファミコンのコントローラーのボタンを各種押すと状態が遷移しているのが確認できる。下の場合は、上キーを押しているので、そのタイミングだけゼロとちゃんと読んでくる。


次は、この2バイトの整数を無線経由でもう一つのESPに送り込む。16.6msec周期なので、その間に、2バイトなら送り込めるはず・・・

 あと、TP4021BPのようなパラシリ変換のICを使っているらしいが、データシート見ると電源電圧が3Vから18Vと記載されているので、今回は5VをICに投入し、レベルコンバーターを利用しているが、全部3.3V系でも動きそう・・・なのでそのチェックはいずれやってみたいと思う。

コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

Attiny85 FuseRest