this *should* be a relatively simple issue, but i am confused
I've been studying an approach to implementing a lookup table (LUT) to
implement a sine function. The two msbs of the phase define the
quadrant. I have decided that an 8 bit address for a single quadrant is
sufficient with an 18 bit output.
10 bits or 1024 points. since you're doing linear interpolation, add one
more, copy the zeroth point x[0] to the last x[1024] so you don't have
to do any modulo (by ANDing with (1023-1) on the address of the second
point. (probably not necessary for hardware implementation.)
x[n] = sin( (pi/512)*n ) for 0 <= n <= 1024
So you are suggesting a table with 2^n+1 entries? Not such a great idea
in some apps, like hardware.
i think about hardware as a technology, not so much an app. i think
that apps can have either hardware or software realizations.
in *software* when using a LUT *and* linear interpolation for sinusoid
generation, you are interpolating between x[n] and x[n+1] where n is
from the upper bits of the word that comes outa the phase accumulator:
#define PHASE_BITS 10
#define PHASE_MASK 0x001FFFFF // 2^21 - 1
#define FRAC_BITS 11
#define FRAC_MASK 0x000007FF // 2^11 - 1
#define ROUNDING_OFFSET 0x000400
long phase, phase_increment, int_part, frac_part;
long y, x[1025];
....
phase = phase + phase_increment;
phase = phase & PHASE_MASK;
int_part = phase >> FRAC_BITS;
frac_part = phase & FRAC_MASK;
y = x[int_part];
y = y + (((x[int_part+1]-y)*frac_part + ROUNDING_OFFSET)>>FRAC_BITS);
now if the lookup table is 1025 long with the last point a copy of the
first (that is x[1024] = x[0]), then you need not mask int_part+1.
x[int_part+1] always exists.
Also, why 10 bit
address for a 1024 element table?
uh, because 2^10 = 1024?
that came from your numbers: 8-bit address for a single quadrant and
there are 4 quadrants, 2 bits for the quadrant.
My calculations indicate a linear
interpolation can be done with 4 ppm accuracy with a 256 element LUT.
I'm not completely finished my simulation, but I'm pretty confident this
much is corrrect.
i'm agnostic about the specs for your numbers. you are saying that 8
bits per quadrant is enough and i am stipulating to that.
No, that is the phase sent to the LUT. The total phase accumulator can
be larger as the need requires.
why wouldn't you use those extra bits in the linear interpolation if
they are part of the phase word? not doing so makes no sense to me at
all. if you have more bits of precision in the fractional part of the phase
Yes, thanks for the correction. The max error? I'm not so worried about
that exactly. The error is a curve with the max magnitude near the
middle if nothing further is done to minimize it.
I'm talking about the LUT. The LUT only considers the first quadrant.
not in software. i realize that in hardware and you're worried about
real estate, you might want only one quadrant in ROM, but in software
you would have an entire cycle of the waveform (plus one repeated point
at the end for the linear interpolation).
and if you *don't* have the size constraint in your hardware target and
you can implement a 1024 point LUT as easily as a 256 point LUT, then
why not? so you don't have to fiddle with reflecting the single
quadrant around a couple of different ways.
No, not quite right. There is a LUT with points spaced at 90/255 degrees
apart starting at just above 0 degrees. The values between points in the
table are interpolated with a maximum deviation near the center of the
interpolation. Next to 90 degrees the interpolation is using the maximum
interpolation factor which will result in a value as close as you can
get to the correct value if the end points are used to construct the
interpolation line. 90 degrees itself won't actually be represented, but
rather points on either side, 90±delta where delta is 360° / 2^(n+1)
with n being the number of bits in the input to the sin function.
i read this over a couple times and cannot grok it quite. need to be
more explicit (mathematically, or with C or pseudocode) with what your
operations are.
Yes, it is a little tricky because at this point we are working with
integer math (or technically fixed point I suppose).
not with defining the points of the table. you do that in MATLAB or in
C or something. your hardware gets its LUT spec from something you
create with a math program.
Rounding errors is
what this is all about. I've done some spreadsheet simulations and I
have some pretty good results. I updated it a bit to generalize it to
the LUT size and I keep getting the same max error counts (adjusted to
work with integers rather than fractions) ±3 no matter what the size of
the interpolation factor. I don't expect this and I think I have
something wrong in the calculations. I'll need to resolve this.
We are talking about the lsbs of a 20+ bit word. Do you think there will
be much of a difference in result?
i'm just thinking that if you were using LUT to generate a sinusoid that
is a *signal* (not some parameter that you use to calculate other
stuff), then i think you want to minimize the mean square error (which
is the power of the noise relative to the power of the sinusoid). so
the LUT values might not be exactly the same as the sine function
evaluated at those points.
I need to actually be able to do the
calculations and get this done rather than continue to work on the
process. Also, each end point affects two lines,
what are "lines"? not quite following you.
so there are tradeoffs,
make one better and the other worse? It seems to get complicated very
quickly.
if you want to define your LUT to minimize the mean square error,
assuming linear interpolation between LUT entries, that can be a little
complicated, but i don't think harder than what i remember doing in grad
school. want me to show you? you get a big system of linear equations
to get the points. if you want to minimize the maximum error (again
assuming linear interpolation), then it's that fitting a straight line
to that little snippet of quadratic curve bit that i mentioned.
How does that imply a quadratic curve at 90 degrees?
sin(t) = t + ... small terms when t is small
cos(t) = 1 - (t^2)/2 + ... small terms when t is small
At least I think like the greats!
but they beat you by a few hundred years.
![Smile :) :)](data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)