ESP-IDF Firmware
Firmware architecture and call graph
Loading...
Searching...
No Matches
dsps_fft2r_sc16_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 "dsp_common.h"
17#include "dsp_types.h"
18#include <math.h>
19#include "esp_attr.h"
20#include <malloc.h>
21#include "dsp_tests.h"
22
23
28
29unsigned short reverse(unsigned short x, unsigned short N, int order);
30
31static const int add_rount_mult = 0x7fff;
32static const int mult_shift_const = 0x7fff; // Used to shift data << 15
33
34static inline int16_t xtfixed_bf_1(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
35{
36 int result = a0 * mult_shift_const;
37 result -= (int32_t)a1 * (int32_t)a2 + (int32_t)a3 * (int32_t)a4;
38 result += add_rount_mult;
39 result = result >> result_shift;
40 return (int16_t)result;
41}
42
43static inline int16_t xtfixed_bf_2(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
44{
45 int result = a0 * mult_shift_const;
46 result -= ((int32_t)a1 * (int32_t)a2 - (int32_t)a3 * (int32_t)a4);
47 result += add_rount_mult;
48 result = result >> result_shift;
49 return (int16_t)result;
50}
51
52static inline int16_t xtfixed_bf_3(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
53{
54 int result = a0 * mult_shift_const;
55 result += (int32_t)a1 * (int32_t)a2 + (int32_t)a3 * (int32_t)a4;
56 result += add_rount_mult;
57 result = result >> result_shift;
58 return (int16_t)result;
59}
60
61static inline int16_t xtfixed_bf_4(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
62{
63 int result = a0 * mult_shift_const;
64 result += (int32_t)a1 * (int32_t)a2 - (int32_t)a3 * (int32_t)a4;
65 result += add_rount_mult;
66 result = result >> result_shift;
67 return (int16_t)result;
68}
69
70esp_err_t dsps_fft2r_init_sc16(int16_t *fft_table_buff, int table_size)
71{
72 esp_err_t result = ESP_OK;
74 return result;
75 }
76 if (table_size > CONFIG_DSP_MAX_FFT_SIZE) {
78 }
79 if (table_size == 0) {
80 return result;
81 }
82 if (fft_table_buff != NULL) {
85 }
86 dsps_fft_w_table_sc16 = fft_table_buff;
87 dsps_fft_w_table_sc16_size = table_size;
88 } else {
90 dsps_fft_w_table_sc16 = (int16_t *)memalign(16, CONFIG_DSP_MAX_FFT_SIZE * sizeof(int16_t));
91 }
94 }
95
97 if (result != ESP_OK) {
98 return result;
99 }
101 if (result != ESP_OK) {
102 return result;
103 }
105 return ESP_OK;
106}
107
116
117esp_err_t dsps_fft2r_sc16_ansi_(int16_t *data, int N, int16_t *sc_table)
118{
119 if (!dsp_is_power_of_two(N)) {
121 }
124 }
125
126 esp_err_t result = ESP_OK;
127
128 uint32_t *w = (uint32_t *)sc_table;
129 uint32_t *in_data = (uint32_t *)data;
130
131 int ie, ia, m;
132 sc16_t cs;// c - re, s - im
133 sc16_t m_data;
134 sc16_t a_data;
135
136 ie = 1;
137 for (int N2 = N / 2; N2 > 0; N2 >>= 1) {
138 ia = 0;
139 for (int j = 0; j < ie; j++) {
140 cs.data = w[j];
141 //c = w[2 * j];
142 //s = w[2 * j + 1];
143 for (int i = 0; i < N2; i++) {
144 m = ia + N2;
145 m_data.data = in_data[m];
146 a_data.data = in_data[ia];
147 //data[2 * m] = data[2 * ia] - re_temp;
148 //data[2 * m + 1] = data[2 * ia + 1] - im_temp;
149 sc16_t m1;
150 m1.re = xtfixed_bf_1(a_data.re, cs.re, m_data.re, cs.im, m_data.im, 16);//(a_data.re - temp.re + shift_const) >> 1;
151 m1.im = xtfixed_bf_2(a_data.im, cs.re, m_data.im, cs.im, m_data.re, 16);//(a_data.im - temp.im + shift_const) >> 1;
152 in_data[m] = m1.data;
153
154 //data[2 * ia] = data[2 * ia] + re_temp;
155 //data[2 * ia + 1] = data[2 * ia + 1] + im_temp;
156 sc16_t m2;
157 m2.re = xtfixed_bf_3(a_data.re, cs.re, m_data.re, cs.im, m_data.im, 16);//(a_data.re + temp.re + shift_const) >> 1;
158 m2.im = xtfixed_bf_4(a_data.im, cs.re, m_data.im, cs.im, m_data.re, 16);//(a_data.im + temp.im + shift_const)>>1;
159 in_data[ia] = m2.data;
160 ia++;
161 }
162 ia += N2;
163 }
164 ie <<= 1;
165 }
166 return result;
167}
168
169
170static inline unsigned short reverse_sc16(unsigned short x, unsigned short N, int order)
171{
172 unsigned short b = x;
173
174 b = (b & 0xff00) >> 8 | (b & 0x00fF) << 8;
175 b = (b & 0xf0F0) >> 4 | (b & 0x0f0F) << 4;
176 b = (b & 0xCCCC) >> 2 | (b & 0x3333) << 2;
177 b = (b & 0xAAAA) >> 1 | (b & 0x5555) << 1;
178 return b >> (16 - order);
179}
180
182{
183 if (!dsp_is_power_of_two(N)) {
185 }
186 esp_err_t result = ESP_OK;
187
188 int j, k;
189 uint32_t temp;
190 uint32_t *in_data = (uint32_t *)data;
191 j = 0;
192 for (int i = 1; i < (N - 1); i++) {
193 k = N >> 1;
194 while (k <= j) {
195 j -= k;
196 k >>= 1;
197 }
198 j += k;
199 if (i < j) {
200 temp = in_data[j];
201 in_data[j] = in_data[i];
202 in_data[i] = temp;
203 }
204 }
205 return result;
206}
207
209{
210 if (!dsp_is_power_of_two(N)) {
212 }
213
214 esp_err_t result = ESP_OK;
215
216 int i;
217 float e = M_PI * 2.0 / N;
218
219 for (i = 0; i < (N >> 1); i++) {
220 w[2 * i] = (int16_t)(INT16_MAX * cosf(i * e));
221 w[2 * i + 1] = (int16_t)(INT16_MAX * sinf(i * e));
222 }
223
224 return result;
225}
226
228{
229 if (!dsp_is_power_of_two(N)) {
231 }
232 esp_err_t result = ESP_OK;
233
234 int i;
235 int n2 = N << (1); // we will operate with int32 indexes
236 uint32_t *in_data = (uint32_t *)data;
237
238 sc16_t kl;
239 sc16_t kh;
240 sc16_t nl;
241 sc16_t nh;
242
243 for (i = 0; i < (N / 4); i++) {
244 kl.data = in_data[i + 1];
245 nl.data = in_data[N - i - 1];
246 kh.data = in_data[i + 1 + N / 2];
247 nh.data = in_data[N - i - 1 - N / 2];
248
249 data[i * 2 + 0 + 2] = kl.re + nl.re;
250 data[i * 2 + 1 + 2] = kl.im - nl.im;
251
252 data[n2 - i * 2 - 1 - N] = kh.re + nh.re;
253 data[n2 - i * 2 - 2 - N] = kh.im - nh.im;
254
255 data[i * 2 + 0 + 2 + N] = kl.im + nl.im;
256 data[i * 2 + 1 + 2 + N] = kl.re - nl.re;
257
258 data[n2 - i * 2 - 1] = kh.im + nh.im;
259 data[n2 - i * 2 - 2] = kh.re - nh.re;
260 }
261 data[N] = data[1];
262 data[1] = 0;
263 data[N + 1] = 0;
264
265 return result;
266}
267
269{
270
271 int order = dsp_power_of_two(N);
273 sc16_t *result = (sc16_t *)data;
274 // Original formula...
275 // result[0].re = result[0].re + result[0].im;
276 // result[N].re = result[0].re - result[0].im;
277 // result[0].im = 0;
278 // result[N].im = 0;
279 // Optimized one:
280 int16_t tmp_re = result[0].re;
281 result[0].re = (tmp_re + result[0].im) >> 1;
282 result[0].im = (tmp_re - result[0].im) >> 1;
283
284 sc16_t f1k, f2k;
285 for (int k = 1; k <= N / 2 ; ++k ) {
286 sc16_t fpk = result[k];
287 sc16_t fpnk;
288 fpnk.re = result[N - k].re;
289 fpnk.im = result[N - k].im;
290 f1k.re = fpk.re + fpnk.re;
291 f1k.im = fpk.im - fpnk.im;
292 f2k.re = fpk.re - fpnk.re;
293 f2k.im = fpk.im + fpnk.im;
294
295 int table_index = reverse(k, N, order);
296
297 // float c = -dsps_fft_w_table_fc32[table_index*2+1];
298 // float s = -dsps_fft_w_table_fc32[table_index*2+0];
299 sc16_t w = table[table_index];
300
301 sc16_t tw;
302 {
303 int re = (w.re * f2k.im - w.im * f2k.re) >> 15;
304 int im = (+w.re * f2k.re + w.im * f2k.im) >> 15;
305 tw.re = re;
306 tw.im = im;
307 }
308
309 result[k].re = (f1k.re + tw.re) >> 2;
310 result[k].im = (f1k.im - tw.im) >> 2;
311 result[N - k].re = (f1k.re - tw.re) >> 2;
312 result[N - k].im = -(f1k.im + tw.im) >> 2;
313 }
314 return ESP_OK;
315}
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
#define memalign(align_, size_)
Definition dsp_tests.h:35
union sc16_u sc16_t
#define CONFIG_DSP_MAX_FFT_SIZE
Definition dsps_fft2r.h:24
esp_err_t dsps_fft2r_init_sc16(int16_t *fft_table_buff, int table_size)
static const int add_rount_mult
esp_err_t dsps_bit_rev_sc16_ansi(int16_t *data, int N)
static unsigned short reverse_sc16(unsigned short x, unsigned short N, int order)
uint8_t dsps_fft2r_sc16_initialized
static int16_t xtfixed_bf_2(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
int16_t * dsps_fft_w_table_sc16
void dsps_fft2r_deinit_sc16()
uint8_t dsps_fft2r_sc16_mem_allocated
esp_err_t dsps_gen_w_r2_sc16(int16_t *w, int N)
static int16_t xtfixed_bf_4(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
unsigned short reverse(unsigned short x, unsigned short N, int order)
esp_err_t dsps_cplx2reC_sc16(int16_t *data, int N)
static int16_t xtfixed_bf_3(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
esp_err_t dsps_cplx2real_sc16_ansi(int16_t *data, int N)
Convert complex FFT result to real array.
static int16_t xtfixed_bf_1(int16_t a0, int16_t a1, int16_t a2, int16_t a3, int16_t a4, int result_shift)
esp_err_t dsps_fft2r_sc16_ansi_(int16_t *data, int N, int16_t *sc_table)
int dsps_fft_w_table_sc16_size
static const int mult_shift_const
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
static float data[128 *2]
Definition test_fft2r.c:34
float x[1024]
Definition test_fir.c:10
#define N
Definition test_mmult.c:13
const int m
Definition test_mmult.c:16
const int k
Definition test_mmult.c:18
int16_t re
Definition dsp_types.h:10
uint32_t data
Definition dsp_types.h:13
int16_t im
Definition dsp_types.h:11