Arduinoにメガドライブのパッドをつなげてみる(改訂版)

前回のスケッチですが、同じ方向を二度連続で押せない(↑↑とか押しても最初の一回しか認識しない)とか、なんか動作が芳しくなかったので、パッド入力 – 魔法使いの森の6502アセンブラのコードをもう一度キチンと読んでから書き直しました。

回路もD0が下位、D5が上位のビットとして読み込むようになっていたのがややこしいので、ちゃんとD0が上位、D5が下位になるようにつなぎ直し。
MDPAD_circuit2
写真だけですが、こんな感じ。DSUBコネクタDIP化基板のオス側は印刷がウソなのでご注意を。

上下左右ABC+STARTで8bitに収まるので、byte型のGAMEPAD変数1個に収めることに。6ボタンに対応したら足りなくなりますが。その時はword型にしますか。

ついでに、前述のサイトでのコードで実行されている「過去16回分の入力をPADHISTに記録」も実装。STARTボタン押下時にシリアルモニタに表示されるようにしました。使い道は今のところありません。
しかし、なんというか、アセンブラのコードを書き慣れている方のコードはスマートですね。見習いたいです。

で、諸々修正後のスケッチはこんな。

// Pins
const byte pinSelect = 8;

// Data
byte PAD_OLD;
byte PADHIST[16];

void setup()
{
  Serial.begin(9600);
  
  // pin2-7 are D0-D5 Input
  DDRD = DDRD | B00000000;
  
  // pin8 is Select OutPut
  pinMode(pinSelect, OUTPUT);
  digitalWrite(pinSelect, HIGH);
  delay(1);
  
  // Input Data Initialize
  PAD_OLD = 0;
  for (int i = 0; i < sizeof(PADHIST); i++){
    PADHIST[i] = 0;
  }
}

void loop()
{
  digitalWrite(pinSelect, LOW);
  delay(1);
  byte GAMEPAD = (((~PIND) >> 2) & B00000011);
  
  digitalWrite(pinSelect, HIGH);
  delay(1);
  GAMEPAD = (((~PIND) & B11111100) | GAMEPAD);

  byte PAD_NEW = ((GAMEPAD ^ PAD_OLD) & GAMEPAD);
  PAD_OLD = GAMEPAD;
  
  if (PAD_NEW != 0)
  {
    debug_print(GAMEPAD);
    for (int i = (sizeof(PADHIST) - 1); i > 0; i--){
      PADHIST[i] = PADHIST[i - 1];
      if (GAMEPAD & 0x01){ // START Button
        Serial.print("PADHIST[");
        Serial.print(i, HEX);
        Serial.print("]>");
        debug_print(PADHIST[i]);
      }
    }
    PADHIST[0] = GAMEPAD;
  }
}

char str[] = "        ";
void debug_print(byte hoge)
{
  str[0] = (hoge & B10000000)? 'U': ' ';
  str[1] = (hoge & B01000000)? 'D': ' ';
  str[2] = (hoge & B00100000)? 'L': ' ';
  str[3] = (hoge & B00010000)? 'R': ' ';
  str[4] = (hoge & B00000010)? 'A': ' ';
  str[5] = (hoge & B00001000)? 'B': ' ';
  str[6] = (hoge & B00000100)? 'C': ' ';
  str[7] = (hoge & B00000001)? 'S': ' ';
  Serial.println(str);
}

古参ゲーマーにはおなじみの例のコマンドを打ち込んでみたところ。
PADHIST
……フルパワーアップも自爆もしませんが。


コメントを残す