lte_sync_time.c 14.9 KB
Newer Older
1
2
3
4
5
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
ghaddab's avatar
ghaddab committed
21

22
23
24
/* file: lte_sync_time.c
   purpose: coarse timing synchronization for LTE (using PSS)
   author: florian.kaltenberger@eurecom.fr, oscar.tonelli@yahoo.it
25
   date: 22.10.2009
26
27
28
29
*/

//#include <string.h>
#include <math.h>
30
#include "LAYER2/MAC/mac.h"
yilmazt's avatar
yilmazt committed
31
32
#include "PHY/defs_UE.h"
#include "PHY/phy_extern_ue.h"
33
#include "PHY_INTERFACE/phy_interface.h"
knopp's avatar
knopp committed
34
#include "PHY/LTE_REFSIG/lte_refsig.h"
yilmazt's avatar
yilmazt committed
35
#include "RRC/LTE/rrc_extern.h"
36

37
38
// Note: this is for prototype of generate_drs_pusch (OTA synchronization of RRUs)
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"
39

Thomas Laurent's avatar
Thomas Laurent committed
40
41
42
43
44
45
static struct complex16 *primary_synch0_time __attribute__((aligned(32)));
static struct complex16 *primary_synch1_time __attribute__((aligned(32)));
static struct complex16 *primary_synch2_time __attribute__((aligned(32)));

static void doIdft(int size, short *in, short *out) {
  switch (size) {
46
  case 6:
Thomas Laurent's avatar
Thomas Laurent committed
47
      idft(IDFT_128,in,out,1);
48
    break;
Thomas Laurent's avatar
Thomas Laurent committed
49

50
  case 25:
Thomas Laurent's avatar
Thomas Laurent committed
51
      idft(IDFT_512,in,out,1);
52
    break;
Thomas Laurent's avatar
Thomas Laurent committed
53

54
  case 50:
Thomas Laurent's avatar
Thomas Laurent committed
55
      idft(IDFT_1024,in,out,1);
56
57
58
    break;
    
  case 75:
Thomas Laurent's avatar
Thomas Laurent committed
59
      idft(IDFT_1536,in,out,1);
60
    break;
Thomas Laurent's avatar
Thomas Laurent committed
61

62
  case 100:
Thomas Laurent's avatar
Thomas Laurent committed
63
      idft(IDFT_2048,in,out,1);
64
    break;
Thomas Laurent's avatar
Thomas Laurent committed
65

66
  default:
Thomas Laurent's avatar
Thomas Laurent committed
67
68
      LOG_E(PHY,"Unsupported N_RB_DL %d\n",size);
      abort();
69
70
    break;
    }
71
72
  }

Thomas Laurent's avatar
Thomas Laurent committed
73
74
static void copyPrimary( struct complex16 *out, struct complex16 *in, int ofdmSize) {
  int k=ofdmSize-36;
75
    
Thomas Laurent's avatar
Thomas Laurent committed
76
  for (int i=0; i<72; i++) {
Thomas Laurent's avatar
Thomas Laurent committed
77
78
    out[k].r = in[i].r>>1;  //we need to shift input to avoid overflow in fft
    out[k].i = in[i].i>>1;
79
    k++;
80

Thomas Laurent's avatar
Thomas Laurent committed
81
    if (k >= ofdmSize) {
82
      k++;  // skip DC carrier
Thomas Laurent's avatar
Thomas Laurent committed
83
      k-=ofdmSize;
84
85
    }
  }
86
  }
87

