石原 博の覚書

電子工作に関する日々の覚書を記載します

Z80-MBC2のIOについて

2021-08-09 16:54:33 | 日記

ブートについて調べたのに引き続き、入出力部分を簡単に整理してみた。(S220618_IOS-LITE-Z80-MBC2.ino)

Z80のINあるいはOUT命令では、メモリ空間とは別のIO空間に対してアクセスする。この時MREQではなくIOREQが有効になる。
そこでIOREQでRSラッチを起動し、WAITをかける。CPUは出力あるいは入力状態で停止するので、その状態のデータバスを読み取る。解除はWAIT_RESでRSラッチを解除する。
(RSラッチは初期状態が不明なため、AVRは初期処理でWAIT_RESをLに、PG LOAD前にはHにしている)

 

気をつけるところは、WAIT解除の部分。以下のようにBUSREQを有効にしてからWAITを解除しその後BUSREQを解除している。Twステートを抜けた後T4ステートになる関係か?
INTERRUPTは現状では使っていないようだ。


WRITE
      // Control bus sequence to exit from a wait state (M I/O write cycle)
      digitalWrite(BUSREQ_, LOW);                 // Request for a DMA
      digitalWrite(WAIT_RES_, LOW);               // Reset WAIT FF exiting from WAIT state
      digitalWrite(WAIT_RES_, HIGH);              // Now Z80 is in DMA, so it's safe set WAIT_RES_ HIGH again
      digitalWrite(BUSREQ_, HIGH);                // Resume Z80 from DMA

READ
        // Control bus sequence to exit from a wait state (M I/O read cycle)
        digitalWrite(BUSREQ_, LOW);               // Request for a DMA
        digitalWrite(WAIT_RES_, LOW);             // Now is safe reset WAIT FF (exiting from WAIT state)
        delayMicroseconds(2);                     // Wait 2us just to be sure that Z80 read the data and go HiZ
        DDRA = 0x00;                              // Configure Z80 data bus D0-D7 (PA0-PA7) as input with pull-up
        PORTA = 0xFF;
        digitalWrite(WAIT_RES_, HIGH);            // Now Z80 is in DMA (HiZ), so it's safe set WAIT_RES_ HIGH again
        digitalWrite(BUSREQ_, HIGH);              // Resume Z80 from DMA

INTERRUPT
        // Control bus sequence to exit from a wait state (M interrupt cycle)
        digitalWrite(BUSREQ_, LOW);               // Request for a DMA
        digitalWrite(WAIT_RES_, LOW);             // Reset WAIT FF exiting from WAIT state
        digitalWrite(WAIT_RES_, HIGH);            // Now Z80 is in DMA, so it's safe set WAIT_RES_ HIGH again
        digitalWrite(BUSREQ_, HIGH);              // Resume Z80 from DMA


void serialEvent()
// Set INT_ to ACTIVE if there are received chars from serial to read and if the interrupt generation is enabled
{
  if ((Serial.available()) && Z80IntEnFlag) digitalWrite(INT_, LOW);
}

void printBinaryByte(byte value)
{
  for (byte mask = 0x80; mask; mask >>= 1)
  {
    Serial.print((mask & value) ? '1' : '0');
  }
}



最新の画像もっと見る

2 コメント

コメント日が  古い順  |   新しい順
Unknown (Norihiro Kumagai)
2022-01-25 14:25:33
WAIT解除後、BUSRQで止めている理由は、止めないと、次のサイクルの先頭までにATmega32Aのデータバス出力が解除できない可能性があるからです。WAIT解除した瞬間にZ80は猛然とサイクルを進めます。Z80がREADサイクルのとき、ATmega32Aはデータバスに出力状態ですが、Z80が次のサイクルをライトサイクルとする場合、ATmega32Aがデータバスを入力モードに切り替えるのが間に合わず、Z80とATmega32Aともにデータバスに出力状態でかち合う可能性があるのです。
BUSRQ入れていったんZ80を止めておき、その間にATmega32Aはデータバスを入力モードに切り替えます。そのあとBUSRQを外してZ80実行を再開することで、次のサイクル開始からデータバスを3-stateにすることができるのです。よく考えられていると思います。
返信する
Unknown (ishihara-h)
2022-01-30 17:02:25
なるほど、良くわかりました。説明ありがとうございます。
返信する

コメントを投稿