From d175e8b4820549bf2b93a0c0bddfd3696277477d Mon Sep 17 00:00:00 2001 From: Paul Sutton Date: Fri, 20 Jun 2014 15:35:37 +0100 Subject: [PATCH] Cleanup and bugfix of dft module --- lte/phy/include/liblte/phy/utils/dft.h | 76 ++++--- lte/phy/lib/common/src/fft.c | 16 +- lte/phy/lib/common/test/fft_test.c | 1 - lte/phy/lib/phch/test/pbch_file_test.c | 1 - lte/phy/lib/phch/test/pcfich_file_test.c | 1 - lte/phy/lib/phch/test/pdcch_file_test.c | 1 - lte/phy/lib/phch/test/pdsch_file_test.c | 3 +- lte/phy/lib/phch/test/phich_file_test.c | 1 - lte/phy/lib/sync/src/find_sss.c | 2 +- lte/phy/lib/sync/src/pss.c | 7 +- lte/phy/lib/sync/src/sss.c | 6 +- lte/phy/lib/sync/test/sync_test.c | 2 - lte/phy/lib/utils/src/convolution.c | 12 +- lte/phy/lib/utils/src/dft.c | 239 +++++++---------------- lte/phy/lib/utils/test/CMakeLists.txt | 36 ++++ lte/phy/lib/utils/test/dft_test.c | 137 +++++++++++++ 16 files changed, 301 insertions(+), 240 deletions(-) create mode 100644 lte/phy/lib/utils/test/CMakeLists.txt create mode 100644 lte/phy/lib/utils/test/dft_test.c diff --git a/lte/phy/include/liblte/phy/utils/dft.h b/lte/phy/include/liblte/phy/utils/dft.h index 17503bfc3..9f180d0a1 100644 --- a/lte/phy/include/liblte/phy/utils/dft.h +++ b/lte/phy/include/liblte/phy/utils/dft.h @@ -29,42 +29,42 @@ #ifndef DFT_H_ #define DFT_H_ -#include +#include #include "liblte/config.h" -/* dft is a frontend to the fftw3 library. It facilitates the computation of - * complex or real DFT, power spectral density, normalization, etc. - * It also supports the creation of multiple FFT plans for different FFT sizes - * or options, selecting a different one at runtime. +/* Generic DFT module. + * Supports one-dimensional complex and real transforms. Options are set + * using the dft_plan_set_x functions. + * + * Options (default is false): + * mirror - Rearranges negative and positive frequency bins. Swaps after + * transform for FORWARD, swaps before transform for BACKWARD. + * db - Provides output in dB (10*log10(x)). + * norm - Normalizes output (by sqrt(len) for complex, len for real). + * dc - Handles insertion and removal of null DC carrier internally. */ - typedef enum { - COMPLEX_2_COMPLEX, REAL_2_REAL, COMPLEX_2_REAL + COMPLEX, REAL }dft_mode_t; typedef enum { FORWARD, BACKWARD }dft_dir_t; - -#define DFT_MIRROR_PRE 1 -#define DFT_PSD 2 -#define DFT_OUT_DB 4 -#define DFT_MIRROR_POS 8 -#define DFT_NORMALIZE 16 -#define DFT_DC_OFFSET 32 - typedef struct LIBLTE_API { - int size; - int sign; - void *in; - void *out; - void *p; - int options; - dft_dir_t dir; - dft_mode_t mode; + int size; // DFT length + void *in; // Input buffer + void *out; // Output buffer + void *p; // DFT plan + bool forward; // Forward transform? + bool mirror; // Shift negative and positive frequencies? + bool db; // Provide output in dB? + bool norm; // Normalize output? + bool dc; // Handle insertion/removal of null DC carrier internally? + dft_dir_t dir; // Forward/Backward + dft_mode_t mode; // Complex/Real }dft_plan_t; typedef _Complex float dft_c_t; @@ -72,32 +72,24 @@ typedef float dft_r_t; /* Create DFT plans */ -LIBLTE_API int dft_plan(dft_plan_t *plan, const int dft_points, - dft_mode_t mode, dft_dir_t dir); -LIBLTE_API int dft_plan_c2c(dft_plan_t *plan, const int dft_points, dft_dir_t dir); -LIBLTE_API int dft_plan_r2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir); -LIBLTE_API int dft_plan_c2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir); +LIBLTE_API int dft_plan(dft_plan_t *plan, const int dft_points, dft_dir_t dir, + dft_mode_t type); +LIBLTE_API int dft_plan_c(dft_plan_t *plan, const int dft_points, dft_dir_t dir); +LIBLTE_API int dft_plan_r(dft_plan_t *plan, const int dft_points, dft_dir_t dir); LIBLTE_API void dft_plan_free(dft_plan_t *plan); +/* Set options */ -/* Create a vector of DFT plans */ - -LIBLTE_API int dft_plan_vector(dft_plan_t *plans, const int *dft_points, - dft_mode_t *modes, dft_dir_t *dirs, int nof_plans); -LIBLTE_API int dft_plan_multi_c2c(dft_plan_t *plans, const int *dft_points, - dft_dir_t dir, int nof_plans); -LIBLTE_API int dft_plan_multi_c2r(dft_plan_t *plans, const int *dft_points, - dft_dir_t dir, int nof_plans); -LIBLTE_API int dft_plan_multi_r2r(dft_plan_t *plans, const int *dft_points, - dft_dir_t dir, int nof_plans); -LIBLTE_API void dft_plan_free_vector(dft_plan_t *plans, int nof_plans); +LIBLTE_API void dft_plan_set_mirror(dft_plan_t *plan, bool val); +LIBLTE_API void dft_plan_set_db(dft_plan_t *plan, bool val); +LIBLTE_API void dft_plan_set_norm(dft_plan_t *plan, bool val); +LIBLTE_API void dft_plan_set_dc(dft_plan_t *plan, bool val); /* Compute DFT */ LIBLTE_API void dft_run(dft_plan_t *plan, void *in, void *out); -LIBLTE_API void dft_run_c2c(dft_plan_t *plan, dft_c_t *in, dft_c_t *out); -LIBLTE_API void dft_run_r2r(dft_plan_t *plan, dft_r_t *in, dft_r_t *out); -LIBLTE_API void dft_run_c2r(dft_plan_t *plan, dft_c_t *in, dft_r_t *out); +LIBLTE_API void dft_run_c(dft_plan_t *plan, dft_c_t *in, dft_c_t *out); +LIBLTE_API void dft_run_r(dft_plan_t *plan, dft_r_t *in, dft_r_t *out); #endif // DFT_H_ diff --git a/lte/phy/lib/common/src/fft.c b/lte/phy/lib/common/src/fft.c index 7057f4240..508c63264 100644 --- a/lte/phy/lib/common/src/fft.c +++ b/lte/phy/lib/common/src/fft.c @@ -42,7 +42,7 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp_type, int nof_prb, dft_dir_t dir) { fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); return -1; } - if (dft_plan_c2c(&q->fft_plan, symbol_sz, dir)) { + if (dft_plan_c(&q->fft_plan, symbol_sz, dir)) { fprintf(stderr, "Error: Creating DFT plan\n"); return -1; } @@ -52,12 +52,10 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp_type, int nof_prb, dft_dir_t dir) { return -1; } - q->fft_plan.options = DFT_NORMALIZE; - if (dir==FORWARD) { - q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_POS; - } else { - q->fft_plan.options |= DFT_DC_OFFSET | DFT_MIRROR_PRE; - } + dft_plan_set_mirror(&q->fft_plan, true); + dft_plan_set_norm(&q->fft_plan, true); + dft_plan_set_dc(&q->fft_plan, true); + q->symbol_sz = symbol_sz; q->nof_symbols = CP_NSYMB(cp_type); q->cp_type = cp_type; @@ -109,7 +107,7 @@ void lte_fft_run(lte_fft_t *q, cf_t *input, cf_t *output) { int i; for (i=0;inof_symbols;i++) { input += CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); - dft_run_c2c(&q->fft_plan, input, q->tmp); + dft_run_c(&q->fft_plan, input, q->tmp); memcpy(output, &q->tmp[q->nof_guards], q->nof_re * sizeof(cf_t)); input += q->symbol_sz; output += q->nof_re; @@ -124,7 +122,7 @@ void lte_ifft_run(lte_fft_t *q, cf_t *input, cf_t *output) { for (i=0;inof_symbols;i++) { cp_len = CP_ISNORM(q->cp_type)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); - dft_run_c2c(&q->fft_plan, q->tmp, &output[cp_len]); + dft_run_c(&q->fft_plan, q->tmp, &output[cp_len]); input += q->nof_re; /* add CP */ memcpy(output, &output[q->symbol_sz], cp_len * sizeof(cf_t)); diff --git a/lte/phy/lib/common/test/fft_test.c b/lte/phy/lib/common/test/fft_test.c index 0a12cffd1..a5e1e3662 100644 --- a/lte/phy/lib/common/test/fft_test.c +++ b/lte/phy/lib/common/test/fft_test.c @@ -136,6 +136,5 @@ int main(int argc, char **argv) { n_prb++; } - fftwf_cleanup(); exit(0); } diff --git a/lte/phy/lib/phch/test/pbch_file_test.c b/lte/phy/lib/phch/test/pbch_file_test.c index 6982537ff..c356620cf 100644 --- a/lte/phy/lib/phch/test/pbch_file_test.c +++ b/lte/phy/lib/phch/test/pbch_file_test.c @@ -212,7 +212,6 @@ int main(int argc, char **argv) { n = pbch_decode(&pbch, fft_buffer, ce, 1, &mib); base_free(); - fftwf_cleanup(); if (n < 0) { fprintf(stderr, "Error decoding PBCH\n"); diff --git a/lte/phy/lib/phch/test/pcfich_file_test.c b/lte/phy/lib/phch/test/pcfich_file_test.c index 02c9aa0d0..f66b445f9 100644 --- a/lte/phy/lib/phch/test/pcfich_file_test.c +++ b/lte/phy/lib/phch/test/pcfich_file_test.c @@ -233,7 +233,6 @@ int main(int argc, char **argv) { printf("cfi: %d, distance: %d\n", cfi, distance); base_free(); - fftwf_cleanup(); if (n < 0) { fprintf(stderr, "Error decoding PCFICH\n"); diff --git a/lte/phy/lib/phch/test/pdcch_file_test.c b/lte/phy/lib/phch/test/pdcch_file_test.c index cce20a23d..9a77d3a54 100644 --- a/lte/phy/lib/phch/test/pdcch_file_test.c +++ b/lte/phy/lib/phch/test/pdcch_file_test.c @@ -304,6 +304,5 @@ int main(int argc, char **argv) { } while (nof_frames <= max_frames); base_free(); - fftwf_cleanup(); exit(ret); } diff --git a/lte/phy/lib/phch/test/pdsch_file_test.c b/lte/phy/lib/phch/test/pdsch_file_test.c index 55b4dd833..882b612fb 100644 --- a/lte/phy/lib/phch/test/pdsch_file_test.c +++ b/lte/phy/lib/phch/test/pdsch_file_test.c @@ -328,7 +328,6 @@ int main(int argc, char **argv) { } while (nof_frames <= max_frames); goout: - base_free(); - fftwf_cleanup(); + base_free(); exit(ret); } diff --git a/lte/phy/lib/phch/test/phich_file_test.c b/lte/phy/lib/phch/test/phich_file_test.c index 6f3bd03c4..03deeda9d 100644 --- a/lte/phy/lib/phch/test/phich_file_test.c +++ b/lte/phy/lib/phch/test/phich_file_test.c @@ -272,7 +272,6 @@ int main(int argc, char **argv) { } base_free(); - fftwf_cleanup(); if (n < 0) { fprintf(stderr, "Error decoding phich\n"); diff --git a/lte/phy/lib/sync/src/find_sss.c b/lte/phy/lib/sync/src/find_sss.c index 72e1db859..33c4e015c 100644 --- a/lte/phy/lib/sync/src/find_sss.c +++ b/lte/phy/lib/sync/src/find_sss.c @@ -69,7 +69,7 @@ void sss_synch_m0m1(sss_synch_t *q, cf_t *input, int *m0, float *m0_value, int i; - dft_run_c2c(&q->dftp_input, input, input_fft); + dft_run_c(&q->dftp_input, input, input_fft); for (i = 0; i < N_SSS; i++) { y[0][i] = input_fft[SSS_POS_SYMBOL + 2 * i]; diff --git a/lte/phy/lib/sync/src/pss.c b/lte/phy/lib/sync/src/pss.c index cb4044188..6d17a93ff 100644 --- a/lte/phy/lib/sync/src/pss.c +++ b/lte/phy/lib/sync/src/pss.c @@ -183,12 +183,13 @@ int pss_synch_set_N_id_2(pss_synch_t *q, int N_id_2) { memset(q->pss_signal_freq, 0, PSS_LEN_FREQ * sizeof(cf_t)); memcpy(&pss_signal_pad[33], pss_signal_time, PSS_LEN * sizeof(cf_t)); - if (dft_plan(&plan, PSS_LEN_FREQ - 1, COMPLEX_2_COMPLEX, BACKWARD)) { + if (dft_plan(&plan, PSS_LEN_FREQ - 1, BACKWARD, COMPLEX)) { return -1; } - plan.options = DFT_MIRROR_PRE | DFT_DC_OFFSET; + dft_plan_set_mirror(&plan, true); + dft_plan_set_dc(&plan, true); - dft_run_c2c(&plan, pss_signal_pad, q->pss_signal_freq); + dft_run_c(&plan, pss_signal_pad, q->pss_signal_freq); vec_sc_prod_cfc(q->pss_signal_freq, (float) 1 / (PSS_LEN_FREQ - 1), pss_signal_pad, PSS_LEN_FREQ); diff --git a/lte/phy/lib/sync/src/sss.c b/lte/phy/lib/sync/src/sss.c index 550a081b4..f3b4bb62a 100644 --- a/lte/phy/lib/sync/src/sss.c +++ b/lte/phy/lib/sync/src/sss.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include "liblte/phy/sync/sss.h" @@ -42,11 +43,12 @@ void generate_N_id_1_table(int table[30][30]); int sss_synch_init(sss_synch_t *q) { bzero(q, sizeof(sss_synch_t)); - if (dft_plan(&q->dftp_input, SSS_DFT_LEN, COMPLEX_2_COMPLEX, FORWARD)) { + if (dft_plan(&q->dftp_input, SSS_DFT_LEN, FORWARD, COMPLEX)) { return -1; } generate_N_id_1_table(q->N_id_1_table); - q->dftp_input.options = DFT_MIRROR_POS | DFT_DC_OFFSET; + dft_plan_set_mirror(&q->dftp_input, true); + dft_plan_set_dc(&q->dftp_input, true); return 0; } diff --git a/lte/phy/lib/sync/test/sync_test.c b/lte/phy/lib/sync/test/sync_test.c index 71fc670e0..f1641c9eb 100644 --- a/lte/phy/lib/sync/test/sync_test.c +++ b/lte/phy/lib/sync/test/sync_test.c @@ -158,8 +158,6 @@ int main(int argc, char **argv) { sync_free(&sync); lte_ifft_free(&ifft); - fftwf_cleanup(); - printf("Ok\n"); exit(0); } diff --git a/lte/phy/lib/utils/src/convolution.c b/lte/phy/lib/utils/src/convolution.c index 3e2eec954..2ab27e041 100644 --- a/lte/phy/lib/utils/src/convolution.c +++ b/lte/phy/lib/utils/src/convolution.c @@ -44,13 +44,13 @@ int conv_fft_cc_init(conv_fft_cc_t *state, int input_len, int filter_len) { if (!state->input_fft || !state->filter_fft || !state->output_fft) { return -1; } - if (dft_plan(&state->input_plan,state->output_len,COMPLEX_2_COMPLEX,FORWARD)) { + if (dft_plan(&state->input_plan,state->output_len,FORWARD,COMPLEX)) { return -2; } - if (dft_plan(&state->filter_plan,state->output_len,COMPLEX_2_COMPLEX,FORWARD)) { + if (dft_plan(&state->filter_plan,state->output_len,FORWARD,COMPLEX)) { return -3; } - if (dft_plan(&state->output_plan,state->output_len,COMPLEX_2_COMPLEX,BACKWARD)) { + if (dft_plan(&state->output_plan,state->output_len,BACKWARD,COMPLEX)) { return -4; } return 0; @@ -73,12 +73,12 @@ void conv_fft_cc_free(conv_fft_cc_t *state) { int conv_fft_cc_run(conv_fft_cc_t *state, _Complex float *input, _Complex float *filter, _Complex float *output) { - dft_run_c2c(&state->input_plan, input, state->input_fft); - dft_run_c2c(&state->filter_plan, filter, state->filter_fft); + dft_run_c(&state->input_plan, input, state->input_fft); + dft_run_c(&state->filter_plan, filter, state->filter_fft); vec_prod_ccc(state->input_fft,state->filter_fft,state->output_fft,state->output_len); - dft_run_c2c(&state->output_plan, state->output_fft, output); + dft_run_c(&state->output_plan, state->output_fft, output); return state->output_len; diff --git a/lte/phy/lib/utils/src/dft.c b/lte/phy/lib/utils/src/dft.c index d7e06b7ba..dda8512b2 100644 --- a/lte/phy/lib/utils/src/dft.c +++ b/lte/phy/lib/utils/src/dft.c @@ -33,73 +33,15 @@ #include "liblte/phy/utils/dft.h" -#define div(a,b) ((a-1)/b+1) +#define dft_ceil(a,b) ((a-1)/b+1) +#define dft_floor(a,b) (a/b) - -int dft_plan_vector(dft_plan_t *plans, const int *dft_points, - dft_mode_t *modes, dft_dir_t *dirs, int nof_plans) { - int i; - for (i=0;iout = fftwf_malloc(size_out*len); } -int dft_plan_c2c(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { - int sign; - sign = (dir == FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; +int dft_plan_c(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { allocate(plan,sizeof(fftwf_complex),sizeof(fftwf_complex), dft_points); - + int sign = (dir == FORWARD) ? FFTW_FORWARD : FFTW_BACKWARD; plan->p = fftwf_plan_dft_1d(dft_points, plan->in, plan->out, sign, 0U); if (!plan->p) { return -1; } - plan->size = dft_points; - plan->mode = COMPLEX_2_COMPLEX; + plan->mode = COMPLEX; + plan->dir = dir; + plan->forward = (dir==FORWARD)?true:false; + plan->mirror = false; + plan->db = false; + plan->norm = false; return 0; } -int dft_plan_r2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { - int sign; - sign = (dir == FORWARD) ? FFTW_R2HC : FFTW_HC2R; - +int dft_plan_r(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { allocate(plan,sizeof(float),sizeof(float), dft_points); - + int sign = (dir == FORWARD) ? FFTW_R2HC : FFTW_HC2R; plan->p = fftwf_plan_r2r_1d(dft_points, plan->in, plan->out, sign, 0U); if (!plan->p) { return -1; } - plan->size = dft_points; - plan->mode = REAL_2_REAL; + plan->mode = REAL; + plan->dir = dir; + plan->forward = (dir==FORWARD)?true:false; + plan->mirror = false; + plan->db = false; + plan->norm = false; return 0; } -int dft_plan_c2r(dft_plan_t *plan, const int dft_points, dft_dir_t dir) { - if (dft_plan_c2c(plan, dft_points, dir)) { - return -1; - } - plan->mode = COMPLEX_2_REAL; - return 0; +void dft_plan_set_mirror(dft_plan_t *plan, bool val){ + plan->mirror = val; +} +void dft_plan_set_db(dft_plan_t *plan, bool val){ + plan->db = val; +} +void dft_plan_set_norm(dft_plan_t *plan, bool val){ + plan->norm = val; +} +void dft_plan_set_dc(dft_plan_t *plan, bool val){ + plan->dc = val; } -static void copy(char *dst, char *src, int size_d, int len, int mirror, int dc_offset) { - int offset=dc_offset?1:0; - int hlen; - if (mirror == DFT_MIRROR_PRE) { - hlen = div(len,2); +static void copy_pre(char *dst, char *src, int size_d, int len, + bool forward, bool mirror, bool dc) { + int offset = dc?1:0; + if(mirror && !forward){ + int hlen = dft_floor(len,2); memset(dst,0,size_d*offset); - memcpy(&dst[offset*size_d], &src[size_d*hlen], size_d*(hlen-offset)); - memcpy(&dst[hlen*size_d], src, size_d*(len - hlen)); - } else if (mirror == DFT_MIRROR_POS) { - hlen = div(len,2); - memcpy(dst, &src[size_d*hlen], size_d*hlen); - memcpy(&dst[hlen*size_d], &src[size_d*offset], size_d*(len - hlen)); + memcpy(&dst[size_d*offset], &src[size_d*hlen], size_d*(len-hlen-offset)); + memcpy(&dst[(len-hlen)*size_d], src, size_d*hlen); + } else { + memcpy(dst,src,size_d*len); + } +} + +static void copy_post(char *dst, char *src, int size_d, int len, + bool forward, bool mirror, bool dc) { + int offset = dc?1:0; + if(mirror && forward){ + int hlen = dft_ceil(len,2); + memcpy(dst, &src[size_d*hlen], size_d*(len-hlen)); + memcpy(&dst[(len-hlen)*size_d], &src[size_d*offset], size_d*(hlen-offset)); } else { memcpy(dst,src,size_d*len); } } void dft_run(dft_plan_t *plan, void *in, void *out) { - switch(plan->mode) { - case COMPLEX_2_COMPLEX: - dft_run_c2c(plan,in,out); - break; - case REAL_2_REAL: - dft_run_r2r(plan,in,out); - break; - case COMPLEX_2_REAL: - dft_run_c2r(plan,in,out); - break; + if(plan->mode == COMPLEX) { + dft_run_c(plan,in,out); + } else { + dft_run_r(plan,in,out); } } -void dft_run_c2c(dft_plan_t *plan, dft_c_t *in, dft_c_t *out) { +void dft_run_c(dft_plan_t *plan, dft_c_t *in, dft_c_t *out) { float norm; int i; fftwf_complex *f_out = plan->out; - copy((char*) plan->in,(char*) in,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - + copy_pre((char*)plan->in, (char*)in, sizeof(dft_c_t), plan->size, + plan->forward, plan->mirror, plan->dc); fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { + if (plan->norm) { /**FIXME: Use VOLK */ norm = sqrtf(plan->size); for (i=0;isize;i++) { f_out[i] /= norm; } } - if (plan->options & DFT_OUT_DB) { + if (plan->db) { for (i=0;isize;i++) { f_out[i] = 10*log10(f_out[i]); } } - copy((char*) out,(char*) plan->out,sizeof(dft_c_t),plan->size,plan->options & DFT_MIRROR_POS, - plan->options & DFT_DC_OFFSET); + copy_post((char*)out, (char*)plan->out, sizeof(dft_c_t), plan->size, + plan->forward, plan->mirror, plan->dc); } -void dft_run_r2r(dft_plan_t *plan, dft_r_t *in, dft_r_t *out) { +void dft_run_r(dft_plan_t *plan, dft_r_t *in, dft_r_t *out) { float norm; int i; int len = plan->size; float *f_out = plan->out; - copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - + memcpy(plan->in,in,sizeof(dft_r_t)*plan->size); fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { + if (plan->norm) { norm = plan->size; for (i=0;ioptions & DFT_PSD) { - for (i=0;i<(len+1)/2-1;i++) { - out[i] = sqrtf(f_out[i]*f_out[i]+f_out[len-i-1]*f_out[len-i-1]); - } - } - if (plan->options & DFT_OUT_DB) { + if (plan->db) { for (i=0;iout; - - copy((char*) plan->in,(char*) in,sizeof(dft_r_t),plan->size,plan->options & DFT_MIRROR_PRE, - plan->options & DFT_DC_OFFSET); - - fftwf_execute(plan->p); - - if (plan->options & DFT_NORMALIZE) { - norm = plan->size; - for (i=0;isize;i++) { - f_out[i] /= norm; - } - } - if (plan->options & DFT_PSD) { - for (i=0;isize;i++) { - out[i] = (__real__ f_out[i])*(__real__ f_out[i])+ - (__imag__ f_out[i])*(__imag__ f_out[i]); - if (!(plan->options & DFT_OUT_DB)) { - out[i] = sqrtf(out[i]); - } - } - } - if (plan->options & DFT_OUT_DB) { - for (i=0;isize;i++) { - out[i] = 10*log10(out[i]); + f_out[i] = 10*log10(f_out[i]); } } + memcpy(out,plan->out,sizeof(dft_r_t)*plan->size); } - void dft_plan_free(dft_plan_t *plan) { if (!plan) return; if (!plan->size) return; @@ -278,12 +188,5 @@ void dft_plan_free(dft_plan_t *plan) { bzero(plan, sizeof(dft_plan_t)); } -void dft_plan_free_vector(dft_plan_t *plan, int nof_plans) { - int i; - for (i=0;i +#include +#include +#include +#include +#include +#include + +#include "liblte/phy/utils/dft.h" + +typedef _Complex float cf_t; + +int N = 256; +bool forward = true; +bool mirror = false; +bool norm = false; +bool dc = false; + +void usage(char *prog) { + printf("Usage: %s\n", prog); + printf("\t-N Transform size [Default 256]\n"); + printf("\t-b Backwards transform first [Default Forwards]\n"); + printf("\t-m Mirror the transform freq bins [Default false]\n"); + printf("\t-n Normalize the transform output [Default false]\n"); + printf("\t-d Handle insertion/removal of null DC carrier internally [Default false]\n"); +} + +void parse_args(int argc, char **argv) { + int opt; + while ((opt = getopt(argc, argv, "Nbmnd")) != -1) { + switch (opt) { + case 'N': + N = atoi(argv[optind]); + break; + case 'b': + forward = false; + break; + case 'm': + mirror = true; + break; + case 'n': + norm = true; + break; + case 'd': + dc = true; + break; + default: + usage(argv[0]); + exit(-1); + } + } +} + +void print(cf_t* in, int len) +{ + for(int i=0;i 0.01) + res = -1; + } + + dft_plan_free(&plan); + dft_plan_free(&plan_rev); + free(out1); + free(out2); + + return res; +} + +int main(int argc, char **argv) { + parse_args(argc, argv); + cf_t* in = malloc(sizeof(cf_t)*N); + bzero(in, sizeof(cf_t)*N); + for(int i=1;i