Linear interpolation in direct digital synthesis

I am working on a DDS microcontroller project in C, and I have some problems figuring out how to calculate linear interpolation to smooth out the output values. The program in its current form
uses the upper 8 bits of a 24-bit battery as an index for an array of 8-bit output values. I need to come up with a function that will take the middle and lower bytes of the battery and create a value between the "previous" and "next" value in the array. That would be easy enough on fast hardware, but since I use a microcontroller, I really need to avoid floating point operations or units!

With these limitations, I'm not sure that I need to get an 8-bit interpolation value from my two 8-bit input numbers and the bottom 2 bytes of the battery, which is the "distance" between the two value inputs. Thank you in advance for any advice!

EXPLANATION

DDS = Direct Digital Synthesis

in DDS, a waveform is generated from a lookup table using a phase accumulator. The phase accumulator typically contains an integer component and a fractional component. The integer component is used as an index in the lookup table. In simple DDS implementations, the fractional part is ignored, but to obtain higher quality, the fractional component is used to interpolate (usually only linear interpolation) between adjacent values ​​of the lookup table. On the above question, we will consider how to effectively perform this linear interpolation between the two values ​​of the lookup table for a given fraction, f, where 0 <= f < 1.

+5
source share
5 answers

, ( , ), . , , N = 256 LUT[N], , LUT_delta[N]. LUT_delta[i] = LUT[i+1] - LUT[i]. LUT[i] LUT[i+1], , , LUT[i] delta, LUT_delta[i] . , . , DSP, + + CPU . , LUT LUT_delta, LUT[i] LUT_delta[i] , .

-:

extract integer LUT index, i, from accumulator // just need a shift for this
extract fractional part of accumulator, f // mask or subtract to get f
get p = LUT[i] // lookup waveform value
get delta = LUT_delta[i] // lookup delta
calculate p_interp = p + p_delta * f // single multiply-accumulate instruction on most DSPs - need scaling on general purpose CPUs
+7

, , 2.

(x) = ,
(x + 1) = next (x + dx) = + ( - ) * dx

: dx? , (16 ) , (dx = 1) :

value(x + dx) = previous + ((next - previous) * index) / 1024

, 1024 dx = 1. Index = 512 dx = 0,5 ..

+4

, . , 4 1:

Acc += 0x2000;
uint lower_bits = Acc & 0xffff;
int rl = LUT[ Acc >> 16];
int rh = LUT[(Acc >> 16) + 1];
if (lower_bits < 0x4000)
    return rl;
if (lower_bits < 0x8000)
    return (rl * 3 + rh) >> 2;
if (lower_bits < 0xC000)
    return (rl + rh) >> 1;
return (rl + rh * 3) >> 2;
+1

, AVR.

0

a b (a + b)/2.

.

Divide-by-2 == right shift one bit.

-1
source

All Articles