ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
dsps_fft4r_fc32_ansi.c
Go to the documentation of this file.
1// Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "dsps_fft2r.h"
16#include "dsps_fft4r.h"
17#include "dsp_common.h"
18#include "dsp_types.h"
19#include <math.h>
20#include "esp_attr.h"
21#include "esp_log.h"
22#include <string.h>
23#include <malloc.h>
24
25static const char *TAG = "fftr4 ansi";
26
31//float* win2;
32uint16_t *dsps_fft4r_ram_rev_table = NULL;
33
34esp_err_t dsps_fft4r_init_fc32(float *fft_table_buff, int max_fft_size)
35{
36 esp_err_t result = ESP_OK;
37 if (dsps_fft4r_initialized != 0) {
38 return result;
39 }
40 if (max_fft_size > CONFIG_DSP_MAX_FFT_SIZE) {
42 }
43 if (max_fft_size == 0) {
44 return result;
45 }
46 if (fft_table_buff != NULL) {
49 }
50 dsps_fft4r_w_table_fc32 = fft_table_buff;
51 dsps_fft4r_w_table_size = max_fft_size * 2;
52 } else {
54 dsps_fft4r_w_table_fc32 = (float *)malloc(max_fft_size * sizeof(float) * 4);
55 if (NULL == dsps_fft4r_w_table_fc32) {
57 }
58 }
59 dsps_fft4r_w_table_size = max_fft_size * 2;
61 }
62
63 // FFT ram_rev table allocated
64 int pow = dsp_power_of_two(max_fft_size) >> 1;
65 if ((pow >= 2) && (pow <= 6)) {
66 dsps_fft4r_ram_rev_table = (uint16_t *)malloc(2 * dsps_fft4r_rev_tables_fc32_size[pow - 2] * sizeof(uint16_t));
67 if (NULL == dsps_fft4r_ram_rev_table) {
69 }
70 memcpy(dsps_fft4r_ram_rev_table, dsps_fft4r_rev_tables_fc32[pow - 2], 2 * dsps_fft4r_rev_tables_fc32_size[pow - 2] * sizeof(uint16_t));
72 }
73
74 for (int i = 0; i < dsps_fft4r_w_table_size; i++) {
75 float angle = 2 * M_PI * i / (float)dsps_fft4r_w_table_size;
76 dsps_fft4r_w_table_fc32[2 * i + 0] = cosf(angle);
77 dsps_fft4r_w_table_fc32[2 * i + 1] = sinf(angle);
78 }
79
81
82 return ESP_OK;
83}
84
86{
89 }
90 if (dsps_fft4r_ram_rev_table != NULL) {
93 }
94 // Re init bitrev table for next use
96
99}
100
102{
103 if (!dsp_is_power_of_two(N)) {
105 }
106 if (0 == dsps_fft4r_initialized) {
108 }
109 esp_err_t result = ESP_OK;
110 int log2N = dsp_power_of_two(N);
111 int log4N = log2N >> 1;
112 if ((log2N & 0x01) != 0) {
114 }
115 float r_temp, i_temp;
116 for (int i = 0; i < N; i++) {
117 int cnt;
118 int xx;
119 int bits2;
120 xx = 0;
121 cnt = log4N;
122 int j = i;
123 while (cnt > 0) {
124 bits2 = j & 0x3;
125 xx = (xx << 2) + bits2;
126 j = j >> 2;
127 cnt--;
128 }
129 if (i < xx) {
130 r_temp = data[i * 2 + 0];
131 i_temp = data[i * 2 + 1];
132 data[i * 2 + 0] = data[xx * 2 + 0];
133 data[i * 2 + 1] = data[xx * 2 + 1];
134 data[xx * 2 + 0] = r_temp;
135 data[xx * 2 + 1] = i_temp;
136 }
137 }
138 return result;
139}
140
141esp_err_t dsps_fft4r_fc32_ansi_(float *data, int length, float *table, int table_size)
142{
143 if (0 == dsps_fft4r_initialized) {
145 }
146
147 fc32_t bfly[4];
148 int log2N = dsp_power_of_two(length);
149 int log4N = log2N >> 1;
150 if ((log2N & 0x01) != 0) {
152 }
153
154 int m = 2;
155 int wind_step = table_size / length;
156 while (1) {
157 if (log4N == 0) {
158 break;
159 }
160 length = length >> 2;
161 for (int j = 0; j < m; j += 2) { // j: which FFT of this step
162 int start_index = j * (length << 1); // n: n-point FFT
163
164 fc32_t *ptrc0 = (fc32_t *)data + start_index;
165 fc32_t *ptrc1 = ptrc0 + length;
166 fc32_t *ptrc2 = ptrc1 + length;
167 fc32_t *ptrc3 = ptrc2 + length;
168
169 fc32_t *winc0 = (fc32_t *)table;
170 fc32_t *winc1 = winc0;
171 fc32_t *winc2 = winc0;
172
173 for (int k = 0; k < length; k++) {
174 fc32_t in0 = *ptrc0;
175 fc32_t in2 = *ptrc2;
176 fc32_t in1 = *ptrc1;
177 fc32_t in3 = *ptrc3;
178
179 bfly[0].re = in0.re + in2.re + in1.re + in3.re;
180 bfly[0].im = in0.im + in2.im + in1.im + in3.im;
181
182 bfly[1].re = in0.re - in2.re + in1.im - in3.im;
183 bfly[1].im = in0.im - in2.im - in1.re + in3.re;
184
185 bfly[2].re = in0.re + in2.re - in1.re - in3.re;
186 bfly[2].im = in0.im + in2.im - in1.im - in3.im;
187
188 bfly[3].re = in0.re - in2.re - in1.im + in3.im;
189 bfly[3].im = in0.im - in2.im + in1.re - in3.re;
190
191
192
193 *ptrc0 = bfly[0];
194 ptrc1->re = bfly[1].re * winc0->re + bfly[1].im * winc0->im;
195 ptrc1->im = bfly[1].im * winc0->re - bfly[1].re * winc0->im;
196 ptrc2->re = bfly[2].re * winc1->re + bfly[2].im * winc1->im;
197 ptrc2->im = bfly[2].im * winc1->re - bfly[2].re * winc1->im;
198 ptrc3->re = bfly[3].re * winc2->re + bfly[3].im * winc2->im;
199 ptrc3->im = bfly[3].im * winc2->re - bfly[3].re * winc2->im;
200
201 winc0 += 1 * wind_step;
202 winc1 += 2 * wind_step;
203 winc2 += 3 * wind_step;
204
205 ptrc0++;
206 ptrc1++;
207 ptrc2++;
208 ptrc3++;
209 }
210 }
211 m = m << 2;
212 wind_step = wind_step << 2;
213 log4N--;
214 }
215 return ESP_OK;
216}
217
218esp_err_t dsps_cplx2real_fc32_ansi_(float *data, int N, float *table, int table_size)
219{
220 if (0 == dsps_fft4r_initialized) {
222 }
223 int wind_step = table_size / (N);
224 fc32_t *result = (fc32_t *)data;
225 // Original formula...
226 // result[0].re = result[0].re + result[0].im;
227 // result[N].re = result[0].re - result[0].im;
228 // result[0].im = 0;
229 // result[N].im = 0;
230 // Optimized one:
231 float tmp_re = result[0].re;
232 result[0].re = tmp_re + result[0].im;
233 result[0].im = tmp_re - result[0].im;
234
235 fc32_t f1k, f2k;
236 for (int k = 1; k <= N / 2 ; k++ ) {
237 fc32_t fpk = result[k];
238 fc32_t fpnk = result[N - k];
239 f1k.re = fpk.re + fpnk.re;
240 f1k.im = fpk.im - fpnk.im;
241 f2k.re = fpk.re - fpnk.re;
242 f2k.im = fpk.im + fpnk.im;
243
244 float c = -table[k * wind_step + 1];
245 float s = -table[k * wind_step + 0];
246 fc32_t tw;
247 tw.re = c * f2k.re - s * f2k.im;
248 tw.im = s * f2k.re + c * f2k.im;
249
250 result[k].re = 0.5 * (f1k.re + tw.re);
251 result[k].im = 0.5 * (f1k.im + tw.im);
252 result[N - k].re = 0.5 * (f1k.re - tw.re);
253 result[N - k].im = 0.5 * (tw.im - f1k.im);
254 }
255 return ESP_OK;
256}
257
258esp_err_t dsps_gen_bitrev4r_table(int N, int step, char *name_ext)
259{
260 if (!dsp_is_power_of_two(N)) {
262 }
263
264 int items_count = 0;
265 ESP_LOGD(TAG, "const uint16_t bitrev4r_table_%i_%s[] = { ", N, name_ext);
266 int log2N = dsp_power_of_two(N);
267 int log4N = log2N >> 1;
268
269 for (int i = 1; i < N - 1; i++) {
270 int cnt;
271 int xx;
272 int bits2;
273 xx = 0;
274 cnt = log4N;
275 int j = i;
276 while (cnt > 0) {
277 bits2 = j & 0x3;
278 xx = (xx << 2) + bits2;
279 j = j >> 2;
280 cnt--;
281 }
282 if (i < xx) {
283 ESP_LOGD(TAG, "%i, %i, ", i * step, xx * step);
284 items_count++;
285 if ((items_count % 8) == 0) {
286 ESP_LOGD(TAG, " ");
287 }
288 }
289 }
290
291 ESP_LOGD(TAG, "};");
292 ESP_LOGD(TAG, "const uint16_t bitrev4r_table_%i_%s_size = %i;\n", N, name_ext, items_count);
293
294 ESP_LOGD(TAG, "extern const uint16_t bitrev4r_table_%i_%s[];", N, name_ext);
295 ESP_LOGD(TAG, "extern const uint16_t bitrev4r_table_%i_%s_size;\n", N, name_ext);
296 return ESP_OK;
297}
298
300{
301 uint16_t *table;
302 uint16_t table_size;
303 switch (N) {
304 case 16:
305 table = (uint16_t *)dsps_fft4r_rev_tables_fc32[0];
306 table_size = dsps_fft4r_rev_tables_fc32_size[0];
307 break;
308 case 64:
309 table = (uint16_t *)dsps_fft4r_rev_tables_fc32[1];
310 table_size = dsps_fft4r_rev_tables_fc32_size[1];
311 break;
312 case 256:
313 table = (uint16_t *)dsps_fft4r_rev_tables_fc32[2];
314 table_size = dsps_fft4r_rev_tables_fc32_size[2];
315 break;
316 case 1024:
317 table = (uint16_t *)dsps_fft4r_rev_tables_fc32[3];
318 table_size = dsps_fft4r_rev_tables_fc32_size[3];
319 break;
320 case 4096:
321 table = (uint16_t *)dsps_fft4r_rev_tables_fc32[4];
322 table_size = dsps_fft4r_rev_tables_fc32_size[4];
323 break;
324
325 default:
327 break;
328 }
329
330 return dsps_bit_rev_lookup_fc32(data, table_size, table);
331}
bool dsp_is_power_of_two(int x)
check power of two The function check if the argument is power of 2. The implementation use ANSI C an...
int dsp_power_of_two(int x)
Power of two The function return power of 2 for values 2^N. The implementation use ANSI C and could b...
#define ESP_ERR_DSP_PARAM_OUTOFRANGE
#define ESP_ERR_DSP_UNINITIALIZED
#define ESP_ERR_DSP_INVALID_LENGTH
#define ESP_ERR_DSP_REINITIALIZED
union fc32_u fc32_t
#define dsps_bit_rev_lookup_fc32
Definition dsps_fft2r.h:252
#define CONFIG_DSP_MAX_FFT_SIZE
Definition dsps_fft2r.h:24
#define dsps_bit_rev4r_fc32
Definition dsps_fft4r.h:184
void dsps_fft4r_rev_tables_init_fc32(void)
uint16_t * dsps_fft4r_rev_tables_fc32[]
const uint16_t dsps_fft4r_rev_tables_fc32_size[]
esp_err_t dsps_cplx2real_fc32_ansi_(float *data, int N, float *table, int table_size)
Convert FFT result to complex array for real input data.
esp_err_t dsps_fft4r_init_fc32(float *fft_table_buff, int max_fft_size)
init fft tables
uint16_t * dsps_fft4r_ram_rev_table
int dsps_fft4r_w_table_size
esp_err_t dsps_fft4r_fc32_ansi_(float *data, int length, float *table, int table_size)
complex FFT of radix 4
float * dsps_fft4r_w_table_fc32
uint8_t dsps_fft4r_mem_allocated
esp_err_t dsps_gen_bitrev4r_table(int N, int step, char *name_ext)
esp_err_t dsps_bit_rev4r_direct_fc32_ansi(float *data, int N)
uint8_t dsps_fft4r_initialized
void dsps_fft4r_deinit_fc32()
deinit fft tables
int esp_err_t
Definition esp_err.h:21
#define ESP_OK
Definition esp_err.h:23
#define M_PI
Definition esp_err.h:26
#define ESP_LOGD
Definition esp_log.h:22
static const char * TAG
Definition main/main.c:31
static float data[128 *2]
Definition test_fft2r.c:34
#define N
Definition test_mmult.c:13
const int m
Definition test_mmult.c:16
const int k
Definition test_mmult.c:18
float re
Definition dsp_types.h:18
float im
Definition dsp_types.h:19