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