PC-6001: November 2008アーカイブ


AVRのプログラマを作り、ブレッドボード上でプログラムできることを確認したので、いよいよ(?)まともにSDカードリーダを作り始めました。

回路図

回路図は以下のようになっています。

20081130-AVR_SD.PNG

SDカードが3.3V動作なので、途中で電圧変換をしなくて済むようにAVRはATmega8Lを使います。きわめて簡単な回路ですね。

一応説明をすると、入力の5Vは48M033Fで3.3Vに降圧しています。 ^A7と^IORQのORを割り込み入力とします。 A6~A3はすべてORをとってPB0に入力しており、I/O空間はA2~A0の3ビット分を予約しています。 PC側からみれば、ポート00~ポート07までを使います。

SDカードとの入出力はmega8Lに搭載されているSPIをそのまま使います。 同時に、ISPにも接続することにより、PC-6001からの電源をもらってプログラムできるようにしてあります。 プログラムを行う際はリセット端子がPCからの入力では都合が悪いので、スイッチをつけています。

ハード実装

手抜き実装で、プルアップ抵抗をまだ入れていませんが、とりあえず実装したものはこんな感じです。 一応この程度でも動くことはブレッドボード上で確認してあります。

20081130-AVRSD-card.jpg

中央下部に空間を空けてあるのは、あとでBIOS ROMを入れることを考えているためです。

簡単なテストプログラムを作って試してみているのですが、今のところPC本体がちゃんと起動しません...。

ロジアナでいろいろ計測するにあたり、初めてPC-6001(初代)をメイン基板が見えるところまでバラしたのですが、以下のICのみがソケットに挿してあるのですね。

  • 8049
  • 2364 x 2 (BIOS ROM)
  • 2332 (キャラクタROM)

ソフトウェアが入っているもの全てです。いざという時の差し替えを考えていたのでしょう。

BIOS ROMはこんな感じ。24ピンのマスクROM(1個8kB)が2個あります。

PC6001_2364.jpg

キャラクタROMと思われる2332。

PC6001_2332.jpg

それで気付いたのですが、BIOS ROMがソケット挿しになっているということは、ここを交換できるということではありませんか!

8kB/24ピンのEPROMはないと思うので、下駄付きで差し替えになるでしょうが、起動をBASICかSDOSかの手動切り替え、とかできるかもしれません。

MEMWRをちょっとアレすれば、RAMも載せられるかも?

まぁ、そこまでやるとカセットポンの簡便性が失われてしまいますが。


PC-6001で垂直同期が取れるのか。

それを調べるため、DMA ON/OFFを繰り返したときにどうなるのか、試してみました。 プログラムは以下のようなものを使いました。 WAITの影響を少なくするため、RAMで動作させます。

	di
