Tim's own version of the Catweasel/Compaticard/whatever

From: Tim Mann <mann_at_pa.dec.com>
Date: Wed Jul 5 17:17:39 2000

I can't keep track of all the directions this discussion is going in, but
here are a few bits of information that might be useful.

My software for reading FM and MFM with the Catweasel is available from
my Web pages, so you can look at the source code for details of what it
does, adapt it to work with different hardware if you prefer to build
your own, dissect it and note all its shortcomings, ignore it, or whatever.
See www.tim-mann.org/trs80resources.html. There's also a link there to
the Linux drivers for the card, which include some writing support and
have a different implementation of reading (but which uses the same idea),
so you can look at that source code too.

The basic idea for reading is very simple. I have two thresholds, t1
and t2. Given a sample s, if s <= t1, I classify it as short (10); if
t1 < s <= t2, as medium (100); if t2 < s, as long (1000). This lets me
reconstruct the MFM clock/data bit stream. I set the thresholds statically,
by looking at histograms of samples from various tracks of different disks,
and placing the thresholds rougly in the middle of the valleys between
the three observed peaks. This technique is crude (maybe it would be
better to emulate a phase locked loop in software, for instance), but
it works well for 3.5" and 5.25" disks, and some 8" disks too. I'll come
back to the other 8" disks in a bit.

When I said something about "bit-shifting" with the Catweasel, I was *not*
talking about reading the same track repeatedly and getting different results.

On what I was *not* talking about: I haven't done any systematic tests
to see how much the sample data read from a track varies from one attempt
to another. I do know that when I fail to decode some data (getting a
CRC error), rereading the track sometimes helps. I would expect some
variation from one read to the next because the magnetic signal on the
disk doesn't really have sharp edges; the electronics inside the drive
that decide where the flux transitions are going to produce somewhat
different results from one try to the next. I would expect this is worse
on old disks that are fading or where tiny bits of oxide are starting
to flake off.

On what I *was* talking about: There is a physical effect where two flux
transitions that are recorded close together tend to move apart. An Intel
FDC data sheet that I have calls this effect "bit-shifting", but I don't
know whether that's a standard term or not. Write precompensation
approximately corrects for this effect, but not exactly. On some 8" disks
that I've read, I've seen severe cases of this effect, enough that I had
to put a heuristic into my program to compensate for it. On at least
a few disks, the effect increased up to track 43, backed way off at track
44, and then slowly increased again; this is consistent with the disk
having been written in a system that turns on write precomp using the
TG43 (track greater than 43) signal, but that doesn't have enough precomp.
The size of the errors I've seen is much more than one Catweasel clock,
so it doesn't have anything to do with the Catweasel sample rate beating
against the data rate.

So, what's the heuristic? It's quite crude and oversimplified too, but
seems to work pretty well. The general idea is that if an interval is
a bit off from what you were expecting it to be, multiply the error by
some factor around 0.5 to 0.8 (you sometimes have to tune it for each
disk if they are particularly bad), and add that to the next interval
before classifying it as short, medium, or long. This helped immensely,
making some disks that previously had a CRC error on about half the tracks
even after many retries read perfectly, with no retries. Here is some
code that should make it clearer:

mfm_decode(int sample)
  static float adj = 0.0;
  int len;

  if (sample + adj <= mfmthresh1) {
    /* Short */
    len = 2;
  } else if (sample + adj <= mfmthresh2) {
    /* Medium */
    len = 3;
  } else {
    /* Long */
    len = 4;
  adj = (sample - (len/2.0 * mfmshort)) * postcomp;

  if (out_fmt == OUT_SAMPLES) printf("%d%c ", sample, "--sml"[len]);

  while (--len) mfm_bit(0);

Tim Mann tim.mann_at_compaq.com http://www.tim-mann.org
Compaq Computer Corporation, Systems Research Center, Palo Alto, CA
Received on Wed Jul 05 2000 - 17:17:39 BST

This archive was generated by hypermail 2.3.0 : Fri Oct 10 2014 - 23:32:56 BST