1 #include "demodulator.h"
2 #include "appglobal.h"
3 #include "drm.h"
4 #include <math.h>
5 #include <float.h>
6 #include "nrutil.h"
7 #include "supportfunctions.h"
8
9 #include <QDebug>
10
11
12 demodulator *demodulatorPtr;
13
14 void ludcmp(float **, int, int *, float *);
15 void lubksb(float **, int, int *, float *);
16
17 int Ts_list[DRMNUMMODES] = { Ts_A, Ts_B, Ts_C, Ts_D };
18 int Tu_list[DRMNUMMODES] = { Tu_A, Tu_B, Tu_C, Tu_D };
19 int Tg_list[DRMNUMMODES] = { Tg_A, Tg_B, Tg_C, Tg_D };
20
21 float FAC_cells_sequence[200];
22 bool FACAvailable;
23 float deltaFS;
24 float freqOffset;
25 float tempbuf[30000];
26
demodulator()27 demodulator::demodulator()
28 {
29 addToLog("fftwf_plan_dft_1d start",LOGFFT);
30 p1 = fftwf_plan_dft_1d(256,(fftwf_complex *)ss,(fftwf_complex *)S, FFTW_FORWARD, FFTW_ESTIMATE);
31 addToLog("fftwf_plan_dft_1d stop",LOGFFT);
32 }
33
~demodulator()34 demodulator::~demodulator()
35 {
36 fftwf_destroy_plan(p1);
37 }
38
39
init()40 void demodulator::init()
41 {
42 int i,j,k;
43 FACAvailable=false;
44 N_symbols_mode_detection = 20;
45 N_symbols_frequency_pilot_search = 15;
46 time_offset_log_last = 0;
47 symbol_counter = 0;
48 N_samples_needed = N_symbols_mode_detection * 320;
49 input_samples_buffer_request = N_samples_needed;
50 SNR_time_out_counter = SNR_TIMEOUT;
51 fac_not_valid_counter = FACVALIDCNTR;
52 mode_and_occupancy_code_last = -1;
53 timeSyncFlag = false;
54 frequencySyncFlag = false;
55 frameSyncFlag = false;
56 doSynchronize=false;
57 rsbufwidx = 0;
58 symbufwidx = 0;
59 iterationCounter=0;
60
61 samplerate_offset_estimation = 0;
62 samplerate_offset=0;
63 smp_rate_conv_fft_phase_diff = 0;
64 smp_rate_conv_fft_phase_offset = 0;
65 smp_rate_conv_in_out_delay = 0;
66
67
68 transmission_frame_buffer_data_valid = 0;
69
70 counter=0;
71 k = 0;
72 for (i = 0; i < 4; i++) // number of robustness modes
73 {
74 for (j = 0; j < 6; j++) /* number of spectrumoccupancies */
75 {
76 no_of_used_cells_per_frame_list[k++] = (K_min_K_max_list[1][j + i * 6] - K_min_K_max_list[0][j + i * 6] + 1 - no_of_unused_carriers_list[i]) * symbols_per_frame_list[i];
77 }
78 }
79 sigmaq_noise_list[0] = (float) pow(10.0, -16.0 / 10.0);
80 sigmaq_noise_list[1] = (float) pow(10.0, -14.0 / 10.0);
81 sigmaq_noise_list[2] = (float) pow(10.0, -14.0 / 10.0);
82 sigmaq_noise_list[3] = (float) pow(10.0, -12.0 / 10.0);
83 SNR_timeout_counter=0;
84 delta_freq_offset=0;
85 }
86
demodulate(float * sigin,int numSamples)87 bool demodulator::demodulate(float *sigin,int numSamples)
88 {
89 int i;
90 numberOfSamples=numSamples;
91 transmission_frame_buffer_data_valid = 0;
92 // fac_valid can be -1,0,1
93
94
95 addToLog(QString("block %1 samples %2" ).arg(iterationCounter).arg(numSamples),LOGDRMDEMOD);
96 // if(iterationCounter<40) arrayDump(QString("DEM %1").arg(iterationCounter),sigin,128,true);
97 // arrayDump(QString("bl%1").arg(iterationCounter),sigin,32,true);
98 // logfile->addToAux(QString("block %1").arg(iterationCounter));
99 // arrayDump(QString("rs"),sigin,numSamples*2,true);
100 // if (fac_valid == 0)
101 // {
102 // fac_not_valid_counter--;
103 // if (fac_not_valid_counter <= 0)
104 // {
105 // doSynchronize = true;
106 // fac_not_valid_counter = FACVALIDCNTR;
107 // }
108 // }
109 // else
110 // {
111 // if (fac_valid == 1)
112 // {
113 // fac_not_valid_counter = FACVALIDCNTR;
114 // }
115 // }
116 if (doSynchronize)
117 {
118 doSynchronize = false;
119 init();
120 }
121 if (numberOfSamples> 0)
122 {
123 ++iterationCounter;
124 // logfile->addToAux(QString("iterationCounter %1").arg(iterationCounter));
125 // arrayDump("sig1",sigin,RXSTRIPE,true);
126 // logfile->addToAux(QString("rsbufwidx %1 offset %2").arg(rsbufwidx).arg(320 * N_symbols_mode_detection/2));
127
128 // arrayDump("sigD",&rs_buffer[320 * N_symbols_mode_detection],16,true);
129 for(i=0;i<numberOfSamples;i++)
130 {
131 rs_buffer[(i + rsbufwidx)*2] = sigin[i*2];
132 rs_buffer[(i + rsbufwidx) * 2 + 1] = sigin[i*2+1];
133 }
134 rsbufwidx += numberOfSamples; /* index of next complex number to fill rs_buffer */
135 int block=rsbufwidx/256;
136 if(block>20)
137 {
138 for(i=0;i<(256*block);i++)tempbuf[i]=rs_buffer[2*i];
139 psdmean(tempbuf, psd, 256, block); /* globals pa0mbo */
140 for(i=0;i<(256*block);i++)tempbuf[i]=rs_buffer[2*i+1];
141 psdmean(tempbuf, cpsd, 256, block); /* globals pa0mbo */
142 }
143
144 }
145 if(!timeSync())
146 {
147 return false;
148 }
149 if(!frequencySync())
150 {
151 return false;
152 }
153 if(!frameSync())
154 {
155 return false;
156 }
157
158 if(channelEstimation())
159 {
160 channel_decoding();
161 srcDecoder->decode();
162 }
163 if(doSynchronize)
164 {
165 // see if we have to save the data (for BSR and endOfImage)
166 // srcDecoder.checkSaveImage();
167 }
168
169 return true;
170 }
171
timeSync()172 bool demodulator::timeSync()
173 {
174 int i;
175 samplerate_offset= samplerate_offset_estimation;
176 if (!timeSyncFlag)
177 {
178 frequencySyncFlag=false;
179 // enough data for time sync ?
180 N_samples_needed = N_symbols_mode_detection * 320 - rsbufwidx;
181 if (N_samples_needed > 0)
182 {
183 input_samples_buffer_request = N_samples_needed;
184 return false;
185 }
186 spectrum_occupancy = -1; /* -1 denotes unknown */
187 getmode(rs_buffer, N_symbols_mode_detection * 320, &mode_block);
188
189 robustness_mode = mode_block.mode_indx;
190 time_offset = mode_block.time_offset;
191 samplerate_offset_estimation = mode_block.sample_rate_offset;
192 frequency_offset_fractional_init = mode_block.freq_offset_fract;
193 time_offset_integer = (int) floor(time_offset + 0.5);
194 if(robustness_mode!=99)
195 {
196 addToLog(QString("numSamples %1, robustmode %2,timeoffset %3,smplrateOffsetEst %4,freqOffsetFracInit %5,timeOffsetInteger %6")
197 .arg(numberOfSamples).arg( robustness_mode).arg(time_offset).arg(samplerate_offset_estimation).arg(frequency_offset_fractional_init).arg(time_offset_integer),LOGDRMDEMOD);
198 }
199
200 if ((fabsf(samplerate_offset_estimation) > 200.0E-5) && (robustness_mode != 99))
201 {
202 // sample_rate offset too large
203 N_samples_needed = N_symbols_mode_detection * 320;
204 input_samples_buffer_request = N_samples_needed;
205 rsbufwidx = 0;
206 // samplerate_offset_estimation=0;
207 return false;
208 }
209 if (robustness_mode != 99)
210 {
211 // logfile->addToAux("timesync found");
212 addToLog(QString("found robustness_mode: %1").arg(robustness_mode),LOGDRMDEMOD);
213 timeSyncFlag = true;
214 Ts = Ts_list[robustness_mode];
215 Tu = Tu_list[robustness_mode];
216 Tg = Tg_list[robustness_mode];
217 Tgh = (int) floor(Tg / 2 + 0.5);
218 symbols_per_frame = symbols_per_frame_list[robustness_mode];
219 K_dc = Tu / 2;
220 K_modulo = Tu;
221 for (i = 0; i < 21; i++) time_ref_cells_k[i] = time_ref_cells_k_list[robustness_mode][i];
222 for (i = 0; i < 21; i++) time_ref_cells_theta_1024[i] = time_ref_cells_theta_1024_list[robustness_mode][i];
223 y = y_list[robustness_mode];
224 symbols_per_2D_window = symbols_per_2D_window_list[robustness_mode];
225 symbols_to_delay = symbols_to_delay_list[robustness_mode];
226
227 // symbol align rs_buffer
228 rsbufwidx = rsbufwidx - time_offset_integer;
229 for (i = 0; i < rsbufwidx; i++)
230 {
231 rs_buffer[i * 2] = rs_buffer[(i + time_offset_integer) * 2];
232 rs_buffer[i * 2 + 1] =rs_buffer[(i + time_offset_integer) * 2 + 1];
233 }
234 counter++;
235 (void) getofdm(NULL, 0.0, 0.0, 0.0, Ts, Tu, NULL, NULL, 1, 1, 1); /* initialisation */
236 }
237
238 else
239 {
240 samplerate_offset_estimation = 0.0;
241 int shift=320 * N_symbols_mode_detection;
242 // int shift=512;
243 memmove(rs_buffer,&rs_buffer[shift*2],sizeof(float)*2*(rsbufwidx-shift));
244 rsbufwidx -= shift;
245 // arrayDump("sig2",rs_buffer,16,true);
246 // for (i = 0; i < rsbufwidx; i++) /* pa0mbo was rsbufwidx-1 ? */
247 // {
248 // rs_buffer[i * 2] = rs_buffer[(shift + i) * 2];
249 // rs_buffer[i * 2 + 1] = rs_buffer[(shift + i) * 2 + 1];
250 // }
251 N_samples_needed = N_symbols_mode_detection * 320 - rsbufwidx;
252 if (N_samples_needed > 0)
253 {
254 input_samples_buffer_request = N_samples_needed;
255 }
256 else
257 {
258 input_samples_buffer_request = 0;
259 }
260 return false;
261 }
262 addToLog(QString("timeSync found robustness mode:%1").arg(robustness_mode),LOGDRMDEMOD);
263 }
264 return true;
265 }
266
267
268
frequencySync()269 bool demodulator::frequencySync()
270 {
271 int i,j;
272 int sp_idx, K_min_, K_max_, K_dc_indx, K_dc_plus2_indx;
273 int K_min_indx, K_min_minus4_indx, K_max_indx, K_max_plus1_indx;
274 float tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
275 // float energy_ratio_K2_to_K0;
276 float energy_ratio_K_max_to_K_max_p1;
277 float energy_ratio_K_min_to_K_min_m4;
278 float spectrum_occupancy_indicator[6];
279 int t_smp;
280 struct drmComplex S_buffer[288][20]; /* pa0mbo check */
281
282
283 if (!frequencySyncFlag)
284 {
285 frameSyncFlag=false;
286 // enough f=date for pilot search?
287 N_samples_needed = (N_symbols_frequency_pilot_search + 1) * Ts - (rsbufwidx);
288 if (N_samples_needed > 0)
289 {
290 input_samples_buffer_request = N_samples_needed;
291 return false;
292 }
293 Zi[0] = -1.0;
294 delta_time_offset_integer = 0;
295 freq_offset_init = frequency_offset_fractional_init;
296 time_offset_fractional_init = time_offset - time_offset_integer;
297 delta_time_offset_I_init = samplerate_offset_estimation * Ts;
298
299 t_smp = 0;
300 for (i = 0; i < N_symbols_frequency_pilot_search; i++)
301 {
302 delta_time_offset_integer = getofdm(&rs_buffer[2 * t_smp], time_offset_fractional_init,freq_offset_init, delta_time_offset_I_init, Ts, Tu, Zi,
303 symbol_temp, 0, 1,1);
304 for (j = 0; j < K_modulo; j++)
305 {
306 symbol_buffer[(i * K_modulo + j) * 2] = symbol_temp[j * 2];
307 symbol_buffer[(i * K_modulo + j) * 2 + 1] = symbol_temp[j * 2 + 1];
308 }
309 t_smp = t_smp + Ts + delta_time_offset_integer;
310 }
311
312 freq_offset_integer = getfoffsint(symbol_buffer, N_symbols_frequency_pilot_search, K_dc,K_modulo, Tu);
313 // prepare for new round
314 delta_time_offset_integer = 0;
315 freq_offset_init = -freq_offset_integer + frequency_offset_fractional_init;
316 time_offset_fractional_init = 0.0;
317 Zi[0] = -1.0;
318
319 // detmn frequency occupancy
320 // start with reshaping symbol_buffer to S_buffer
321 for (i = 0; i < N_symbols_frequency_pilot_search; i++)
322 {
323 for (j = 0; j < K_modulo; j++)
324 {
325 (S_buffer[j][i]).re = symbol_buffer[(j + i * K_modulo) * 2];
326 (S_buffer[j][i]).im = symbol_buffer[(j + i * K_modulo) * 2 + 1];
327
328 }
329 }
330
331 /*
332 now per freq occupancy mode
333 */
334 for (sp_idx = 0; sp_idx < 2; sp_idx++)
335
336 {
337 K_min_ = K_min_K_max_list[0][sp_idx + robustness_mode * 6];
338 K_max_ = K_min_K_max_list[1][sp_idx + robustness_mode * 6];
339
340 if (K_min_ != K_max_)
341
342 {
343 K_dc_indx = (int) floor(freq_offset_integer / (2.0 * M_PI) + 0.5) + Tu / 2;
344
345 K_dc_indx = K_dc_indx % Tu;
346 K_dc_plus2_indx = (K_dc_indx + 2 + Tu) % Tu;
347 K_min_indx = (K_dc_indx + K_min_ + Tu) % Tu;
348 K_min_minus4_indx = (K_min_indx - 4 + Tu) % Tu;
349 K_max_indx = (K_dc_indx + K_max_ + Tu) % Tu;
350 K_max_plus1_indx = (K_max_indx + 1 + Tu) % Tu;
351
352 // calc energy ratios
353 tmp1 = 0.0;
354 tmp2 = 0.0;
355 tmp3 = 0.0;
356 tmp4 = 0.0;
357 tmp5 = 0.0;
358 tmp6 = 0.0;
359 for (i = 0; i < N_symbols_frequency_pilot_search; i++)
360
361 {
362 tmp1 +=
363 (S_buffer[K_dc_plus2_indx][i]).re *
364 (S_buffer[K_dc_plus2_indx][i]).re +
365 (S_buffer[K_dc_plus2_indx][i]).im *
366 (S_buffer[K_dc_plus2_indx][i]).im;
367 tmp2 +=
368 (S_buffer[K_dc_indx][i]).re *
369 (S_buffer[K_dc_indx][i]).re +
370 (S_buffer[K_dc_indx][i]).im * (S_buffer[K_dc_indx][i]).im;
371 tmp3 +=
372 (S_buffer[K_max_indx][i]).re *
373 (S_buffer[K_max_indx][i]).re +
374 (S_buffer[K_max_indx][i]).im *
375 (S_buffer[K_max_indx][i]).im;
376 tmp4 +=
377 (S_buffer[K_max_plus1_indx][i]).re *
378 (S_buffer[K_max_plus1_indx][i]).re +
379 (S_buffer[K_max_plus1_indx][i]).im *
380 (S_buffer[K_max_plus1_indx][i]).im;
381 tmp5 +=
382 (S_buffer[K_min_indx][i]).re *
383 (S_buffer[K_min_indx][i]).re +
384 (S_buffer[K_min_indx][i]).im *
385 (S_buffer[K_min_indx][i]).im;
386 tmp6 +=
387 (S_buffer[K_min_minus4_indx][i]).re *
388 (S_buffer[K_min_minus4_indx][i]).re +
389 (S_buffer[K_min_minus4_indx][i]).im *
390 (S_buffer[K_min_minus4_indx][i]).im;
391 }
392 // energy_ratio_K2_to_K0 = tmp1 / tmp2;
393 energy_ratio_K_max_to_K_max_p1 = tmp3 / tmp4;
394 energy_ratio_K_min_to_K_min_m4 = tmp5 / tmp6;
395 spectrum_occupancy_indicator[sp_idx] =
396 energy_ratio_K_min_to_K_min_m4 +
397 energy_ratio_K_max_to_K_max_p1;
398 }
399
400 else spectrum_occupancy_indicator[sp_idx] = 0.0;
401 }
402
403 // detmn max in spectrum_occupancy_indicator and its index
404
405 tmp1 = 0.0;
406 for (sp_idx = 0; sp_idx < 2; sp_idx++)
407 {
408 if (spectrum_occupancy_indicator[sp_idx] > tmp1)
409
410 {
411 tmp1 = spectrum_occupancy_indicator[sp_idx];
412 spectrum_occupancy_estimation = sp_idx;
413 }
414 }
415 frequencySyncFlag = true;
416 addToLog(QString("spectrum occupancy estimation:%1").arg(spectrum_occupancy_estimation),LOGDRMDEMOD);
417 }
418 return true;
419 }
420
frameSync()421 bool demodulator::frameSync()
422 {
423 int i,j,k;
424 int symbol0;
425
426 int symbol_no_to_equalize;
427 int t_smp;
428 if (!frameSyncFlag)
429 {
430 initChannelEstimation=true;
431 // enough data ?
432 N_symbols_needed = symbols_per_frame + symbols_per_2D_window - 1;
433 N_samples_needed = (N_symbols_needed + 1) * Ts - (rsbufwidx);
434 if (N_samples_needed > 0)
435 {
436 input_samples_buffer_request = N_samples_needed;
437 return false;
438 }
439
440 t_smp = 0;
441 for (i = 0; i < symbols_per_frame; i++)
442 {
443 delta_time_offset_integer =
444 getofdm(&rs_buffer[2 * t_smp], time_offset_fractional_init,freq_offset_init, delta_time_offset_I_init, Ts, Tu, Zi,symbol_temp, 0, 1,1);
445 for (j = 0; j < K_modulo; j++)
446 {
447 symbol_buffer[(i * K_modulo + j) * 2] = symbol_temp[j * 2];
448 symbol_buffer[(i * K_modulo + j) * 2 + 1] = symbol_temp[j * 2 + 1];
449 }
450 t_smp = t_smp + Ts + delta_time_offset_integer;
451 }
452
453 // search first symbol of frame using time ref cells
454 symbol0 = getsymbolidx(symbol_buffer, symbols_per_frame, time_ref_cells_k,time_ref_cells_theta_1024, K_dc, K_modulo, 21);
455 symbol_no_to_equalize =((symbol0 - symbols_to_delay + symbols_per_frame) % symbols_per_frame) + 1;
456
457 frameSyncFlag = true;
458 symbol_counter = 0;
459
460 // frame align rs_buffer
461 if (symbol_no_to_equalize != 1)
462 {
463 rsbufwidx -= (symbol_no_to_equalize - 1) * Ts;
464
465 for (j = 0; j < rsbufwidx; j++) /* pa0mbo was rsbufwidx 22-4-07 now better */
466 {
467 rs_buffer[j * 2] = rs_buffer[((symbol_no_to_equalize - 1) * Ts + j) * 2];
468 rs_buffer[j * 2 + 1] = rs_buffer[((symbol_no_to_equalize - 1) * Ts + j) * 2 + 1];
469 }
470 }
471 symbufwidx = 0;
472 Zi[0] = -1.0;
473 t_smp = 0;
474 for(i=0;i<(Tu_A * 2 * 26);i++)
475 {
476 symbol_buffer[i]=0;
477 }
478
479 for (i = 0; i <symbols_per_2D_window; i++)
480
481 {
482 delta_time_offset_integer = getofdm(&rs_buffer[2 * t_smp], time_offset_fractional_init,freq_offset_init, delta_time_offset_I_init, Ts, Tu, Zi,symbol_temp, 0, 1,1);
483 // arrayDump("sm1",symbol_temp,symbols_per_2D_window*2,true);
484 for (j = 0; j < K_modulo; j++)
485 {
486 symbol_buffer[(i * K_modulo + j) * 2] = symbol_temp[j * 2];
487 symbol_buffer[(i * K_modulo + j) * 2 + 1] = symbol_temp[j * 2 + 1];
488 }
489
490 symbufwidx++;
491 t_smp += Ts + delta_time_offset_integer;
492 }
493 // arrayDump("sm1",symbol_buffer,symbols_per_2D_window*K_modulo*2,true);
494 // symbol align rs_buffer
495 rsbufwidx -= t_smp;
496
497 for (i = 0; i < rsbufwidx; i++) /* pa0mbo was rxbufwidx 22-4-07 */
498 {
499 rs_buffer[i * 2] = rs_buffer[(i + t_smp) * 2];
500 rs_buffer[i * 2 + 1] = rs_buffer[(i + t_smp) * 2 + 1];
501 }
502 for (i = 0; i < (2*70); i++)
503 {
504 next_pilots[i] = 1.1; /* real part */ // modified joma was j now i
505 }
506 for (i = 0; i < 458; i++)
507 {
508 actual_pilots[i] = 0.0; /* real part */ // modified joma was j now i
509 }
510 for(i=0;i<5;i++)
511 for(j=0;j<208;j++)
512 for (k=0;k<205;k++)
513 {
514 W_pilots_blk[i][j][k]=0;
515 }
516
517 }
518
519 return true;
520 }
521
522 #define MIN_ABS_H (8.0E-5 * 8.0E-5)
523
channelEstimation()524 bool demodulator::channelEstimation()
525 {
526 int i,j,k,m,p,temp;
527 float t1, t2;
528 float sigmaq_noise;
529 int rndcnt;
530 double rest;
531 float a;
532 int indx;
533 int k_index1, k_index2, t1_pos, t2_pos;
534 int k1_pos, k2_pos;
535 double xsinc1, xsinc2;
536 double f_cut_t, f_cut_k;
537 // double f_D_max;
538 // double tau_max;
539 int *indxlu;
540 float dlu = 0.0, *collu;
541 float **amatrix;
542 int NP,sortbrkpnt;
543 // float freq_offset_log[100];
544 // float time_offset_log[100];
545 int cnt_time_ref_cells;
546 int s, nnn, p_min, p_max, theta_1024;
547 int sorttmp[1024], sorttmp2[1024];
548 int t_smp,nn,ntwee,mtwee,cnt_actual_pilots_rel_indx;
549 int ntc_indx;
550 int trxbuf_indx, symbuf_indx;
551 float hoek,tmpreal,tmpimag;
552 float freq_offset;
553 // float h_absq[256];
554 // int lH;
555 float tmp1, tmp2, tmp3;
556 int gain_ref_cells_per_window;
557 float temp1, temp2;
558 float sum_MERFAC, sum_WMERFAC, sum_weight_FAC, SNR_dB;
559 float MERFAC;
560 float FAC_squared_noise_sequence[200];
561 float squared_weight_sequence[200];
562
563 // channel estimation based on pilots
564
565 N_symbols_needed = symbols_per_frame + symbols_per_2D_window - symbufwidx; // pa0mbo 24-4-07
566 N_samples_needed = (N_symbols_needed + 1) * Ts - (rsbufwidx); // pa0mbo was rsbufwidx-1
567 if (N_samples_needed > 0)
568 {
569 input_samples_buffer_request = N_samples_needed;
570 return false;
571 }
572 // now set the parameter spectrum_occupancy
573 if (spectrum_occupancy <= 0)
574 {
575 if (spectrum_occupancy_estimation < 0) spectrum_occupancy = 3;
576 else spectrum_occupancy = spectrum_occupancy_estimation;
577 }
578 if (spectrum_occupancy > 3) spectrum_occupancy = 3; // 4 and 5 not yet supported
579 mode_and_occupancy_code = mode_and_occupancy_code_table[robustness_mode * 6 + spectrum_occupancy];
580 if (mode_and_occupancy_code < 0)
581 {
582 spectrum_occupancy = 1;
583 mode_and_occupancy_code = mode_and_occupancy_code_table[robustness_mode * 6 + spectrum_occupancy];
584 }
585
586 if (mode_and_occupancy_code != mode_and_occupancy_code_last)
587 {
588 K_min = K_min_K_max_list[0][spectrum_occupancy + robustness_mode * 6];
589 K_max = K_min_K_max_list[1][spectrum_occupancy + robustness_mode * 6];
590 carrier_per_symbol = K_max - K_min + 1;
591 (void) getofdmsync(NULL, Ts, Tu, NULL, K_max - K_min + 1, 0, NULL, NULL, 1, 1, 1); /* initialisation */
592 // reformat pilot index stuff into th K_dc/K_modulo block
593 // first call listsinit to get gain_ref_cells_k etc
594 // Jan 5th 2009 changed listsinit() call to an include of all code from listsinit.c
595
596 Tu = Tu_list[robustness_mode];
597 Ts = Ts_list[robustness_mode];
598 Tg = Ts - Tu;
599 sigmaq_noise = sigmaq_noise_list[robustness_mode];
600 symbols_per_frame = symbols_per_frame_list[robustness_mode];
601 for (i = 0; i < 3; i++)
602 {
603 freq_ref_cells_k[i] = freq_ref_cells_k_list[robustness_mode][i];
604 freq_ref_cells_theta_1024[i] = freq_ref_cells_theta_1024_list[robustness_mode][i];
605 }
606 cnt_time_ref_cells = time_ref_cells_cnt_list[robustness_mode];
607 for (i = 0; i < cnt_time_ref_cells; i++)
608 {
609 time_ref_cells_k[i] = time_ref_cells_k_list[robustness_mode][i];
610 time_ref_cells_theta_1024[i] =time_ref_cells_theta_1024_list[robustness_mode][i];
611 }
612 K_min =
613 K_min_K_max_list[0][spectrum_occupancy_estimation +
614 robustness_mode * 6];
615 K_max =
616 K_min_K_max_list[1][spectrum_occupancy_estimation +
617 robustness_mode * 6];
618 carrier_per_symbol = K_max - K_min + 1;
619 for (i = 0; i < 4; i++)
620 {
621 power_boost[i] = power_boost_list[robustness_mode][spectrum_occupancy_estimation][i];
622 }
623 x = x_list[robustness_mode];
624 y = y_list[robustness_mode];
625 k0 = k0_list[robustness_mode];
626 Q_1024 = Q_1024_list[robustness_mode];
627 mean_energy_of_used_cells =(float) (no_of_used_cells_per_frame_list[spectrum_occupancy_estimation + robustness_mode * 6] + 3 + cnt_time_ref_cells);
628 rndcnt = 0;
629 for (s = 0; s < symbols_per_frame; s++)
630 {
631 nnn = s % y;
632 m = (int) floor((double) (s / y));
633 p_min = (int) ceil((double) ((K_min - k0 - x * nnn) / (x * y)));
634 p_max = (int) floor((double) ((K_max - k0 - x * nnn) / (x * y)));
635 for (p = p_min; p <= p_max; p++)
636
637 {
638 k = k0 + x * nnn + x * y * p;
639 theta_1024 = (4*Z_256_list[robustness_mode][nnn][m]+p*W_1024_list[robustness_mode][nnn][m]+p*p*(1 +s)*Q_1024) % 1024;
640 a = sqrtf(2.0);
641 // power boost
642 for (i = 0; i < 4; i++)
643 {
644 if (k == power_boost[i]) a = 2;
645 }
646
647 // is time ref cell ?
648
649 if (s == 0)
650 {
651 for (i = 0; i < cnt_time_ref_cells; i++)
652 {
653 if (k == time_ref_cells_k[i])
654 {
655 indx = i;
656 theta_1024 = time_ref_cells_theta_1024[indx];
657 a = sqrtf(2.0);
658 mean_energy_of_used_cells -= 1.0;
659 }
660 }
661 }
662
663 // is frequence reference cell?
664 for (i = 0; i < 3; i++)
665 {
666 if (k == freq_ref_cells_k[i])
667 {
668 indx = i;
669 theta_1024 = freq_ref_cells_theta_1024[indx];
670 if (robustness_mode == 3)
671 {
672 theta_1024 = (theta_1024 + 512 * s) % 1024;
673 }
674 a = sqrtf(2.0);
675 mean_energy_of_used_cells -= 1.0;
676 }
677 }
678 gain_ref_cells_k[rndcnt] = k + s * carrier_per_symbol;
679 gain_ref_cells_theta_1024[rndcnt] = theta_1024;
680 gain_ref_cells_a[rndcnt++] = a;
681 mean_energy_of_used_cells =(float) (mean_energy_of_used_cells - 1.0 + a * a);
682 }
683 }
684 mean_energy_of_used_cells /=no_of_used_cells_per_frame_list[spectrum_occupancy_estimation + robustness_mode * 6];
685
686 addToLog(QString("mean_energy_of_used_cells %1").arg(mean_energy_of_used_cells),LOGDRMDEMOD);
687
688 // precompute 2-D Wiener filter matrix
689 // uses gain_ref_cells etc
690 // and rndcnt
691 symbols_per_2D_window = symbols_per_2D_window_list[robustness_mode];
692 symbols_to_delay = symbols_to_delay_list[robustness_mode];
693 f_cut_t = 0.0675 / (1.0 * (double) y);
694 f_cut_k = 1.75 * (float) Tg / (float) Tu;
695
696 for(i=0;i<5;i++) cnt_tr_cells[i]=0;
697 // start nnn-loop
698 for (nnn = 0; nnn < y; nnn++)
699 {
700 for (i = 0; i < rndcnt; i++)
701 {
702 training_cells_k[nnn][i] = (gain_ref_cells_k[i] - K_min +(symbols_per_frame -nnn) * carrier_per_symbol) % (symbols_per_frame * carrier_per_symbol) + K_min;
703
704 }
705
706 // cnt_tr_cells[nnn] = 0;
707 for (i = 0; i < rndcnt; i++)
708 {
709 if ((training_cells_k[nnn][i] - K_min) <(carrier_per_symbol * symbols_per_2D_window))
710 {
711 gain_ref_cells_subset_index[nnn][cnt_tr_cells[nnn]] = i;
712 gain_ref_cells_subset[nnn][(cnt_tr_cells[nnn])++] =training_cells_k[nnn][i];
713 }
714 }
715 cnt_next_pilot_cells[nnn] = 0;
716 for (i = 0; i < rndcnt; i++)
717 {
718 if (((training_cells_k[nnn][i] - K_min) >= (carrier_per_symbol * symbols_per_2D_window)) &&
719 ((training_cells_k[nnn][i] - K_min) < carrier_per_symbol * (symbols_per_2D_window + 1)))
720
721 {
722 next_pilot_cells_k_index[nnn][cnt_next_pilot_cells[nnn]] = i;
723 next_pilot_cells_k[nnn][(cnt_next_pilot_cells[nnn])++] = ((training_cells_k[nnn][i]- K_min) % carrier_per_symbol) + K_min;
724 }
725 }
726 // now sort training cells in subset if necessary
727 sortbrkpnt = 0;
728 for (i = 1; i < cnt_tr_cells[nnn]; i++)
729 {
730 if (gain_ref_cells_subset[nnn][i] < gain_ref_cells_subset[nnn][i - 1]) sortbrkpnt = i; // break in data ?
731 }
732 if (sortbrkpnt > 0)
733 {
734 // keep first part in sorttmp
735 for (i = 0; i < sortbrkpnt; i++)
736 {
737 sorttmp[i] = gain_ref_cells_subset[nnn][i];
738 sorttmp2[i] = gain_ref_cells_subset_index[nnn][i]; /* pa0mbo added 22-jan-2009 */
739 }
740 // now shift smaller ones to start of vector
741 for (i = 0; i < cnt_tr_cells[nnn] - sortbrkpnt; i++)
742 {
743 gain_ref_cells_subset[nnn][i] = gain_ref_cells_subset[nnn][i + sortbrkpnt];
744 gain_ref_cells_subset_index[nnn][i] =gain_ref_cells_subset_index[nnn][i + sortbrkpnt];
745 }
746
747 // replace last part from tmp
748
749 for (i = cnt_tr_cells[nnn] - sortbrkpnt; i < cnt_tr_cells[nnn];i++)
750 {
751 gain_ref_cells_subset[nnn][i] =sorttmp[i + sortbrkpnt - cnt_tr_cells[nnn]];
752 gain_ref_cells_subset_index[nnn][i] =sorttmp2[i + sortbrkpnt - cnt_tr_cells[nnn]];
753 }
754 sortbrkpnt = 0;
755 }
756 // copy to training_cells_k
757 for (i = 0; i < cnt_tr_cells[nnn]; i++)
758 {
759 training_cells_k[nnn][i] = gain_ref_cells_subset[nnn][i];
760 }
761 gain_ref_cells_per_window = cnt_tr_cells[nnn];
762 for (k_index1 = 0; k_index1 < gain_ref_cells_per_window; k_index1++)
763 {
764 for (k_index2 = 0; k_index2 < gain_ref_cells_per_window;k_index2++)
765 {
766 k1_pos = (((gain_ref_cells_subset[nnn][k_index1] -K_min)) % carrier_per_symbol) + K_min;
767 t1_pos = (gain_ref_cells_subset[nnn][k_index1] - K_min) / carrier_per_symbol;
768 k2_pos = ((gain_ref_cells_subset[nnn][k_index2] -K_min)) % carrier_per_symbol + K_min;
769 t2_pos = ((gain_ref_cells_subset[nnn][k_index2] - K_min)) / carrier_per_symbol;
770 xsinc1 = (k1_pos - k2_pos) * f_cut_k;
771 xsinc2 = (t1_pos - t2_pos) * f_cut_t;
772 if (k1_pos == k2_pos) xsinc1 = 1.0;
773 else
774 {
775 rest = sin(M_PI * xsinc1);
776 xsinc1 = rest / (M_PI * xsinc1);
777 }
778 if (fabs(xsinc2) < DBL_EPSILON) xsinc2 = 1.0;
779 else
780 {
781 rest = sin(M_PI * xsinc2);
782 xsinc2 = rest / (M_PI * xsinc2);
783 }
784 PHI[k_index1][k_index2] = (float) (xsinc1 * xsinc2);
785 }
786 }
787 for (i = 0; i < gain_ref_cells_per_window; i++)
788 {
789 PHI[i][i] += sigmaq_noise * 2.0 /((gain_ref_cells_a[gain_ref_cells_subset_index[nnn][i]]) * (gain_ref_cells_a[gain_ref_cells_subset_index[nnn][i]]));
790 }
791
792 // now the matrix inversion from numerical recipes
793 NP = gain_ref_cells_per_window;
794 amatrix = matrix(1, NP, 1, NP);
795 indxlu = ivector(1, NP);
796 collu = fvector(1, NP);
797 for (i = 1; i <= NP; i++)
798 for (j = 1; j <= NP; j++)
799 amatrix[i][j] = PHI[i - 1][j - 1];
800 ludcmp(amatrix, NP, indxlu, &dlu); /* decompose just once */
801 for (j = 1; j <= NP; j++)
802 {
803 for (i = 1; i <= NP; i++) collu[i] = 0.0;
804 collu[j] = 1.0;
805 lubksb(amatrix, NP, indxlu, collu);
806 for (i = 1; i <= NP; i++) PHI_INV[i - 1][j - 1] = collu[i];
807 }
808 free_fvector(collu, 1, NP);
809 free_ivector(indxlu, 1, NP);
810 free_matrix(amatrix, 1, NP, 1, NP);
811
812 for (k_index1 = 0; k_index1 < (K_max - K_min + 1); k_index1++)
813 {
814 for (k_index2 = 0; k_index2 < gain_ref_cells_per_window; k_index2++)
815 {
816 k1_pos = k_index1 + K_min;
817 t1_pos = symbols_to_delay;
818 k2_pos = (training_cells_k[nnn][k_index2] - K_min) % (K_max -K_min + 1) + K_min;
819 t2_pos = (training_cells_k[nnn][k_index2] - K_min) / (K_max -K_min + 1);
820 xsinc1 = (k1_pos - k2_pos) * f_cut_k;
821 xsinc2 = (t1_pos - t2_pos) * f_cut_t;
822 if (k1_pos == k2_pos) xsinc1 = 1.0;
823 else
824 {
825 rest = sin(M_PI * xsinc1);
826 xsinc1 = rest / (M_PI * xsinc1);
827 }
828 if (t1_pos == t2_pos) xsinc2 = 1.0;
829 else
830 {
831 rest = sin(M_PI * xsinc2);
832 xsinc2 = rest / (M_PI * xsinc2);
833 }
834 THETA[k_index2] = (float) (xsinc1 * xsinc2);
835 }
836 // calc matrix product THETA*PHI_INV
837 for (j = 0; j < NP; j++)
838
839 {
840 W_symbol[j] = 0.0;
841 for (k = 0; k < NP; k++) W_symbol[j] += THETA[k] * PHI_INV[k][j];
842 }
843 for (j = 0; j < NP; j++)
844 {
845 W_symbol_blk[nnn][j][k_index1] = W_symbol[j];
846 }
847 }
848 for (k_index1 = 0; k_index1 < cnt_next_pilot_cells[nnn]; k_index1++)
849 {
850 for (k_index2 = 0; k_index2 < gain_ref_cells_per_window;k_index2++)
851
852 {
853 k1_pos = next_pilot_cells_k[nnn][k_index1];
854 t1_pos = symbols_per_2D_window - 1;
855 k2_pos = (training_cells_k[nnn][k_index2] - K_min) % (K_max -K_min + 1) +K_min;
856 t2_pos = (training_cells_k[nnn][k_index2] - K_min) / (K_max -K_min + 1);
857 xsinc1 = (k1_pos - k2_pos) * f_cut_k;
858 xsinc2 = (t1_pos - t2_pos) * f_cut_t;
859 if (k1_pos == k2_pos) xsinc1 = 1.0;
860 else
861 {
862 rest = sin(M_PI * xsinc1);
863 xsinc1 = rest / (M_PI * xsinc1);
864 }
865 if (t1_pos == t2_pos) xsinc2 = 1.0;
866 else
867 {
868 rest = sin(M_PI * xsinc2);
869 xsinc2 = rest / (M_PI * xsinc2);
870 }
871 THETA[k_index2] = (float) (xsinc1 * xsinc2);
872 } /* end k_index2-loop */
873
874 // calc matrix product THETA*PHI_INV
875 for (j = 0; j < NP; j++)
876 {
877 W_pilots[j] = 0.0;
878 for (k = 0; k < NP; k++) W_pilots[j] += THETA[k] * PHI_INV[k][j];
879 }
880 for (j = 0; j < NP; j++)
881 {
882 W_pilots_blk[nnn][j][k_index1] = W_pilots[j];
883 }
884 } /* end k_index1-loop */
885 } /* end nnn-loop pa0mbo 26-5-2007 */
886
887
888 for (i = 0; i < rndcnt; i++)
889 {
890 temp = ((gain_ref_cells_k[i] - K_min) / (carrier_per_symbol)) * (K_modulo - carrier_per_symbol);
891 gain_ref_cells_k[i] += temp + K_dc - 1;
892 }
893 lFAC = mkfacmap(robustness_mode, K_dc, K_modulo, FAC_cells_k);
894 mode_and_occupancy_code_last = mode_and_occupancy_code;
895
896 for (i = 0; i < cnt_tr_cells[y-1]; i++) // joma y-1 was y
897 {
898 next_pilots[2 * i] = 0.0; /* real part */ // modified joma was j now i
899 next_pilots[2 * i + 1] = 0.0; /* imag */
900 }
901 gain_ref_cells_per_frame = rndcnt;
902 gain_ref_cells_per_y_symbols = rndcnt / (symbols_per_frame / y);
903 }
904 // in matlab code here for display toctic_equalization = 0 etc
905
906 t_smp = 0;
907
908 for (i = 0; i < symbols_per_frame; i++)
909 {
910 symbol_counter++;
911 // shifted symbol index
912 nn = (i - symbols_to_delay + symbols_per_frame) % symbols_per_frame;
913 ntwee = nn % y;
914 mtwee = nn / y;
915 for (j = 0; j < cnt_tr_cells[ntwee]; j++)
916 {
917 gain_ref_cells_subset_nn[j] =(mtwee * gain_ref_cells_per_y_symbols + gain_ref_cells_subset_index[ntwee][j]) % gain_ref_cells_per_frame;
918 training_cells_relative_index[j] =(gain_ref_cells_k[gain_ref_cells_subset_nn[j]] +(symbols_per_frame -nn) * K_modulo) % (K_modulo * symbols_per_frame);
919 }
920
921 cnt_actual_pilots_rel_indx = 0;
922 // logfile->addToAux(QString("block %1").arg(iterationCounter));
923 for (j = 0; j < cnt_tr_cells[ntwee]; j++)
924 {
925 if ((training_cells_relative_index[j] - (symbols_per_2D_window-1) * K_modulo) >= 0)
926 {
927 actual_pilots_relative_index[cnt_actual_pilots_rel_indx++] = j;
928 }
929 ntc_indx = training_cells_relative_index[j] + i * K_modulo + 1; /* pa0mbo in matlab +1 =OK trcrindx 1 lager dan in M */
930
931 hoek =(float) (2.0 * M_PI *(float)gain_ref_cells_theta_1024[gain_ref_cells_subset_nn[j]] /1024.0);
932
933 tmpreal =(float) (cos(hoek) / gain_ref_cells_a[gain_ref_cells_subset_nn[j]]);
934 tmpimag =(float) (-sin(hoek) /gain_ref_cells_a[gain_ref_cells_subset_nn[j]]);
935 normalized_training_cells[2 * j] = symbol_buffer[2 * ntc_indx] * tmpreal - symbol_buffer[2 * ntc_indx + 1] * tmpimag; /* real part */
936 normalized_training_cells[2 * j + 1] = symbol_buffer[2 * ntc_indx + 1] * tmpreal + symbol_buffer[2 * ntc_indx] * tmpimag; /* imag part */
937 }
938
939
940 for (j = 0; j < cnt_actual_pilots_rel_indx; j++)
941 {
942 actual_pilots[2 * j] = normalized_training_cells[2 * (actual_pilots_relative_index[j])]; /* real part */
943 actual_pilots[2 * j + 1] = normalized_training_cells[2 * (actual_pilots_relative_index[j]) + 1]; /* imag */
944 }
945 temp1 = 0.0;
946 temp2 = 0.0;
947 for (j = 0; j < cnt_actual_pilots_rel_indx; j++)
948 {
949 temp1 += actual_pilots[2 * j] * next_pilots[2 * j] + actual_pilots[2 * j + 1] * next_pilots[2 * j + 1]; /* real part */
950 temp2 += actual_pilots[2 * j] * next_pilots[2 * j + 1] -actual_pilots[2 * j + 1] * next_pilots[2 * j];
951
952 }
953 if (i != 0) delta_freq_offset = atan2f(temp2, temp1 + MIN_ABS_H);
954
955 for (j = 0; j < K_max - K_min + 1; j++)
956 {
957 H[2 * j] = 0.0;
958 H[2 * j + 1] = 0.0;
959 for (k = 0; k < cnt_tr_cells[ntwee]; k++)
960 {
961 H[2 * j] += normalized_training_cells[2 * k] * W_symbol_blk[ntwee][k][j];
962 H[2 * j + 1] += normalized_training_cells[2 * k + 1] * W_symbol_blk[ntwee][k][j];
963 }
964 }
965
966
967
968 for (j = 0; j < cnt_actual_pilots_rel_indx; j++)
969 {
970 next_pilots[2 * j] = 0.0;
971 next_pilots[2 * j + 1] = 0.0;
972 for (k = 0; k < cnt_tr_cells[ntwee]; k++)
973 {
974 next_pilots[2 * j] += normalized_training_cells[2 * k] * W_pilots_blk[ntwee][k][j];
975 next_pilots[2 * j + 1] += normalized_training_cells[2 * k + 1] * W_pilots_blk[ntwee][k][j];
976
977 }
978 }
979
980
981
982 for (j = K_min; j <= K_max; j++)
983 {
984 trxbuf_indx = transmission_frame_buffer_wptr + i * K_modulo + K_dc + j;
985 symbuf_indx = (i + symbols_to_delay) * K_modulo + K_dc + j;
986 tmp1 = H[2 * (j - K_min)] * H[2 * (j - K_min)] + H[2 * (j - K_min) +1] * H[2 * (j -K_min) +1] + MIN_ABS_H;
987 tmp2 = H[2 * (j - K_min)] / tmp1;
988 tmp3 = -H[2 * (j - K_min) + 1] / tmp1;
989 transmission_frame_buffer[2 * trxbuf_indx] =symbol_buffer[2 * symbuf_indx] * tmp2 -symbol_buffer[2 * symbuf_indx + 1] * tmp3;
990 transmission_frame_buffer[2 * trxbuf_indx + 1] =symbol_buffer[2 * symbuf_indx] * tmp3 +symbol_buffer[2 * symbuf_indx + 1] * tmp2;
991 channel_transfer_function_buffer[2 * trxbuf_indx] =H[2 * (j - K_min)];
992 channel_transfer_function_buffer[2 * trxbuf_indx + 1] =H[2 * (j - K_min) + 1];
993 }
994
995 // get next symbol
996 if ((iterationCounter>=0) && (iterationCounter<=180))
997 {
998 // arrayDump("b179",&rs_buffer[2 * t_smp],Ts,true);
999 // logfile->addToAux(QString("block %1").arg(iterationCounter));
1000 // arrayDump("h179",H,K_max - K_min + 1,true);
1001 }
1002 delta_time_offset_integer =getofdmsync(&rs_buffer[2 * t_smp], Ts, Tu, H, K_max - K_min + 1,delta_freq_offset, Zi, symbol_temp, 0, 1,1);
1003 // arrayDump("symtmp",symbol_temp,K_modulo,true);
1004
1005 // addToLog(QString("delta_time_offset_integer %1").arg(delta_time_offset_integer),LOGDRMDEMOD);
1006 for (j = 0; j < K_modulo; j++)
1007 {
1008 symbol_buffer[(symbufwidx * K_modulo + j) * 2] = symbol_temp[j * 2];
1009 symbol_buffer[(symbufwidx * K_modulo + j) * 2 + 1] = symbol_temp[j * 2 + 1];
1010 }
1011 symbufwidx++;
1012 t_smp += Ts + delta_time_offset_integer; /* next symbol */
1013 } /* end i-loop over symbols_per_frame */
1014
1015
1016 // fac_valid=0;
1017
1018 freq_offset = Zi[4];
1019 time_offset_fractional = Zi[5];
1020 delta_time_offset_I = Zi[2];
1021 addToLog("GREEN on channel estimation",LOGDRMDEMOD);
1022
1023 // clock too slow or too fast: adjust playing speed
1024
1025 smp_rate_conv_fft_phase_diff = 4 * (t_smp - N_symbols_needed * Ts);
1026 smp_rate_conv_fft_phase_offset = 4 * time_offset_fractional;
1027 smp_rate_conv_in_out_delay += smp_rate_conv_fft_phase_diff;
1028
1029
1030 addToLog(QString("Rate %1 %2 %3").arg(smp_rate_conv_fft_phase_diff).arg(smp_rate_conv_fft_phase_offset).arg(smp_rate_conv_in_out_delay),LOGDRMDEMOD);
1031 // display results
1032 freqOffset=-freq_offset * 12000.0 / (float) Tu / (2.0 * M_PI);
1033 deltaFS= (1.0 / (delta_time_offset_I / Ts + 1.0) - 1.0) ;
1034 samplerate_offset=delta_time_offset_I /Ts;
1035
1036
1037 // symbol align rs_buffer
1038
1039
1040
1041 // swap symbol buffer
1042
1043 symbufwidx -= symbols_per_frame;
1044 for (i = 0; i < symbufwidx * K_modulo; i++)
1045 {
1046 symbol_buffer[i * 2] = symbol_buffer[2 * symbols_per_frame * K_modulo + 2 * i];
1047 symbol_buffer[i * 2 + 1] = symbol_buffer[2 * symbols_per_frame * K_modulo + 2 * i + 1];
1048 }
1049
1050 // SNR estimation using FAC cells
1051 // mean energy of used cells set in listsinit()
1052
1053 sum_MERFAC = 0.0;
1054 sum_WMERFAC = 0.0;
1055 sum_weight_FAC = 0.0;
1056 for (i = 0; i < lFAC; i++)
1057
1058 {
1059 trxbuf_indx = transmission_frame_buffer_wptr + FAC_cells_k[i]; /* pa0mbo 18-5-2007 checked */
1060 FAC_cells_sequence[i * 2] = transmission_frame_buffer[2 * trxbuf_indx];
1061 FAC_cells_sequence[i * 2 + 1] = transmission_frame_buffer[2 * trxbuf_indx + 1];
1062 t1 = (float) (fabs(FAC_cells_sequence[i * 2]) - sqrt(0.5));
1063 t1 = t1 * t1;
1064 t2 = (float) (fabs(FAC_cells_sequence[i * 2 + 1]) - sqrt(0.5));
1065 t2 = t2 * t2;
1066 FAC_squared_noise_sequence[i] = t1 + t2;
1067 t1 = channel_transfer_function_buffer[trxbuf_indx * 2];
1068 t1 = t1 * t1;
1069 t2 = channel_transfer_function_buffer[trxbuf_indx * 2 + 1];
1070 t2 = t2 * t2;
1071 squared_weight_sequence[i] = t1 + t2;
1072 sum_MERFAC += FAC_squared_noise_sequence[i];
1073 sum_WMERFAC += FAC_squared_noise_sequence[i] * (squared_weight_sequence[i] + 1.0E-10);
1074 sum_weight_FAC += squared_weight_sequence[i];
1075 }
1076
1077 FACAvailable=true;
1078 avgSNRAvailable=true;
1079 MERFAC = (float) (log(sum_MERFAC / lFAC + 1.0E-10));
1080 MERFAC /= (log(10.0));
1081 MERFAC *= -10.0;
1082 WMERFAC =(float) (log(sum_WMERFAC /(mean_energy_of_used_cells * (sum_weight_FAC + lFAC * 1.0E-10))));
1083 WMERFAC /= (log(10.0));
1084 WMERFAC *= -10.0;
1085 SNR_dB = WMERFAC;
1086
1087 addToLog(QString("SNR-FAC =%1").arg(SNR_dB),LOGDRMDEMOD);
1088 // N_samples_needed = (symbols_per_frame + 1) * Ts - rsbufwidx;
1089
1090 if (SNR_dB < SNR_MIN_DB)
1091 {
1092 SNR_timeout_counter--;
1093 if (SNR_timeout_counter <= 0)
1094 {
1095 doSynchronize = true;
1096 SNR_timeout_counter = SNR_TIMEOUT;
1097 }
1098 transmission_frame_buffer_data_valid = 0;
1099 fac_not_valid_counter--;
1100 if (fac_not_valid_counter <= 0)
1101 {
1102 doSynchronize = true;
1103 fac_not_valid_counter = FACVALIDCNTR;
1104 }
1105 }
1106 else
1107 {
1108 SNR_timeout_counter = SNR_TIMEOUT;
1109 transmission_frame_buffer_data_valid = 1;
1110 fac_valid = 1;
1111 }
1112 if (doSynchronize) N_samples_needed = N_symbols_mode_detection * 320 - rsbufwidx;
1113 else
1114 {
1115 rsbufwidx -= t_smp;
1116 for (i = 0; i < rsbufwidx; i++)
1117 {
1118 rs_buffer[i * 2] = rs_buffer[(i + t_smp) * 2];
1119 rs_buffer[i * 2 + 1] = rs_buffer[(i + t_smp) * 2 + 1];
1120 }
1121 N_samples_needed = (symbols_per_frame + 1) * Ts - rsbufwidx;
1122 }
1123 if (N_samples_needed > 0)
1124 {
1125 input_samples_buffer_request = N_samples_needed;
1126 }
1127 else
1128 {
1129 input_samples_buffer_request = 0;
1130 }
1131 return true;
1132 }
1133