From 4dbebd84060c2b830a08f87f50be055b1a8d7773 Mon Sep 17 00:00:00 2001 From: Jon Nordby Date: Sat, 15 Jun 2024 14:57:22 +0200 Subject: [PATCH] Tool for generating RFFT twiddle tables Workaround for https://github.com/ARM-software/CMSIS-DSP/issues/25 A quick spot check of the output against CMSIS-DSP realCoefAQ15 / realCoefBQ15 looks OK --- Misc/fft_table_generate.c | 159 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 159 insertions(+) create mode 100644 Misc/fft_table_generate.c diff --git a/Misc/fft_table_generate.c b/Misc/fft_table_generate.c new file mode 100644 index 0000000..1a134ab --- /dev/null +++ b/Misc/fft_table_generate.c @@ -0,0 +1,159 @@ + +/* +FFT twiddle table generator for CMSIS-DSP + +This is a workaround for CMSIS-DSP not having different tables for different lengths for q15/q31 RFFT. +Meaning that it always always uses a table 4096 long FFT - which takes 32 kB of program memory. +This wastes a lot of program space for short FFTs: 64/128/256/512 etc. + +Ref: https://github.com/ARM-software/CMSIS-DSP/issues/25 + +Usage: + + gcc -Wall -o fft_table_generate Misc/fft_table_generate.c -lm + ./fft_table_generate > User/fft_tables.h +*/ + + + +#include +#include +#include +#include +#include +#include + +/* +Original CMSIS-DSP documentation on generating the tables + + @par + Generation fixed-point realCoefAQ15 array in Q15 format: + @par + n = 4096 +
for (i = 0; i < n; i++)
+  {
+     pATable[2 * i]     = 0.5 * ( 1.0 - sin (2 * PI / (double) (2 * n) * (double) i));
+     pATable[2 * i + 1] = 0.5 * (-1.0 * cos (2 * PI / (double) (2 * n) * (double) i));
+  }
+ @par + Convert to fixed point Q15 format + round(pATable[i] * pow(2, 15)) + + + @par + Generation of real_CoefB array: + @par + n = 4096 +
for (i = 0; i < n; i++)
+  {
+     pBTable[2 * i]     = 0.5 * (1.0 + sin (2 * PI / (double) (2 * n) * (double) i));
+     pBTable[2 * i + 1] = 0.5 * (1.0 * cos (2 * PI / (double) (2 * n) * (double) i));
+  }
+ @par + Convert to fixed point Q15 format + round(pBTable[i] * pow(2, 15)) +*/ + +int +fill_table_a(double *table, int table_length, int fft_length) +{ + if (table_length != 2*fft_length) { + return -1; + } + + const int n = fft_length; + for (int i = 0; i < n; i++) { + table[2 * i] = 0.5 * ( 1.0 - sin (2 * M_PI / (double) (2 * n) * (double) i)); + table[2 * i + 1] = 0.5 * (-1.0 * cos (2 * M_PI / (double) (2 * n) * (double) i)); + } + return 0; +} + +int +fill_table_b(double *table, int table_length, int fft_length) +{ + if (table_length != 2*fft_length) { + return -1; + } + + const int n = fft_length; + for (int i = 0; i < n; i++) { + table[2 * i] = 0.5 * (1.0 + sin (2 * M_PI / (double) (2 * n) * (double) i)); + table[2 * i + 1] = 0.5 * (1.0 * cos (2 * M_PI / (double) (2 * n) * (double) i)); + } + return 0; +} + +int +print_table(const double *table, int table_length, + const int fft_length, + const char *prefix, + const char *specifiers, + const char *ctype, + const int fixed_bits, + const int width + ) +{ + if (table_length != 2*fft_length) { + return -1; + } + /* + Prints table out as a C variable definition: + + const q15_t __ALIGNED(4) realCoefBQ15[8192] = { + (q15_t)0x4000, ... + }; + */ + + printf("const %s %s %s%d = {\n", ctype, specifiers, prefix, fft_length); + + for (int i=0; i