summaryrefslogtreecommitdiffstats
path: root/baseline/source/fmref/fmref.c
diff options
context:
space:
mode:
Diffstat (limited to 'baseline/source/fmref/fmref.c')
-rw-r--r--baseline/source/fmref/fmref.c281
1 files changed, 0 insertions, 281 deletions
diff --git a/baseline/source/fmref/fmref.c b/baseline/source/fmref/fmref.c
deleted file mode 100644
index b086f5a..0000000
--- a/baseline/source/fmref/fmref.c
+++ /dev/null
@@ -1,281 +0,0 @@
1/*
2* fmref.c: C reference implementation of FM Radio
3* David Maze <dmaze@cag.lcs.mit.edu>
4* $Id: fmref.c,v 1.2 2010-10-04 21:21:26 garus Exp $
5*/
6
7
8#include "extra.h"
9#include "wcclibm.h"
10#ifndef M_PI
11#define M_PI 3.1415926535897932384626433832795
12#endif
13
14// Defines
15#define SAMPLING_RATE 250000000
16#define CUTOFF_FREQUENCY 108000000
17#define NUM_TAPS 64
18#define MAX_AMPLITUDE 27000.0
19#define BANDWIDTH 10000
20#define DECIMATION 4
21/* Must be at least NUM_TAPS+1: */
22#define IN_BUFFER_LEN 200
23#define EQUALIZER_BANDS 10
24
25
26// Type declarations
27typedef struct FloatBuffer
28{
29 float buff[IN_BUFFER_LEN];
30 int rpos, rlen;
31}
32FloatBuffer;
33/* Low pass filter: */
34typedef struct LPFData
35{
36 float coeff[NUM_TAPS];
37 float freq;
38 int taps, decimation;
39}
40LPFData;
41typedef struct EqualizerData
42{
43 LPFData lpf[EQUALIZER_BANDS + 1];
44 FloatBuffer fb[EQUALIZER_BANDS + 1];
45 float gain[EQUALIZER_BANDS];
46}
47EqualizerData;
48
49// Global vars
50float fmref_lpf_coeff[NUM_TAPS];
51float fmref_eq_cutoffs[EQUALIZER_BANDS + 1] =
52 { 55.000004f, 77.78174f, 110.00001f, 155.56354f, 220.00002f, 311.12695f,
53 440.00003f, 622.25415f, 880.00006f, 1244.5078f, 1760.0001f };
54static int fmref_numiters = 2;
55
56// Forward declarations
57void fmref_fb_compact(FloatBuffer *fb);
58int fmref_fb_ensure_writable(FloatBuffer *fb, int amount);
59void fmref_get_floats(FloatBuffer *fb);
60void fmref_init_lpf_data(LPFData *data, float freq, int taps, int decimation);
61void fmref_run_lpf(FloatBuffer *fbin, FloatBuffer *fbout, LPFData *data);
62void fmref_run_demod(FloatBuffer *fbin, FloatBuffer *fbout);
63void fmref_init_equalizer(EqualizerData *data);
64void fmref_run_equalizer(FloatBuffer *fbin, FloatBuffer *fbout, EqualizerData *data);
65void fmref_main(void);
66
67void fmref_init(void)
68{
69 // dummy init function
70}
71
72int fmref_return(void)
73{
74 // dummy return value
75 return 0;
76}
77
78int main(int argc, char **argv){
79
80 SET_UP
81 for_each_job {
82 fmref_init();
83 fmref_main();
84 }
85 WRITE_TO_FILE
86 return fmref_return();
87}
88
89FloatBuffer fmref_fb1, fmref_fb2, fmref_fb3, fmref_fb4;
90LPFData fmref_lpf_data;
91
92void fmref_main(void)
93{
94 int i;
95 EqualizerData eq_data;
96
97 fmref_fb1.rpos = fmref_fb1.rlen = 0;
98 fmref_fb2.rpos = fmref_fb2.rlen = 0;
99 fmref_fb3.rpos = fmref_fb3.rlen = 0;
100 fmref_fb4.rpos = fmref_fb4.rlen = 0;
101
102 fmref_init_lpf_data(&fmref_lpf_data, CUTOFF_FREQUENCY, NUM_TAPS, DECIMATION);
103 fmref_init_equalizer(&eq_data);
104
105 /* Startup: */
106 fmref_get_floats(&fmref_fb1);
107 /* LPF needs at least NUM_TAPS+1 inputs; fmref_get_floats is fine. */
108 fmref_run_lpf(&fmref_fb1, &fmref_fb2, &fmref_lpf_data);
109 /* run_demod needs 1 input, OK here. */
110 /* run_equalizer needs 51 inputs (same reason as for LPF). This means
111 * running the pipeline up to demod 50 times in advance: */
112 _Pragma( "loopbound min 64 max 64" )
113 for (i = 0; i < 64; i++) {
114 if (fmref_fb1.rlen - fmref_fb1.rpos < NUM_TAPS + 1)
115 fmref_get_floats(&fmref_fb1);
116 fmref_run_lpf(&fmref_fb1, &fmref_fb2, &fmref_lpf_data);
117 fmref_run_demod(&fmref_fb2, &fmref_fb3);
118 }
119
120 /* Main loop: */
121 _Pragma( "loopbound min 2 max 2" )
122 while (fmref_numiters-- > 0) {
123 /* The low-pass filter will need NUM_TAPS+1 items; read them if we
124 * need to. */
125 if (fmref_fb1.rlen - fmref_fb1.rpos < NUM_TAPS + 1)
126 fmref_get_floats(&fmref_fb1);
127 fmref_run_lpf(&fmref_fb1, &fmref_fb2, &fmref_lpf_data);
128 fmref_run_demod(&fmref_fb2, &fmref_fb3);
129 fmref_run_equalizer(&fmref_fb3, &fmref_fb4, &eq_data);
130
131 }
132}
133
134void fmref_fb_compact(FloatBuffer *fb)
135{
136
137 int i;
138 char *source;
139 char *target;
140 target = (char*)(fb->buff);
141 source = (char*)(fb->buff + fb->rpos);
142 _Pragma( "loopbound min 0 max 60" )
143 for (i = 0; i < fb->rlen - fb->rpos; i++) {
144 target[i] = source[i];
145 }
146 fb->rlen -= fb->rpos;
147 fb->rpos = 0;
148}
149
150int fmref_fb_ensure_writable(FloatBuffer *fb, int amount)
151{
152 int available = IN_BUFFER_LEN - fb->rlen;
153 if (available >= amount)
154 return 1;
155
156 /* Nope, not enough room, move current contents back to the beginning. */
157 fmref_fb_compact(fb);
158
159 available = IN_BUFFER_LEN - fb->rlen;
160 if (available >= amount)
161 return 1;
162
163 return 0;
164}
165
166void fmref_get_floats(FloatBuffer *fb)
167{
168 static int x = 0;
169 fmref_fb_compact(fb);
170
171 /* Fill the remaining space in fb with 1.0. */
172 _Pragma( "loopbound min 200 max 200" )
173 while (fb->rlen < IN_BUFFER_LEN) {
174 fb->buff[fb->rlen++] = (float)x;
175 x++;
176 }
177}
178
179void fmref_init_lpf_data(LPFData *data, float freq, int taps, int decimation)
180{
181 /* Assume that CUTOFF_FREQUENCY is non-zero. See comments in
182 * StreamIt LowPassFilter.java for origin. */
183 float w = 2 * M_PI * freq / SAMPLING_RATE;
184 int i;
185 float m = taps - 1.0f;
186
187 data->freq = freq;
188 data->taps = taps;
189 data->decimation = decimation;
190
191 _Pragma( "loopbound min 64 max 64" )
192 for (i = 0; i < taps; i++) {
193 if (i - m / 2 == 0.0f)
194 data->coeff[i] = w / M_PI;
195 else
196 data->coeff[i] = sin(w * (i - m / 2)) / M_PI / (i - m / 2) *
197 (0.54f - 0.46f * cos(2 * M_PI * i / m));
198 }
199}
200
201void fmref_run_lpf(FloatBuffer *fbin, FloatBuffer *fbout, LPFData *data)
202{
203 float sum = 0.0f;
204 int i = 0;
205
206 _Pragma( "loopbound min 64 max 64" )
207 for (i = 0; i < data->taps; i++) {
208 sum += fbin->buff[fbin->rpos + i] * data->coeff[i];
209 }
210
211 fbin->rpos += data->decimation + 1;