Software-based floppy disc data separator
classiccmp at philpem.me.uk
Tue Jun 15 10:37:07 CDT 2010
On 15/06/10 16:10, Chuck Guzis wrote:
> On 15 Jun 2010 at 8:39, Philip Pemberton wrote:
>> No -- the hardware only stores "time since last edge". So the edges
>> are always one "virtual nanosecond" wide. The code extends these to
>> two PLL clock cycles for the DPLL counter reset, and also stores
>> whether there was a data pulse (transition) in the current data
> Okay, it was the commentary that was throwing me off. This looks
> something like the code that I use.
I've done a bit of improvement on the commenting (see below) -- this
should clarify it a bit. Also, I got GCD mixed up with LCM -- you want
the greatest common divisor to set TIMER_INCREMENT, not the lowest
Ideally you want NSECS_PER_* to be as low as possible, and
TIMER_INCREMENT as close to 1 as possible. Pick a pair of NSECS_PER_...
values which have a common factor, then divide both by that factor and
leave TIMER_INCREMENT set to 1.
If you want speed over all else, you can increase TIMER_INCREMENT
further, which will speed up the loop at a cost of killing accuracy. You
might be able to turn the clock-error accumulators into floating point
values, but IME you usually need double-precision for that, and floating
point math tends to be slower than integer math (even on modern CPUs
with fast FPUs).
At the end of the day, it's a starting point...
> * This is a software implementation of Jim Thompson's Phase-Jerked Loop
> * design, available from AnalogInnovations.com as the PDF file
> * "FloppyDataExtractor.pdf".
> * This consists of:
> * A data synchroniser which forces RD_DATA to be active for 2 clock cycles.
> * A counter which increments constantly while the PLL is running, and is
> * reset to zero when a data bit is detected.
> * A flip-flop which changes state when the counter reaches half its maximum
> * value
> * The actual values of NSECS_PER_ACQ and NSECS_PER_PLLCK don't really matter.
> * What actually matters is the ratio between the two -- if you have a 40MHz
> * acquisition clock and a PLL clock of 16MHz (data rate 500kbps), then the
> * starting values will be NSECS_PER_ACQ=25 and NSECS_PER_PLLCK=62.5. Problem
> * is, 62.5 isn't an integer multiple, so we might have issues with
> * short-term clock jitter. So we multiply by two, which gives us
> * NSECS_PER_ACQ=50 and NSECS_PER_PLLCK=125, and a timestep of 0.5ns. Much
> * better.
> * We can also change the PJL Counter maximum value if it makes the math
> * work out better. Be careful though -- reducing the value WILL reduce the
> * number of available phase-shift steps and thus the PLL accuracy.
> * Now we know the ticks-per-acqclk and ticks-per-pllclk values, we can
> * figure out the optimal timer increment --
> * TIMER_INCREMENT = gcd(NSECS_PER_ACQ, NSECS_PER_PLLCK)
> * (gcd == greatest common divisor)
> * Ideally we want a TIMER_INCREMENT greater than 1. If we get an increment
> * of 1, then the loop has to run at 1x speed and will be SLOW. Try
> * increasing NSECS_PER_ACQ and NSECS_PER_PLLCK (multiply them by the same
> * number e.g. 2, 4, 8, ...), then run the gcd again. Problem is, this isn't
> * going to gain much if anything in speed because you're going to be running
> * more loops at a faster rate, thus it's a zero-gain :-/
classiccmp at philpem.me.uk
More information about the cctalk