Skip to content

Commit 49723d0

Browse files
committed
Update documentation with lots more stuff about disk densities.
1 parent f75422a commit 49723d0

10 files changed

+223
-48
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,9 @@ following friendly articles:
7070
- [Troubleshooting dubious disks](doc/problems.md) ∾ it's not an exact
7171
science ∾ the sector map ∾ clock detection and the histogram
7272

73-
- [Checking your drive](doc/driveresponse.md) ∾ you can't do that with that ∾
74-
measuring your drive's ability to work with exotic formats
73+
- [Disk densities](doc/driveresponse.md) ∾ what's the difference between an HD
74+
and DD disk? ∾ you can't do that with that ∾ measuring your drive's ability to
75+
work with exotic formats ∾ I think my drive is broken
7576

7677
Which?
7778
------

doc/driveresponse.md

Lines changed: 209 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,78 +1,246 @@
1-
Analysing drive response
2-
========================
1+
Disk and drive density
2+
======================
3+
4+
**tl;dr:** with 5.25" drives, it is _vitally important_ that you set
5+
`--drive.high_density=0|1` correctly when working with disks.
36

47
Not all PC drives are made equal. Some are less equal than others.
58

69
The way floppy disk storage works is that the floppy drive controller will
710
generate a series of pulses, which the drive stores on the disk. Then, when the
811
disk is read, the drive will reproduce the same series of pulses and return it
9-
to the floppy drive controller. The data is stored in the intervals between
12+
to the floppy drive controller. The data is stored by the intervals between
1013
pulses.
1114

