[elektro-etc] periodicitas detektor
Andras Huszti
kyrk at villamvadasz.hu
Tue Jun 15 21:46:13 CEST 2010
Hali!
Ha nem tudod a periodicitas frekvenciajat akkor FFT, ha tudod akkor sima
korrelacio. Pl DTMF-nel a korrelacio gyorsabb lehet.
En ezt hasznaltam egy PIC-es projectemben, de nem tudom 100%-ra hogy
mukodik-e:
#include <math.h>
#include "fft.h"
#include "lcd.h"
#define SWAP(a,b)tempr=(a);(a)=(b);(b)=tempr
float PI = 3.14159265354;
static void DanielsonLanzcosRoutine(FftInputType *data, unsigned long
sizeofData, int isign);
static void BitReversal(FftInputType *data, unsigned long sizeofData);
void FFT (FftInputType *data, unsigned long sizeofData) {
//the complex array is real + complex so the array
//as a size n = 2 * number of complex samples
//real part is the data[index] and
//the complex part is the data[index+1]
BitReversal(data, sizeofData);
DanielsonLanzcosRoutine(data, sizeofData, 1);
}
void IFFT (FftInputType *data, unsigned long sizeofData) {
unsigned long i = 0;
unsigned long n = sizeofData / sizeof(FftInputType);
BitReversal(data, sizeofData);
DanielsonLanzcosRoutine(data, sizeofData, -1);
for (i = 0; i < n / 2; i++) {
data[i * 2] /= (n / 2);
}
}
void calculateMagnitueAndPhaseFromComplex(FftInputType *data, unsigned
long sizeofData) {
unsigned long x;
unsigned long freqs = (sizeofData / sizeof(FftInputType)) / 2;
float ampl = 0;
float fiPI = 0;
float fiC = 0;
for (x = 0; x < freqs; x++) {
ampl = sqrt((pow((float)data[x * 2], 2)) + (pow((float)data[(x * 2) +
1], 2)));
fiPI = tan((float)data[(x * 2) + 1] / (float)data[x * 2]);
fiC = (180 * fiPI / (2 * PI));
if ((ampl < 0.0001) && (ampl > -0.0001)) {
fiC = 0;
}
while (fiC > 360) {
fiC -= 360;
}
while (fiC < -360) {
fiC += 360;
}
data[x * 2] = (FftInputType)ampl;
data[(x * 2) + 1] = (FftInputType)fiC ;
}
}
static void BitReversal(FftInputType *data, unsigned long sizeofData) {
//binary inversion (note that the indexes
//start from 0 witch means that the
//real part of the complex is on the even-indexes
//and the complex part is on the odd-indexes
unsigned long i = 0;
unsigned long j = 0;
unsigned long n = 0;
double tempr = 0;
n = (sizeofData / sizeof(FftInputType));
for (i = 0; i < n / 2; i += 2) {
unsigned long m = 0;
if (j > i) {
//swap the real part
SWAP(data[j], data[i]);
//swap the complex part
SWAP(data[j + 1], data[i + 1]);
// checks if the changes occurs in the first half
// and use the mirrored effect on the second half
if ((j / 2) < (n / 4)) {
//swap the real part
SWAP(data[(n - (i + 2))] , data[(n - (j + 2))]);
//swap the complex part
SWAP(data[(n - (i + 2)) + 1] , data[(n - (j + 2)) + 1]);
}
}
m = n / 2;
while (m >= 2 && j >= m) {
j -= m;
m = m / 2;
}
j += m;
}
}
static void DanielsonLanzcosRoutine(FftInputType *data, unsigned long
sizeofData, int isign) {
unsigned long n = 0;
unsigned long mmax = 0;
//Danielson-Lanzcos routine
n = (sizeofData / sizeof(FftInputType));
mmax = 2;
//external loop
while (n > mmax) {
double wtemp = 0;
double theta = 0;
double wi = 0;
double wpi = 0;
double wr = 0;
double wpr = 0;
unsigned long m = 0;
unsigned long istep = 0;
istep = mmax << 1;
theta = isign * (2 * PI / mmax);
wtemp = sin(0.5 * theta);
wpr = -2.0 * wtemp * wtemp;
wpi = sin(theta);
wr = 1.0;
wi = 0.0;
//internal loops
for (m = 1; m < mmax; m += 2) {
unsigned long i = 0;
unsigned long j = 0;
for (i = m; i <= n; i += istep) {
double tempi = 0;
double tempr = 0;
j = i + mmax;
tempr = wr * (float)data[j - 1] - wi * (float)data[j + 1
- 1];
tempi = wr * (float)data[j + 1 - 1] + wi * (float)data[j
- 1];
data[j - 1] = (float)data[i - 1] - tempr;
data[j + 1 - 1] = (float)data[i + 1 - 1] - tempi;
data[i - 1] += tempr;
data[i + 1 - 1] += tempi;
}
wr = (wtemp = wr) * wpr - wi * wpi + wr;
wi = wi * wpr + wtemp * wpi + wi;
}
mmax = istep;
}
}
#ifndef _FFT_H_
#define _FFT_H_
typedef float FftInputType;
extern float PI;
extern void FFT (FftInputType *data, unsigned long sizeofData);
extern void IFFT (FftInputType *data, unsigned long sizeofData);
extern void calculateMagnitueAndPhaseFromComplex(FftInputType *data,
unsigned long sizeofData);
#endif
More information about the Elektro-etc
mailing list