スーパーファミコン コントローラーの無線化プロジェクト:attachinterrupt後のバラつき問題


スーパーファミコン コントローラーの無線化プロジェクトの続き
(今回で結論として今のアプローチでは無線化は形の上では動かせた(ドンキーコングの1面がクリアできるぐらい)。しかし、バグ(時折Bボタンが押されてしまう)が取り切れないとないという結論。)


デジアナでキャプチャーした二つを見比べる。比べるのは、赤のESPで生成しているDAT信号。テストで101010.....と送っているが、立ち上がり開始時間が異なる!
アルゴリズム的には、P/Sのパルスが入ってくるのを検出、その検出を基準にして、SFC側にコントローラーの信号をESPで生成して送り込むという事で対処してきた。

ほとんどの場合、2.5usecぐらいP/Sから遅れてDATのデータが始まる。以前のテストは5usecだったが、今回、ESPのCPUのクロックを80MHzから160MHzに処理速度をあげて.2.5usecの検出時間を得ている

上のグラフの二つを見比べると、最初のパルスの開始時期が異なる。

ただこのP/Sの立ち上がり検出して、DATをHIGHにするまでの時間がばらつく。

上の場合14.5usecになっている。数usecとかなら、吸収できるが、14.5usecはCLKの周期の12usecより長く意図した動作にならない!

毎回14.5usecなら修正のやりようもあるが・・・・10usecだったりと、それもランダムに事象が起こる・・

【対処】

Bボタンの所だけどうしても他より長い処理をするので、if文で最初なら・・・と条件分岐していた。他のelse以降は、12usecで一定に出力できるのに、立ち上がりにあわせて異なるではないか!!という事から・・・

まずは最初作ったソース

void onRising() {
  noInterrupts();
  //B Y SELECT  START 上 下 左 右 A X L R HHH
  button_status = 0b1010101010101011; //ボタンが押されていたら1

  for (int j = 0; j < 16; j++) {
    if (bitRead(button_status, 15 - j) == 0B00) {
      digitalWrite(DAT_OUTPIN, LOW);
    } else {
      digitalWrite(DAT_OUTPIN, HIGH);
    }
     if (i == 0) {
      delayMicroseconds(20);
      for (int i = 0; i < 24; i++) { asm("nop \n"); };  // i<10 0.65usec
     } else {
      delayMicroseconds(11);
      for (int i = 0; i < 13; i++) { asm("nop \n"); };  // i<10 0.65usec
   }
  }
  digitalWrite(DAT_OUTPIN, LOW);
  interrupts();
}

このOnRisingのイベントハンドラーの関数を以下のように書き換え。

void onRising() {
  noInterrupts();
  //B Y SELECT  START 上 下 左 右 A X L R HHH
  //button_status = 0b1010101010101011; // for test

  delayMicroseconds(7);
  for (int j = 0; j < 16; j++) {
    WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + (8 - 4 * (bitRead(button_status, 15 - j))), DAT_OUTPIN_BIT);

    delayMicroseconds(11);
    for (int i = 0; i < 13; i++) { asm("nop \n"); };  // i<10 0.65usec
  }
  digitalWrite(DAT_OUTPIN, LOW);
  interrupts();
}

①digitalWrite→レジスターに直接書き込みで高速化←実はこれが最終的な決め手ではなかったかもしれないが・・・。

②if文の排除

for文は使うが、if文を排除。最初のBの所は、LOWで時間調整を入れて対処!

通常意図したのがこの下のような状態。PSが立ち下がったらすぐにBボタンが立ち上がる状態。

5回に1回ぐらい遅れて立ちあがる。ただ、すごい遅延する訳ではなくて、5usecぐらい遅れる場合がある。



コメント

このブログの人気の投稿

Attiny85とAQM0802A(LCD)のI2C接続

Attiny85 FuseRest