12-
The problem is that some PC drives assume that they're going to be used with
13-
IBM scheme disks, which use particular pulse intervals --- in the case of DD
14-
disks, intervals are always 4us, 6us or 8us. So, in a misguided attempt to
15-
improve reliability, they sometimes... tidy... the incoming pulse stream. This
16-
can have nasty effects if you're not a disk which _doesn't_ use those intervals.
15+
However, the underlying physics of the magnetic media put limitations on how far
16+
apart the pulses can be. If they're too close, they will physically move further
17+
apart... and if they're too far apart, the drive will detect spurious pulses
18+
that don't exist in real life (due to the way the drive's automatic gain
19+
adjustment on the head amplifiers work).
20+
21+
So, it's very important what kind of disks you use, and what kind of drives you
22+
put those disks in: these can vary.
23+
24+
Disk densities
25+
--------------
26+
27+
Disks usually come in two varieties: SD/DD/QD disks, and HD disks. (There's
28+
also ED and TD but they're fairly specialist and FluxEngine doesn't support
29+
them.)
30+
31+
SD (single density), DD (double density) and QD (quad density) actually refer to
32+
the way the data is stored on the disk. SD usually implies FM, and DD implies
33+
MFM, which allows 60% more data; QD implies MFM _plus_ narrower tracks, doubling
34+
the track count and hence the amount of data. This distinction was important
35+
back when you had to buy pre-formatted disks, so you needed disks which matched
36+
your drive. FluxEngine, of course, formats them itself.
37+
38+
HD disks use a different magnetic medium, based on cobalt rather than iron
39+
oxide. This allows the pulses on the disk to be much closer together. This
40+
doubles the amount of data yet again. The downside of HD disks is that the
41+
pulses _have_ to be closer together so you're likely to have problems if you try
42+
to write SD/DD/QD formats onto HD disks.
43+
44+
It's also worth noting that 3.5" SD/DD/QD disks are much more like 3.5" HD disks
45+
than 5.25" SD/DD/QD disks are like 5.25" HD disks. If you own an Amiga which
46+
uses 3.5" DD disks, you'll know that HD disks will mostly work just fine in an
47+
Amiga; but if you own a C64 with 5.25" SD disks, you'll know that HD disks are
48+
likely to be error-prone.
49+
50+
Drive types
51+
-----------
52+
53+
Of course, the disk itself is only half the story...
54+
55+
Old floppy disk drives vary in what formats they support. The usual variables are:
56+
disk rotation speed (either 300rpm or 360rpm); number of tracks (either 40 or
57+
80); and whether they can support HD disks. (Plus, of course, whether it's 3.5"
58+
or 5.25", but the technology is largely identical so I'm ignoring that.)
59+
60+
'Modern' drives are pretty consistent in that they run at 300rpm (for a 3.5"
61+
drive) or 360rpm (for a 5.25" drive), have 80 tracks, and support HD.
62+
63+
There are two additional wrinkles:
1764

18-
In addition, they won't work properly if the intervals are too great, or too
19-
small. Partly this is a limitation of the underlying physics of the magnetic
20-
media, and partly it's due to the drive's automatic gain adjustment: if the
21-
drive doesn't see a pulse, it'll start ramping up the gain of its amplifier,
22-
until it starts interpreting random noise as a valid pulse.
65+
- the drive must be configured for SS/DD/QD media or HD media. 3.5" drives can
66+
do this automatically, as there's a hole in the disk case which a drive sensor
67+
can detect, but 5.25" drives don't, and must be told what medium is being used
68+
by the computer. (FluxEngine uses the `--drive.high_density=0|1` option for
69+
this.)
70+
71+
- some drives are designed to only support IBM formats, which use pulse widths
72+
of 4µs, 6µs or 8µs, and when given pulses that aren't this wide they behave...
73+
poorly.
74+
75+
Actually measuring things
76+
-------------------------
2377

2478
FluxEngine has a tool to analyse a drive and report on this behaviour. It works
2579
by writing a sequence of timed pulses to the disk, then reading them back and
2680
seeing what the drive actually reports. To use it, do:
2781

2882
```
2983
fluxengine analyse driveresponse --cylinder 0 \
30-
--min-interval-us=0 --max-interval-us=30 --interval-step-us=.1 \
84+
--min-interval-us=0 --max-interval-us=15 --interval-step-us=.1 \
3185
--write-img=driveresponse.png
3286
```
3387

34-
This will scan all intervals from 0us to 30us, at 0.1us steps, draw a graph,
35-
and write out the result. The graphs look like this.
88+
This will scan all intervals from 0µs to 15µs, at 0.1µs steps, draw a graph,
89+
and write out the result.
90+
91+
Using mismatched media and drive configuration
92+
----------------------------------------------
93+
94+
There are four possible options when using 5.25" media in my Panasonic JU-475
95+
5.25" drive. The following table shows what the analysis tool shows for all
96+
these options.
3697

3798
(Click to expand)
3899

39100
<div style="text-align: center">
40-
<a href="sony-mpf920-dd.png"><img src="sony-mpf920-dd.png" style="width:40%" alt="Sony MPF-920, DD"></a>
41-
<a href="sony-mpf920-hd.png"><img src="sony-mpf920-hd.png" style="width:40%" alt="Sony MPF-920, HD"></a>
101+
<table class="datatable">
102+
<tr>
103+
<th></th>
104+
<th>DD drive</th>
105+
<th>HD drive</th>
106+
</tr>
107+
<tr>
108+
<th>DD media</th>
109+
<td>
110+
<a href="ju475-dd-lo.png">
111+
<img src="ju475-dd-lo.png" style="width:100%"
112+
alt="Panasonic JU-475, DD media, DD drive setting">
113+
</a>
114+
</td>
115+
<td>
116+
<a href="ju475-dd-hi.png">
117+
<img src="ju475-dd-hi.png" style="width:100%"
118+
alt="Panasonic JU-475, DD media, HD drive setting">
119+
</a>
120+
</td>
121+
</tr>
122+
<tr>
123+
<th>HD media</th>
124+
<td>
125+
<a href="ju475-hd-lo.png">
126+
<img src="ju475-hd-lo.png" style="width:100%"
127+
alt="Panasonic JU-475, HD media, DD drive setting">
128+
</a>
129+
</td>
130+
<td>
131+
<a href="ju475-hd-hi.png">
132+
<img src="ju475-hd-hi.png" style="width:100%"
133+
alt="Panasonic JU-475, HD media, HD drive setting">
134+
</a>
135+
</td>
136+
</tr>
137+
</table>
42138
</div>
43139

44-
This is the analysis from the [Sony
45-
MPF-920](https://docs.sony.com/release/MPF920Z.pdf) 3.5" drive I mostly use for
46-
testing. The left-hand image shows the result from a DD disk, while the right
47-
hand image shows the result from a HD disk.
140+
The X axis shows the width of the pulse being sent to the drive. This gets
141+
recorded to the disk (repeatedly). The Y axis shows a heatmap of the pulses read
142+
back again. What we want to see is a solid diagonal line, showing that the
143+
pulses are being read back accurately. However, once the pulse width gets wide
144+
enough, spurious pulses appear, which show up on the graph as the rainbow smear
145+
in the bottom left corner. You can see that this is much more pronounced on the
146+
HD media than it is on the DD media --- the DD media is capable of accurately
147+
reproducing pulses up to about 12µs, while the HD media only goes up to 7µs.
148+
149+
This demonstrates that some formats, such as the [Apple II](doc/disk-apple2.md)
150+
which uses a maximum pulse width of 8µs, cannot be written to HD media at all.
151+
152+
We would also normally see spurious pulses on the left of the graph, indicating
153+
that pulses are too close together to be reproduced accurately, but we're not
154+
--- the Panasonic is a good drive.
155+
156+
For comparison, following is the same table for my Sony MPF-90 3.5" drive.
157+
158+
(Click to expand)
159+
160+
<div style="text-align: center">
161+
<table class="datatable">
162+
<tr>
163+
<th></th>
164+
<th>DD drive</th>
165+
<th>HD drive</th>
166+
</tr>
167+
<tr>
168+
<th>DD media</th>
169+
<td>
170+
<a href="mpf90-dd-lo.png">
171+
<img src="mpf90-dd-lo.png" style="width:100%"
172+
alt="Sony MPF-90, DD media, DD drive setting">
173+
</a>
174+
</td>
175+
<td>
176+
</td>
177+
</tr>
178+
<tr>
179+
<th>HD media</th>
180+
<td>
181+
<a href="mpf90-hd-lo.png">
182+
<img src="mpf90-hd-lo.png" style="width:100%"
183+
alt="Sony MPF-90, HD media, DD drive setting">
184+
</a>
185+
</td>
186+
<td>
187+
<a href="mpf90-hd-hi.png">
188+
<img src="mpf90-hd-hi.png" style="width:100%"
189+
alt="Sony MPF-90, HD media, HD drive setting">
190+
</a>
191+
</td>
192+
</tr>
193+
</table>
194+
</div>
48195

49-
The horizontal axis is the width of pulse being written; the vertical axis and
50-
heatmap shows the distribution of pulses being read back. You can see the
51-
diagonal line, which represents correct pulses. The triangular smear in the
52-
bottom right shows spurious pulses which are being read back because the
53-
interval is too great; these start at about 12us for DD disks and 7us for HD
54-
disks. This is an artifact of the different magnetic media for the two types of
55-
disk.
196+
As 3.5" drives autodetect the media type, I had to tape over the hole in a HD
197+
disk to make the drive treat it as a DD disk. Unfortunately, doing it the other
198+
way around would require drilling a hole in a DD disk, which I'm unwilling to
199+
do! So there are only three graphs here.
56200

57-
(This, by the way, is why you shouldn't use DD formats on HD disks. The
58-
intervals on a DD disk can go up to 8us, which is on the edge of the ability of
59-
an HD disk and drive to correctly report back the pulses.)
201+
We get the same smear of spurious pulses in the bottom left, but we _also_ get
202+
some incorrect pulses on the left. In addition, the line itself only starts at
203+
about 2.5µs --- it turns out that this drive simply returns nothing at all for
204+
pulses shorter than that.
60205

61-
You also note the hard cut-off on the left: this represents the filter on the
62-
drive, which will simply refuse to report pulse intervals shorter than about
63-
1.5us. FluxEngine itself can't write intervals shorter than 2us.
206+
(FluxEngine itself can't write intervals shorter than 2us.)
64207

65-
For comparison purposes, here's another set of graphs.
208+
And, finally, here is one additional pair of graphs.
66209

67210
<div style="text-align: center">
68-
<a href="fdd-90206-dd.png"><img src="fdd-90206-dd.png" style="width:40%" alt="FDD-90206, DD"></a>
69-
<a href="fdd-90206-hd.png"><img src="fdd-90206-hd.png" style="width:40%" alt="FDD-90206, HD"></a>
211+
<table class="datatable">
212+
<tr>
213+
<th></th>
214+
<th>DD drive</th>
215+
<th>HD drive</th>
216+
</tr>
217+
<tr>
218+
<th>DD media</th>
219+
<td>
220+
<a href="fdd-90206-dd.png">
221+
<img src="fdd-90206-dd.png" style="width:100%" alt="FDD-90206, DD">
222+
</a>
223+
</td>
224+
<td>
225+
</td>
226+
</tr>
227+
<tr>
228+
<th>HD media</th>
229+
<td></td>
230+
</td>
231+
<td>
232+
<a href="fdd-90206-hd.png">
233+
<img src="fdd-90206-hd.png" style="width:100%" alt="FDD-90206, HD">
234+
</a>
235+
</td>
236+
</tr>
237+
</table>
70238
</div>
71239

72240
This is from another drive I have; it's an unbranded combo
73-
card-reader-and-floppy drive unit; the 90206 is the only identification mark it
74-
has. The DD graph shows that intervals below about 4us are reported as double
241+
card-reader-and-3.5"-floppy drive unit; the 90206 is the only identification mark it
242+
has. The DD graph shows that intervals below about 4µs are reported as double
75243
what they should be: so, this drive won't work on [Macintosh 800kB
76244
formats](disk-macintosh.md) at all, because they use intervals starting at
77-
2.6us, below this limit. But it should work on PC formats --- just.
245+
2.6µs, below this limit. But it should work on PC formats --- just.
78246

doc/ju475-dd-hi.png

23.2 KB
Loading

doc/ju475-dd-lo.png

18.8 KB
Loading

doc/mpf90-dd-lo.png

18.3 KB
Loading

doc/mpf90-hd-hi.png

31.3 KB
Loading

doc/mpf90-hd-lo.png

20.9 KB
Loading

doc/sony-mpf920-dd.png

-67.9 KB
Binary file not shown.

doc/sony-mpf920-hd.png

-61.6 KB
Binary file not shown.

src/fe-analysedriveresponse.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ static IntFlag imgHeight(
6969
"Height of output graph",
7070
600);
7171

72+
static IntFlag buckets(
73+
{ "--buckets" },
74+
"Number of heatmap buckets",
75+
250);
76+
7277
/* This is the Turbo colourmap.
7378
* https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html
7479
*/
@@ -225,7 +230,7 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
225230
csv.open(writeCsv);
226231

227232
int numRows = (maxInterval - minInterval) / intervalStep;
228-
const int numColumns = 512;
233+
const int numColumns = buckets;
229234
std::vector<std::vector<double>> frequencies(numRows, std::vector<double>(numColumns, 0.0));
230235

231236
double interval;
@@ -237,16 +242,17 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
237242
std::cout << fmt::format("Interval {:.2f}: ", ticks * US_PER_TICK);
238243
std::cout << std::flush;
239244

245+
/* Write the test pattern. */
246+
240247
if (interval >= 2.0)
241248
{
242-
/* Write the test pattern. */
243-
244249
Fluxmap outFluxmap;
245250
while (outFluxmap.duration() < period)
246251
{
247252
outFluxmap.appendInterval(ticks);
248253
outFluxmap.appendPulse();
249254
}
255+
250256
usbWrite(destHead, outFluxmap.rawBytes(), 0);
251257

252258
/* Read the test pattern in again. */
@@ -353,8 +359,8 @@ int mainAnalyseDriveResponse(int argc, const char* argv[])
353359
}
354360

355361
draw_y_axis(painter, colourbarBounds.x1-5, colourbarBounds.y2, colourbarBounds.y1, 0.0, 1.0, 0.1, "{:.1f}");
356-
draw_y_axis(painter, graphBounds.x1-5, graphBounds.y2, graphBounds.y1, 0.0, 512.0/TICKS_PER_US, 5.0, "{:.0f}");
357-
draw_y_graticules(painter, graphBounds.x1, graphBounds.y2, graphBounds.x2, graphBounds.y1, 0.0, 512.0/TICKS_PER_US, 5.0);
362+
draw_y_axis(painter, graphBounds.x1-5, graphBounds.y2, graphBounds.y1, 0.0, buckets/TICKS_PER_US, 5.0, "{:.0f}");
363+
draw_y_graticules(painter, graphBounds.x1, graphBounds.y2, graphBounds.x2, graphBounds.y1, 0.0, buckets/TICKS_PER_US, 5.0);
358364
draw_x_axis(painter, graphBounds.x1, graphBounds.x2, graphBounds.y2+5, minInterval, maxInterval, 5.0, "{:.0f}");
359365
draw_x_graticules(painter, graphBounds.x1, graphBounds.y1, graphBounds.x2, graphBounds.y2, minInterval, maxInterval, 5.0);
360366

0 commit comments

Comments
 (0)