Kipróbálván az FFT algoritmust egy DSP-n, a következő oldalon levőket kaptam. De előtte egy kis áttekintés:
Harvard architektúrájú DSP, 12 analóg bemenettel, 2 full-duplex UART-tal, 16× belső PLL-el, max 30MIPS, hogy csak a fontosabb paramétereket említsem.
Erre programoztam egy FFT-t, a C30-as compiler függvényeit és példaprogramjait felhasználva. Nem volt igazi nagy munka, hiszen szinte minden függvény már megvolt, csak meg kellett őket hívni.
Maga az FFT-számítás, a butterfly algoritmusok meg a keresztbeszorzás mind-mind assembly nyelven van leprogramozva a kis programmemóriát megcélozva.
A forrást nem fogom sorrol-sorra bemutatni, inkább egy ilyen áttekintést próbálok nyújtani:
// 1.) SAMPLING
UARTsendString("Sampling with 256 samples started.\n\0");
T1CON = 0x8000; //prescaler of T1 decrease to 1-divide
for (i=0; i
//these operations take appr. 50 ASM commands, we have time by 32000s/sec for 625
TMR1=0;
sigCmpx[i].real = ADC10read(0);//read analogue for each sample
// 0V ... 0x0000, 5V ... 0x0FFF (4095)
while (TMR1 < 0x0271); //wait 31.5 us. Refer to dsPICcalc.xls!
}
T1CON = 0x8030; //prescaler of T1 restore to 256-divide
UARTsendString("Sampling with 256 samples finished.\n\0");
// 2.) Sending sample buffer on UART
UARTsendString("[INPUTBUFFER]\n\0");
for (i=0; i
UARTint2Str(sigCmpx[i].real); //send each value to UART
UARTsendByte(0x0A); //terminate with \r
}
UARTsendString("[ENDINPUTBUFFER]\n\0");
// 3.) SCALING
// The FFT function requires input data to be in the fractional fixed-point range [-0.5, +0.5]
for (i=0; i
*p_real = *p_real >>1 ; // So, we shift all data samples by 1 bit to the right.
*p_real++; // Should you desire to optimize this process,
//perform data scaling when first obtaining the time samples or within the BitReverseComplex function
}
// 4.) CLEARING complex parts
p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real; // Set up pointers to convert real array to a complex array!!!
p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1]; // The input array initially has all the real input,
// samples followed by a series of zeros
for (i=FFT_BLOCK_LENGTH; i>0; i--){ // Convert the Real input sample array to a Complex input sample array
(*p_cmpx).real = (*p_real--); // We will simpy write zero to the imaginary part of each sample
(*p_cmpx--).imag = 0x0000;
}
// 5.) FFT (algorythmus in ASM)
FFTComplexIP(LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *)
__builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0]));
// 6.) BIT reversing:
//Store output samples in bit-reversed order of their addresses
BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);
// 7.) CALCULATING REAL part vector (Z = Re^2 + Im^2 )
// not neccessary, may lead to reset of CPU
// Compute the square magnitude of the complex FFT output array so we have a Real output vetor
// SquareMagnitudeCplx(FFT_BLOCK_LENGTH, &sigCmpx[0], &sigCmpx[0].real);
// 8a.) SEARCH the largest spectral component - AMPLITUDE
// Find the frequency Bin ( =index into the SigCmpx[] array) that has the largest energy
VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);
// 8b.) FREQUENCY of the largest spectral component
// Compute the frequency (in Hz) of the largest spectral component
peakFrequency = peakFrequencyBin*(SAMPLING_RATE/FFT_BLOCK_LENGTH);
// 9.) REPORT UART
UARTsendString("Fourier Transform and calculations finished!\n\0");
UARTsendString("Largest spectral component Amax = \0");
UARTint2Str(sigCmpx[peakFrequencyBin]);
UARTsendString("\nFrequency of the largest spectral component fmax = \0");
UARTint2Str(peakFrequency);
UARTsendString("\n\0");
//Sending output buffer on UART
UARTsendString("[OUTPUTBUFFER]\n\0");
for (i=0; i
UARTint2Str(sigCmpx[i].real); //send real and
UARTsendByte(0x0A); //terminate with \n
UARTint2Str(sigCmpx[i].imag); //imaginary part to UART
UARTsendByte(0x0A); //terminate with \n
}
UARTsendString("[ENDOUTPUTBUFFER]\n\0");
Mivel egy előadást is tartottam a témából, a programot angol nyelven kellett felkommenteznem, de remélem érthető mi-mit csinál. Egy 1000 szavas angol alap-szókinccsel már érthető szerintem.
Jóságok:
Egy egyszerű számolási segítség timerekhez, baud-rate számításhoz, meg a PLL és hasonló dolgokban való eligazodáshoz: Egy MS-Excel munkafüzet
Az előadás német nyelven, ha valakit érdekelne FFT.pdf
A kidolgozás, egyenletek, színtiszta matek: FFT_math.pdf
Zárszó:
Remélem sikerült röviden és átfogóan körbejárni a témát, hangsúlyozom, hogy a cikk nem tér ki minden részletre, és nem válaszol meg minden felmerülő kérdést, arra ott a fórum.
Ha valaki kedvet érez és kibővítené a cikket akármilyen ide kapcsolódó anyaggal, azt szívesen fogadom, természetesen neve feltüntetése mellett.
Sok sikert fejlesztés során! deguss 2008
Értékeléshez bejelentkezés szükséges!