PC-6001の最近のブログ記事

ロジアナでいろいろ計測するにあたり、初めて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品を使っているとすればまぁ納得のいく仕様でしょう。

ファイルシステムのアクセス方法や、コマンドプロンプトからの引数の受け渡し方法などを書いておきました。

Sourceforgeで参照できるようにしてあります。

それと、普通のユーザーズガイドをこのサイトに出してませんでしたので、以下に置いておきます。

アダプタの販売はこちらで扱っていますのでよろしくお願いします。

PSGによるPCM再生の問題

PSG(AY-3-8910)では、音量レジスタを高速に操作することによって任意の音声波形の再生をすることができます。PCM相当のことができるわけですね。

この辺はPSGPCMやSSGPCMといった技術が確立しているので、細かい説明は省きます。 Wikipediaなどには「PSGで高音質のPCMを再生したものはほとんど皆無」とあります。確かにそうなのですが、不可能ではないのです。それにはPSGの性質を理解する必要があります。

PCM再生の音質は標本化周波数(サンプリング周波数)と量子化ビット数により決まります。 大雑把に言うと、PSGでは、標本化周波数は1秒間に音量レジスタを変化させる回数、 量子化ビット数は音量レジスタのとりうる値です。

ここで、PSG(AY-3-8910)の音量レジスタは0~15の4ビットの値をとります。

そのため、PSGでPCMを再生するときに"4ビットPCM"といったりすることがありますが、 実はこれは通常のPCMでいうビット数の考え方からすると誤りです。 というのは、PSGにおける音量レジスタの値と音量の関係はリニアではなく、 対数値であるためです。

nを音量レジスタの値とすると、出力yは以下の式で表せます。

y = 2^-((15-n)/2)
 (if n > 0)
y = 0(if n == 0)


そのため、特に大音量域での解像度が極端に低くなります。

psg.PNG
上図で、横軸は音量レジスタに与える値で、縦軸は音量です。

もしデータが上位半分以上の音量域をメインとして構成されていた場合、0, 0.5, 約0.7, 1の4つの値しか取れず、実質2ビットになってしまうわけです。 これが、「PSGではまともなPCM再生はできない」と言われてしまう所以です。

ミキシングによる高音質化


ところで、PSGには3つのチャネルがあります。発音時はこの3チャネルを合わせるわけですが、この合わせ方とは3つのアナログ信号出力を単に合成するだけです。

このため、この仕様をうまく使うと、粒度の荒い大音領域と細かい小音領域を2つのチャネルで再生し、合成することによってビットの低さを補えるのです。

たとえば、0.5(n=13)と約0.03(n=5)の2チャネルを合わせて約0.53を出力したりすることができる、というわけです。

この方法を3チャネルで使うことにより、計608種類の異なる音量を発生させることができます。これは9ビット強に相当します(以前3チャネルで12ビット相当と他サイトで書いていましたが、厳密には誤りで、およそ9ビットが正しいようです)。

ただ、先ほども説明したように、出力は対数値なので、リニアに9ビットの出力値を得られるというわけではありません。その辺はエンコード時に上手に計算してあげる必要があります。

これ、MSX用にViterbiアルゴリズムとinterpolationを使って高音質なエンコードをした人がいて、PC-6001でも応用ができます。それが私がやってみた実験です。

実のところ、もとのMSX版の完成度が高いため、私がわざわざやったことは大したことはないのです。 まぁ、PC-6001でここまでやった人はいないだろうということで。

この文章は、以下を大いに参考にさせていただきました。

http://map.tni.nl/articles/psg_sample.php

実機での再生結果
こんな感じです。音質そんなに悪くないでしょ?

さて、AVRを使ってSDカードリーダを作ろうと思っています。本体側からIn/Out 1命令で入出力ができれば、リアルタイムでの動画再生なども不可能ではありません。

とりあえず現状の回路図。

AVR_SD.PNGポイントは以下のようなところです。
  • SDカードは3.3V動作なので、回路全体を3.3V動作にしています。
  • ATmega8Lは内蔵クロックで8MHz動作させます。
  • ISPインタフェースを用意しておいて、プログラムの書き換えに備えます。
  • アドレス線は7432でプリデコードしておくことにより、AVRのI/Oを節約します。
AVRのI/Oポートが少しあまっているのですが、とりあえず未使用にしておきます。

先日秋葉原でEジスPenやらプリント基板キットやらを買い込んできたのですが、この回路図からレイアウトを起こすのが面倒でそのままになっています。きっと世の中には自動レイアウトツールもあるんでしょうね...。

続いて、ムービーエンコーダとプレーヤをリリースします。

それぞれ中にREADMEがありますので参考にしてください。

プレーヤですが、実はこのままでは再コンパイルできません。Hexameterをダウンロードし、適切にMakefileを設定しなおす必要があります。私の環境のままアーカイブにしてしまったためなのですが、直しているといつまでたってもアップロードできないので、とりあえずまずはこれで許してください。

Hexameter 2.1.2をリリースしました.

Sourcceforgeからダウンロードできます.

変わったのは、SDOS 1.1用のテンプレートを用意したことだけですのでたいして大きな変化ではないですが、もしSDカードアダプタをお持ちの方でSDカードをアクセスしたいという奇特な(?)方がいらっしゃればぜひご利用ください. また、SDOS開発時に作成したいろいろ有用なルーチンも用意してますので、良かったら使ってみてください. 戦士カートリッジ版、1M ROMアダプタ版双方で動作するはずです.

一昨日日本から戻ってきました. 時差ぼけで体の調子が悪いのですが、SDOS関連ファイルの公開に向けてファイルの整理を始めました.

Hexameter (SDCC用コンパイル環境)のテンプレートとしてSDOS 1.1用の環境を準備しているほか、ムービープレイヤーなどのソース/バイナリファイルを公開できるように整理しています. とりあえず、Hexameterの方はsourceforgeのCVSの更新は終わったのでダウンロード自身は可能ですが、簡単にダウンロードできるリリース用のアーカイブはまだ準備していません.

私はいったん「入って」しまうと夢中で作業して一気に終わらせてしまう方なのですが、気が乗らないときは途中でほっぽり出してなかなか進みません. よくないことは分かっているのですが...

このアーカイブについて

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

前のカテゴリはLondonです。

次のカテゴリはPC/Gadgetです。

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