Vous êtes sur la page 1sur 12

Readme File for Code Example: CE018 - Using the Fast Fourier Transform (FFT) for Frequency Detection

----------------------------------------------------------------------

This file contains the following sections: 1. Code Example Description 2. Folder Contents 3. Suggested Development Resources 4. Reconfiguring the project for a different dsPIC30F device 5. Reconfiguring the project for a different FFT Size: 6. Revision History

1. Code Example Description: ---------------------------Microchip's 16-bit dsPIC Digital Signal Controllers feature a DSP Engine in the CPU that is capable of executing a Fast Fourier Transform (FFT) with great efficiency (high speed and low RAM usage). The on-chip features enabling the FFT implementation include, bit-reversed addressing, Multiply-accumulate (MAC) type instructions and the ability to store and retrieve constants stored in Program memory.

Microchip provides a DSP functions library that provides in-place FFT functions.

In this code example, we demonstrate how the DSP library functions can be used to perform an FFT on an input signal (vector). The code example is reconfigurable to perfrom an FFT of any size, including common sizes of 64, 128, 256 and 512 points. The code example also allows the user to place the FFT coefficients (known as Twiddle Factors) in RAM or in Program Flash Memory. The project may be easily reconfigured by modifying the header file, FFT.h. By default, the example implements a 256-point FFT using coefficients stored in Program Flash memory.

The input signal for our example will be 256 points of a Square wave signal of frequency 1KHz sampled at 10 KHz. This signal was first generated by dsPICworks and then exported as an assembler file from dsPICworks. After exporting it out, the assembler file was modified to ensure the samples reside in Y-data space.

The FFT operation is performed on the input signal, in-place. This means that the output of the FFT resides in the same RAM locations where the input signal used to reside. The FFT is performed in the following steps:

1. Initialization: Generate Twiddle Factor Coefficients and store them in X-RAM or alternately use twiddle factor coefficients stored in Program Flash.

2. Scale the input signal to lie within the range [-0.5, +0.5]. For fixed point fractional input data, this translates to input samples in the range [0xC000,0x3FFF]. The scaling is achieved by simply right-shifting the input samples by 1 bit, assuming the input samples lie in the fixed point range [0x8000,0x7FFF] or [-1,+1).

3. Convert the real input signal vector to a complex vector by placing zeros in every other location to signify a complex input whose imaginary part is 0x0000.

4. Butterfly computation: This is achieved by performing a call to the FFTComplexIP() function.

5. Bit-Reversed Re-ordering: The output array is re-ordered to be in bit-reversed order of the addresses. This is achieved by a function call to BitReverseComplex().

6. SquareMagnitude computation: We then need to compute the magnitude of each complex element in the output vector, so that we can estimate the energy in each spectral component/frequency bin. This is achieved by a call to a special C-callable routine, SquareMagnitudeCplx(), written in assembler language. This routine will be incorporated into the DSP library in future revisions of the C30 toolsuite. At that time, you may remove the source file, cplxsqrmag.s from the project and include the latest DSP library file, libdsp-coff.a.

7. Peak-picking: We then find the frequency component with the largest energy by using the VectorMax() routine in the DSP library.

8. Frequency Calculation: The value of the spectral component with the highest energy, in Hz, is calculated by multiplying the array index of the largest element in the output array with the spectral (bin) resolution ( = sampling rate/FFT size).

2. Folder Contents: ------------------This folder contains the following sub-folders:

a. gld This folder contains the linker script file for the example project. This file is used for building the project. This file was provided with the MPLAB C30 v1.33 toolsuite.

b. h This folder contains C header files useful in building this project. Device register and bit definitions are provided in the *.h file that follows the device name. These files were provided with the MPLAB C30 v1.33 toolsuite.

c. hex This folder contains three file types - coff, hex and map. These are files generated by the MPLAB C30 toolsuite on build operation performed within MPLAB IDE. The *.map file contains details on memory allocation for various variables, constants and dsPIC30F instructions specified in the source and library code. The *.hex file contains a binary file that may be programmed into the dsPIC30F device. The *.coff file contains a binary file that is used by MPLAB IDE for simulation.

d. inc This folder contains Assembler include files useful in building this project. Device register and bit definitions are provided in the *.inc file that follows the device name. These files were provided with the MPLAB C30 v1.33 toolsuite.

e. lib This folder contains library archive files, which are a collection of precompiled object files. The file

named "libpic30-coff.a" contains the C run-time start-up library. These file were provided with the MPLAB C30 v1.33 toolsuite.

f. src This folder contains all the C and Assembler source files (*.c, *.s) used in demonstrating the described example. This folder also contains a sub-folder named "obj" that stores compiled object files generated when the project is built.

g. dsPICworks This folder contains files created by dsPIC Filter Design and dsPICworks Data Analysis and Design Software. Input signal files, output signal files and filter specifications have been provided here.

