dan@irtelemetrics.com said:
I'm looking for a quick and dirty algorithm or method to generate a pulse
train at arbitrary frequencies based on a fixed clock source. This will be
run as code in a timer ISR in a microcontroller, so some
Google for DDS.
The hardware implementation is simple. Consider a register, as wide as you
like. Think of that register as a fraction. An overflow would be a whole
integer 1.
Each cycle, you add a number to that register. The output signal is the top
bit.
If your register is N bits wide and you add K each cycle:
Fout = Fin * K/2^N
K = 2^N * Fout / Fin
The output signal will have spurs. (unless there is only 1 bit turned on in K)
The output frequency will be rock solid, but it may not be the one you want. You can get closer by making the N bigger (register wider) and filling in more low order bits of K.
If you have a graphics background, it's the same math as Bresenham's algorithm for drawing slanted lines.
--
These are my opinions. I hate spam.
I did something similar in the Beaglebone Black AM335x PRU. Division is
done using a delay loop with variable number of cycles instead of an
interrupt. Converting a delay with a fractional amount to integer is
essentially a quantization problem. I'm using a triangular PDF dither
and first order noise shaping/error feedback ([1], last slide). The
dither randomizes the errors which should eliminate spurs. The feedback
reduces the error at DC to zero but will increase the jitter at high
frequencies. Zero error at DC means the time interval error (TIE) will
not drift. I don't have equipment to test the implementation in the BBB
so I'm just assuming it works.
The disadvantage is that you need a PRNG and do fixed point arithmetic.
I think this method is related to sigma-delta fractional-N techniques in
PLLs.
[1] Udo Zölzer, Quantization_Web_Summary.pdf
http://www.hsu-hh.de/ant/index_vNIYuPdokWfAvSaT.html
The code below is a Matlab/Octave simulation which plots the TIE and TIE
jitter spectrum.
% -------------------------------------------------------------------------
% cycle period (200 MHz)
T = 1/200e6;
% output frequency
f = 24000;
% delay in clock cycles, with fractional part
delay = 1/(f*T);
% enable/disable error feedback
feedback = true;
err = 0;
t = zeros(2048, 2);
for i = 2:2048
% exact
t(i,1) = t(i-1,1) + delay;
d2 = delay - err;
% add triangular PDF noise then quantize
qd = floor(d2 + rand()+rand()-0.5);
if feedback
err = qd - d2;
end
% delay d3 cycles
t(i,2) = t(i-1,2) + qd;
end
tie = t(:,1)-t(:,2);
plot(tie);
title('Time interval error (cycles)');
figure;
f = fft(tie);
f = f(1:end/2);
plot(20*log10(abs(f)));
title('TIE jitter spectrum');