Contiki 2.6
|
00001 /* 00002 * Copyright (c) 2008, Swedish Institute of Computer Science 00003 * All rights reserved. 00004 * 00005 * Redistribution and use in source and binary forms, with or without 00006 * modification, are permitted provided that the following conditions 00007 * are met: 00008 * 1. Redistributions of source code must retain the above copyright 00009 * notice, this list of conditions and the following disclaimer. 00010 * 2. Redistributions in binary form must reproduce the above copyright 00011 * notice, this list of conditions and the following disclaimer in the 00012 * documentation and/or other materials provided with the distribution. 00013 * 3. Neither the name of the Institute nor the names of its contributors 00014 * may be used to endorse or promote products derived from this software 00015 * without specific prior written permission. 00016 * 00017 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 00018 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00019 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00020 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 00021 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 00022 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 00023 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00024 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 00025 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00026 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00027 * SUCH DAMAGE. 00028 * 00029 * ----------------------------------------------------------------- 00030 * ifft - Integer FFT (fast fourier transform) library 00031 * 00032 * 00033 * Author : Joakim Eriksson 00034 * Created : 2008-03-27 00035 * Updated : $Date: 2008/07/03 23:40:12 $ 00036 * $Revision: 1.3 $ 00037 */ 00038 #include "lib/ifft.h" 00039 00040 /*---------------------------------------------------------------------------*/ 00041 /* constant table of sin values in 8/7 bits resolution */ 00042 /* NOTE: symmetry can be used to reduce this to 1/2 or 1/4 the size */ 00043 #define SIN_TAB_LEN 120 00044 #define RESOLUTION 7 00045 #define ABS(x) (x < 0 ? -x : x) 00046 00047 static const int8_t SIN_TAB[] = { 00048 0,6,13,20,26,33,39,45,52,58,63,69,75,80, 00049 85,90,95,99,103,107,110,114,116,119,121, 00050 123,125,126,127,127,127,127,127,126,125, 00051 123,121,119,116,114,110,107,103,99,95,90, 00052 85,80,75,69,63,58,52,45,39,33,26,20,13,6, 00053 0,-6,-13,-20,-26,-33,-39,-45,-52,-58,-63, 00054 -69,-75,-80,-85,-90,-95,-99,-103,-107,-110, 00055 -114,-116,-119,-121,-123,-125,-126,-127,-127, 00056 -127,-127,-127,-126,-125,-123,-121,-119,-116, 00057 -114,-110,-107,-103,-99,-95,-90,-85,-80,-75, 00058 -69,-63,-58,-52,-45,-39,-33,-26,-20,-13,-6 00059 }; 00060 00061 00062 static uint16_t bitrev(uint16_t j, uint16_t nu) 00063 { 00064 uint16_t k; 00065 k = 0; 00066 for (; nu > 0; nu--) { 00067 k = (k << 1) + (j & 1); 00068 j = j >> 1; 00069 } 00070 return k; 00071 } 00072 00073 00074 /* Non interpolating sine... which takes an angle of 0 - 999 */ 00075 static int16_t sinI(uint16_t angleMilli) 00076 { 00077 uint16_t pos; 00078 pos = (uint16_t) ((SIN_TAB_LEN * (uint32_t) angleMilli) / 1000); 00079 return SIN_TAB[pos % SIN_TAB_LEN]; 00080 } 00081 00082 static int16_t cosI(uint16_t angleMilli) 00083 { 00084 return sinI(angleMilli + 250); 00085 } 00086 00087 static uint16_t ilog2(uint16_t val) 00088 { 00089 uint16_t log; 00090 log = 0; 00091 val = val >> 1; /* The 20 = 1 => log = 0 => val = 0 */ 00092 while (val > 0) { 00093 val = val >> 1; 00094 log++; 00095 } 00096 return log; 00097 } 00098 00099 00100 /* ifft(xre[], n) - integer (fixpoint) version of Fast Fourier Transform 00101 An integer version of FFT that takes in-samples in an int16_t array 00102 and does an fft on n samples in the array. 00103 The result of the FFT is stored in the same array as the samples 00104 was stored. Them imaginary part of the result is stored in xim which 00105 needs to be of the same size as xre (e.g. n ints). 00106 00107 Note: This fft is designed to be used with 8 bit values (e.g. not 00108 16 bit values). The reason for the int16_t array is for keeping some 00109 'room' for the calculations. It is also designed for doing fairly small 00110 FFT:s since to large sample arrays might cause it to overflow during 00111 calculations. 00112 */ 00113 void 00114 ifft(int16_t xre[], int16_t xim[], uint16_t n) 00115 { 00116 uint16_t nu; 00117 uint16_t n2; 00118 uint16_t nu1; 00119 int p, k, l, i; 00120 int32_t c, s, tr, ti; 00121 00122 nu = ilog2(n); 00123 nu1 = nu - 1; 00124 n2 = n / 2; 00125 00126 for (i = 0; i < n; i++) 00127 xim[i] = 0; 00128 00129 for (l = 1; l <= nu; l++) { 00130 for (k = 0; k < n; k += n2) { 00131 for (i = 1; i <= n2; i++) { 00132 p = bitrev(k >> nu1, nu); 00133 c = cosI((1000 * p) / n); 00134 s = sinI((1000 * p) / n); 00135 00136 tr = ((xre[k + n2] * c + xim[k + n2] * s) >> RESOLUTION); 00137 ti = ((xim[k + n2] * c - xre[k + n2] * s) >> RESOLUTION); 00138 00139 xre[k + n2] = xre[k] - tr; 00140 xim[k + n2] = xim[k] - ti; 00141 xre[k] += tr; 00142 xim[k] += ti; 00143 k++; 00144 } 00145 } 00146 nu1--; 00147 n2 = n2 / 2; 00148 } 00149 00150 for (k = 0; k < n; k++) { 00151 p = bitrev(k, nu); 00152 if (p > k) { 00153 n2 = xre[k]; 00154 xre[k] = xre[p]; 00155 xre[p] = n2; 00156 00157 n2 = xim[k]; 00158 xim[k] = xim[p]; 00159 xim[p] = n2; 00160 } 00161 } 00162 00163 /* This is a fast but not 100% correct magnitude calculation */ 00164 /* Should be sqrt(xre[i]^2 + xim[i]^2) and normalized with div. by n */ 00165 for (i = 0, n2 = n / 2; i < n2; i++) { 00166 xre[i] = (ABS(xre[i]) + ABS(xim[i])); 00167 } 00168 }