diff --git a/README.md b/README.md index b21a1ee5..d832ccd8 100644 --- a/README.md +++ b/README.md @@ -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? ------ diff --git a/doc/driveresponse.md b/doc/driveresponse.md index c80c21d0..2b67d7db 100644 --- a/doc/driveresponse.md +++ b/doc/driveresponse.md @@ -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)
-Sony MPF-920, DD -Sony MPF-920, HD + + + + + + + + + + + + + + + + +
DD driveHD drive
DD media + + Panasonic JU-475, DD media, DD drive setting + + + + Panasonic JU-475, DD media, HD drive setting + +
HD media + + Panasonic JU-475, HD media, DD drive setting + + + + Panasonic JU-475, HD media, HD drive setting + +
-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)
-FDD-90206, DD -FDD-90206, HD + + + + + + + + + + + + + + + + +
DD driveHD drive
DD media + + Sony MPF-90, DD media, DD drive setting + + +
HD media + + Sony MPF-90, HD media, DD drive setting + + + + Sony MPF-90, HD media, HD drive setting + +
+
+ +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. + +
+ + + + + + + + + + + + + + + + + +
DD driveHD drive
DD media + + FDD-90206, DD + + +
HD media + + FDD-90206, HD + +
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. diff --git a/doc/ju475-dd-hi.png b/doc/ju475-dd-hi.png new file mode 100644 index 00000000..2544637a Binary files /dev/null and b/doc/ju475-dd-hi.png differ diff --git a/doc/ju475-dd-lo.png b/doc/ju475-dd-lo.png new file mode 100644 index 00000000..94eb782f Binary files /dev/null and b/doc/ju475-dd-lo.png differ diff --git a/doc/mpf90-dd-lo.png b/doc/mpf90-dd-lo.png new file mode 100644 index 00000000..e763bfa2 Binary files /dev/null and b/doc/mpf90-dd-lo.png differ diff --git a/doc/mpf90-hd-hi.png b/doc/mpf90-hd-hi.png new file mode 100644 index 00000000..d1fa10ba Binary files /dev/null and b/doc/mpf90-hd-hi.png differ diff --git a/doc/mpf90-hd-lo.png b/doc/mpf90-hd-lo.png new file mode 100644 index 00000000..5a57a0c6 Binary files /dev/null and b/doc/mpf90-hd-lo.png differ diff --git a/doc/sony-mpf920-dd.png b/doc/sony-mpf920-dd.png deleted file mode 100644 index bd3c55fd..00000000 Binary files a/doc/sony-mpf920-dd.png and /dev/null differ diff --git a/doc/sony-mpf920-hd.png b/doc/sony-mpf920-hd.png deleted file mode 100644 index 22ea99e6..00000000 Binary files a/doc/sony-mpf920-hd.png and /dev/null differ diff --git a/src/fe-analysedriveresponse.cc b/src/fe-analysedriveresponse.cc index b49962fd..a915edca 100644 --- a/src/fe-analysedriveresponse.cc +++ b/src/fe-analysedriveresponse.cc @@ -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> frequencies(numRows, std::vector(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);