piFDC(仮)

はじめに

概要

ダウンロード

使い方

SLFについて

本サイトで提供しているものが一体どんなものであるのか知って頂くために、ダウンロード前にご一読ください。

プログラムの構成

プログラムの規模はそれほど大きくありません。以下に概要を示します。

・gpioctl.c
GPIOおよびSPIを制御するドライバ

・fddif.c
GPIO/SPIドライバを制御して、フロッピーディスクの基本的なコントロールと、トラック単位での読み書きを行うための関数を提供するライブラリ

・fdanalyze.c
フロッピーディスクから読み出したデータの解析処理
フロッピーディスクの読み出しは、メディアの物理フォーマットに基づくデータレート(2HDでMFMフォーマットの場合クロックとデータの1サイクルが2~4μs)よりかなり高いレートで読み出しを行います。その読み出したデータの1サイクルに使用するビット数について統計を取り、物理フォーマットのサイズの推定と統計に基づき、データパターンからMFM/FMフォーマットの構造解析を行います。
また、読み取ったデータの速度「むら」を補正するための関数も用意しています(ただし、効果のほどは不明)。

・slflib.c
読み出したフロッピーディスクのデータをSLFフォーマットのイメージファイルとして保存、およびSLFフォーマットのイメージファイルをフロッピーディスクへ書き戻すための関数、また、フロッピーディスクイメージをエミュレータのFDCから制御することを想定した関数群のライブラリ
SLFフォーマットについては、別のページに詳細を記述しています。

・fdr.c
フロッピーディスクのデータを読み出しイメージファイルに保存します。コマンドラインの詳細については後述します。

・fdw.c
イメージファイルからフロッピーディスクへ書き戻しを行います。コマンドラインの詳細については後述します。

・fdstop.c
フロッピーディスクドライブのモータを停止します。プログラムがバグで中断したり、Ctrl+Cで中断した場合ドライブのモータが動作したままになってしまうため、そのような状態のときにモータを停止させるためのコマンドです。

このほかに、fdr_debug.cというファイルも入れておきました。うまく動かないときに評価に使っているソースコードです。動作検証する際の参考になると思い入れておきましたが、ソースコードは極めて汚いです。また、メディアから読み出した生のデータをトラック毎にバイナリ形式とテキスト形式のファイルで吐き出すため大量のファイルがカレントディレクトリに作成されるのでそのまま使う際には注意してください。

プログラムの特徴

このプログラムの大きな特徴としては、フロッピーディスクドライブの読み書きの際のデータ通信にSPIを使用していることです。
SPIは本来クロック信号を同時に発信(スレーブ側なら受信)し、そのクロックに同期させる形でデータの送受信を行いますが、本プログラムではクロックは使わず非同期のままSPIの定周期性のみを利用して送受信を行います。
非同期なのにSPIを使うメリットはFIFOを利用できることにあります。FIFOは8ビット×16段あるため、GPIOで直接制御する場合最短で2μsで1サイクルの信号の処理を完結させなければならないのに対し、SPIでは仮に精度を10倍で読み取るように(2μsで20ビット)したとしても、およそ12μsの猶予を持つことが出来ます。さほど違いがないように見えますがこれは結構大きな違いだったりします。
デメリットとしては、周期をコアクロックから分周した値にしか出来ないということがあるのですが、ここでの使い方としては指定しなければならない決まった周期というものがあるわけではないのであまり問題にはなりません。また、コアクロックに関してはCPUの動作モードに連動して変化してしまうため、SPI通信中はCPUのクロックが作業中に変化しないようにondemandではなくpowersave(あるいはperformance)にしておく必要があります。

課題としては、ベリファイなしではデータの読み書き共に信頼性が低いということです。これでも動き始めた当初よりは大分信頼性は向上できたのですが...。現状は正しく読めているかもしくは書けているかどうかをセクタ構造の正常性から判定し、正しく読めていないor書けていないと判断したらリトライをするという形で一定の信頼性を確保しています(逆に言うと正しく読めているかの判断が出来ない場合、信頼性も落ちるということになります)。

動作環境と他モデルへの移植性について

動作環境はこちらで実際に動作させているRaspberry Pi 3 ModelBを想定しています。

それよりスペックの低いモデルへの移植性に関してですが、フロッピーディスクのトラック情報の読み書きの際には、CPUをデフォルトでpowersaveモード(600MHz)固定にしています。ですのでシングルコアのモデルはバックグラウンドでサービスを起動していたりすると厳しいかもしれませんが、高クロックを要求しているわけではないのでマルチコアのモデルであればもしかしたら動くかもしれません。

他のモデルで動作させるに当たってはハードウェア制御に関して大きく以下の2点に注意してください。
・ペリフェラルのI/Oアクセスベースアドレス
・GPIOが28ピンの場合

ペリフェラルへのI/OアクセスのベースアドレスはRaspberry Pi 3では、0x3f000000からになっています。古いモデルでは0x20000000からというのもあるようですので、実行するハードウェアがどちらか確認して必要な修正を行ってください。修正箇所はgpioctl.cの先頭付近にあります。
GPIOが28ピンの場合は、修正方法として2つの方法があります。
・fddifの初期化関数fddifInitの第一引数に、FDDIF_GPIO40を設定しているのを、FDDIF_GPIO28に変更する。
・fddif.cで定義しているピン配置の設定を直接変更する。(fddifInitの第一引数を変更しない場合、変更対象はg_fddif_gpio40のテーブルになります)
いずれにしても、28ピンしかない場合はGPIOのピンアサインを変えないといけないため、fddif.cの先頭部分のコメント等を参考にして結線も28ピン用にあわせる必要があります。

もう一つ、これはよく分からないのですが、SPIのクロックの分周値の設定値について「BCM2835 ARM Peripherals」の10.5 SPI Register MapのCLK Registerの項目には2の累乗でなければならない(The divisor must be a power of 2.)との記述があるのですが、実際には2の倍数での指定が許されているようで、2の倍数で設定した場合でも指定した値で分周してくれます(CLK Registerの項目には「Odd numbers rounded down.」とも書かれていて偶数が許容されているようにも読める記述もあります)。
分周値の設定が2の累乗でないといけないのか、偶数であればよいのかということがRaspberry Piのモデルによって異なるのであれば、フロッピーディスクへ書き込むプログラムでは2の累乗ではない値を設定するため、動かないかもしれません。

※ダウンロードしたファイルには実行ファイルも添付してありますが、Raspberry Pi 3 ModelB用ですので、他のモデルではそれらは実行せずソースコードに必要な修正を加えた上でコンパイルしたものを実行するようにしてください。