Thomas Laurent's avatar
Thomas Laurent committed
88
int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) { // LTE_UE_COMMON *common_vars
Thomas Laurent's avatar
Thomas Laurent committed
89
  struct complex16 syncF_tmp[2048]__attribute__((aligned(32)))= {{0}};
Thomas Laurent's avatar
Thomas Laurent committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
  int sz=frame_parms->ofdm_symbol_size*sizeof(*primary_synch0_time);
  AssertFatal( NULL != (primary_synch0_time = (struct complex16 *)malloc16(sz)),"");
  bzero(primary_synch0_time,sz);
  AssertFatal( NULL != (primary_synch1_time = (struct complex16 *)malloc16(sz)),"");
  bzero(primary_synch1_time,sz);
  AssertFatal( NULL != (primary_synch2_time = (struct complex16 *)malloc16(sz)),"");
  bzero(primary_synch2_time,sz);
  // generate oversampled sync_time sequences
  copyPrimary( syncF_tmp, (struct complex16 *) primary_synch0, frame_parms->ofdm_symbol_size);
  doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch0_time);
  copyPrimary( syncF_tmp, (struct complex16 *) primary_synch1, frame_parms->ofdm_symbol_size);
  doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch1_time);
  copyPrimary( syncF_tmp, (struct complex16 *) primary_synch2, frame_parms->ofdm_symbol_size);
  doIdft(frame_parms->N_RB_DL, (short *)syncF_tmp,(short *)primary_synch2_time);

105
  if ( LOG_DUMPFLAG(DEBUG_LTEESTIM)){
106
107
108
109
    LOG_M("primary_sync0.m","psync0",primary_synch0_time,frame_parms->ofdm_symbol_size,1,1);
    LOG_M("primary_sync1.m","psync1",primary_synch1_time,frame_parms->ofdm_symbol_size,1,1);
    LOG_M("primary_sync2.m","psync2",primary_synch2_time,frame_parms->ofdm_symbol_size,1,1);
  }
Thomas Laurent's avatar
Thomas Laurent committed
110

111
112
113
114
  return (1);
}


Thomas Laurent's avatar
Thomas Laurent committed
115
void lte_sync_time_free(void) {
116
  if (primary_synch0_time) {
117
    LOG_D(PHY,"Freeing primary_sync0_time ...\n");
118
119
    free(primary_synch0_time);
  }
120

121
  if (primary_synch1_time) {
122
    LOG_D(PHY,"Freeing primary_sync1_time ...\n");
123
124
    free(primary_synch1_time);
  }
125

126
  if (primary_synch2_time) {
127
    LOG_D(PHY,"Freeing primary_sync2_time ...\n");
128
129
    free(primary_synch2_time);
  }
130

gauthier's avatar
gauthier committed
131
132
133
  primary_synch0_time = NULL;
  primary_synch1_time = NULL;
  primary_synch2_time = NULL;
134
135
}

yilmazt's avatar
yilmazt committed
136

Thomas Laurent's avatar
Thomas Laurent committed
137
static inline int abs32(int x) {
138
  return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1]));
Thomas Laurent's avatar
Thomas Laurent committed
139
140
141
142
}

static inline double absF(struct complexd x) {
  return x.r*x.r+x.i*x.i;
143
144
}

Thomas Laurent's avatar
Thomas Laurent committed
145
#define complexNull(c) bzero((void*) &(c), sizeof(c))
yilmazt's avatar
yilmazt committed
146

147
148
#define SHIFT 17

yilmazt's avatar
yilmazt committed
149

