いまさらのファミコンディスクシステム

  • 2012/07/31(火) 09:39:40

久しぶりの更新となってしまっています。
ちょこちょこっといじっていますが、あまりうまく行っていないので、まだ公開できないことが多いですが、そのなかの一つでファミコンディスクシステムをもう一度いじっています。
#下書きばっかり溜まっていく

今更ですし、誰得なんだといえばそれまでですが、以前から一般的なFDS形式では、各ブロック毎のデータが並んでいるだけのバイナリデータで、実際のディスクに書かれているGAPなども含めた全データのベタイメージではないことがちょっと疑問でした。
#昔、どこかでいろいろGAPの事書いている人がいましたが、私は別人ですw

で、どうすればベタイメージなど全てのデータが手に入るのか?考えていましたが、結局のところ昔のPCで後年主流となった、ハードウェアデュプリケータの理屈が一番いいだろうと。
つまり、タイムカウント方式で全ビットを測定し、データにしてしまってPCで保存するのはどうかなと。

というわけで、あまりに暑いので妄想を書きますので、突っ込んでいただけると幸いです。

まずはローレベルフォーマットから。
まあ一番詳しい解説はこれしかしらないんですが。
Brad Taylor氏が2004年に公開された、FDS technical referenceです。
あと、昔のバックアップ活用テクニックに載ってたこれ。


WDのことなので、RDの論理反転ですが、パルスの長さなど参考になります。
で、要するにRDからH(1)はおおよそ1usec(FDS tech refより)、L(0)はそのデータによって8.8usec〜18.7usec程ということでした。
んで、AVRの16ビットタイマ/カウンタ1でインプットキャプチャを使って、パルスの長さをH、Lともに測定して、PCへUSBで出力してやろうというのが考想です。
20MHzで動作させると、1usecのHの場合、20クロックしかありません。
インプットキャプチャ割り込みが掛かり、そのなかで
1,キャプチャの方向を変更をする(0で捕獲なら次は1での捕獲、1なら0へ変更)
2,カウンタ値を取り込んでPCへ出力
ということを終了しないとだめなんですが、間に合わなければ25MHz程度へオーバークロックですw
25MHzだと理論的には40nsec程度の精度でキャプチャできるかなと。

当初は扱いが簡単でピン数も少ないのでUARTで通信しようと、WindowsとAVR間の通信にはFT232RLを使おうと思っていましたが、最速で1Mbps程度、90Kbyte/sほどしか速度が出ず、おそらく取りこぼしが起こると思い、FT245RLのパラレル通信でD2XXを利用して1MByte/s程度にすることと決めました。

やってることは単純でATmega328程度で良いかと思っていましたが、ピン数が足りず結局ATmega644を利用することにしました。
#ホントはぎりぎり足りるかも

FT245RLとの制御、データ転送に13ピンが必要です。
VCC、GND、AVCC、GND、Reset、外部クロック2ピンで、ここまでで20pin。
ディスクシステムの制御に、-write、-scan media、write data、motor on、-writable media、read data、-media set、-ready、-stop motorで9ピン必要です。
全部で29ピンですので、328などだと1ピン足りませんし、ある程度、信号を無視するようにしてもいいのですが、デバッグやもしものピンが足りないと考えました。

次、実際のデータについてです。
ディスクシステムは96.4KHzのクロックでデータをリードしていきます。
→に時間が進んでいきます。


Rate ----____----____----____----____----____----____----____----____----____
(96.4KHzのクロックパルス)
Data ----------------________________________--------________----------------
1 1 0 0 0 1 0 1 1
実際のデータとクロックをXORしたものが、⇣
XOR ____----____--------____----____----________--------________----____----
ディスクからは、その立ち上がりビット部分だけパルスが出力されます。
Disk ____-_______-___________-_______-___________-_______________-_______-___

んっ!って、これただのMFM変調じゃんw
しかも96.4KHzだったら、バッ活の計測は微妙に間違ってますよw
96.4KHzだったら、1クロックがおおよそ10.37usecですので、以下ディスクの部分の時間計測をするとおおよそですが、
Rate   ----____----____----____----____----____----____----____----____----____

Data ----------------________________________--------________----------------
1 1 0 0 0 1 0 1 1
Disk ____-_______-___________-_______-___________-_______________-_______-___
|1| 9.3 |1| 14.4 |1| 9.3 |1| 14.4 |1| 19.6 |1| 9.3 |1|
(MFM) 5|1| 4| 5|1| 4| 10.3 |1| 9.3 |1| 9.3 | 5 |1| 4| 10.3 | 5|1| 4| 5|1|4
MFM変調として分かりやすくするとこんな感じ(小数点以下は切り捨てあり)

