Update documentation with lots more stuff about disk densities.

This commit is contained in:
David Given
2022-03-29 23:08:07 +02:00
parent f75422a412
commit 49723d05cf
10 changed files with 223 additions and 48 deletions

View File

@@ -70,8 +70,9 @@ following friendly articles:
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact
science ∾ the sector map ∾ clock detection and the histogram
- [Checking your drive](doc/driveresponse.md) ∾ you can't do that with that ∾
measuring your drive's ability to work with exotic formats
- [Disk densities](doc/driveresponse.md) ∾ what's the difference between an HD
and DD disk? ∾ you can't do that with that ∾ measuring your drive's ability to
work with exotic formats ∾ I think my drive is broken
Which?
------

View File

@@ -1,25 +1,79 @@
Analysing drive response
========================
Disk and drive density
======================
**tl;dr:** with 5.25" drives, it is _vitally important_ that you set
`--drive.high_density=0|1` correctly when working with disks.
Not all PC drives are made equal. Some are less equal than others.
The way floppy disk storage works is that the floppy drive controller will
generate a series of pulses, which the drive stores on the disk. Then, when the
disk is read, the drive will reproduce the same series of pulses and return it
to the floppy drive controller. The data is stored in the intervals between
to the floppy drive controller. The data is stored by the intervals between
pulses.
The problem is that some PC drives assume that they're going to be used with
IBM scheme disks, which use particular pulse intervals --- in the case of DD
disks, intervals are always 4us, 6us or 8us. So, in a misguided attempt to
improve reliability, they sometimes... tidy... the incoming pulse stream. This
can have nasty effects if you're not a disk which _doesn't_ use those intervals.
However, the underlying physics of the magnetic media put limitations on how far
apart the pulses can be. If they're too close, they will physically move further
apart... and if they're too far apart, the drive will detect spurious pulses
that don't exist in real life (due to the way the drive's automatic gain
adjustment on the head amplifiers work).
In addition, they won't work properly if the intervals are too great, or too
small. Partly this is a limitation of the underlying physics of the magnetic
media, and partly it's due to the drive's automatic gain adjustment: if the
drive doesn't see a pulse, it'll start ramping up the gain of its amplifier,
until it starts interpreting random noise as a valid pulse.
So, it's very important what kind of disks you use, and what kind of drives you
put those disks in: these can vary.
Disk densities
--------------
Disks usually come in two varieties: SD/DD/QD disks, and HD disks. (There's
also ED and TD but they're fairly specialist and FluxEngine doesn't support
them.)
SD (single density), DD (double density) and QD (quad density) actually refer to
the way the data is stored on the disk. SD usually implies FM, and DD implies
MFM, which allows 60% more data; QD implies MFM _plus_ narrower tracks, doubling
the track count and hence the amount of data. This distinction was important
back when you had to buy pre-formatted disks, so you needed disks which matched
your drive. FluxEngine, of course, formats them itself.
HD disks use a different magnetic medium, based on cobalt rather than iron
oxide. This allows the pulses on the disk to be much closer together. This
doubles the amount of data yet again. The downside of HD disks is that the
pulses _have_ to be closer together so you're likely to have problems if you try
to write SD/DD/QD formats onto HD disks.
It's also worth noting that 3.5" SD/DD/QD disks are much more like 3.5" HD disks
than 5.25" SD/DD/QD disks are like 5.25" HD disks. If you own an Amiga which
uses 3.5" DD disks, you'll know that HD disks will mostly work just fine in an
Amiga; but if you own a C64 with 5.25" SD disks, you'll know that HD disks are
likely to be error-prone.
Drive types
-----------
Of course, the disk itself is only half the story...
Old floppy disk drives vary in what formats they support. The usual variables are:
disk rotation speed (either 300rpm or 360rpm); number of tracks (either 40 or
80); and whether they can support HD disks. (Plus, of course, whether it's 3.5"
or 5.25", but the technology is largely identical so I'm ignoring that.)
'Modern' drives are pretty consistent in that they run at 300rpm (for a 3.5"
drive) or 360rpm (for a 5.25" drive), have 80 tracks, and support HD.
There are two additional wrinkles:
- the drive must be configured for SS/DD/QD media or HD media. 3.5" drives can
do this automatically, as there's a hole in the disk case which a drive sensor
can detect, but 5.25" drives don't, and must be told what medium is being used
by the computer. (FluxEngine uses the `--drive.high_density=0|1` option for
this.)
- some drives are designed to only support IBM formats, which use pulse widths
of 4µs, 6µs or 8µs, and when given pulses that aren't this wide they behave...
poorly.
Actually measuring things
-------------------------
FluxEngine has a tool to analyse a drive and report on this behaviour. It works
by writing a sequence of timed pulses to the disk, then reading them back and
@@ -27,52 +81,166 @@ seeing what the drive actually reports. To use it, do:
```
fluxengine analyse driveresponse --cylinder 0 \
--min-interval-us=0 --max-interval-us=30 --interval-step-us=.1 \
--min-interval-us=0 --max-interval-us=15 --interval-step-us=.1 \
--write-img=driveresponse.png
```
This will scan all intervals from 0us to 30us, at 0.1us steps, draw a graph,
and write out the result. The graphs look like this.
This will scan all intervals from 0µs to 15µs, at 0.1µs steps, draw a graph,
and write out the result.
Using mismatched media and drive configuration
----------------------------------------------
There are four possible options when using 5.25" media in my Panasonic JU-475
5.25" drive. The following table shows what the analysis tool shows for all
these options.
(Click to expand)
<div style="text-align: center">
<a href="sony-mpf920-dd.png"><img src="sony-mpf920-dd.png" style="width:40%" alt="Sony MPF-920, DD"></a>
<a href="sony-mpf920-hd.png"><img src="sony-mpf920-hd.png" style="width:40%" alt="Sony MPF-920, HD"></a>
<table class="datatable">
<tr>
<th></th>
<th>DD drive</th>
<th>HD drive</th>
</tr>
<tr>
<th>DD media</th>
<td>
<a href="ju475-dd-lo.png">
<img src="ju475-dd-lo.png" style="width:100%"
alt="Panasonic JU-475, DD media, DD drive setting">
</a>
</td>
<td>
<a href="ju475-dd-hi.png">
<img src="ju475-dd-hi.png" style="width:100%"
alt="Panasonic JU-475, DD media, HD drive setting">
</a>
</td>
</tr>
<tr>
<th>HD media</th>
<td>
<a href="ju475-hd-lo.png">
<img src="ju475-hd-lo.png" style="width:100%"
alt="Panasonic JU-475, HD media, DD drive setting">
</a>
</td>
<td>
<a href="ju475-hd-hi.png">
<img src="ju475-hd-hi.png" style="width:100%"
alt="Panasonic JU-475, HD media, HD drive setting">
</a>
</td>
</tr>
</table>
</div>
This is the analysis from the [Sony
MPF-920](https://docs.sony.com/release/MPF920Z.pdf) 3.5" drive I mostly use for
testing. The left-hand image shows the result from a DD disk, while the right
hand image shows the result from a HD disk.
The X axis shows the width of the pulse being sent to the drive. This gets
recorded to the disk (repeatedly). The Y axis shows a heatmap of the pulses read
back again. What we want to see is a solid diagonal line, showing that the
pulses are being read back accurately. However, once the pulse width gets wide
enough, spurious pulses appear, which show up on the graph as the rainbow smear
in the bottom left corner. You can see that this is much more pronounced on the
HD media than it is on the DD media --- the DD media is capable of accurately
reproducing pulses up to about 12µs, while the HD media only goes up to 7µs.
The horizontal axis is the width of pulse being written; the vertical axis and
heatmap shows the distribution of pulses being read back. You can see the
diagonal line, which represents correct pulses. The triangular smear in the
bottom right shows spurious pulses which are being read back because the
interval is too great; these start at about 12us for DD disks and 7us for HD
disks. This is an artifact of the different magnetic media for the two types of
disk.
This demonstrates that some formats, such as the [Apple II](doc/disk-apple2.md)
which uses a maximum pulse width of 8µs, cannot be written to HD media at all.
(This, by the way, is why you shouldn't use DD formats on HD disks. The
intervals on a DD disk can go up to 8us, which is on the edge of the ability of
an HD disk and drive to correctly report back the pulses.)
We would also normally see spurious pulses on the left of the graph, indicating
that pulses are too close together to be reproduced accurately, but we're not
--- the Panasonic is a good drive.
You also note the hard cut-off on the left: this represents the filter on the
drive, which will simply refuse to report pulse intervals shorter than about
1.5us. FluxEngine itself can't write intervals shorter than 2us.
For comparison, following is the same table for my Sony MPF-90 3.5" drive.
For comparison purposes, here's another set of graphs.
(Click to expand)
<div style="text-align: center">
<a href="fdd-90206-dd.png"><img src="fdd-90206-dd.png" style="width:40%" alt="FDD-90206, DD"></a>
<a href="fdd-90206-hd.png"><img src="fdd-90206-hd.png" style="width:40%" alt="FDD-90206, HD"></a>
<table class="datatable">
<tr>
<th></th>
<th>DD drive</th>
<th>HD drive</th>
</tr>
<tr>
<th>DD media</th>
<td>
<a href="mpf90-dd-lo.png">
<img src="mpf90-dd-lo.png" style="width:100%"
alt="Sony MPF-90, DD media, DD drive setting">
</a>
</td>
<td>
</td>
</tr>
<tr>
<th>HD media</th>
<td>
<a href="mpf90-hd-lo.png">
<img src="mpf90-hd-lo.png" style="width:100%"
alt="Sony MPF-90, HD media, DD drive setting">
</a>
</td>
<td>
<a href="mpf90-hd-hi.png">
<img src="mpf90-hd-hi.png" style="width:100%"
alt="Sony MPF-90, HD media, HD drive setting">
</a>
</td>
</tr>
</table>
</div>
As 3.5" drives autodetect the media type, I had to tape over the hole in a HD
disk to make the drive treat it as a DD disk. Unfortunately, doing it the other
way around would require drilling a hole in a DD disk, which I'm unwilling to
do! So there are only three graphs here.
We get the same smear of spurious pulses in the bottom left, but we _also_ get
some incorrect pulses on the left. In addition, the line itself only starts at
about 2.5µs --- it turns out that this drive simply returns nothing at all for
pulses shorter than that.
(FluxEngine itself can't write intervals shorter than 2us.)
And, finally, here is one additional pair of graphs.
<div style="text-align: center">
<table class="datatable">
<tr>
<th></th>
<th>DD drive</th>
<th>HD drive</th>
</tr>
<tr>
<th>DD media</th>
<td>
<a href="fdd-90206-dd.png">
<img src="fdd-90206-dd.png" style="width:100%" alt="FDD-90206, DD">
</a>
</td>
<td>
</td>
</tr>
<tr>
<th>HD media</th>
<td></td>
</td>
<td>
<a href="fdd-90206-hd.png">
<img src="fdd-90206-hd.png" style="width:100%" alt="FDD-90206, HD">
</a>
</td>
</tr>
</table>
</div>
This is from another drive I have; it's an unbranded combo
card-reader-and-floppy drive unit; the 90206 is the only identification mark it
has. The DD graph shows that intervals below about 4us are reported as double
card-reader-and-3.5"-floppy drive unit; the 90206 is the only identification mark it
has. The DD graph shows that intervals below about 4µs are reported as double
what they should be: so, this drive won't work on [Macintosh 800kB
formats](disk-macintosh.md) at all, because they use intervals starting at
2.6us, below this limit. But it should work on PC formats --- just.
2.6µs, below this limit. But it should work on PC formats --- just.

BIN
doc/ju475-dd-hi.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
doc/ju475-dd-lo.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
doc/mpf90-dd-lo.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
doc/mpf90-hd-hi.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
doc/mpf90-hd-lo.png Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

View File

@@ -69,6 +69,11 @@ static IntFlag imgHeight(
"Height of output graph",
600);
static IntFlag buckets(
{ "--buckets" },
"Number of heatmap buckets",
250);
/* This is the Turbo colourmap.
* https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html
*/
@@ -225,7 +230,7 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
csv.open(writeCsv);
int numRows = (maxInterval - minInterval) / intervalStep;
const int numColumns = 512;
const int numColumns = buckets;
std::vector<std::vector<double>> frequencies(numRows, std::vector<double>(numColumns, 0.0));
double interval;
@@ -237,16 +242,17 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
std::cout << fmt::format("Interval {:.2f}: ", ticks * US_PER_TICK);
std::cout << std::flush;
/* Write the test pattern. */
if (interval >= 2.0)
{
/* Write the test pattern. */
Fluxmap outFluxmap;
while (outFluxmap.duration() < period)
{
outFluxmap.appendInterval(ticks);
outFluxmap.appendPulse();
}
usbWrite(destHead, outFluxmap.rawBytes(), 0);
/* Read the test pattern in again. */
@@ -353,8 +359,8 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
}
draw_y_axis(painter, colourbarBounds.x1-5, colourbarBounds.y2, colourbarBounds.y1, 0.0, 1.0, 0.1, "{:.1f}");
draw_y_axis(painter, graphBounds.x1-5, graphBounds.y2, graphBounds.y1, 0.0, 512.0/TICKS_PER_US, 5.0, "{:.0f}");
draw_y_graticules(painter, graphBounds.x1, graphBounds.y2, graphBounds.x2, graphBounds.y1, 0.0, 512.0/TICKS_PER_US, 5.0);
draw_y_axis(painter, graphBounds.x1-5, graphBounds.y2, graphBounds.y1, 0.0, buckets/TICKS_PER_US, 5.0, "{:.0f}");
draw_y_graticules(painter, graphBounds.x1, graphBounds.y2, graphBounds.x2, graphBounds.y1, 0.0, buckets/TICKS_PER_US, 5.0);
draw_x_axis(painter, graphBounds.x1, graphBounds.x2, graphBounds.y2+5, minInterval, maxInterval, 5.0, "{:.0f}");
draw_x_graticules(painter, graphBounds.x1, graphBounds.y1, graphBounds.x2, graphBounds.y2, minInterval, maxInterval, 5.0);