[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