ちなみにMFM変換は
1のとき、Lを半クロック(実際の時間は転送レートに依ります)待って、短いパルス(H)+Lで半クロック
1の後の0は、Lで1クロック
0の後の0は、短いパルス(H)+Lで1クロック
となるように構成されます。

実際のデータは、GAPは全て0x00のデータで、ディスクの先頭からおよそ40000ビットが0で埋まっています
ディスクの最外周からデータが始まり(-readyがアサートされる)その直後、13000ビットにはゴミがあるそうです。
#そのためディスクシステムは最初の26100ビットを無視します。
ブロックの始まりは0x80ですが、これはLSBから始まるで2進数で書くと00000001ですので、要するに1が来たらその後からデータが始まるということですね。
0x00と0x80は以下のようになります。

Rate ----____----____----____----____----____----____----____----____
DATA(L)________________________________________________________________(H)
(00000000)
XOR ----____----____----____----____----____----____----____----____
Disk -_______-_______-_______-_______-_______-_______-_______-_______

Rate ----____----____----____----____----____----____----____----____
DATA(L)________________________________________________________--------(H)
(00000001)
XOR ----____----____----____----____----____----____----________----
Disk -_______-_______-_______-_______-_______-_______-___________-___

ブロックの終わりは2バイトのCRCですが、各ブロックを書きこむとその直後にゴミが入るため、リード時はブロック直後の488ビットを無視するそうです。
で、全てのブロックが終了後、ディスクの最後までは0x00が書き込まれるということでした。

次、ディスクシステムがドライブとやり取りしている信号、リードプロセスは、

1.ドライブにメディアがセットされると、-media setがアサート(L)になったままになる。(ドライブ→RAMアダプター)
  同時に書き込み可能メディアであれば、-writable mediaがアサートされたままになる。(ドライブ→RAMアダプター)

2.-scan mediaをアサート(L)、-stop motorをネゲート(H)にする。(RAMアダプター→ドライブ)
バッテリーなど問題なければmotor on/battery goodがアサート(H)(ドライブ→RAMアダプター)

3.-ヘッドが最外周のディスクスタート位置に移動すると-readyがアサート(L)になる(立ち下がる)(ドライブ→RAMアダプター)これでRAMアダプターは、ヘッドが先頭位置にあることを理解する。

4.-readyがLのまま、データリード、RDから転送が続く(ドライブ→RAMアダプター)

5.データ転送量を見計らって、-scan mediaをH、-stop motorをLにする(RAMアダプター→ドライブ)、-readyがHになってリード終了。

もしくは
5.転送が最内周まで行われると-readyがHになる。(ドライブ→RAMアダプター)
scan mediaをH、-stop motorをLにする(RAMアダプター→ドライブ)
リード終了

ということなので、以下の方法でリードできるのでは?
0.-write(H),-scan media(H),-stop motor(L)が初期状態

1.-media set(L)を待期(-writable mediaはどっちでもいい)

2.-scan media(L)、-stop motor(H)にする(motor on/battery goodがHを見てもいいがどっちでもいい)

3.-readyのLを待ち、Lとなったら、RDからのデータを所得。

4.-ready(H)を検出したら(ディスク終了位置、最内周)、転送終了。-scan mediaをH、-stop motorをLで一回のリード終了。

こんな感じ。

PCからは、USBからリード命令を送信し(例えば0x01とか)、リード待機状態にAVRを初期化して、ディスクセット。
データが来たら、どんどん受信するっていうものを作ればいいですかね?
#ってwindowsのプログラムなんて殆どやったこと無いので、VBでとか思ってたり。

とりあえず、WindowsとFT245RLの通信。FT245RLとAVRの通信を組んでみます。
では〜

この記事に対するコメント

お久です。
細かな波形などは難しくて良く理解できてませんが・・・
FDSと違ったベタなイメージというと、任天公式の形式(qd形式?)のブロック間に2Byteの0x00が入っているタイプになる・・・のかな?
(MGD1ではヘッダに3Byte余分なデータが入る)

いずれにしてもとっても興味あるので楽しみにしてます(^-^)

お久しぶりでございます。

記事の内容は半分以上、理解不能ですが(^-^;;
とっても興味ある内容ですので、私も楽しみにしています。

ありがとうございます。

ぽんRevさん、ばくてんさん。
コメントありがとうございます。
この方向で、作ってみようと思っています。
おそらく一番問題があるとすると、Windows上でのファイルの取り扱いかなと。
リードした後はいままでのようなバイナリとすることでもいいと思いますが、その場合、書き戻しを考えると速度的に厳しいかもしれませんので、パルスの並びを書きだした中間ファイルのようなものを作成しないとダメかなーとか考えてます。
少しづつ進めてみます。
では〜

この記事にコメントする

管理者にだけ表示を許可する