* Use two periods of the sine for testing instead of one and scale the values
[matthijs/projects/montium-fft.git] / FFT_support.cpp
1 #include "FFT.h"\r
2 #include <cstdio>\r
3 #include <cmath>\r
4 \r
5 \r
6 /* Didn't the Montium use Q15 instead of Q14? */\r
7 #define FIXED_POINT 15\r
8 #define WORD_SIZE   16\r
9 \r
10 #define WORDS_PER_LINE 4\r
11 #define WORDS_PER_GROUP 1\r
12 \r
13 mem input_a_re, input_a_im, input_b_re, input_b_im, output_a_re, output_a_im, output_b_re, output_b_im, twiddle_re, twiddle_im; \r
14 \r
15 int to_fixed(float n)\r
16 {\r
17         int res = (int)(n * (1 << FIXED_POINT));\r
18         /* Crop results */\r
19         if (res > (1 << WORD_SIZE - 1) - 1)\r
20                 return (1 << WORD_SIZE - 1) - 1;\r
21         if (res < -(1 << WORD_SIZE - 1))\r
22                 return -(1 << WORD_SIZE - 1);\r
23         return res;\r
24 }\r
25 \r
26 float from_fixed(int n)\r
27 {\r
28         return n / (float)(1<<FIXED_POINT);\r
29 }\r
30 \r
31 void print_mem(mem m, int offset, int size, bool fixed)\r
32 {\r
33         int i;\r
34         for(i = offset;i<offset+size;i++)\r
35         {\r
36                 if (fixed)\r
37                         printf("%0.4f", from_fixed(get_mem(m->id, i)));\r
38                 else\r
39                         printf("%04hx", (short)get_mem(m->id, i));\r
40                 if ((i + 1) % WORDS_PER_LINE == 0)\r
41                         printf("\n");\r
42                 else if ((i + 1) % WORDS_PER_GROUP == 0)\r
43                         printf(" ");\r
44         }\r
45         if (i % WORDS_PER_LINE != 0)\r
46                 printf("\n");\r
47 }\r
48 \r
49 \r
50 void pre_run()\r
51 {\r
52         int i;\r
53         /* Assign memories, at least for the first stage */\r
54         input_a_re   = alloc_mem(P0M0);\r
55         input_a_im   = alloc_mem(P1M0);\r
56         input_b_re   = alloc_mem(P2M0);\r
57         input_b_im   = alloc_mem(P3M0);\r
58         \r
59         twiddle_re   = alloc_mem(P4M0);\r
60         twiddle_im   = alloc_mem(P4M1);\r
61         \r
62         /* TODO: Init memory and twiddles */\r
63         for (i=0;i<PARAM_N_t/2;i++)\r
64         {\r
65                 set_mem(twiddle_re->id, i, to_fixed(cos(i*2*M_PI/PARAM_N_t)));\r
66                 set_mem(twiddle_im->id, i, to_fixed(sin(i*2*M_PI/PARAM_N_t)));\r
67         }\r
68         \r
69         for (i=0;i<PARAM_N_t;i++)\r
70         {\r
71                 /* We take the sine from 0 to 2*2*Pi, ie two periods. We divide \r
72                  * the value by PARAM_N_t to prevent overflow. */\r
73                 int value = to_fixed(sin((float)i*2*2*M_PI/PARAM_N_t)/PARAM_N_t);\r
74 \r
75                 if (i<PARAM_N_t/2)\r
76                 {\r
77                         if (i % 2 == 0) {\r
78                                 set_mem(input_a_re->id, i, value);\r
79                                 set_mem(input_a_im->id, i, 0);\r
80                         } else {\r
81                                 set_mem(input_b_re->id, i, value);\r
82                                 set_mem(input_b_im->id, i, 0);\r
83                         }\r
84                 }\r
85                 else\r
86                 {\r
87                         if (i % 2 == 0) {\r
88                                 set_mem(input_b_re->id, i - PARAM_N_t/2, value);\r
89                                 set_mem(input_b_im->id, i - PARAM_N_t/2, 0);\r
90                         } else {\r
91                                 set_mem(input_a_re->id, i - PARAM_N_t/2, value);\r
92                                 set_mem(input_a_im->id, i - PARAM_N_t/2, 0);\r
93                         }\r
94                 }\r
95         }\r
96         \r
97         printf("re(W)\n");\r
98         print_mem(twiddle_re, 0, PARAM_N_t/2, true);\r
99         printf("im(W)\n");\r
100         print_mem(twiddle_im, 0, PARAM_N_t/2, true);\r
101         printf("re(in_a)\n");\r
102         print_mem(input_a_re, 0, PARAM_N_t/2, true);\r
103         printf("re(in_b)\n");\r
104         print_mem(input_b_re, 0, PARAM_N_t/2, true);\r
105 }\r
106 \r
107 void post_run()\r
108 {\r
109         if (PARAM_n_t % 2 == 0) {\r
110                 /* When the number of stages is odd, the \r
111                  * outputs end up at the left memories again */\r
112                 output_a_re  = alloc_mem(P0M0);\r
113                 output_a_im  = alloc_mem(P1M0);\r
114                 output_b_re  = alloc_mem(P2M0);\r
115                 output_b_im  = alloc_mem(P3M0);\r
116         } else {\r
117                 output_a_re  = alloc_mem(P0M1);\r
118                 output_a_im  = alloc_mem(P1M1);\r
119                 output_b_re  = alloc_mem(P2M1);\r
120                 output_b_im  = alloc_mem(P3M1);\r
121         }\r
122         printf("re(out_a)\n");\r
123         print_mem(output_a_re, 0, PARAM_N_t/2, true);\r
124         print_mem(output_b_re, 0, PARAM_N_t/2, true);\r
125         printf("im(out_a)\n");\r
126         print_mem(output_a_im, 0, PARAM_N_t/2, true);\r
127         print_mem(output_b_im, 0, PARAM_N_t/2, true);\r
128 \r
129 }\r