150
int lte_sync_time(int **rxdata, ///rx data in time domain
151
                  LTE_DL_FRAME_PARMS *frame_parms,
Thomas Laurent's avatar
Thomas Laurent committed
152
                  int *eNB_id) {
153
154
155
  // perform a time domain correlation using the oversampled sync sequence
  unsigned int n, ar, s, peak_pos, peak_val, sync_source;
  int result,result2;
Thomas Laurent's avatar
Thomas Laurent committed
156
  struct complexd sync_out[3]= {{0}}, sync_out2[3]= {{0}};
157
158
159
160
161
162
  int length =   LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti>>1;
  peak_val = 0;
  peak_pos = 0;
  sync_source = 0;

  for (n=0; n<length; n+=4) {
163
    for (s=0; s<3; s++) {
Thomas Laurent's avatar
Thomas Laurent committed
164
165
      complexNull(sync_out[s]);
      complexNull(sync_out2[s]);
166
    }
167

168
169
170
    //    if (n<(length-frame_parms->ofdm_symbol_size-frame_parms->nb_prefix_samples)) {
    if (n<(length-frame_parms->ofdm_symbol_size)) {
      //calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
171
      for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
Thomas Laurent's avatar
Thomas Laurent committed
172
173
174
175
176
177
        result  = dot_product((short *)primary_synch0_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT);
        result2 = dot_product((short *)primary_synch0_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT);
        sync_out[0].r += ((short *) &result)[0];
        sync_out[0].i += ((short *) &result)[1];
        sync_out2[0].r += ((short *) &result2)[0];
        sync_out2[0].i += ((short *) &result2)[1];
178
      }
179
180

      for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
Thomas Laurent's avatar
Thomas Laurent committed
181
182
183
184
185
186
        result = dot_product((short *)primary_synch1_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT);
        result2 = dot_product((short *)primary_synch1_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT);
        sync_out[1].r += ((short *) &result)[0];
        sync_out[1].i += ((short *) &result)[1];
        sync_out2[1].r += ((short *) &result2)[0];
        sync_out2[1].i += ((short *) &result2)[1];
187
188
      }

189
      for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
Thomas Laurent's avatar
Thomas Laurent committed
190
191
192
193
194
195
        result = dot_product((short *)primary_synch2_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT);
        result2 = dot_product((short *)primary_synch2_time, (short *) &(rxdata[ar][n+length]), frame_parms->ofdm_symbol_size, SHIFT);
        sync_out[2].r += ((short *) &result)[0];
        sync_out[2].i += ((short *) &result)[1];
        sync_out2[2].r += ((short *) &result2)[0];
        sync_out2[2].i += ((short *) &result2)[1];
196
197
      }
    }
198

199
200
    // calculate the absolute value of sync_corr[n]

201
    for (s=0; s<3; s++) {
Thomas Laurent's avatar
Thomas Laurent committed
202
      double tmp = absF(sync_out[s]) + absF(sync_out2[s]);
203

Thomas Laurent's avatar
Thomas Laurent committed
204
205
      if (tmp>peak_val) {
        peak_val = tmp;
206
207
208
209
210
211
212
        peak_pos = n;
        sync_source = s;
        /*
        printf("s %d: n %d sync_out %d, sync_out2  %d (sync_corr %d,%d), (%d,%d) (%d,%d)\n",s,n,abs32(sync_out[s]),abs32(sync_out2[s]),sync_corr_ue0[n],
               sync_corr_ue0[n+length],((int16_t*)&sync_out[s])[0],((int16_t*)&sync_out[s])[1],((int16_t*)&sync_out2[s])[0],((int16_t*)&sync_out2[s])[1]);
        */
      }
213
214
215
216
    }
  }

  *eNB_id = sync_source;
Thomas Laurent's avatar
Thomas Laurent committed
217
  LOG_I(PHY,"[UE] lte_sync_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n",sync_source,peak_pos,peak_val/2,dB_fixed(peak_val/2)/2);
218
219
220
  return(peak_pos);
}

knopp's avatar
knopp committed
221

