|
|
Digital quadrature oscillator, part 2IntroductionThe previous page explained, how to generate a quadrature LO signal.Calculating sine and cosine is expensive, and it may be better to use a table (wavetable). This is straightforward, as long as the length of an LO cycle is a full number of clock cycles. Frequency translation by Now how about other, arbitrary frequencies? Interpolation allows to use the wavetable approach for a conversion frequency with an arbitrary period length. The example uses zero-order interpolation (nearest neighbor). It is simple to implement, but suffers from aliasing at higher frequencies. Alias products scale proportionally with the LO frequency. They can be reduced by using higher wavetable resolution, or better interpolation methods. Example code/* ***************************************************
* Example for a quadrature oscillator using a wavetable
* It can be used in situations, where evaluating sin() and
* cos() is too expensive.
* It uses nearest-neighbor interpolation, which will cause
* severe aliasing at higher frequencies.
*
* Markus Nentwig, 2007
* This program is in the public domain
*/
#include <stdio.h>
#include <math.h>
#include <assert.h>
/* number of points in the wavetable */
/* assuming 32 bit int */
#define NINTBITS 10
#define NFRACBITS 20
#define TLEN (1<<NINTBITS)
#define MASK ((1<<(NFRACBITS+NINTBITS))-1)
#define PI 3.14159265358979
int main(void){
/* wavetable, one period */
float I[TLEN];
float Q[TLEN];
int index;
/* Startup: build wavetable */
for (index=0; index < TLEN; ++index){
float p=2.0*PI*(float)index/(float)TLEN;
I[index]=cos(p);
Q[index]=-sin(p); /* upconconversion */
/* alternative: Q[index]=+sin(p); for downconversion */
}
/* Operation: generate sine wave */
float fsample=38.4e6; /* sampling frequency */
float fLO=1e6; /* LO frequency */
float f_increment=fLO/fsample*(float)(1<<(NFRACBITS+NINTBITS));
unsigned int increment=(int)(f_increment+0.5); /* round */
int count=10000;
unsigned int phase=0;
while (--count){
int index=(phase>>NFRACBITS);
assert(index < TLEN);
printf("%1.7f\t%1.7f\n", I[index], Q[index]);
/* advance oscillator phase */
phase += increment;
/* wrap around full cycle */
phase &= MASK;
}
return 0;
}
download wavetable.c Compilation:
RunningUnix:
Windows MSYS etc:
PlottingGnuplot:
Result
© Markus Nentwig 2007-2008 The content of this page is provided without any warranty and may not be reproduced without permission. Comments? Questions?Please send me a mail! mnentwig@elisanet.fi |