Example #1
0
/* Initializes the PSS synchronization object. 
 * 
 * It correlates a signal of frame_size samples with the PSS sequence in the frequency 
 * domain. The PSS sequence is transformed using fft_size samples. 
 */
int pss_synch_init_fft(pss_synch_t *q, uint32_t frame_size, uint32_t fft_size) {
  int ret = LIBLTE_ERROR_INVALID_INPUTS;
    
  if (q != NULL) {
  
    uint32_t N_id_2; 
    uint32_t buffer_size; 
    bzero(q, sizeof(pss_synch_t));
    
    q->N_id_2 = 10;
    q->fft_size = fft_size;
    q->frame_size = frame_size;
    
    buffer_size = fft_size + frame_size + 1;
    
    q->tmp_input = vec_malloc(buffer_size * sizeof(cf_t));
    if (!q->tmp_input) {
      fprintf(stderr, "Error allocating memory\n");
      goto clean_and_exit;
    }
    q->conv_output = vec_malloc(buffer_size * sizeof(cf_t));
    if (!q->conv_output) {
      fprintf(stderr, "Error allocating memory\n");
      goto clean_and_exit;
    }
    for (N_id_2=0;N_id_2<3;N_id_2++) {
      q->pss_signal_freq[N_id_2] = vec_malloc(buffer_size * sizeof(cf_t));
      if (!q->pss_signal_freq[N_id_2]) {
        fprintf(stderr, "Error allocating memory\n");
        goto clean_and_exit;
      }
      /* The PSS is translated into the frequency domain for each N_id_2  */
      if (pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], N_id_2, fft_size)) {
        fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size);
        goto clean_and_exit;
      }      
    }    
    #ifdef CONVOLUTION_FFT
    if (conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) {
      fprintf(stderr, "Error initiating convolution FFT\n");
      goto clean_and_exit;
    }
    #endif
    
    ret = LIBLTE_SUCCESS;
  }

clean_and_exit: 
  if (ret == LIBLTE_ERROR) {
    pss_synch_free(q);
  }
  return ret;
}
Example #2
0
int filter2d_init(filter2d_t* q, float **taps, int ntime, int nfreq, int sztime,
    int szfreq) {

  int ret = -1;
  bzero(q, sizeof(filter2d_t));

  if (matrix_init((void***)&q->taps, ntime, nfreq, sizeof(float))) {
    goto free_and_exit;
  }

  matrix_copy((void**) q->taps, (void**) taps, ntime, nfreq, sizeof(float));

  q->output = vec_malloc((ntime+sztime)*(szfreq)*sizeof(cf_t));
  if (!q->output) {
    goto free_and_exit;
  }

  bzero(q->output, (ntime+sztime)*(szfreq)*sizeof(cf_t));

  q->nfreq = nfreq;
  q->ntime = ntime;
  q->szfreq = szfreq;
  q->sztime = sztime;

  ret = 0;

  free_and_exit: if (ret == -1) {
    filter2d_free(q);
  }
  return ret;
}
Example #3
0
 void
 init (unsigned cap)
 {
     buf = vec_malloc (cap);
     buf_last = buf;
     buf_end = buf + cap;
 }