Thomas Laurent's avatar
Thomas Laurent committed
222
int ru_sync_time_init(RU_t *ru) { // LTE_UE_COMMON *common_vars
TheoniJ's avatar
TheoniJ committed
223
  /*
knopp's avatar
knopp committed
224
225
  int16_t dmrs[2048];
  int16_t *dmrsp[2] = {dmrs,NULL};
TheoniJ's avatar
TheoniJ committed
226
  */
yilmazt's avatar
yilmazt committed
227
228
  int32_t dmrs[ru->frame_parms->ofdm_symbol_size*14] __attribute__((aligned(32)));
  //int32_t *dmrsp[2] = {&dmrs[(3-ru->frame_parms->Ncp)*ru->frame_parms->ofdm_symbol_size],NULL};
knopp's avatar
knopp committed
229
  int32_t *dmrsp[2] = {&dmrs[0],NULL};
TheoniJ's avatar
TheoniJ committed
230
  generate_ul_ref_sigs();
Thomas Laurent's avatar
Thomas Laurent committed
231
232
  ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms->ofdm_symbol_size*2*sizeof(int16_t));
  ru->dmrs_corr = (uint64_t *)malloc16_clear(ru->frame_parms->samples_per_tti*10*sizeof(uint64_t));
yilmazt's avatar
yilmazt committed
233
234
235
236
237
238
239
240
241
242
243
244
  generate_drs_pusch(NULL,
                     NULL,
                     ru->frame_parms,
                     dmrsp,
                     0,
                     AMP,
                     0,
                     0,
                     ru->frame_parms->N_RB_DL,
                     0);

  switch (ru->frame_parms->N_RB_DL) {
Thomas Laurent's avatar
Thomas Laurent committed
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
    case 6:
      idft(IDFT_128,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]),
           ru->dmrssync, /// complex output
           1);
      break;

    case 25:
      idft(IDFT_512,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]),
           ru->dmrssync, /// complex output
           1);
      break;

    case 50:
      idft(IDFT_1024,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]),
           ru->dmrssync, /// complex output
           1);
      break;

    case 75:
      idft(IDFT_1536,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]),
           ru->dmrssync,
           1); /// complex output
      break;

    case 100:
      idft(IDFT_2048,(int16_t *)(&dmrsp[0][3*ru->frame_parms->ofdm_symbol_size]),
           ru->dmrssync, /// complex output
           1);
      break;

    default:
      AssertFatal(1==0,"Unsupported N_RB_DL %d\n",ru->frame_parms->N_RB_DL);
      break;
knopp's avatar
knopp committed
278
279
280
281
282
  }

  return(0);
}

yilmazt's avatar
yilmazt committed
283

knopp's avatar
knopp committed
284
285
286
void ru_sync_time_free(RU_t *ru) {
  AssertFatal(ru->dmrssync!=NULL,"ru->dmrssync is NULL\n");
  free(ru->dmrssync);
Thomas Laurent's avatar
Thomas Laurent committed
287
288
289

  if (ru->dmrs_corr)
    free(ru->dmrs_corr);
knopp's avatar
knopp committed
290
291
}

292
293
//#define DEBUG_PHY

gauthier's avatar
gauthier committed
294
int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
295
296
297
                      LTE_DL_FRAME_PARMS *frame_parms,
                      uint32_t length,
                      uint32_t *peak_val_out,
