Parth Chandak
/
c_FFT_Function
fft_implementation_draft1
main.cpp@1:b86b60ae81af, 2018-03-25 (annotated)
- Committer:
- parthchandak02
- Date:
- Sun Mar 25 18:50:02 2018 +0000
- Revision:
- 1:b86b60ae81af
- Parent:
- 0:b723ff6df537
mbed LPC1768 C FFT Function Revision 1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
parthchandak02 | 0:b723ff6df537 | 1 | #include <mbed.h> |
parthchandak02 | 0:b723ff6df537 | 2 | |
parthchandak02 | 0:b723ff6df537 | 3 | #include <iostream> |
parthchandak02 | 0:b723ff6df537 | 4 | #include <complex> |
parthchandak02 | 1:b86b60ae81af | 5 | #include <cmath> |
parthchandak02 | 1:b86b60ae81af | 6 | |
parthchandak02 | 1:b86b60ae81af | 7 | #define MAX 256 |
parthchandak02 | 0:b723ff6df537 | 8 | #define M_PI 3.1415926535897932384 |
parthchandak02 | 0:b723ff6df537 | 9 | |
parthchandak02 | 1:b86b60ae81af | 10 | |
parthchandak02 | 1:b86b60ae81af | 11 | Serial pc(USBTX, USBRX); |
parthchandak02 | 0:b723ff6df537 | 12 | using namespace std; |
parthchandak02 | 0:b723ff6df537 | 13 | |
parthchandak02 | 0:b723ff6df537 | 14 | |
parthchandak02 | 0:b723ff6df537 | 15 | float s; |
parthchandak02 | 1:b86b60ae81af | 16 | float a = 1.0; //amplitude |
parthchandak02 | 0:b723ff6df537 | 17 | float pi = 3.142; //pi |
parthchandak02 | 1:b86b60ae81af | 18 | float o = 1; //offset |
parthchandak02 | 1:b86b60ae81af | 19 | float time_count = 0.0; |
parthchandak02 | 0:b723ff6df537 | 20 | |
parthchandak02 | 0:b723ff6df537 | 21 | int i = 0; //iteration counter |
parthchandak02 | 0:b723ff6df537 | 22 | int f1 = 100; //frequency in Hz |
parthchandak02 | 1:b86b60ae81af | 23 | |
parthchandak02 | 1:b86b60ae81af | 24 | float step = 1.0/(10.0*f1); |
parthchandak02 | 0:b723ff6df537 | 25 | |
parthchandak02 | 1:b86b60ae81af | 26 | float* generateTimeVector (int vecSize, float stepSize) |
parthchandak02 | 0:b723ff6df537 | 27 | { |
parthchandak02 | 1:b86b60ae81af | 28 | // pc.printf("\nGenerating Time Vector...\n"); |
parthchandak02 | 1:b86b60ae81af | 29 | float *timeVec = new float[vecSize]; |
parthchandak02 | 0:b723ff6df537 | 30 | for(int i=1; i<=vecSize; i++) |
parthchandak02 | 0:b723ff6df537 | 31 | { |
parthchandak02 | 0:b723ff6df537 | 32 | timeVec[i] = i*stepSize; |
parthchandak02 | 1:b86b60ae81af | 33 | // pc.printf("%f\n",timeVec[i]); |
parthchandak02 | 0:b723ff6df537 | 34 | } |
parthchandak02 | 0:b723ff6df537 | 35 | return timeVec; |
parthchandak02 | 0:b723ff6df537 | 36 | } |
parthchandak02 | 0:b723ff6df537 | 37 | |
parthchandak02 | 1:b86b60ae81af | 38 | float* generateFreqVector(int vecSize, float stepSize) |
parthchandak02 | 1:b86b60ae81af | 39 | { |
parthchandak02 | 1:b86b60ae81af | 40 | // pc.printf("\nGenerating Frequency Vector...\n"); |
parthchandak02 | 1:b86b60ae81af | 41 | float *freqVec = new float[vecSize]; |
parthchandak02 | 1:b86b60ae81af | 42 | float v = vecSize; |
parthchandak02 | 1:b86b60ae81af | 43 | for(int i=1; i<=(vecSize); i++) |
parthchandak02 | 1:b86b60ae81af | 44 | { |
parthchandak02 | 1:b86b60ae81af | 45 | freqVec[i] = (1.0/stepSize)*(i/v); |
parthchandak02 | 1:b86b60ae81af | 46 | // pc.printf("%f\n",freqVec[i]); |
parthchandak02 | 1:b86b60ae81af | 47 | } |
parthchandak02 | 1:b86b60ae81af | 48 | return freqVec; |
parthchandak02 | 1:b86b60ae81af | 49 | } |
parthchandak02 | 1:b86b60ae81af | 50 | |
parthchandak02 | 0:b723ff6df537 | 51 | bool set1 = false; |
parthchandak02 | 0:b723ff6df537 | 52 | bool set2 = false; |
parthchandak02 | 0:b723ff6df537 | 53 | bool set3 = false; |
parthchandak02 | 0:b723ff6df537 | 54 | |
parthchandak02 | 1:b86b60ae81af | 55 | void sineGenerate(complex<double>* sineVector, int index, float time, int freqHz, int amplitude, int offset) |
parthchandak02 | 1:b86b60ae81af | 56 | { |
parthchandak02 | 1:b86b60ae81af | 57 | sineVector[index] = offset + amplitude*sin((2*pi) * freqHz * time); |
parthchandak02 | 1:b86b60ae81af | 58 | // pc.printf("%d, %f\n", index, sineVector[index]); |
parthchandak02 | 1:b86b60ae81af | 59 | } |
parthchandak02 | 0:b723ff6df537 | 60 | int log2(int N) /*function to calculate the log2(.) of int numbers*/ |
parthchandak02 | 0:b723ff6df537 | 61 | { |
parthchandak02 | 0:b723ff6df537 | 62 | int k = N, i = 0; |
parthchandak02 | 0:b723ff6df537 | 63 | while(k) { |
parthchandak02 | 0:b723ff6df537 | 64 | k >>= 1; |
parthchandak02 | 0:b723ff6df537 | 65 | i++; |
parthchandak02 | 0:b723ff6df537 | 66 | } |
parthchandak02 | 0:b723ff6df537 | 67 | return i - 1; |
parthchandak02 | 0:b723ff6df537 | 68 | } |
parthchandak02 | 0:b723ff6df537 | 69 | |
parthchandak02 | 0:b723ff6df537 | 70 | int check(int n) //checking if the number of element is a power of 2 |
parthchandak02 | 0:b723ff6df537 | 71 | { |
parthchandak02 | 0:b723ff6df537 | 72 | return n > 0 && (n & (n - 1)) == 0; |
parthchandak02 | 0:b723ff6df537 | 73 | } |
parthchandak02 | 0:b723ff6df537 | 74 | |
parthchandak02 | 0:b723ff6df537 | 75 | int reverse(int N, int n) //calculating revers number |
parthchandak02 | 0:b723ff6df537 | 76 | { |
parthchandak02 | 0:b723ff6df537 | 77 | int j, p = 0; |
parthchandak02 | 0:b723ff6df537 | 78 | for(j = 1; j <= log2(N); j++) { |
parthchandak02 | 0:b723ff6df537 | 79 | if(n & (1 << (log2(N) - j))) |
parthchandak02 | 0:b723ff6df537 | 80 | p |= 1 << (j - 1); |
parthchandak02 | 0:b723ff6df537 | 81 | } |
parthchandak02 | 0:b723ff6df537 | 82 | return p; |
parthchandak02 | 0:b723ff6df537 | 83 | } |
parthchandak02 | 0:b723ff6df537 | 84 | |
parthchandak02 | 0:b723ff6df537 | 85 | void ordina(complex<double>* f1, int N) //using the reverse order in the array |
parthchandak02 | 0:b723ff6df537 | 86 | { |
parthchandak02 | 0:b723ff6df537 | 87 | complex<double> f2[MAX]; |
parthchandak02 | 0:b723ff6df537 | 88 | for(int i = 0; i < N; i++) |
parthchandak02 | 0:b723ff6df537 | 89 | f2[i] = f1[reverse(N, i)]; |
parthchandak02 | 0:b723ff6df537 | 90 | for(int j = 0; j < N; j++) |
parthchandak02 | 0:b723ff6df537 | 91 | f1[j] = f2[j]; |
parthchandak02 | 0:b723ff6df537 | 92 | } |
parthchandak02 | 0:b723ff6df537 | 93 | |
parthchandak02 | 0:b723ff6df537 | 94 | void transform(complex<double>* f, int N) // |
parthchandak02 | 0:b723ff6df537 | 95 | { |
parthchandak02 | 0:b723ff6df537 | 96 | ordina(f, N); //first: reverse order |
parthchandak02 | 0:b723ff6df537 | 97 | complex<double> *W; |
parthchandak02 | 0:b723ff6df537 | 98 | W = (complex<double> *)malloc(N / 2 * sizeof(complex<double>)); |
parthchandak02 | 0:b723ff6df537 | 99 | W[1] = polar(1., -2. * M_PI / N); |
parthchandak02 | 0:b723ff6df537 | 100 | W[0] = 1; |
parthchandak02 | 0:b723ff6df537 | 101 | for(int i = 2; i < N / 2; i++) |
parthchandak02 | 0:b723ff6df537 | 102 | W[i] = pow(W[1], i); |
parthchandak02 | 0:b723ff6df537 | 103 | int n = 1; |
parthchandak02 | 0:b723ff6df537 | 104 | int a = N / 2; |
parthchandak02 | 0:b723ff6df537 | 105 | for(int j = 0; j < log2(N); j++) { |
parthchandak02 | 0:b723ff6df537 | 106 | for(int i = 0; i < N; i++) { |
parthchandak02 | 0:b723ff6df537 | 107 | if(!(i & n)) { |
parthchandak02 | 0:b723ff6df537 | 108 | complex<double> temp = f[i]; |
parthchandak02 | 0:b723ff6df537 | 109 | complex<double> Temp = W[(i * a) % (n * a)] * f[i + n]; |
parthchandak02 | 0:b723ff6df537 | 110 | f[i] = temp + Temp; |
parthchandak02 | 0:b723ff6df537 | 111 | f[i + n] = temp - Temp; |
parthchandak02 | 0:b723ff6df537 | 112 | } |
parthchandak02 | 0:b723ff6df537 | 113 | } |
parthchandak02 | 0:b723ff6df537 | 114 | n *= 2; |
parthchandak02 | 0:b723ff6df537 | 115 | a = a / 2; |
parthchandak02 | 0:b723ff6df537 | 116 | } |
parthchandak02 | 0:b723ff6df537 | 117 | } |
parthchandak02 | 0:b723ff6df537 | 118 | |
parthchandak02 | 0:b723ff6df537 | 119 | void FFT(complex<double>* f, int N, double d) |
parthchandak02 | 0:b723ff6df537 | 120 | { |
parthchandak02 | 0:b723ff6df537 | 121 | transform(f, N); |
parthchandak02 | 0:b723ff6df537 | 122 | for(int i = 0; i < N; i++) |
parthchandak02 | 0:b723ff6df537 | 123 | f[i] *= d; //multiplying by step |
parthchandak02 | 0:b723ff6df537 | 124 | } |
parthchandak02 | 0:b723ff6df537 | 125 | |
parthchandak02 | 0:b723ff6df537 | 126 | int main() |
parthchandak02 | 0:b723ff6df537 | 127 | { |
parthchandak02 | 1:b86b60ae81af | 128 | float* timeVector = generateTimeVector (MAX, step); |
parthchandak02 | 1:b86b60ae81af | 129 | float* freqVector = generateFreqVector (MAX, step); |
parthchandak02 | 1:b86b60ae81af | 130 | |
parthchandak02 | 0:b723ff6df537 | 131 | complex<double> vec[MAX]; |
parthchandak02 | 0:b723ff6df537 | 132 | for (i = 0; i < MAX; i++) |
parthchandak02 | 0:b723ff6df537 | 133 | { |
parthchandak02 | 1:b86b60ae81af | 134 | float t = timeVector[i]; |
parthchandak02 | 1:b86b60ae81af | 135 | sineGenerate(vec, i, t, f1, a, 0); |
parthchandak02 | 0:b723ff6df537 | 136 | } |
parthchandak02 | 0:b723ff6df537 | 137 | |
parthchandak02 | 0:b723ff6df537 | 138 | FFT(vec, MAX, 1); //'d' should be 1 in order to have the same results of matlab fft(.) |
parthchandak02 | 0:b723ff6df537 | 139 | cout << "...printing the FFT of the array specified" << endl; |
parthchandak02 | 1:b86b60ae81af | 140 | float absFFT = 0.0; |
parthchandak02 | 0:b723ff6df537 | 141 | for(int j = 0; j < MAX; j++) |
parthchandak02 | 0:b723ff6df537 | 142 | { |
parthchandak02 | 1:b86b60ae81af | 143 | absFFT = 2*(std::abs(vec[j]))/MAX; |
parthchandak02 | 1:b86b60ae81af | 144 | pc.printf("%f, %f\n", freqVector[j], absFFT); //Y: absFFT, X: freqVector |
parthchandak02 | 0:b723ff6df537 | 145 | } |
parthchandak02 | 0:b723ff6df537 | 146 | |
parthchandak02 | 0:b723ff6df537 | 147 | return 0; |
parthchandak02 | 0:b723ff6df537 | 148 | } |