Hi Community,
I have a set of FFT codes that is suppose to create an array of number after processing the incoming signal.
When I build my codes in code composer studio it was successfully built.
However, when I run it on debug mode it face problems.
The purpose of my project is to simply program a set of FFT algorithm in c, and allow my LM3s8962 micro-controller to process the incoming signal(Voice or sound).
I have another question, can I use the algorithm to run it in my keil uvision, since the keil uvision has the spectrum/logic analyser which I can see the frequency spectrum.
I will attach my algorithms here, if any kind hearted soul spot any mistakes in my algorithm please enlighten me.
/* * main.c */#include <stdio.h>#include <math.h>#include <stdbool.h>#include <stdint.h>#include "inc/hw_memmap.h"#include "inc/hw_types.h"#include "inc/hw_ints.h"#include "driverlib/sysctl.h"#include "driverlib/adc.h"#include "driverlib/interrupt.h"#include "driverlib/gpio.h"#include "driverlib/pin_map.h"#include "grlib/grLib.h"#include "grlib/grLibDriver.h"
short sample[8];
#pragma vector=unused_interruptsinterrupt void user_trap_function(void) //ISR to handle the end of sampling interrup, being the only enabled interrupt{ int df = 15625; //fs/N = 125000/8 int Re[8]; int Im[8]; int Ampl[8]; int fr[8]; int N = 8; //number of samples x[N] = (short)sample; // convert sample values to short integers for computation int out[2] = {0,0}; //init Re and Im results int j=0; for (j = 0; j < N; j++){ dft(x,j,out); //call DFT function Re[j] = out[0]; Im[j] = out[1]; //collect real and imaginary parts Ampl[j] = ((Re[j]^2)+(Im[j]^2))^(1/2); fr[j] = df*j;
long lX1 = (long)Ampl[j]; long lX2 = (long)Ampl[j]+1; long lY = (long)fr[j]; long ulValue = 128;
void LineDrawH (pvDisplayData, lX1, , lX1, lY, ulValue);
}
int M = 0;unsigned long sample[8]
void LineDrawH (void *pvDisplayData, long lX1, long lX2, long lY, unsigned long ulValue);
void ADC_init( void ) { SYSCTL_RCGC0_R |= SYSCTL_RCGC0_ADC; // Enable the clock to the ADC module SYSCTL_RCGC0_R |= SYSCTL_RCGC0_ADCSPD125K; // Configure the ADC to sample at 125KS/s ADCSequenceDisable(ADC_BASE, 0); // Disable sample sequences 0 ADCSequenceConfigure(ADC_BASE, 0, ADC_TRIGGER_PROCESSOR, 1); // Configure sample sequence 0: processor trigger, priority = 1 IntPrioritySet(INT_ADC0SS0,0); // Set SS0 interrupt priority to 0 ADCSequenceStepConfigure(ADC_BASE, 0, 0, ADC_CTL_CH0); // Configure sample sequence 0 to sample external input ADCSequenceStepConfigure(ADC_BASE, 0, 1, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 2, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 3, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 4, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 5, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 6, ADC_CTL_CH0); ADCSequenceStepConfigure(ADC_BASE, 0, 7, ADC_CTL_CH0 | ADC_CTL_IE | ADC_CTL_END); //set interrupt flag after the seventh step ADCIntEnable(ADC_BASE, 0); // Enable the interrupt for sample sequence 0 IntEnable(INT_ADC0SS0); // Enable SS0 Interupt in NVIC M+=M; // integer to detect if ADC is initialized}
unsigned long getADC0(void){
ADCProcessorTrigger(ADC0_BASE, 0); //initiate sampling while(!ADCIntStatus(ADC0_BASE, 0, false)); //monitor interrupt flag for completion of sampling ADCSequenceDataGet(ADC0_BASE, 0, sample); //assign samples to global variable, sample
return sample; //return sample to calling function}
int dft(long *x, short k, int *out) //DFT function { int sumRe = 0; //init real component int sumIm = 0; //init imaginary component int i = 0; int N = 8; float pi = 3.1416 ; float cs = 0; //init cosine component float sn = 0; //init sine component for (i = 0; i < N; i++) //for N-point DFT { cs = cos(2*pi*(k)*i/N); //real component sn = sin(2*pi*(k)*i/N); //imaginary component sumRe += x[i]*cs; //sum of real components sumIm -= x[i]*sn; //sum of imaginary components } out[0] = sumRe; //sum of real components out[1] = sumIm; //sum of imaginary components
return(out); }int main(void) { if (M>0){ ADC_init(); //initialize ADC module if not already initialized } getADC0(); //start conversion. Interrupt flag will be set after sampling and this functioned called again after ISR executes return 0;}
Hi xingjunmarco,
You can state the details of the problems so that fellow members will be able to help you.
Yes, you can use it under µVision IDE and µVision Debugger.
For some part(s) of your program I will just give recommendations and it's up to you if you will do the modification. Here are the minor problems
float pi = 3.1416 ;
you can use
float pi = 3.14159265;
or
float pi = 3.1415927;
For some other issues, I decided to post them separately. If other members will give their comments the subject matters are already segregated so if you will reply be sure to do it in the appropriate post.
Ultimately, I recommend that you consider CMSIS, there is an elegant way of realizing your project.
Regards,
Goodwin
In main there is this block
if (M>0){ ADC_init(); //initialize ADC module if not already initialized}
if (M>0){
ADC_init(); //initialize ADC module if not already initialized
Here, ADC_init() will never be executed. The reason is
int M = 0;
you initialized M to 0 in its declaration. I'll leave the correction to you to conform to your preferences. Besides, you have a reason for putting ADC_init() in the if block.
You are executing your DFT and other calculations relating to the complex magnitude of the output samples inside an ISR
interrupt void user_trap_function(void) //ISR to handle the end of sampling interrup, being the only enabled interrupt{int df = 15625; //fs/N = 125000/8int Re[8];int Im[8];int Ampl[8];int fr[8];int N = 8; //number of samplesx[N] = (short)sample; // convert sample values to short integers for computationint out[2] = {0,0}; //init Re and Im resultsint j=0;for (j = 0; j < N; j++){ dft(x,j,out); //call DFT function Re[j] = out[0]; Im[j] = out[1]; //collect real and imaginary parts Ampl[j] = ((Re[j]^2)+(Im[j]^2))^(1/2); fr[j] = df*j; long lX1 = (long)Ampl[j]; long lX2 = (long)Ampl[j]+1; long lY = (long)fr[j]; long ulValue = 128; void LineDrawH (pvDisplayData, lX1, , lX1, lY, ulValue);}}
interrupt void user_trap_function(void) //ISR to handle the end of sampling interrup, being the only enabled interrupt
{
int df = 15625; //fs/N = 125000/8
int Re[8];
int Im[8];
int Ampl[8];
int fr[8];
int N = 8; //number of samples
x[N] = (short)sample; // convert sample values to short integers for computation
int out[2] = {0,0}; //init Re and Im results
int j=0;
for (j = 0; j < N; j++){
dft(x,j,out); //call DFT function
Re[j] = out[0];
Im[j] = out[1]; //collect real and imaginary parts
Ampl[j] = ((Re[j]^2)+(Im[j]^2))^(1/2);
fr[j] = df*j;
long lX1 = (long)Ampl[j];
long lX2 = (long)Ampl[j]+1;
long lY = (long)fr[j];
long ulValue = 128;
Although the length of your DFT is only 8, it will still take considerable time to execute. While you've stated in the comment that it is the only enabled interrupt, it seems like you will be dedicating your MCU to just this task. I don't know if this is acceptable to other programmers but I believe there is a better way where you can maximize the utilization of your microcontroller.
The statement below
which you have used to compute the magnitude of the DFT output will not work as intended. In MATLAB and some other languages such as BASIC, caret (^) is the exponentiation operator. In C/C++, the caret is a bitwise XOR operator.
You used j as the loop counter and index to the output samples and related quantities in part of your program where you are doing computations involving complex numbers. When you will analyze your program and relate it to the DFT equation, your use of j can confuse or at least distract you. The use of j in cases like this is basically discouraged; since in electrical/electronics engineering, j is used as the symbol for the imaginary unit.
int j=0;for (j = 0; j < N; j++){ dft(x,j,out); //call DFT function Re[j] = out[0]; Im[j] = out[1]; //collect real and imaginary parts Ampl[j] = ((Re[j]^2)+(Im[j]^2))^(1/2); fr[j] = df*j; long lX1 = (long)Ampl[j]; long lX2 = (long)Ampl[j]+1; long lY = (long)fr[j]; long ulValue = 128; void LineDrawH (pvDisplayData, lX1, , lX1, lY, ulValue);}}
For a reason similar to the case of j, the use of i in the for block below is somewhat discouraged. In this case, i is the symbol for the imaginary unit in mathematics.
for (i = 0; i < N; i++) //for N-point DFT { cs = cos(2*pi*(k)*i/N); //real component sn = sin(2*pi*(k)*i/N); //imaginary component sumRe += x[i]*cs; //sum of real components sumIm -= x[i]*sn; //sum of imaginary components }
for (i = 0; i < N; i++) //for N-point DFT
cs = cos(2*pi*(k)*i/N); //real component
sn = sin(2*pi*(k)*i/N); //imaginary component
sumRe += x[i]*cs; //sum of real components
sumIm -= x[i]*sn; //sum of imaginary components
Hi, Goodwin.
I am very new to keil uvision and c programming.
My project requires me to program fft/dft in c algorithm and allow my micro-processor to process the algorithm.
I am actually quite weak at this area.
You mention, there is actually an elegant way in doing my project.
Is there any available source code to be use for my intended project. Such that I no need to come out with my own algorithm.
But use an available dft or fft algorithm that was created to process an incoming signal.? Please advise
so what will suggest? I change all the j to i?
As you mentioned earlier on, is there any available ready available source code that can be use?
I am looking for a set of fft/dft algorithm. A simple one that can, just so enough to allow my lm3s8962 to process the algorithm.
Since, there are quite a number of mistakes in this set of algorithm.
What is the best suggestion that you recommend me to adopt now.
I am referring to your code. Regarding the LM3s8962 and evaluation board, I'm not sure, but Cortex-M3 is supported and LM3s8962 is a popular (albeit in NRND status already) MCU so most likely it's supported in µVision. To be sure, you have to verify in KEIL's website http://www2.keil.com/mdk5/uvision/ or in µVision if you already have it installed.
In the first case you can use k instead of j, in the second case you can use n instead of i. These are the variables used in DFT equations in most references. However, you are not restricted to these suggestions. You can use anything that suits your preference and you are not limited to single-character variable name. For example inIndex or timeIdx instead of j; outIndex or freqIdx instead of i. Note that if you use n instead of i, there will be a minor conflict with N (your variable for the number of samples). Although C is case-sensitive making n and N different, you can choose to replace N with something like numOfSamples or dftLength.
Are you a student (is this a project in school)? I asked this so I will not have to make assumptions, and hopefully provide you with more useful answer. Specifically, I would like to know the ff:
By the way, in C++ the operators can be overloaded. However, if it is applied to the caret in this case, it's going to have several drawbacks.
Hi,
I am a student, and this is a project in my school. I am task to do this. I am more compelled to use this lm3s8962 evaluation toolkit and keil uvision for my project. I already have this board with me now. I am not compelled to use just dft. So as long fft or dft has readily available algorithms.
My project aims to do a real time digital signal analysis.
I am looking for a set of fft realistic algorithm that I can use it for my project. I am trying to come out by myself, as you can see there are just too many errors haha. My professor kept saying, there is already available online. But I cannot find it. Will you be an angel to help me out here? Also, there are just too many different kinds of fft algorithms out there. Which one is the right one?
All my project require me to do is, program fft in c algorithm and allow my micro-controller to process this algorithm. Where can I find the readily available fft algorithm that someone probably wrote it and available for me to put it in my keil uvision, change some peripherals of my texas board and do some I/O changes. I want to do a real time signal processing, use my micro-controller to process the incoming audio signal that been uploaded to my micro-controller.
I am looking for a set of fft realistic algorithm that I can use it for my project. I am trying to come out by myself, as you can see there are just too many errors haha.
With little more familiarity and experience with C, you will be able to make your DFT work.
My professor kept saying, there is already available online. But I cannot find it.
If you want a black box FFT (when you don't have to be concerned about the details on how it works, you just need to know how to use it), the CMSIS DSP Software Library is the answer to your problem.
Visit these pages from Texas Instruments and try if you can find the FFT functions that you need from the software packages:
The CMSIS DSP Software Library from KEIL can be found here, CMSIS DSP Software Library.
If you are required to show the code of the FFT, you can find an example or template from textbooks, application notes from MPU/MCU/DSP suppliers, or from online articles. You need to port these codes to the LM3S8962.
Also, there are just too many different kinds of fft algorithms out there. Which one is the right one?
The differences exist because the FFT algorithms
All of these will produce practically the same result for the same input, they will differ in speed, size, overall efficiency and suitability to a particular problem. You don't have to be concerned about these in the meantime. If you want a simpler version, look for these in the description: radix-2, decimation-in-time, floating-point.