Thomas Laurent's avatar
Thomas Laurent committed
298
                      uint32_t *sync_corr_eNB) {
299
  // perform a time domain correlation using the oversampled sync sequence
300
301
  unsigned int n, ar, peak_val, peak_pos;
  uint64_t mean_val;
302
303
304
305
  int result;
  short *primary_synch_time;
  int eNB_id = frame_parms->Nid_cell%3;

306
  // LOG_E(PHY,"[SYNC TIME] Calling sync_time_eNB(%p,%p,%d,%d)\n",rxdata,frame_parms,eNB_id,length);
307
  if (sync_corr_eNB == NULL) {
308
    LOG_E(PHY,"[SYNC TIME] sync_corr_eNB not yet allocated! Exiting.\n");
309
310
311
312
    return(-1);
  }

  switch (eNB_id) {
Thomas Laurent's avatar
Thomas Laurent committed
313
314
315
    case 0:
      primary_synch_time = (short *)primary_synch0_time;
      break;
316

Thomas Laurent's avatar
Thomas Laurent committed
317
318
319
    case 1:
      primary_synch_time = (short *)primary_synch1_time;
      break;
320

Thomas Laurent's avatar
Thomas Laurent committed
321
322
323
    case 2:
      primary_synch_time = (short *)primary_synch2_time;
      break;
324

Thomas Laurent's avatar
Thomas Laurent committed
325
326
327
    default:
      LOG_E(PHY,"[SYNC TIME] Illegal eNB_id!\n");
      return (-1);
328
329
330
331
332
333
334
335
336
337
338
  }

  peak_val = 0;
  peak_pos = 0;
  mean_val = 0;

  for (n=0; n<length; n+=4) {
    sync_corr_eNB[n] = 0;

    if (n<(length-frame_parms->ofdm_symbol_size-frame_parms->nb_prefix_samples)) {
      //calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
339
      for (ar=0; ar<frame_parms->nb_antennas_rx; ar++)  {
Thomas Laurent's avatar
Thomas Laurent committed
340
        result = dot_product((short *)primary_synch_time, (short *) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, SHIFT);
341
342
343
        //((short*)sync_corr)[2*n]   += ((short*) &result)[0];
        //((short*)sync_corr)[2*n+1] += ((short*) &result)[1];
        sync_corr_eNB[n] += abs32(result);
344
345
      }
    }
346

347
348
349
    /*
    if (eNB_id == 2) {
      printf("sync_time_eNB %d : %d,%d (%d)\n",n,sync_corr_eNB[n],mean_val,
350
       peak_val);
351
352
    }
    */
353
    mean_val += sync_corr_eNB[n];
354
355
356
357
358
359
360

    if (sync_corr_eNB[n]>peak_val) {
      peak_val = sync_corr_eNB[n];
      peak_pos = n;
    }
  }

361
  mean_val/=length;
362
363
  *peak_val_out = peak_val;

364
  if (peak_val <= (40*(uint32_t)mean_val)) {
Eurecom's avatar
Eurecom committed
365
    LOG_I(PHY,"[SYNC TIME] No peak found (%u,%u,%"PRIu64",%"PRIu64")\n",peak_pos,peak_val,mean_val,40*mean_val);
366
    return(-1);
367
  } else {
Eurecom's avatar
Eurecom committed
368
    LOG_I(PHY,"[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %"PRIu64"\n",peak_pos,peak_val,mean_val);
369
370
371
372
    return(peak_pos);
  }
}

yilmazt's avatar
yilmazt committed
373

Thomas Laurent's avatar
Thomas Laurent committed
374
375
376
static inline int64_t abs64(int64_t x) {
  return (((int64_t)((int32_t *)&x)[0])*((int64_t)((int32_t *)&x)[0]) + ((int64_t)
          ((int32_t *)&x)[1])*((int64_t)((int32_t *)&x)[1]));
knopp's avatar
knopp committed
377
}
378

yilmazt's avatar
yilmazt committed
379

