PC-6001のROMカートリッジをArduino Mega256 R3で読み込む

PC-6001用のROMカートリッジを、Arduino Mega2560 R3で吸い出してみました。

用意するもの

Arduino Mega2560 R3は純正品ではなく安価な互換品を使いましたが問題なく動きました。

ピンヘッダやピンケーブルも何でもOKですが、オスメスを間違えないでください。

工作

ユニバーサル基板にカードエッジコネクタとピンヘッダを並べて、そのまま平行に繋げるようにハンダ付けしていきます。シール基板とかジャンパ線とかなんでもOKです。

十字配線ユニバーサル基板を使って配線をカットする方が楽かもですね(私は使ったことがないのですが)

ピンヘッダケーブルの配線

PC-6001側のピンと、Arduino側のピンを繋いでいきます。

PC-6001エッジコネクタ側端子

ROMカートリッジを立てた状態で真上から見た時の配置です。

  +5V +5V GND GND D7 D5 D3 D1 A5 A3 A1   A12 A7 A11 A9                
PC-6001 エッジコネクタ
          D6 D4 D2 D0 A4 A2 A0 A13 A8 A6 A10               ROM1 ROM2

Arduino Mega2560 R3側端子

番号 PC-6001 Arduino
PORT名
22 A0 PORT-A
23 A1
24 A2
25 A3
26 A4
27 A5
28 A6
29 A7
37 A8 PORT-C
36 A9
35 A10
34 A11
33 A12
32 A13
31  
30  
49 D0 PORT-L
48 D1
47 D2
46 D3
45 D4
44 D5
43 D6
42 D7
2 ROM1  
3 ROM2  
GND GND  
+5V +5V  

Arudiono側コード

ArduinoのIDEを使ってコードをコンパイル&書き込みします。通信速度は57600bpsにしていますが、PC側と速度が合っていれば115200bpsに書き換えてもOKです。


//
// PC-6001 ROM Cart Reader
//

const int PIN_ROM1  = 2;
const int PIN_ROM2  = 3;

word ReadAddr;
const int START_ADDR      = 0x0000;
const int END_CHECK_ADDR  = 0x2000;

void setup()
{
	// all output(Address Bus Lower, A0-A7)
	DDRA = B11111111;
	PORTA = B00000000;
	// all output(Address Bus Higher, A8-A14)
	DDRC = B11111111;
	PORTC = B00000000;
	// all input(Data Bus, D0-D7)
	DDRL = B00000000;

	pinMode(PIN_ROM1, OUTPUT);
	pinMode(PIN_ROM2, OUTPUT);
	digitalWrite(PIN_ROM1, HIGH);
	digitalWrite(PIN_ROM2, HIGH);
	
	Serial.begin(57600, SERIAL_8N1);
	Serial.flush();

	ReadAddr = START_ADDR;
	
	//Serial.println( "start loop. wait..." );

	// 開始待ち
	Serial.flush();
	while (true)
	{
		if (Serial.available() > 0)
		{
			int incomingByte = Serial.read();
			Serial.flush();
			delay(100);
			break;
		}
	}
}

void ReadRom(byte PortPin)
{
	while(true)
	{
		PORTA = ReadAddr & 0xff;  // low addr
		PORTC = ReadAddr >> 8;    // high addr
		delayMicroseconds(1);
		
		digitalWrite(PortPin, LOW);
		delayMicroseconds(1);
		
		int v = PINL;
		Serial.write(v);
		
		digitalWrite(PortPin, HIGH);
		
		ReadAddr++;
		if (ReadAddr == END_CHECK_ADDR)
		{
			ReadAddr = START_ADDR;
			break;
		}
	}
}

void loop()
{
	ReadRom(PIN_ROM1);
	ReadRom(PIN_ROM2);
	while(true){}
}	

使い方

PC側からArduinoに何でもいいのでデータを送ると、Arduinoから読み込んだROMの内容を送り返してきます。

(例)PC側通信ソフトにAcknowrichを使った場合

補足説明:Arduino側信号線の意味

Arduinoは一般的に各端子のON/OFFや状態の読込みは1端子単位で行います。アドレスバスが16本ある場合、A0-A15それぞれをON/OFF設定することになるのですが、それだと面倒なので、ArduinoのCPUであるATMEGAのポートを直接コントロールすることで、8本単位で信号を読み書きする事が出来るようになっています。

具体的には、以下のページを参考にしました。(ページ内の表示記述ミスがあるので注意)

Arduino処理速度とメモリー使用改善の策

この表(ポートからみたArduinoのピン番号)によると、8ビット単位で制御できるのは、PA0-7, PB0-7, PC0-7, PL0-7です。PF0-7とPK0-7も使えるのですが、デフォルト設定がアナログ用なので除外します。また、ピン番号の方をみると、ポートPB0-7はピン番号が離れたところにあります(D53,D52,D51,D50,D10,D11,D12,D13)。これは配線する時のミスになりそうですから除外します。

となると、残りはPA0-7, PC0-7, PL0-7で、ちょうどいい感じにアドレスバス16本+データバス8本に割り当てられますね。

補足説明:PC-6001側信号線の意味

ROM1とROM2信号がありますが、これはROMカートリッジ内にROMが2個あり、それぞれを選択するための信号です。Active Lowです。両方を同時にLowにすると良くないことが起きます。

PC-6001メモリマップ

C000-FFFF 内部RAM
8000-BFFF 外部RAM
6000-7FFF 外部ROM2
4000-5FFF 外部ROM1
0000-3FFF BASIC ROM

Z80からROMにアクセスする時は、MREQ、RD、アドレスバスといったZ80の信号をやりくりする必要があるのですが、PC-6001は内部の回路で外部ROM選択用の信号を生成していて、それが拡張コネクタに出ています。ただし、この信号に対応していないROMカートリッジの場合は、この信号を使うことは出来ません。PC-6001mkII以降専用のROMカートリッジが該当すると思われます(未確認)。そのようなカートリッジの場合は、MREQやRD信号を使ってROMにアクセスすることになります。(下図参照)

  +5V +5V GND GND D7 D5 D3 D1 A5 A3 A1 A14 A12 A7 A11 A9                
PC-6001 エッジコネクタ
          D6 D4 D2 D0 A4 A2 A0 A13 A8 A6 A10 A15   RD MREQ       ROM1 ROM2