[sdiy] Update - OT - Linear interpolation in C
Tom Wiltshire
tom at electricdruid.net
Wed Feb 2 14:56:57 CET 2011
Hi all,
I thought some of you might be interested to see how I solved the fixed-point maths / linear interpolation problem I asked about the other day. Basically I followed the advice I got here, and put an assembly routine in to do the interp, which is then called from the C.
It goes in its own source file ("assembly.s") and looks like this:
; Declare the functions as global so they're visible to C code
.global _Lerp
;=============================================================
; Linear interpolation
;=============================================================
; This routine is called from C as:
; signed int Linterp(signed int point1, signed int point2, unsigned int index);
;
; These variables come into assembly as:
; W0 - point1
; W1 - point2
; W2 - index
; In addition, we use W3, W4, W5, W6 and W7 for the calculation.
_Lerp:
; Move the points to where the MAC can use them
mov W0, W4
mov W1, W5
; Build the indexes
mov #0X7FFF, W3
lsr W2, W7 ; Shift down to avoid sign bit, index in W7
xor W7, W3, W6 ; 1-index in W6
; Do the interp
mpy W4*W6, A
mac W5*W7, A
; Get the result and return
sac.r A, W0
return
Once you've got this in place, you can easily call it from C like this:
case LFO_SINE:
// Generate linearly interpolated sinewave from the 256-entry waveform table
// The top 8 bits of the PHASE are used for the table lookup. The next 16
// bits are used for the linear interpolation.
sample = Lerp(sine[lookup] , sine[(lookup+1)& 0xFF], this->phase >> 8);
break;
(This is part of a switch statement that deals with each of the different waveforms). the "lookup" variable is defined earlier like this:
unsigned int lookup = (this->phase >> 24); // The top 8-bits
The interesting bit is the way that variables are passed between C and assembly by the compiler. Basically it starts at W0 and uses registers in order as far as possible. Since I've got three 16-bit variables, this is a simple case and they just go into W0, W1 and W2. There's lots about this in the C30 guide.
Hope this helps someone,
Tom
More information about the Synth-diy
mailing list