3. Suggested Development Resources: ----------------------------------a. MPLAB IDE v7.21 or later b. MPLAB C30 v1.33 or later c. MPLAB ICD 2 R23 or later d. dsPICDEM 1.1 Development Board (See below) e. dsPIC30F6014A Digital Signal Controller Plug-In Module (See below)

4. Reconfiguring the project for a different dsPIC30F device: ------------------------------------------------------------The Project/Workspace can be easily reconfigured for any dsPIC30F device. Please use the following general guidelines: a. Change device selection within MPLAB IDE to a dsPIC30F device of your choice by using the following menu option:

MPLAB IDE>>Configure>>Select Device

b. Provide the correct device linker script and header file for your device. Device linker scripts and header files are available in your MPLAB C30 installation folder under: Device Linker ScriptYourDrive:>Program Files\Microchip\MPLAB C30\support\gld Device C Header fileYourDrive:>Program Files\Microchip\MPLAB C30\support\h Device ASM Include fileYourDrive:>Program Files\Microchip\MPLAB C30\support\inc

c. Provide the appropriate path to your MPLAB C30 support file locations using the menu option: MPLAB IDE>>Project>>Build Options>>Project

d. Chose the development board applicable to your device. Some options are provided below: - dsPICDEM 2 Development Board supports: 30F2010, 30F2011, 30F2012, 30F3010, 30F3011, 30F3012, 30F3013, 30F3014, 30F4011, 30F4012, 30F4013

- dsPICDEM 1.1 Development Board supports: 30F5013, 30F6010, 30F6011, 30F6012, 30F6013, 30F6014, 30F6011A, 30F6012A, 30F6013A, 30F6014A

- dsPICDEM MC1 Development Board supports: 30F6010, 30F6010A, 30F5016

e. Re-build the MPLAB project using the menu option:

MPLAB IDE>>Project>>Build All

f. Download the hex file into the device and run.

5. Reconfiguring the project for a different FFT Size: ------------------------------------------------------------The project has been configured for a 256-pt FFT to be performed on a 30F6014A device. Perform the following steps in sequence to change the device and FFT size.

(i) Change device selection within MPLAB IDE to a dsPIC30F device of your choice by using the following menu option: MPLAB IDE>>Configure>>Select Device

(ii) Provide the correct device linker script and header file for your device. Device linker scripts and header files are available in your MPLAB C30 installation folder under: Device Linker ScriptYourDrive:>Program Files\Microchip\MPLAB C30\support\gld Device C Header fileYourDrive:>Program Files\Microchip\MPLAB C30\support\h Device ASM Include fileYourDrive:>Program Files\Microchip\MPLAB C30\support\inc

(iii) In the file FFT.h, perform the following changes: - Change FFT_BLOCK_LENGTH to either 64, 128, 256 or 512 - Correspondingly, change LOG2_BLOCK_LENGTH to either 6, 7, 8 or 9 respectively - If you would like to store Twiddle Factors coefficients in RAM instead of Program Memory comment out the line of code as shown: "//#define FFTTWIDCOEFFS_IN_PROGMEM "

(iv) This project uses an input squarewave signal provided as PCM samples in the file, "inputsignal_square1khz.c" in the array named "sigCmpx[]". This array should be of length, FFT_BLOCK_LENGTH and type "fractcomplex". So, for a 64-pt FFT, it should contain only 64 data samples and padded initially with 64 zeroes. This array stores the output of the complex FFT operation and eventually stores the magnitudes of the frequency bins. Modify this array to suit the FFT size you are using. In a real application, your data will likely be input from a real-world signal.

(v) Re-build the MPLAB project using the menu option: MPLAB IDE>>Project>>Build All

(vi) Download the hex file into the device and run.

6. Revision History : --------------------09/30/2005 - Initial Release of the Code Example 01/05/2006 - Corrected cplxsqrmag.s 01/17/2006 - Added "5. Reconfiguring the project for a different FFT Size:" in this readme file and corrected an extern definition in the main_FFTExample.c file

/********************************************************************** * 2005 Microchip Technology Inc. * * FileName: main_FFTExample.c

* Dependencies: Header (.h) files if applicable, see below * Processor: * Compiler: * IDE: dsPIC30Fxxxx MPLAB C30 v1.33.00 or higher MPLAB IDE v7.20.01 or later

* Dev. Board Used: dsPICDEM 1.1 Development Board * Hardware Dependencies: None * * SOFTWARE LICENSE AGREEMENT: * Microchip Technology Inc. (Microchip) licenses this software to you * solely for use with Microchip dsPIC digital signal controller * products. The software is owned by Microchip and is protected under * applicable copyright laws. All rights reserved. * * SOFTWARE IS PROVIDED AS IS. MICROCHIP EXPRESSLY DISCLAIMS ANY * WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL MICROCHIP * BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR CONSEQUENTIAL * DAMAGES, LOST PROFITS OR LOST DATA, HARM TO YOUR EQUIPMENT, COST OF * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), * ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER SIMILAR COSTS. * * REVISION HISTORY: *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * Author Date Comments on this revision

*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * HV * *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 09/30/05 First release of source file

* * ADDITIONAL NOTES: * * **********************************************************************/ #include <p30Fxxxx.h> #include <dsp.h> #include "fft.h"