loop:
	ld	a, #0x02
	out	(#0x93), a
	call	wait
	ld	a, #0x03
	out	(#0x93), a
	call	wait
	jp	loop	

	;; T-state: 2840(incl. call)
wait:
	ld	hl, #100
wait_loop:
	dec	hl
	ld	a, h
	or	l
	jp	nz, wait_loop
	ret
  

実行の全体像は以下の図のようになります。 記録時間を長くするため、記録周期を粗くしている(1MHz)ので、CLKやM1、WAITは信号ドロップにより不正確です。 気にしないでください。 BUSREQ/BUSACKのみ見てください。

dma1.PNG

この図で、A-B区間は垂直帰線と推測されます。 赤くなっている部分は、H/Lが細かい周期で繰り返されている箇所です。 水平帰線によりH/Lを繰り返しているのでしょう。

dma2.PNG

これは、赤い部分に挟まれた短いHの期間をズームしたものです。 ここはDMA OFFでwaitを実行している部分でしょう。 A-Bの時間(727us)は、DMA OFF時のの論理実行時間(約720us)にきわめて近くなっており、予測は正しそうです。

dma3.PNG

さらに、赤い部分(H/Lが密で、水平帰線を繰り返している部分)のズームです。 本当なら水平線の本数は192本あり、その分のLを繰り返すはずが、ここでは32本分しかありません。 Bの部分でDMA OFFにしているためです。

少なくともここで言えるのは、「ポート0x93のコントロールによるVDGのDMAのON/OFFは垂直帰線に同期しているわけではない」ということです。 残念ながら。

さらに調べると、この計測における一つの水平帰線(BUSACK=L)の時間は40~41usなのですが、DMA ON直後のBUSACK=Lの時間(上図でAから始まるBUSACK=L部分)はそれより短い(21~25usくらい)という結果でした。逆に、DMA OFF直前のBUSACK=Lの時間(上図Bで終わる部分)は41usになっています。垂直帰線によるBUSACK=Hが終わった直後のBUSACK=L(最初の図のBの直後)もおよそ41usです。すなわち、DMA OFFからONにした直後のみDMAが占有する時間が少ないことになります。

これが何を意味するのかはまだよくわかりません。

もう少し考察が必要ですね。また、何か別の方法も考えねば...。

ロジアナが手に入り、CPUの詳細な動作状態がわかるようになったので、動画と音声の同時再生の可能性について検討してみたいと思います。 


計測結果とその妥当性

まず、計測から得られた情報です。 以下は、VDGによる1ライン分のBUSREQ/BUSACKのタイミングを取ったものです。


busack3.PNG
  BUSACK=LBUSACK=H
水平帰線40.16us 22.64us
垂直帰線  4482.32us


BUSACK=Lのときは、MC6847(VDG)からのDMAが動作していて、CPUは完全に停止しています。 多少測定誤差がありますが、Techknowの数値(1ライン=63.5us)とほぼ符合します(図では62.8usと出ています)。 一画面分(192ライン)、1秒60フレームとして逆算すると、

(1,000,000 / 60) - (63.5 x 192) = 4,474.67us
  

となり、垂直帰線の数値もほぼ符合しています。

1画面の描画の間で使える時間は、おおよそですが以下のとおりです。

1水平線: 40us ≒ 160 T-states
1垂直線: 4474.67us ≒ 17870 T-states
1画面分: 40us x 192 + 4474.67us ≒ 48,541 T-states
  

T-stateの計算にクロック(3.993600MHz)を使っています。 丸め誤差が発生していますが、ここではとりあえず置いておきます。


1画面描画にかけられる時間

以上から、1画面にかけられるのはおおよそ48,500 T-statesとなります。 128x96ドットのモードの場合は、VRAMの容量は1,536バイト。 以前ムービープレイヤーを最適化していたときに計算したT-statesの平均値が37,000ほどだったのですが、この数値はWAITを入れていません。 すべて1バイト命令であるという単純な仮定で計算しなおすと、

37,000 x (5 / 4) = 46,250 T-states
    

となり、けっこうぎりぎりです。 ただし、これには2msecのクロック割り込みの時間なども入っています。 圧縮も何も考えずに単に1,536バイトのldirを行うとすると、WAITを考慮して33,787 T-statesです。 セットアップやらいろいろ考えても何とかなりそうですね。

256x192ドットのモードの場合は、VRAMの容量は6,144バイト。 以前のムービープレイヤーでは142,000 T-states (WAIT考慮なし、クロック割り込み時間込み)でした。 WAITを考慮したldirのみの実行時間でも135,163 T-statesです。 話になりません。


もっとも、これは秒間60フレームの描画を前提にした計算ですから、以前のように秒間15フレームにすれば4倍の時間、およそ185,000 T-statesかけられるということです。 処理のタイミング合わせは複雑になりそうですが。 128x96ドットなら音声も含めて再生が期待できそうです。


水平帰線期間中の処理の可能性

水平帰線期間中に1ライン分描画できるでしょうか。

128x96ドットのモードを使うとすると、縦1ドットに対して2水平線分の時間を割くことができますから、320 T-statesとなります。 これなら128ドット分(16bytes)の転送と音声の発声が何とかなるかもしれません。

ちなみに、256x192ドットのモードだと、160 T-statesで256ドット分(32 bytes)の転送となり、画像だけで5 T-state/byteしかかけられません。 M1ステート時のWAITを考慮すると、転送系最速のpush/popを使っても12/11 T-statesかかるため、この時点でアウトです。

ただ、PC-6001の場合は垂直帰線時間で描画しても問題ないので、それほど深刻ではないかもしれません。


問題点

さて、ここで以下の問題があります。

  1. RAM空間ではM1ステートで1クロックのウェイトが入ります(調査の結果、ROM空間ではアクセスのたびに1クロックWAITが入ります)。 また、CB/DD/ED/FD prefixを持つ命令や、IN/OUT系ではさらにそれぞれ1クロックづつWAITが入ります。 これらを考慮して設計する必要があります。
  2. VDPが画面を描画中のときは、CPUがVRAMにアクセスしたら停止するわけではなく、完全停止です。 そのため、MC6847が描画中に表示データのセットアップをすることができません。
  3. 垂直・水平帰線期間中であることを検出する術がありません。 特に垂直帰線時に行う処理のタイミングが計れないので、致命的かもしれません。

以上は通常、他機種では問題の出ない部分でしょう。 例えば、MZ-700では上記の2, 3を活用しています。

3.を何とかすることはできるのでしょうかね? BUSACKは拡張ポートにも出ていないため、信号変化をトリガーに割り込みをかけるのも、本体に手を入れない限り難しそうです。


これまで、VDGのタイミングが全くわからなかったため、盲目状態で行っていたタイミング計算がだいぶ正確に把握できるようになってきました。ロジアナって便利ですね...。

ただ、タイミングあわせについてはもう少し調査が必要です...。


カメレオンUSBのロジアナを買ったので、さっそくWAIT信号について調査しました。

用意したプローブ(=ただのICピン)が足りず、アドレス線は10ビットしか取れていませんが、どこを実行しているかはわかります。

計測したのは、起動後に"How Many Pages?"と表示され、入力待ちになっている状態です。ROM内を実行していることになります。 

0xfbf-call.png

この画面で青い線で区切られたA-Bの区間は、0x0fbfを実行しています(ADは10ビットのみ表示されていることに注意)。 この部分のアセンブリ表現は次のようになります。

0FBF CDFF0F    CALL    $0FFF

すなわち、3バイト命令のCALLを実行していて、M1ステートの0xfbfで2回、 続く0xfc0, 0xfc1の読み込みでそれぞれ2回ずつWAITが入っていることがわかります。 そして次の命令が0x0fffから始まっていることが読み取れます。

もう少し詳しくアドレス線を読み解くと、まず0xfbf(0x3bf)からオペコードを読込み、次にリフレッシュアドレス0x45(0x245)を送出します。M2サイクルでは0xfc0(0x3c0)、M3サイクルで0xfc1(0x3c1)からそれぞれオペランドを読込みます。これはCALL命令なので、PCの2バイトをスタックにプッシュ(0x0eb, 0x0ea)しています。その後、次の命令である0xfff(0x3ff)に飛びます。

クロックを見ると、本来17クロックのCALLに20クロックかかっています。 どうやら2バイト目と3バイト目を読み込む際のWAITは1クロックずつで、 各マシンサイクルでの2回目のWAITは実際には入っていないようです。

次に実行する命令を見てみます。

0FFF 2130FA    LD      HL,$FA30

0xfff-ld.png

この命令では、本来10クロックのところが13クロックかかっていて、やはりM1だけでなく、2バイト目、3バイト目の読み込みにも1クロックずつWAITがかかっています。

以上のことより、ROMからの読み出しのときは、常に1クロックずつWAITが入ることがわかります。 PC-6001のROMに使われているuPD2364のアクセス性能は製品により異なりますが、300/350/450nsです。 450ns品を使っているとすればまぁ納得のいく仕様でしょう。

このアーカイブについて

このページには、November 2008以降に書かれたブログ記事のうちPC-6001カテゴリに属しているものが含まれています。

前のアーカイブはPC-6001: October 2008です。

次のアーカイブはPC-6001: December 2008です。

最近のコンテンツ アーカイブ