knopp's avatar
knopp committed
380
int ru_sync_time(RU_t *ru,
yilmazt's avatar
yilmazt committed
381
                 int64_t *lev,
Thomas Laurent's avatar
Thomas Laurent committed
382
                 int64_t *avg) {
yilmazt's avatar
yilmazt committed
383
  LTE_DL_FRAME_PARMS *frame_parms = ru->frame_parms;
knopp's avatar
knopp committed
384
  RU_CALIBRATION *calibration = &ru->calibration;
knopp's avatar
knopp committed
385
386
387
388
  // perform a time domain correlation using the oversampled sync sequence
  int length =   LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti;

  // circular copy of beginning to end of rxdata buffer. Note: buffer should be big enough upon calling this function
Thomas Laurent's avatar
Thomas Laurent committed
389
390
391
392
393
  for (int ar=0; ar<ru->nb_rx; ar++)
    memcpy((void *)&ru->common.rxdata[ar][2*length],
           (void *)&ru->common.rxdata[ar][0],
           frame_parms->ofdm_symbol_size);

knopp's avatar
knopp committed
394
  int32_t maxlev0=0;
knopp's avatar
knopp committed
395
396
  int     maxpos0=0;
  int64_t avg0=0;
knopp's avatar
knopp committed
397
398
399
  int64_t result;
  int64_t dmrs_corr;
  int maxval=0;
Thomas Laurent's avatar
Thomas Laurent committed
400
401

  for (int i=0; i<2*(frame_parms->ofdm_symbol_size); i++) {
knopp's avatar
knopp committed
402
403
404
    maxval = max(maxval,ru->dmrssync[i]);
    maxval = max(maxval,-ru->dmrssync[i]);
  }
knopp's avatar
knopp committed
405
406

  if (ru->state == RU_CHECK_SYNC) {
Thomas Laurent's avatar
Thomas Laurent committed
407
408
409
410
    for (int i=0; i<2*(frame_parms->ofdm_symbol_size); i++) {
      maxval = max(maxval,calibration->drs_ch_estimates_time[0][i]);
      maxval = max(maxval,-calibration->drs_ch_estimates_time[0][i]);
    }
knopp's avatar
knopp committed
411
412
  }

knopp's avatar
knopp committed
413
  int shift = log2_approx(maxval);
414

knopp's avatar
knopp committed
415
  for (int n=0; n<length; n+=4) {
knopp's avatar
knopp committed
416
    dmrs_corr = 0;
417

knopp's avatar
knopp committed
418
419
    //calculate dot product of primary_synch0_time and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n];
    for (int ar=0; ar<ru->nb_rx; ar++) {
knopp's avatar
knopp committed
420
      result  = dot_product64(ru->dmrssync,
Thomas Laurent's avatar
Thomas Laurent committed
421
                              (int16_t *) &ru->common.rxdata[ar][n],
knopp's avatar
knopp committed
422
423
                              frame_parms->ofdm_symbol_size,
                              shift);
Thomas Laurent's avatar
Thomas Laurent committed
424
425
426
427
428
429

      if (ru->state == RU_CHECK_SYNC) {
        result  = dot_product64((int16_t *) &calibration->drs_ch_estimates_time[ar],
                                (int16_t *) &ru->common.rxdata[ar][n],
                                frame_parms->ofdm_symbol_size,
                                shift);
knopp's avatar
knopp committed
430
      }
Thomas Laurent's avatar
Thomas Laurent committed
431

knopp's avatar
knopp committed
432
      dmrs_corr += abs64(result);
433
    }
Thomas Laurent's avatar
Thomas Laurent committed
434
435
436

    if (ru->dmrs_corr != NULL)
      ru->dmrs_corr[n] = dmrs_corr;
knopp's avatar
knopp committed
437
438
439

    // tmpi holds <synchi,rx0>+<synci,rx1>+...+<synchi,rx_{nbrx-1}>

Thomas Laurent's avatar
Thomas Laurent committed
440
441
442
443
    if (dmrs_corr>maxlev0) {
      maxlev0 = dmrs_corr;
      maxpos0 = n;
    }
knopp's avatar
knopp committed
444

knopp's avatar
knopp committed
445
    avg0 += dmrs_corr;
446
  }
knopp's avatar
knopp committed
447

Thomas Laurent's avatar
Thomas Laurent committed
448
  avg0/=(length/4);
knopp's avatar
knopp committed
449
  int dmrsoffset = frame_parms->samples_per_tti + (3*frame_parms->ofdm_symbol_size)+(3*frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0;
Thomas Laurent's avatar
Thomas Laurent committed
450
451
452
453
454
455

  if ((int64_t)maxlev0 > (10*avg0)) {
    *lev = maxlev0;
    *avg=avg0;
    return((length+maxpos0-dmrsoffset)%length);
  }
456

457
458
  return(-1);
}