/* Device configuration register macros for building the hex file */ _FOSC(CSW_FSCM_OFF & XT_PLL8); _FWDT(WDT_OFF); /* XT with 8xPLL oscillator, Failsafe clock off */

/* Watchdog timer disabled */ /* Brown-out reset disabled, MCLR reset enabled */

_FBORPOR(PBOR_OFF & MCLR_EN); _FGS(CODE_PROT_OFF);

/* Code protect disabled */

/* Extern definitions */ extern fractcomplex sigCmpx[FFT_BLOCK_LENGTH] /* Typically, the input signal to an FFT */

__attribute__ ((section (".ydata, data, ymemory"), /* routine is a complex array containing samples */ aligned (FFT_BLOCK_LENGTH * 2 *2))); /* of an input signal. For this example, */

/* we will provide the input signal in an */ /* array declared in Y-data space. */ /* Global Definitions */ #ifndef FFTTWIDCOEFFS_IN_PROGMEM fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2] /* Declare Twiddle Factor array in X-space*/ __attribute__ ((section (".xbss, bss, xmemory"), aligned (FFT_BLOCK_LENGTH*2))); #else extern const fractcomplex twiddleFactors[FFT_BLOCK_LENGTH/2] /* Twiddle Factor array in Program memory */ __attribute__ ((space(auto_psv), aligned (FFT_BLOCK_LENGTH*2))); #endif

int peakFrequencyBin = 0;

/* Declare post-FFT variables to compute the */ /* frequency of the largest spectral component */

unsigned long peakFrequency = 0;

int main(void) { int i = 0; fractional *p_real = &sigCmpx[0].real ; fractcomplex *p_cmpx = &sigCmpx[0] ;

#ifndef FFTTWIDCOEFFS_IN_PROGMEM

/* Generate TwiddleFactor Coefficients */

TwidFactorInit (LOG2_BLOCK_LENGTH, &twiddleFactors[0], 0); /* We need to do this only once at start-up */ #endif

for ( i = 0; i < FFT_BLOCK_LENGTH; i++ )/* The FFT function requires input data */ { /* to be in the fractional fixed-point range [-0.5, +0.5]*/ *p_real = *p_real >>1 ; *p_real++; } /* So, we shift all data samples by 1 bit to the right. */

/* Should you desire to optimize this process, perform */

/* data scaling when first obtaining the time samples */ /* Or within the BitReverseComplex function source code */

p_real = &sigCmpx[(FFT_BLOCK_LENGTH/2)-1].real ; /* Set up pointers to convert real array */ p_cmpx = &sigCmpx[FFT_BLOCK_LENGTH-1] ; /* to a complex array. 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 zero out the imaginary */

(*p_cmpx--).imag = 0x0000; /* part of each data sample */ }

/* Perform FFT operation */ #ifndef FFTTWIDCOEFFS_IN_PROGMEM FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], &twiddleFactors[0], COEFFS_IN_DATA); #else FFTComplexIP (LOG2_BLOCK_LENGTH, &sigCmpx[0], (fractcomplex *) __builtin_psvoffset(&twiddleFactors[0]), (int) __builtin_psvpage(&twiddleFactors[0])); #endif

/* Store output samples in bit-reversed order of their addresses */ BitReverseComplex (LOG2_BLOCK_LENGTH, &sigCmpx[0]);

/* 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);

/* Find the frequency Bin ( = index into the SigCmpx[] array) that has the largest energy*/ /* i.e., the largest spectral component */ VectorMax(FFT_BLOCK_LENGTH/2, &sigCmpx[0].real, &peakFrequencyBin);

/* Compute the frequency (in Hz) of the largest spectral component */ peakFrequency = peakFrequencyBin*(SAMPLING_RATE/FFT_BLOCK_LENGTH);

while (1); /* Place a breakpoint here and observe the watch window variables */ }

---------------------------------------------------------------------------------------/* Constant Definitions */ #define FFT_BLOCK_LENGTH 256 /* = Number of frequency points in the FFT */

#define LOG2_BLOCK_LENGTH 8 /* = Number of "Butterfly" Stages in FFT processing */ #define SAMPLING_RATE 10000 /* = Rate at which input signal was sampled */

/* SAMPLING_RATE is used to calculate the frequency*/ /* of the largest element in the FFT output vector*/

#define FFTTWIDCOEFFS_IN_PROGMEM /*<---Comment out this line of the code if twiddle factors (coefficients) */ /*reside in data memory (RAM) as opposed to Program Memory */ /*Then remove the call to "TwidFactorInit()" and add the twiddle factor*/ /*coefficient file into your Project. An example file for a 256-pt FFT*/ /*is provided in this Code example */ ----------------------------------------------------------------------------------------------

Vous aimerez peut-être aussi