スーパーファミコン コントローラーの無線化プロジェクト:2ch化(コントローラー側)

 これまで、コントローラーは一つまでだったので、2つへの対応。

ここで重要な情報は、”スーパーファミコンのコントローラーに入っているシフトレジスタのICは3Vでも動く!”ってこと。

以前は、ケーブルを切断したものを利用していたが、今回はメスのコネクターを入手。

QIコネクタのメスのプラスチックの部分をはずして、少しづつ押し込むとジャストフィット。半田してもよいですが、テスト段階でこれで。

【回路図】

電源回りの回路を組んで、ESP-WROOM-O2でLチカするところまで作っていたので、コントローラーを2つ接続。

https://funasover.blogspot.com/2025/05/2.html

で1コン、2コンともにクロック、P/Sの信号は同タイミングで入ってくる事がわかっているので、単に分配して供給。DAT1とDAT2をそれぞれ、IO14とIO4に入れて押されたボタンの状態を読み取る。


ここでポイントは、コントローラー内部のICにSFC本体からは5Vが本来供給されているので、当初(これまでも)は、レベルコンバーターを入れて、5V系に変換して供給を計画。

そのため、昇圧回路も用意していた。(https://funasover.blogspot.com/2025/05/34v5vme2108a50pg.html

ところが、このIC、3Vでも動くのです!!!!昇圧回路のICを中国大陸から入手してテストしてという時間が無駄に(勉強にはなったのでどこかで必要になったら使えるが)

前々から、気にはなっていた・・・初期型は、W545 12pin 2個使用、中期型、V520 20pin、後期型はV520B 20pinが使われている。V520データシートが見つけられないが、互換があると言われているファミコンのICの一つTC4021は今でもデータシートを参照できる。これ眺めているとVDDってVSS-0.5~VSS+20Vと記載されている。ってことは3Vでも動くのでは・・・とは思っていた。


https://qiita.com/fukufukusonreiz/items/b66000aabc227becf1c2

とか見ると5Vに昇圧しているので、昇圧しなければならない・・・と思い込んでしまっていた。昇圧回路まで含めた回路を作って、ひょっとして動くのではと試したら動いた。

昇圧回路がブレッドボードに形成してあるが、不要。またこれもテスト段階ではレベルシフタを入れていたが、それもとっぱらった。
ESP-WROOMの電源回りとESP-WROOMだけでよい事になる。
実際のブレッドボートに実装したのがこんな感じ。あいかわらずごっちゃっとしているが、これでも随分すっきりと。WROOM-02のENピンのコンデンサー0.1uFとプルアップの10kの抵抗、IO2のプルアップ、IO15のプルダウン、これらを表面実装部品で、変換基板に直接半田してしまった。将来的にピンの数がどうしても必要で、IO2,IO15をどうしても必要な時にははずすしてテストする事として、いままでそこまで使った事が結局ないので。

【スケッチ】

#include <ESP8266WiFi.h>  // WiFih>
#include <WiFiUdp.h>
#include "ESP8266TimerInterrupt.h"

const char ssid[] = "esp8266";   // SSID
const char pass[] = "12345678";  // password

static WiFiUDP wifiUdp;  //create UDP instance

// IP address to send UDP data to.
// it can be ip address of the server or
static const char *kRemoteIpadr = "192.168.4.1";
static const int kRmoteUdpPort = 5000;

#define PS_PIN 12
#define CLK_PIN 13
#define DAT_PIN1 14
#define DAT_PIN2 4

ESP8266Timer ITimer;

uint16_t status1 = 0b0;
uint16_t status2 = 0b0;

bool wifi_sleeping = false;

void timertask() {
  String D_DATA;

  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_PIN1) == LOW) {
      bitWrite(status1, 15 - i, 0);
    } else {
      bitWrite(status1, 15 - i, 1);
    };
    if (digitalRead(DAT_PIN2) == LOW) {
      bitWrite(status2, 15 - i, 0);
    } else {
      bitWrite(status2, 15 - i, 1);
    };
    delayMicroseconds(6);
    digitalWrite(CLK_PIN, HIGH);
    delayMicroseconds(6);
  }
  D_DATA = String(status1)+String(status2);
  wifiUdp.beginPacket(kRemoteIpadr, kRmoteUdpPort);
  //wifiUdp.write(String(val,BIN), 16);
  wifiUdp.print(D_DATA);
  wifiUdp.endPacket();
  Serial.print(status1, BIN);
  Serial.print(" ");
  Serial.println(status2, BIN);
}

void setup() {
  static const int kLocalPort = 5000;  //local port

   WiFi.mode(WIFI_STA);
   WiFi.begin(ssid, pass);  //Connect to the WiFi network
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
  wifiUdp.begin(kLocalPort);

  pinMode(PS_PIN, OUTPUT);
  pinMode(CLK_PIN, OUTPUT);
  pinMode(DAT_PIN1, INPUT);
  pinMode(DAT_PIN2, INPUT);
  digitalWrite(PS_PIN, LOW);    //normal state of PS pin
  digitalWrite(CLK_PIN, HIGH);  //nomal state of CLK pin
  Serial.begin(115200);
  Serial.println("");                  // to separate line
    Serial.print("IP address:");
  Serial.println(WiFi.localIP());
  ITimer.attachInterruptInterval(16666, timertask);//16666
}

void loop() {
}

ホスト側は、以前作ったもの
をそのまま利用。スケッチで通信が確立しないと、無限ループに入るので親機は必要。ただこの時点では受け取った文字列を処理していない。

上記のスケッチを動作させて、1コン、2コンの複数のボタンを押す。
のように出力される。左の16個が1コン、右の16個が2コン。押されたボタンに対応するところがゼロに!




コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

CH9329で日本語キーボード109で正しく表示する方法