Example #4
0
/*** Default Allocation/Deallocation Function ***/
static ILvoid* ILAPIENTRY DefaultAllocFunc(ILuint Size)
{
#ifdef VECTORMEM
	return (ILvoid*)vec_malloc(Size);
#else
	return malloc(Size);
#endif
}
Example #5
0
ILvoid *ivec_align_buffer( ILvoid *buffer, ILuint size ) {
	if( (size_t)buffer % 16 != 0 ) {
        void *aligned_buffer = vec_malloc( size );
        memcpy( aligned_buffer, buffer, size );
        ifree( buffer );
        return aligned_buffer;
    }
    return buffer;
}
Example #6
0
void *ivec_align_buffer(void *buffer, const ILsizei size)
{
	if( (ILsizei)buffer % 16 != 0 ) {
        void *aligned_buffer = vec_malloc( size );
        memcpy( aligned_buffer, buffer, size );
        ifree( buffer );
        return aligned_buffer;
    }
    return buffer;
}
Example #7
0
int conv_fft_cc_init(conv_fft_cc_t *state, int input_len, int filter_len) {
	state->input_len = input_len;
	state->filter_len = filter_len;
	state->output_len = input_len+filter_len-1;
	state->input_fft = vec_malloc(sizeof(_Complex float)*state->output_len);
	state->filter_fft = vec_malloc(sizeof(_Complex float)*state->output_len);
	state->output_fft = vec_malloc(sizeof(_Complex float)*state->output_len);
	if (!state->input_fft || !state->filter_fft || !state->output_fft) {
		return -1;
	}
	if (dft_plan(state->output_len,COMPLEX_2_COMPLEX,FORWARD,&state->input_plan)) {
		return -2;
	}
	if (dft_plan(state->output_len,COMPLEX_2_COMPLEX,FORWARD,&state->filter_plan)) {
		return -3;
	}
	if (dft_plan(state->output_len,COMPLEX_2_COMPLEX,BACKWARD,&state->output_plan)) {
		return -4;
	}
	return 0;
}
Example #8
0
int cfo_init(cfo_t *h, uint32_t nsamples) {
  int ret = LIBLTE_ERROR;
  bzero(h, sizeof(cfo_t));

  if (cexptab_init(&h->tab, CFO_CEXPTAB_SIZE)) {
    goto clean;
  }
  h->cur_cexp = vec_malloc(sizeof(cf_t) * nsamples);
  if (!h->cur_cexp) {
    goto clean;
  }
  h->tol = CFO_TOLERANCE;
  h->last_freq = 0;
  h->nsamples = nsamples;
  cexptab_gen(&h->tab, h->cur_cexp, h->last_freq, h->nsamples);

  ret = LIBLTE_SUCCESS;
clean:
  if (ret == LIBLTE_ERROR) {
    cfo_free(h);
  }
  return ret;
}
Example #9
0
int main(int argc, char **argv) {
  int n; 
  void *uhd;
  ue_celldetect_t s;
  ue_celldetect_result_t found_cells[3]; 
  cf_t *buffer; 
  int nof_freqs; 
  lte_earfcn_t channels[MAX_EARFCN];
  uint32_t freq;
  pbch_mib_t mib; 

  parse_args(argc, argv);
    
  printf("Opening UHD device...\n");
  if (cuhd_open(uhd_args, &uhd)) {
    fprintf(stderr, "Error opening uhd\n");
    exit(-1);
  }  
  cuhd_set_rx_gain(uhd, uhd_gain);
  
  nof_freqs = lte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
  if (nof_freqs < 0) {
    fprintf(stderr, "Error getting EARFCN list\n");
    exit(-1);
  }
    
  buffer = vec_malloc(sizeof(cf_t) * 96000);
  if (!buffer) {
    perror("malloc");
    return LIBLTE_ERROR;
  }
  
  if (ue_celldetect_init(&s)) {
    fprintf(stderr, "Error initiating UE sync module\n");
    exit(-1);
  }
  if (threshold > 0) {
    ue_celldetect_set_threshold(&s, threshold);    
  }
  
  if (nof_frames_total > 0) {
    ue_celldetect_set_nof_frames_total(&s, nof_frames_total);
  }
  if (nof_frames_detected > 0) {
    ue_celldetect_set_nof_frames_detected(&s, nof_frames_detected);
  }

  for (freq=0;freq<nof_freqs;freq+=10) {
  
    /* set uhd_freq */
    cuhd_set_rx_freq(uhd, (double) channels[freq].fd * MHZ);
    cuhd_rx_wait_lo_locked(uhd);
    usleep(10000);
    INFO("Set uhd_freq to %.3f MHz\n", (double) channels[freq].fd * MHZ/1000000);
    
    printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS. \r", freq, nof_freqs,
                      channels[freq].id, channels[freq].fd);fflush(stdout);
    
    if (VERBOSE_ISINFO()) {
      printf("\n");
    }
    
    n = find_cell(uhd, &s, buffer, found_cells);
    if (n < 0) {
      fprintf(stderr, "Error searching cell\n");
      exit(-1);
    }
    if (n == CS_CELL_DETECTED) {
      for (int i=0;i<3;i++) {
        if (found_cells[i].peak > threshold/2) {
          if (decode_pbch(uhd, buffer, &found_cells[i], nof_frames_total, &mib)) {
            fprintf(stderr, "Error decoding PBCH\n");
            exit(-1);
          }          
        }
      }
    }    
  }
    
  ue_celldetect_free(&s);
  cuhd_close(uhd);
  exit(0);
}
Example #10
0
int main(int argc, char **argv) {
  cf_t *input_buffer, *sf_symbols = NULL; 
  int frame_cnt;
  ue_sync_t s; 
  int pos;
  pss_synch_t pss; 
  float peak;
  struct timeval t[3];
  float mean_ce_time=0;
  bool signal_detected; 
  lte_fft_t fft; 
  lte_cell_t cell; 
  
  bzero(&cell, sizeof(lte_cell_t));
  
  parse_args(argc, argv);
    
  #ifndef DISABLE_GRAPHICS
  if (!disable_plots) {
    init_plots();    
  }
  #endif
  
  input_init();
        
  if (ue_sync_init(&s, cuhd_set_rx_srate, cuhd_recv_wrapper, uhd)) {
    fprintf(stderr, "Error initiating UE sync module\n");
    exit(-1);
  }
  
  ue_sync_pbch_enable(&s, true);
  
  signal_detected = true;
  frame_cnt = 0;
  mean_ce_time=0;
  uint32_t valid_frames=0;
  //uint32_t unaligned = 0; 
  while (frame_cnt < nof_frames || nof_frames == -1) {    

    int n = ue_sync_get_buffer(&s, &input_buffer);
    if (n < 0) {
      fprintf(stderr, "Error calling sync work()\n");
      exit(-1);      
    }
    
    if (n == 1 && ue_sync_get_sfidx(&s) == 0) {

      if (signal_detected) {
        cell = ue_sync_get_cell(&s);
        pss_synch_init_fft(&pss, 
                          SF_LEN(lte_symbol_sz(cell.nof_prb), cell.cp), 
                          lte_symbol_sz(cell.nof_prb));
        pss_synch_set_N_id_2(&pss, cell.id%3);
        
        sf_symbols = vec_malloc(SLOT_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
        if (!sf_symbols) {
          perror("malloc");
          exit(-1);
        }
        lte_fft_init(&fft, cell.cp, cell.nof_prb);
        signal_detected = false; 
      }
      
      mean_ce_time = (float) (mean_ce_time + (float) t[0].tv_usec * valid_frames) / (valid_frames+1);
      valid_frames++;
      
      #ifndef DISABLE_GRAPHICS
      if (!disable_plots && !(valid_frames % 5) && sf_symbols) {
        
        /* Run FFT for the second slot */
        lte_fft_run_slot(&fft, input_buffer, sf_symbols);
    
        int i;
        int nof_re = SLOT_LEN_RE(cell.nof_prb, cell.cp);
        for (i = 0; i < nof_re; i++) {
          tmp_plot[i] = 10 * log10f(cabsf(sf_symbols[i]));
          if (isinf(tmp_plot[i])) {
            tmp_plot[i] = -80;
          }
        }
        plot_real_setNewData(&poutfft, tmp_plot, nof_re);        
      }
    #endif
      
      pos = pss_synch_find_pss(&pss, input_buffer, &peak, NULL);      
      /*if (pos > 962 || pos < 958) {
        unaligned++;
      }
      */
      printf("CELL_ID: %3d CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Exec: %3.2f\r",
              cell.id, ue_sync_get_cfo(&s)/1000, ue_sync_get_sfo(&s)/1000, pos, 
             s.mean_exec_time);
          fflush(stdout);
      if (VERBOSE_ISINFO()) {
        printf("\n");
      }
    }
      
    frame_cnt++;
  }

  printf("\nBye\n");
  exit(0);
}
Example #11
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

  int i;
  lte_cell_t cell; 
  chest_dl_t chest;
  precoding_t cheq; 
  cf_t *input_signal = NULL, *output_signal[MAX_LAYERS]; 
  cf_t *output_signal2 = NULL;
  cf_t *ce[MAX_PORTS]; 
  double *outr0=NULL, *outi0=NULL;
  double *outr1=NULL, *outi1=NULL;
  double *outr2=NULL, *outi2=NULL;
  
  if (nrhs < NOF_INPUTS) {
    help();
    return;
  }

  if (!mxIsDouble(CELLID) && mxGetN(CELLID) != 1 && 
      !mxIsDouble(PORTS) && mxGetN(PORTS) != 1 && 
      mxGetM(CELLID) != 1) {
    help();
    return;
  }

  cell.id = (uint32_t) *((double*) mxGetPr(CELLID));
  cell.nof_prb = mxGetM(INPUT)/RE_X_RB;
  cell.nof_ports = (uint32_t) *((double*) mxGetPr(PORTS)); 
  if ((mxGetN(INPUT)%14) == 0) {
    cell.cp = CPNORM;    
  } else if ((mxGetN(INPUT)%12)!=0) {
    cell.cp = CPEXT;
  } else {
    mexErrMsgTxt("Invalid number of symbols\n");
    help();
    return;
  }
  
  if (chest_dl_init(&chest, cell)) {
    mexErrMsgTxt("Error initiating channel estimator\n");
    return;
  }
  
  int nsubframes;
  if (cell.cp == CPNORM) {
    nsubframes = mxGetN(INPUT)/14;
  } else {
    nsubframes = mxGetN(INPUT)/12;
  }
  
  uint32_t sf_idx=0; 
  if (nsubframes == 1) {
    if (nrhs != NOF_INPUTS+1) {
      mexErrMsgTxt("Received 1 subframe. Need to provide subframe index.\n");
      help();
      return;
    }
    sf_idx = (uint32_t) *((double*) mxGetPr(SFIDX));
  } else {
    if (nrhs != NOF_INPUTS) {
      help();
      return;
    }
  }
    
  uint32_t filter_len = 0;
  float *filter; 
  double *f; 
  
  filter_len = mxGetNumberOfElements(FREQ_FILTER);
  filter = malloc(sizeof(float) * filter_len);
  f = (double*) mxGetPr(FREQ_FILTER);
  for (i=0;i<filter_len;i++) {
    filter[i] = (float) f[i];
  }

  chest_dl_set_filter_freq(&chest, filter, filter_len);

  filter_len = mxGetNumberOfElements(TIME_FILTER);
  filter = malloc(sizeof(float) * filter_len);
  f = (double*) mxGetPr(TIME_FILTER);
  for (i=0;i<filter_len;i++) {
    filter[i] = (float) f[i];
  }
  chest_dl_set_filter_time(&chest, filter, filter_len);
  


  double *inr=(double *)mxGetPr(INPUT);
  double *ini=(double *)mxGetPi(INPUT);
  
  /** Allocate input buffers */
  int nof_re = 2*CP_NSYMB(cell.cp)*cell.nof_prb*RE_X_RB;
  for (i=0;i<MAX_PORTS;i++) {
    ce[i] = vec_malloc(nof_re * sizeof(cf_t));
  }
  input_signal = vec_malloc(nof_re * sizeof(cf_t));
  for (i=0;i<MAX_PORTS;i++) {
    output_signal[i] = vec_malloc(nof_re * sizeof(cf_t));
  }
  output_signal2 = vec_malloc(nof_re * sizeof(cf_t));
  
  precoding_init(&cheq, nof_re);
  
  /* Create output values */
  if (nlhs >= 1) {
    plhs[0] = mxCreateDoubleMatrix(nof_re * nsubframes, cell.nof_ports, mxCOMPLEX);
    outr0 = mxGetPr(plhs[0]);
    outi0 = mxGetPi(plhs[0]);
  }  
  if (nlhs >= 2) {
    plhs[1] = mxCreateDoubleMatrix(REFSIGNAL_MAX_NUM_SF(cell.nof_prb)*nsubframes, cell.nof_ports, mxCOMPLEX);
    outr1 = mxGetPr(plhs[1]);
    outi1 = mxGetPi(plhs[1]);
  }
  if (nlhs >= 3) {
    plhs[2] = mxCreateDoubleMatrix(nof_re * nsubframes, 1,  mxCOMPLEX);
    outr2 = mxGetPr(plhs[2]);
    outi2 = mxGetPi(plhs[2]);
  }
    
  for (int sf=0;sf<nsubframes;sf++) {
    /* Convert input to C complex type */
    for (i=0;i<nof_re;i++) {
      __real__ input_signal[i] = (float) *inr;
      if (ini) {
        __imag__ input_signal[i] = (float) *ini;
      }
      inr++;
      ini++;
    }
    
    if (nsubframes != 1) {
      sf_idx = sf%10;
    }
    
    if (chest_dl_estimate(&chest, input_signal, ce, sf_idx)) {
      mexErrMsgTxt("Error running channel estimator\n");
      return;
    }    
       
    if (cell.nof_ports == 1) {
      predecoding_single(&cheq, input_signal, ce[0], output_signal2, nof_re, chest_dl_get_noise_estimate(&chest));            
    } else {
      predecoding_diversity(&cheq, input_signal, ce, output_signal, cell.nof_ports, nof_re, chest_dl_get_noise_estimate(&chest));
      layerdemap_diversity(output_signal, output_signal2, cell.nof_ports, nof_re/cell.nof_ports);
    }
    
    if (nlhs >= 1) { 
      for (int j=0;j<cell.nof_ports;j++) {
        for (i=0;i<nof_re;i++) {      
          *outr0 = (double) crealf(ce[j][i]);
          if (outi0) {
            *outi0 = (double) cimagf(ce[j][i]);
          }
          outr0++;
          outi0++;
        } 
      }
    }
    if (nlhs >= 2) {    
      for (int j=0;j<cell.nof_ports;j++) {
        for (i=0;i<REFSIGNAL_NUM_SF(cell.nof_prb,j);i++) {
          *outr1 = (double) crealf(chest.pilot_estimates_average[j][i]);
          if (outi1) {
            *outi1 = (double) cimagf(chest.pilot_estimates_average[j][i]);
          }
          outr1++;
          outi1++;
        }
      }    
    }
    if (nlhs >= 3) {
      for (i=0;i<nof_re;i++) {      
        *outr2 = (double) crealf(output_signal2[i]);
        if (outi2) {
          *outi2 = (double) cimagf(output_signal2[i]);
        }
        outr2++;
        outi2++;
      }
    }
  }

  if (nlhs >= 4) {
    plhs[3] = mxCreateDoubleScalar(chest_dl_get_snr(&chest));
  }
  if (nlhs >= 5) {
    plhs[4] = mxCreateDoubleScalar(chest_dl_get_noise_estimate(&chest));
  }
  if (nlhs >= 6) {
    plhs[5] = mxCreateDoubleScalar(chest_dl_get_rsrp(&chest));
  }
  
  chest_dl_free(&chest);
  precoding_free(&cheq);

  return;
}
Example #12
0
/* the gateway function */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
  int i; 
  lte_cell_t cell; 
  pcfich_t pcfich;
  chest_dl_t chest; 
  lte_fft_t fft; 
  regs_t regs;
  uint32_t sf_idx; 
  cf_t *input_fft, *input_signal;
  
  if (nrhs != NOF_INPUTS) {
    help();
    return;
  }
    
  if (mexutils_read_cell(ENBCFG, &cell)) {
    help();
    return;
  }
  
  if (mexutils_read_uint32_struct(ENBCFG, "NSubframe", &sf_idx)) {
    help();
    return;
  }

  if (chest_dl_init(&chest, cell)) {
    mexErrMsgTxt("Error initializing equalizer\n");
    return;
  }

  if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) {
    mexErrMsgTxt("Error initializing FFT\n");
    return;
  }
  
  if (regs_init(&regs, cell)) {
    mexErrMsgTxt("Error initiating regs\n");
    return;
  }
  
  if (pcfich_init(&pcfich, &regs, cell)) {
    mexErrMsgTxt("Error creating PBCH object\n");
    return;
  }
      
  /** Allocate input buffers */
  if (mexutils_read_cf(INPUT, &input_signal) < 0) {
    mexErrMsgTxt("Error reading input signal\n");
    return; 
  }
  input_fft = vec_malloc(SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
  
  // Set Channel estimates to 1.0 (ignore fading) 
  cf_t *ce[MAX_PORTS];
  for (i=0;i<cell.nof_ports;i++) {
    ce[i] = vec_malloc(SF_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
  }
  
  lte_fft_run_sf(&fft, input_signal, input_fft);

  if (nrhs > NOF_INPUTS) {
    cf_t *cearray; 
    mexutils_read_cf(prhs[NOF_INPUTS], &cearray);
    for (i=0;i<cell.nof_ports;i++) {
      for (int j=0;j<SF_LEN_RE(cell.nof_prb, cell.cp);j++) {
        ce[i][j] = *cearray;
        cearray++;
      }
    }
  } else {
    chest_dl_estimate(&chest, input_fft, ce, sf_idx);    
  }
  float noise_power;
  if (nrhs > NOF_INPUTS + 1) {
    noise_power = mxGetScalar(prhs[NOF_INPUTS+1]);
  } else {
    noise_power = chest_dl_get_noise_estimate(&chest);
  }
    
    
  uint32_t cfi;
  float corr_res; 
  int n = pcfich_decode(&pcfich, input_fft, ce, noise_power,  sf_idx, &cfi, &corr_res);

  if (nlhs >= 1) { 
    if (n < 0) {      
      plhs[0] = mxCreateDoubleScalar(-1);
    } else {
      plhs[0] = mxCreateDoubleScalar(cfi);      
    }
  }
  if (nlhs >= 2) {
    mexutils_write_cf(pcfich.pcfich_d, &plhs[1], 16, 1);  
  }
  if (nlhs >= 3) {
    mexutils_write_cf(pcfich.pcfich_symbols[0], &plhs[2], 16, 1);  
  }
  
  chest_dl_free(&chest);
  lte_fft_free(&fft);
  pcfich_free(&pcfich);
  regs_free(&regs);
  
  for (i=0;i<cell.nof_ports;i++) {
    free(ce[i]);
  }
  free(input_signal);
  free(input_fft);
  
  return;
}
Example #13
0
/* Setup USRP or input file */
int iodev_init(iodev_t *q, iodev_cfg_t *config, lte_cell_t *cell, pbch_mib_t *mib) {
  
  if (config->input_file_name) {
    
    mib->phich_resources = R_1; 
    mib->phich_length = PHICH_NORM;
    
    cell->id = config->cell_id_file;
    cell->cp = CPNORM; 
    cell->nof_ports = config->nof_ports_file; 
    cell->nof_prb = config->nof_prb_file; 

    if (filesource_init(&q->fsrc, config->input_file_name, COMPLEX_FLOAT_BIN)) {
      return LIBLTE_ERROR;
    }
    q->mode = FILESOURCE;
    int symbol_sz = lte_symbol_sz(cell->nof_prb);
    if (symbol_sz > 0) {
      q->sf_len = SF_LEN(symbol_sz);      
    } else {
      fprintf(stderr, "Invalid number of PRB %d\n", cell->nof_prb);
      return LIBLTE_ERROR; 
    }

    q->input_buffer_file = vec_malloc(q->sf_len * sizeof(cf_t));
    if (!q->input_buffer_file) {
      perror("malloc");
      return LIBLTE_ERROR; 
    }
    q->sf_idx = 9; 
    
  } else {
#ifndef DISABLE_UHD
    printf("Opening UHD device...\n");
    if (cuhd_open(config->uhd_args, &q->uhd)) {
      fprintf(stderr, "Error opening uhd\n");
      return LIBLTE_ERROR;
    }
    
    cuhd_set_rx_gain(q->uhd, config->uhd_gain);

    /* set receiver frequency */
    cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq);

    cuhd_rx_wait_lo_locked(q->uhd);
    DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq);

    int n; 
    ue_celldetect_t cd;
    ue_celldetect_result_t found_cells[3];

    cf_t *buffer = vec_malloc(sizeof(cf_t) * 96000);
    if (!buffer) {
      perror("malloc");
      return LIBLTE_ERROR;
    }
    if (ue_celldetect_init(&cd)) {
      fprintf(stderr, "Error initiating UE cell detect\n");
      exit(-1);
    }
    n = find_cell(q->uhd, &cd, buffer, found_cells);
    if (n < 0) {
      fprintf(stderr, "Error searching cell\n");
      exit(-1);
    }

    int max_peak_cell = 0;
    float max_peak_value = -1.0;
    if (n > 0) {
      for (int i=0;i<3;i++) {
        if (found_cells[i].peak > max_peak_value) {
          max_peak_value = found_cells[i].peak;
          max_peak_cell = i;
        }
      }
      if (decode_pbch(q->uhd, buffer, &found_cells[max_peak_cell], 400, mib)) {
        fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", found_cells[max_peak_cell].cell_id);
        return LIBLTE_ERROR;
      }
    } else {
      fprintf(stderr, "Could not find any cell in this frequency\n");
      return LIBLTE_ERROR;
    }
    
    free(buffer);
    cell->cp = found_cells[max_peak_cell].cp;
    cell->id = found_cells[max_peak_cell].cell_id;
    cell->nof_prb = mib->nof_prb;
    cell->nof_ports = mib->nof_ports; 
    
    /* set sampling frequency */
    int srate = lte_sampling_freq_hz(cell->nof_prb);
    if (srate != -1) {  
      cuhd_set_rx_srate(q->uhd, (double) srate);      
    } else {
      fprintf(stderr, "Invalid number of PRB %d\n", cell->nof_prb);
      return LIBLTE_ERROR;
    }

    DEBUG("Starting receiver...\n", 0);
    cuhd_start_rx_stream(q->uhd);
    
    if (ue_sync_init(&q->sframe, *cell, cuhd_recv_wrapper, q->uhd)) {
      fprintf(stderr, "Error initiating ue_sync\n");
      return LIBLTE_ERROR; 
    }

    /* Decodes the SSS signal during the tracking phase. Extra overhead, but makes sure we are in the correct subframe */  
    ue_sync_decode_sss_on_track(&q->sframe, true);

    // Here, the subframe length and input buffer is managed by ue_sync
    q->mode = UHD; 
  
#else
    printf("Error UHD not available. Select an input file\n");
    return LIBLTE_ERROR;
#endif
  }
  
  memcpy(&q->config, config, sizeof(iodev_cfg_t));
  
  return LIBLTE_SUCCESS;
}