Hello and thanks for the replies!
As a lecturer, I never present all that can be said, and when
posting the idea of a DDS basing on the Chinese Remainder Theorem,
I hoped to get response. And it was my feeling, Alberto will ask,
how to get the phase increment. He did it, and Zim contributed the
example and a very useful link. Thanks! That is encouragement
to set my priorities new.
My problem is lack of time. So, what I shall do is: first try to
answer your questions here directly, and second, hopefully, post
something in a readable form later somewhere.
Indeed, Chapter 12 of my course material on Digital Signal Processing
is "Direct Digital Synthesis". The material is completely made for
interactive e-learning. It is not public domain, but for private use
in the ham-radio area, I have no problem to send it on request. But
it requires MATLAB (5.0 or higher, Student Edition works o.k.). You
will not be able to see the text or any of the graphs and movies or
hear the audio or change anything interactively without MATLAB.
The Chapter 12 alone containes nearly a hundred computer pages, all
in German, sorry. To press this into a stone-aged dead read-only
paper is not so easy.
Now to the question of Alberto:
Let z(k) (k=1,...,n) be n different numbers that are used as
length of cos/sin-tables and let p(k) be the natural phase increments
within these tables. No two of the z(k) should have any factor in
common. Prime numbers for p(k) are optimal for best SFDR, but not
required. For shortness, we set Z = product of all z(k).
To get the p(k), two steps have to be done:
(1) Determine the p(k) for generation of the smallest possible
positive frequency, the frequency step df = fs/Z (fs = sampling
frequency). We denote them p1(k).
(2) Determine the p(k) for generation of frequency f = m * df .
Let me start with the second (2). The p(k) are simply m*p1(k). But
m and p1(k) possibly are large, so the angles m*p1(k) can be very
large, i.e. many wrap-arounds in the table of length z(k) plus a
remainder. We therefore only take the remainder:
p(k) = remainder of division ( m*p1(k) / z(k) )
Example: n=3; z(1)=29; z(2)=83; z(3)=599; Z=1441793;
p1(1)=8; p1(2)=45; p1(3)=109;
fs = 11025 Hz; df = 11025/1441793 = 0.007647 Hz
f = 800 Hz; m = round(f/df) = 104620;
p(1)= remainder of division ( 8 * 104620) / 29 = 20
p(2)= remainder of division ( 45 * 104620) / 83 = 57
p(3)= remainder of division (109 * 104620) /599 = 417
Proof: The three individual tables yield with the computed increment
the frequencies fs*20/29=7603.4; fs*57/83=7571.4; fs*417/599=7675.2 Hz
The sum of them modulo the sampling frequency fs is 800.000763 Hz.
Because the signals are complex (cos + i*sin) there is no alias or
mirror within the frequency interval 0 ... fs.
The computation (1) of the p1(k) is not so easy, but it has to be
done only once. The table k with the increment p1(k) yields the
relative frequency f1(k)/fs = p(k)/z(k). The product of all complex
(cos + i*sin)-waves gives the sum of all these frequencies. This sum
must be equal to the relative frequency step df/fs = 1/Z.
Multiplying the resulting equation by Z yields
remainder of ( sum of all Z*p1(k)/z(k) ) / Z ) = 1
This is an equation that is to be solved with natural numbers p1(k).
Equations of this type are called diophantine after Diophantos from
Alexandria. Zim found the link to a mathematical discussion of this
problem by E.L. Lady. I made a simple MATLAB-function that solves
the problem. It is available on request.
And here the answer to John, G4CNN
My post surely was a bit cryptic and misunderstanding was probable.
Indeed, the frequency is divided in steps of fs/29 by the first
generator. But the others are in parallel, and not serial. So they
generate fs/83 and fs/599 as their frequency steps, not a finer and
finer division of the first. Therefore the Chinese Remainder Theorem
is required, but you are right, prime numbers are not necessary.
Sorry for the cryptic assembly program. It performs the two complex
multiplications and additions per otput sample and in parrallel the
6 table look ups, the 3 phase increments, and the write into an
output buffer with auto-increment of its address. It is fascinating
for me to see all the many parts of the old DSP-architecture 100%
busy in every clock cycle, such that this processor can generate sin
and cos up to an output frequency of 2.5 MHz with a processor clock
of 40 MHz.
Now the question of Zim
<In the special case where the increment value is a power of two
<(1,2,4,8,16,etc), the DDS steps land exactly on the minima and
<maxima of the wave (eg includes counts of 0, 64, 128, 193, 256).
<At all other frequencies the samples miss the min/max/zero and
<thus the output contains some jitter (unless considerable "Q" is
<available to act as a Flywheel).
That depends on the initial phase which can be any number 0 ... 255.
<The above is (I think) the Address Quantitisation which Klaus
<mentions.
No. In your case (and in that I posted) we use a phase accumulator
that is used as address into a table without cutting away lower
bits as it must be done in conventional DDS design in order to
obtain both, small frequency step and resonably small table.
In your as in my case there is definitely no phase jitter. The
SFDR only is produced by the quantization of the cos/sin-values
in the table and by the arithmetic. And here is the advantage
of primes for table lengths: with any phase step the table is
stepped through all values of the table thereby averaging the
effect of quantization.
(As an exercise design a DDS that requires less than 1k memory for
fs = 44100 Hz and df = 1.000000 Hz)
73 de Klaus, DJ5HG
|