• Please review our updated Terms and Rules here

RetroChallenge Jan 2016: MFM Primer (Alt: It's Like the Option Board, Except Not)

cr1901

Veteran Member
Joined
Dec 28, 2011
Messages
817
Location
NJ
Despite amazing progress last week, real life continues to be in the way. I need to work on time management skills in order to get more things done in a timely manner.

Last week, I created a circuit on a breadboard attached to Mercury, a breadboard-friendly FPGA dev board. The resulting contraption is a little... less neat than I would like it to look, not to mention that I don't have the proper TTL parts ad mentioned in the previous entry. I'm in the process of making a floppy breakout board when I have the extra money to get some made so that I can easily continue my work.

So, did I make a floppy controller on FPGA? Sadly no :(. I hesitated on the PLL design and spent to much time verifying that my setup even worked in the first place. However, I did at least verify that as is, I am collecting real data from the drive. I'm not going to get to discussing IBM track format in detail by the time RetroChallenge is over, but I do intend to work on these blog posts after RetroChallenge ends.

MFM Encoding
Right now, I'm going to introduce Modified Frequency Modulation Encoding, or MFM encoding, as promised. MFM encoding, as the name suggests is an extension to FM encoding that removes some clock bits from the equivalent FM signal in order to guarantee that signal voltage transitions, or logic level transitions if you prefer, happen no sooner and no later than a specific interval of time.

Like in FM, this interval of time can be represented in terms bit cells (though a single clock interval need not constitute a bit cell). Recall that in FM, bit cells are referenced with respect to signal voltage transitions. The start of bit cells are delineated by clock bits, and the middle of which are indicated where the whether data is logic 0 or 1, no bit written and bit written respectively. When I say "clock bits" and "data bits", I mean a logical one being written, or the data signal having a logic level transition. Let's call this "something happening" to the data signal. A logical 0 in that data stream is a "bit not written", or "nothing happening", in these types of encodings. The signal simply retains its previous voltage level. FM works by making sure that "something happening" always occurs (clock) followed by something or nothing happening a short period of time later (data). The time interval between events is limited by magnetic media; not too close together or fun magnetic effects ruin the data signal.

So if MFM removes some clock bits to give the data signal desireable properties, how do we always know where a bit cell begins? Using the clock and bits that do remain, it's possible to simultaneously distinguish which transitions are data and clock, while being able to recover/infer the missing clock transitions; data 1's are always written in MFM, so those transitions always occur. This is why a PLL is needed; a PLL is capable of tracking where missing clock transitions should be, and can also use data transitions to infer where clock transitions should be. Sadly, I'm not going to be able to get into why this is so right now, but TLDR; the signal transitions that are left over after MFM encoding is applied, both clock and data, can be used to infer where the missing clock transitions should be.

If too many signal transitions are missing, it becomes possible for circuitry meant to recover the clock and data not be able to do so reliably. Data transitions with a recovered clock that's out of sync can be completely missed, a situation called bit slip. To help prevent this, MFM encoding makes sure to place limits on the number of consecutive lack of transitions- zeros- that a properly encoded data stream can have (three). In addition, MFM ensures that there will be at least one time interval between data transitions where a data transition does not occur. Bit cells will therefore only have one or zero transitions; we can halve the amount of physical space that each bit cell takes on the magnetic medium to get the same number of transitions per unit length as FM, which has up to two transitions per bit cell! This is the reason we do MFM encoding in the first place!

The below image (and corresponding WaveDrom JSON) shows how the byte "C2" is encoded in an FM and MFM stream. Note that the write clock in the MFM signal is doubled, but the the transitions remain the same distance apart as FM, while encoding a bit in zero or one transitions instead of one or two. Because in a real circuit the important part of a logical one is the leading edge, which toggles a coil's current direction, the pulse length for clock and data bits should be treated as symbolic only. The spacing between pulse leading edges, however, is proportional.
4or9wBO.png

Code:
{signal: [
  ['fm',
    {name: 'wr_clk', wave: 'p...............', period: 2},
    ['FF', {name: 'clk', wave: 'pl..pl..pl..pl..pl..pl..pl..pl..', period: 1}],
    ['C2', {name: 'data', wave: 'l.pl..pl..................pl....', period: 1}],
    ['FAAE', {name: 'comp', wave: 'plplplplpl..pl..pl..pl..plplpl..', period: 1}],
  ],
  {},
  ['mfm',
    {name: 'wr_clk', wave: 'p...............', period: 1},
    ['1C', {name: 'clk', wave: 'l.....plplpl....', period: 1}],
    ['C2', {name: 'data', wave: 'lplpl........pl.', period: 1}],
    ['52A4',{name: 'comp', wave: 'lplpl.plplpl.pl.', period: 1}],
  ]
]}


For all these points that need to be considered, MFM encoding is actually pretty simple and can easily be done on paper:
  • A data one is always encoded using the bit pattern 01
  • If the current data zero was preceded by a data zero, encode zero as 10.
  • If the current data zero was preceded by a data one, encode zero as 00.

Indeed, the same data pattern has multiple valid MFM encodings based on what preceded it. I'll get to that in a future post. Something important to gleam from this is that not all sequences that satisfy MFM encoding rules are actually generated from MFM encoding; a real floppy disk controller in fact uses these sequences for control information in a form of in-band signaling.

Using Litescope and an Ipython notebook, both of which I will publish after I clean it up, I was able to determine that my current setup can read floppy signals correctly. Writes are another matter that I'm not addressing yet!

https://twitter.com/cr1901/status/690832221305896961
CZZUPowWIAI4d6W.png

This is the MFM sync mark immediately after the floppy index from data that I collected at 2.5 MHz sample rate. Note that the signal is "normally high" because of processing on the floppy drive that limits the time the signal is spent low; It does not reflect how the signal is actually stored.

https://twitter.com/cr1901/status/690845693259440128
CZZgf0RUAAAfGpV.png

This is the C2 sync mark with a missing clock bit. The normal MFM encoding of C2 is 0101001010100100; the captured signal is 0101001000100100. This is deliberate, and the topic of another post.

Storing a whole track is prohibitive in my current setup w/o compression, as it requires about 1.5MB raw when I previously calculated it, even at 2.5 MHz sample rate. But in effect, I'm close to creating a new Option Board :D!

Now about that PLL/clock recovery circuit...
 
Back
Top