Пример #1
0
int pbch_cp(cf_t *input, cf_t *output, int nof_prb, lte_cp_t cp, int cell_id,
    bool put) {
  int i;
  cf_t *ptr;
  assert(cell_id >= 0);
  if (put) {
    ptr = input;
    output += nof_prb * RE_X_RB / 2 - 36;
  } else {
    ptr = output;
    input += nof_prb * RE_X_RB / 2 - 36;
  }

  /* symbol 0 & 1 */
  for (i = 0; i < 2; i++) {
    prb_cp_ref(&input, &output, cell_id % 3, 4, 6, put);
  }
  /* symbols 2 & 3 */
  if (CP_ISNORM(cp)) {
    for (i = 0; i < 2; i++) {
      prb_cp(&input, &output, 6);
    }
  } else {
    prb_cp(&input, &output, 6);
    prb_cp_ref(&input, &output, cell_id % 3, 4, 6, put);
  }
  if (put) {
    return input - ptr;
  } else {
    return output - ptr;
  }
}
Пример #2
0
/**
 * Returns the number of REGs in a PRB
 * 36.211 Section 6.2.4
 */
int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, lte_cp_t cp) {

  switch (symbol) {
  case 0:
    return 2;
  case 1:
    switch (nof_port) {
    case 1:
    case 2:
      return 3;
    case 4:
      return 2;
    default:
      return LIBLTE_ERROR;
    }
    break;
  case 2:
    return 3;
  case 3:
    if (CP_ISNORM(cp)) {
      return 3;
    } else {
      return 2;
    }
  default:
    return LIBLTE_ERROR;
  }
}
Пример #3
0
/* Returns 1 if the SSS is found, 0 if not and -1 if there is not enough space 
 * to correlate
 */
int sync_sss(sync_t *q, cf_t *input, uint32_t peak_pos, lte_cp_t cp) {
  int sss_idx, ret;

  sss_synch_set_N_id_2(&q->sss, q->N_id_2);

  /* Make sure we have enough room to find SSS sequence */
  sss_idx = (int) peak_pos-2*q->fft_size-CP(q->fft_size, (CP_ISNORM(q->cp)?CPNORM_LEN:CPEXT_LEN));
  if (sss_idx < 0) {
    INFO("Not enough room to decode CP SSS (sss_idx=%d, peak_pos=%d)\n", sss_idx, peak_pos);
    return LIBLTE_ERROR;
  }
  DEBUG("Searching SSS around sss_idx: %d, peak_pos: %d\n", sss_idx, peak_pos);
      
  switch(q->sss_alg) {
    case SSS_DIFF:
      sss_synch_m0m1_diff(&q->sss, &input[sss_idx], &q->m0, &q->m0_value, &q->m1, &q->m1_value);
      break;
    case SSS_PARTIAL_3:
      sss_synch_m0m1_partial(&q->sss, &input[sss_idx], 3, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value);
      break;
    case SSS_FULL:
      sss_synch_m0m1_partial(&q->sss, &input[sss_idx], 1, NULL, &q->m0, &q->m0_value, &q->m1, &q->m1_value);
      break;
  }

  q->sf_idx = sss_synch_subframe(q->m0, q->m1);
  ret = sss_synch_N_id_1(&q->sss, q->m0, q->m1);
  if (ret >= 0) {
    q->N_id_1 = (uint32_t) ret;
    DEBUG("SSS detected N_id_1=%d, sf_idx=%d, %s CP\n",
      q->N_id_1, q->sf_idx, CP_ISNORM(q->cp)?"Normal":"Extended");
    return 1;
  } else {
    q->N_id_1 = 1000;
    return LIBLTE_SUCCESS;
  }
}
Пример #4
0
int pbch_cp(cf_t *input, cf_t *output, lte_cell_t cell, bool put) {
  int i;
  cf_t *ptr;

  if (put) {
    ptr = input;
    output += cell.nof_prb * RE_X_RB / 2 - 36;
  } else {
    ptr = output;
    input += cell.nof_prb * RE_X_RB / 2 - 36;
  }
  
  /* symbol 0 & 1 */
  for (i = 0; i < 2; i++) {
    prb_cp_ref(&input, &output, cell.id % 3, 4, 4*6, put);
    if (put) {
      output += cell.nof_prb * RE_X_RB - 2*36;
    } else {
      input += cell.nof_prb * RE_X_RB - 2*36;
    }
  }
  /* symbols 2 & 3 */
  if (CP_ISNORM(cell.cp)) {
    for (i = 0; i < 2; i++) {
      prb_cp(&input, &output, 6);
      if (put) {
        output += cell.nof_prb * RE_X_RB - 2*36;
      } else {
        input += cell.nof_prb * RE_X_RB - 2*36;
      }
    }
  } else {
    prb_cp(&input, &output, 6);
    if (put) {
      output += cell.nof_prb * RE_X_RB - 2*36;
    } else {
      input += cell.nof_prb * RE_X_RB - 2*36;
    }
    prb_cp_ref(&input, &output, cell.id % 3, 4, 4*6, put);
  }
  if (put) {
    return input - ptr;
  } else {
    return output - ptr;
  }
}
Пример #5
0
/** Initializes the PBCH transmitter and receiver. 
 * At the receiver, the field nof_ports in the cell structure indicates the 
 * maximum number of BS transmitter ports to look for.  
 */
int pbch_init(pbch_t *q, lte_cell_t cell) {
  int ret = LIBLTE_ERROR_INVALID_INPUTS;

  if (q                       != NULL &&
      lte_cell_isvalid(&cell))
  {
    ret = LIBLTE_ERROR;

    bzero(q, sizeof(pbch_t));
    q->cell = cell;

    if (modem_table_lte(&q->mod, LTE_QPSK, true)) {
      goto clean;
    }
    demod_soft_init(&q->demod);
    demod_soft_table_set(&q->demod, &q->mod);
    demod_soft_alg_set(&q->demod, APPROX);
    if (sequence_pbch(&q->seq_pbch, q->cell.cp, q->cell.id)) {
      goto clean;
    }

    uint32_t poly[3] = { 0x6D, 0x4F, 0x57 };
    if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) {
      goto clean;
    }
    if (crc_init(&q->crc, LTE_CRC16, 16)) {
      goto clean;
    }
    q->encoder.K = 7;
    q->encoder.R = 3;
    q->encoder.tail_biting = true;
    memcpy(q->encoder.poly, poly, 3 * sizeof(int));

    q->nof_symbols = (CP_ISNORM(q->cell.cp)) ? PBCH_RE_CPNORM : PBCH_RE_CPEXT;

    q->pbch_d = malloc(sizeof(cf_t) * q->nof_symbols);
    if (!q->pbch_d) {
      goto clean;
    }
    int i;
    for (i = 0; i < q->cell.nof_ports; i++) {
      q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols);
      if (!q->ce[i]) {
        goto clean;
      }
      q->pbch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols);
      if (!q->pbch_x[i]) {
        goto clean;
      }
      q->pbch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols);
      if (!q->pbch_symbols[i]) {
        goto clean;
      }
    }
    q->pbch_llr = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
    if (!q->pbch_llr) {
      goto clean;
    }
    q->temp = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
    if (!q->temp) {
      goto clean;
    }
    q->pbch_rm_f = malloc(sizeof(float) * 120);
    if (!q->pbch_rm_f) {
      goto clean;
    }
    q->pbch_rm_b = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
    if (!q->pbch_rm_b) {
      goto clean;
    }
    q->data = malloc(sizeof(char) * 40);
    if (!q->data) {
      goto clean;
    }
    q->data_enc = malloc(sizeof(char) * 120);
    if (!q->data_enc) {
      goto clean;
    }
    ret = LIBLTE_SUCCESS;
  }
clean: 
  if (ret == LIBLTE_ERROR) {
    pbch_free(q);
  }
  return ret;
}
Пример #6
0
int main(int argc, char **argv) {
  int N_id_2, ns, find_ns;
  cf_t *buffer, *fft_buffer;
  cf_t pss_signal[PSS_LEN];
  float sss_signal0[SSS_LEN]; // for subframe 0
  float sss_signal5[SSS_LEN]; // for subframe 5
  int cid, max_cid; 
  uint32_t find_idx;
  sync_t sync;
  lte_fft_t ifft;

  parse_args(argc, argv);

  buffer = malloc(sizeof(cf_t) * FLEN);
  if (!buffer) {
    perror("malloc");
    exit(-1);
  }

  fft_buffer = malloc(sizeof(cf_t) * 2 * FLEN);
  if (!fft_buffer) {
    perror("malloc");
    exit(-1);
  }

  if (lte_ifft_init(&ifft, cp, 6)) {
    fprintf(stderr, "Error creating iFFT object\n");
    exit(-1);
  }

  if (sync_init(&sync, FLEN, 128, 128)) {
    fprintf(stderr, "Error initiating PSS/SSS\n");
    return -1;
  }

  sync_set_threshold(&sync, 1, 1);

  if (cell_id == -1) {
    cid = 0;
    max_cid = 49;
  } else {
    cid = cell_id;
    max_cid = cell_id;
}
  while(cid <= max_cid) {
    N_id_2 = cid%3;

    /* Generate PSS/SSS signals */
    pss_generate(pss_signal, N_id_2);
    sss_generate(sss_signal0, sss_signal5, cid);

    for (ns=0;ns<2;ns++) {
      memset(buffer, 0, sizeof(cf_t) * FLEN);
      pss_put_slot(pss_signal, buffer, 6, cp);
      sss_put_slot(ns?sss_signal5:sss_signal0, buffer, 6, cp);

      /* Transform to OFDM symbols */
      memset(fft_buffer, 0, sizeof(cf_t) * 2 * FLEN);
      lte_ifft_run_slot(&ifft, buffer, &fft_buffer[offset]);

      sync_find(&sync, fft_buffer, &find_idx);
      find_ns = sync_get_slot_id(&sync);
      printf("cell_id: %d find: %d, offset: %d, ns=%d find_ns=%d\n", cid, find_idx, offset,
          ns, find_ns);
      if (find_idx != offset + 960) {
        printf("offset != find_offset: %d != %d\n", find_idx, offset + 960);
        exit(-1);
      }
      if (ns*10 != find_ns) {
        printf("ns != find_ns\n", 10 * ns, find_ns);
        exit(-1);
      }
      if (sync_get_cp(&sync) != cp) {
        printf("Detected CP should be %s\n", CP_ISNORM(cp)?"Normal":"Extended");
        exit(-1);
      }
    }
    cid++;
  }

  free(fft_buffer);
  free(buffer);

  sync_free(&sync);
  lte_ifft_free(&ifft);

  printf("Ok\n");
  exit(0);
}
Пример #7
0
/**
 * Initializes REGs structure.
 * Sets all REG indices and initializes PCFICH, PHICH and PDCCH REGs
 * Returns 0 if OK, -1 on error
 */
int regs_init(regs_t *h, phich_resources_t phich_res, phich_length_t phich_len, lte_cell_t cell) {
  int ret = LIBLTE_ERROR_INVALID_INPUTS;
  uint32_t i, k;
  uint32_t j[4], jmax, prb;
  uint32_t n[4], vo;
  uint32_t max_ctrl_symbols;

  if (h != NULL &&
      lte_cell_isvalid(&cell))
  {
    bzero(h, sizeof(regs_t));
    ret = LIBLTE_ERROR;
    
    max_ctrl_symbols = cell.nof_prb<10?4:3;
    vo = cell.id % 3;
    h->cell = cell;
    h->max_ctrl_symbols = max_ctrl_symbols;
    h->cfi_initiated = false;
    h->phich_res = phich_res;
    h->phich_len = phich_len;

    h->nof_regs = 0;
    for (i = 0; i < max_ctrl_symbols; i++) {
      n[i] = regs_num_x_symbol(i, h->cell.nof_ports, h->cell.cp);
      if (n[i] == -1) {
        return -1;
      }
      h->nof_regs += h->cell.nof_prb * n[i];
    }
    INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s\n", h->nof_regs, h->cell.id, h->cell.nof_prb,
        CP_ISNORM(h->cell.cp)?"Normal":"Extended");
    h->regs = malloc(sizeof(regs_reg_t) * h->nof_regs);
    if (!h->regs) {
      perror("malloc");
      goto clean_and_exit;
    }

    /* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */
    bzero(j, sizeof(int) * 4);
    k = i = prb = jmax = 0;
    while (k < h->nof_regs) {
      if (n[i] == 3 || (n[i] == 2 && jmax != 1)) {
        if (regs_reg_init(&h->regs[k], i, j[i], prb * RE_X_RB, n[i], vo)) {
          fprintf(stderr, "Error initializing REGs\n");
          goto clean_and_exit;
        }
        /*DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)\n", k, i, prb, j[i],
            h->regs[k].k0);
        */
        j[i]++;
        k++;
      }
      i++;
      if (i == max_ctrl_symbols) {
        i = 0;
        jmax++;
      }
      if (jmax == 3) {
        prb++;
        bzero(j, sizeof(int) * 4);
        jmax = 0;
      }
    }
    if (regs_pcfich_init(h)) {
      fprintf(stderr, "Error initializing PCFICH REGs\n");
      goto clean_and_exit;
    }

    if (regs_phich_init(h)) {
      fprintf(stderr, "Error initializing PHICH REGs\n");
      goto clean_and_exit;
    }
    if (regs_pdcch_init(h)) {
      fprintf(stderr, "Error initializing PDCCH REGs\n");
      goto clean_and_exit;
    }

    ret = LIBLTE_SUCCESS;
  }
clean_and_exit:
  if (ret == LIBLTE_ERROR) {
    regs_free(h);
  }
  return ret;
}
Пример #8
0
int main(int argc, char **argv) {
	phich_t phich;
	regs_t regs;
	int i, j;
	cf_t *ce[MAX_PORTS_CTRL];
	int nof_re;
	cf_t *slot_symbols[MAX_PORTS_CTRL];
	char ack[50][PHICH_NORM_NSEQUENCES], ack_rx;
	int nsf, distance;
	int cid, max_cid;
	int ngroup, nseq, max_nseq;

	parse_args(argc,argv);

	max_nseq = CP_ISNORM(cp)?PHICH_NORM_NSEQUENCES:PHICH_EXT_NSEQUENCES;

	nof_re = CPNORM_NSYMB * nof_prb * RE_X_RB;

	/* init memory */
	for (i=0;i<MAX_PORTS_CTRL;i++) {
		ce[i] = malloc(sizeof(cf_t) * nof_re);
		if (!ce[i]) {
			perror("malloc");
			exit(-1);
		}
		for (j=0;j<nof_re;j++) {
			ce[i][j] = 1;
		}
		slot_symbols[i] = malloc(sizeof(cf_t) * nof_re);
		if (!slot_symbols[i]) {
			perror("malloc");
			exit(-1);
		}
	}

	if (cell_id == -1) {
		cid = 0;
		max_cid = 503;
	} else {
		cid = cell_id;
		max_cid = cell_id;
	}
	while(cid <= max_cid) {

		printf("Testing CellID=%d...\n", cid);

		if (regs_init(&regs, cid, nof_prb, nof_ports, phich_res, phich_length, cp)) {
			fprintf(stderr, "Error initiating regs\n");
			exit(-1);
		}

		if (phich_init(&phich, &regs, cid, nof_prb, nof_ports, cp)) {
			fprintf(stderr, "Error creating PBCH object\n");
			exit(-1);
		}

		for (nsf=0;nsf<10;nsf++) {

			phich_reset(&phich, slot_symbols);

			/* Transmit all PHICH groups and sequence numbers */
			for (ngroup=0;ngroup<phich_ngroups(&phich);ngroup++) {
				for (nseq=0;nseq<max_nseq;nseq++) {

					ack[ngroup][nseq] = rand()%2;

					phich_encode(&phich, ack[ngroup][nseq], ngroup, nseq, nsf, slot_symbols);
				}
			}
			/* combine outputs */
			for (i=1;i<nof_ports;i++) {
				for (j=0;j<nof_re;j++) {
					slot_symbols[0][j] += slot_symbols[i][j];
				}
			}

			/* Receive all PHICH groups and sequence numbers */
			for (ngroup=0;ngroup<phich_ngroups(&phich);ngroup++) {
				for (nseq=0;nseq<max_nseq;nseq++) {

					if (phich_decode(&phich, slot_symbols[0], ce, ngroup, nseq, nsf, &ack_rx, &distance)<0) {
						printf("Error decoding ACK\n");
						exit(-1);
					}
					INFO("%d/%d, ack_tx: %d, ack_rx: %d, ns: %d, distance: %d\n",
							ngroup, nseq, ack[ngroup][nseq], ack_rx, nsf, distance);
					if (ack[ngroup][nseq] != ack_rx) {
						printf("Invalid received ACK: %d!=%d\n", ack[ngroup][nseq], ack_rx);
						exit(-1);
					}
					if (distance) {
						printf("Error\n");
						exit(-1);
					}
				}
			}
		}
		phich_free(&phich);
		regs_free(&regs);
		cid++;
	}

	for (i=0;i<MAX_PORTS_CTRL;i++) {
		free(ce[i]);
		free(slot_symbols[i]);
	}
	printf("OK\n");
	exit(0);
}
Пример #9
0
int main(int argc, char **argv) {
	int distance;
	int i, n;
	int ngroup, nseq, max_nseq;
	char ack_rx;

	if (argc < 3) {
		usage(argv[0]);
		exit(-1);
	}

	parse_args(argc,argv);

	max_nseq = CP_ISNORM(cp)?PHICH_NORM_NSEQUENCES:PHICH_EXT_NSEQUENCES;

	if (base_init()) {
		fprintf(stderr, "Error initializing memory\n");
		exit(-1);
	}

	n = filesource_read(&fsrc, input_buffer, flen);

	lte_fft_run(&fft, input_buffer, fft_buffer);

	if (fmatlab) {
		fprintf(fmatlab, "infft=");
		vec_fprint_c(fmatlab, input_buffer, flen);
		fprintf(fmatlab, ";\n");

		fprintf(fmatlab, "outfft=");
		vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cp) * nof_prb * RE_X_RB);
		fprintf(fmatlab, ";\n");
	}

	/* Get channel estimates for each port */
	for (i=0;i<nof_ports;i++) {
		chest_ce_slot_port(&chest, fft_buffer, ce[i], 0, i);
		if (fmatlab) {
			chest_fprint(&chest, fmatlab, 0, i);
		}
	}

	INFO("Decoding PHICH\n", 0);

	/* Receive all PHICH groups and sequence numbers */
	for (ngroup=0;ngroup<phich_ngroups(&phich);ngroup++) {
		for (nseq=0;nseq<max_nseq;nseq++) {

			if (phich_decode(&phich, fft_buffer, ce, ngroup, nseq, numsubframe, &ack_rx, &distance)<0) {
				printf("Error decoding ACK\n");
				exit(-1);
			}

			INFO("%d/%d, ack_rx: %d, ns: %d, distance: %d\n",
					ngroup, nseq, ack_rx, numsubframe, distance);
		}
	}

	base_free();
	fftwf_cleanup();

	if (n < 0) {
		fprintf(stderr, "Error decoding phich\n");
		exit(-1);
	} else if (n == 0) {
		printf("Could not decode phich\n");
		exit(-1);
	} else {
		exit(0);
	}
}
Пример #10
0
/** Initializes the PBCH transmitter and receiver */
int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) {
  int ret = -1;
  if (cell_id < 0) {
    return -1;
  }
  bzero(q, sizeof(pbch_t));
  q->cell_id = cell_id;
  q->cp = cp;
  q->nof_prb = nof_prb;

  if (modem_table_std(&q->mod, LTE_QPSK, true)) {
    goto clean;
  }
  demod_soft_init(&q->demod);
  demod_soft_table_set(&q->demod, &q->mod);
  demod_soft_alg_set(&q->demod, APPROX);
  if (sequence_pbch(&q->seq_pbch, q->cp, q->cell_id)) {
    goto clean;
  }

  int poly[3] = { 0x6D, 0x4F, 0x57 };
  if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) {
    goto clean;
  }
  if (crc_init(&q->crc, LTE_CRC16, 16)) {
    goto clean;
  }
  q->encoder.K = 7;
  q->encoder.R = 3;
  q->encoder.tail_biting = true;
  memcpy(q->encoder.poly, poly, 3 * sizeof(int));

  q->nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM : PBCH_RE_CPEXT;

  q->pbch_d = malloc(sizeof(cf_t) * q->nof_symbols);
  if (!q->pbch_d) {
    goto clean;
  }
  int i;
  for (i = 0; i < MAX_PORTS_CTRL; i++) {
    q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols);
    if (!q->ce[i]) {
      goto clean;
    }
    q->pbch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols);
    if (!q->pbch_x[i]) {
      goto clean;
    }
    q->pbch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols);
    if (!q->pbch_symbols[i]) {
      goto clean;
    }
  }
  q->pbch_llr = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
  if (!q->pbch_llr) {
    goto clean;
  }
  q->temp = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
  if (!q->temp) {
    goto clean;
  }
  q->pbch_rm_f = malloc(sizeof(float) * 120);
  if (!q->pbch_rm_f) {
    goto clean;
  }
  q->pbch_rm_b = malloc(sizeof(float) * q->nof_symbols * 4 * 2);
  if (!q->pbch_rm_b) {
    goto clean;
  }
  q->data = malloc(sizeof(char) * 40);
  if (!q->data) {
    goto clean;
  }
  q->data_enc = malloc(sizeof(char) * 120);
  if (!q->data_enc) {
    goto clean;
  }

  ret = 0;
  clean: if (ret == -1) {
    pbch_free(q);
  }
  return ret;
}
Пример #11
0
int sync_run(sync_t *q, cf_t *input) {
  int N_id_2, peak_pos[3], sss_idx_n, sss_idx_e;
  int m0, m1;
  float m0_value_e, m1_value_e,m0_value_n, m1_value_n;
  int slot_id_e, N_id_1_e, slot_id_n, N_id_1_n;
  float peak_value[3];
  float mean_value[3];
  float max=-999;
  int i;
  int peak_detected;

  if (q->force_N_id_2 == -1) {
    for (N_id_2=0;N_id_2<3;N_id_2++) {
      peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input,
          &peak_value[N_id_2], &mean_value[N_id_2]);
    }
    for (i=0;i<3;i++) {
      if (peak_value[i] > max) {
        max = peak_value[i];
        N_id_2 = i;
      }
    }
  } else {
    N_id_2 = q->force_N_id_2;
    peak_pos[N_id_2] = pss_synch_find_pss(&q->pss[N_id_2], input,
        &peak_value[N_id_2], &mean_value[N_id_2]);
  }

  q->peak_to_avg = peak_value[N_id_2] / mean_value[N_id_2];

  DEBUG("PSS possible peak N_id_2=%d, pos=%d peak=%.2f par=%.2f threshold=%.2f\n",
      N_id_2, peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold);

  /* If peak detected */
  peak_detected = 0;
  if (peak_pos[N_id_2] - 128 >= 0) {
    if (q->pss_mode == ABSOLUTE) {
      if (peak_value[N_id_2] > q->threshold) {
        peak_detected = 1;
      }
    } else {
      if (q->peak_to_avg  > q->threshold) {
        peak_detected = 1;
      }
    }
  }
  if (peak_detected) {

    q->cfo = pss_synch_cfo_compute(&q->pss[N_id_2], &input[peak_pos[N_id_2]-128]);

    INFO("PSS peak detected N_id_2=%d, pos=%d peak=%.2f par=%.2f th=%.2f cfo=%.4f\n", N_id_2,
        peak_pos[N_id_2], peak_value[N_id_2], q->peak_to_avg, q->threshold, q->cfo);

    if (q->sss_en) {

      /* Make sure we have enough room to find SSS sequence */
      sss_idx_n = peak_pos[N_id_2]-2*(128+CP(128,CPNORM_LEN));
      sss_idx_e = peak_pos[N_id_2]-2*(128+CP(128,CPEXT_LEN));

      if (q->detect_cp) {
        if (sss_idx_n < 0 || sss_idx_e < 0) {
          INFO("Not enough room to decode SSS (%d, %d)\n", sss_idx_n, sss_idx_e);
          return -1;
        }
      } else {
        if (CP_ISNORM(q->cp)) {
          if (sss_idx_n < 0) {
            INFO("Not enough room to decode SSS (%d)\n", sss_idx_n);
            return -1;
          }
        } else {
          if (sss_idx_e < 0) {
            INFO("Not enough room to decode SSS (%d)\n", sss_idx_e);
            return -1;
          }
        }
      }
      N_id_1_e = -1;
      N_id_1_n = -1;
      slot_id_e = -1;
      slot_id_n = -1;
      /* try Normal CP length */
      if (q->detect_cp || CP_ISNORM(q->cp)) {
        sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_n],
            &m0, &m0_value_n, &m1, &m1_value_n);

        slot_id_n = 2 * sss_synch_subframe(m0, m1);
        N_id_1_n = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1);
      }

      if (q->detect_cp || CP_ISEXT(q->cp)) {
        /* Now try Extended CP length */
        sss_synch_m0m1(&q->sss[N_id_2], &input[sss_idx_e],
            &m0, &m0_value_e, &m1, &m1_value_e);

        slot_id_e = 2 * sss_synch_subframe(m0, m1);
        N_id_1_e = sss_synch_N_id_1(&q->sss[N_id_2], m0, m1);
      }

      /* Correlation with extended CP hypoteshis is greater than with normal? */
      if ((q->detect_cp && m0_value_e * m1_value_e > m0_value_n * m1_value_n)
          || CP_ISEXT(q->cp)) {
        q->cp = CPEXT;
        q->slot_id = slot_id_e;
        q->N_id_1 = N_id_1_e;
      /* then is normal CP */
      } else {
        q->cp = CPNORM;
        q->slot_id = slot_id_n;
        q->N_id_1 = N_id_1_n;
      }
      q->N_id_2 = N_id_2;

      INFO("SSS detected N_id_1=%d, slot_idx=%d, %s CP\n",
          q->N_id_1, q->slot_id, CP_ISNORM(q->cp)?"Normal":"Extended");
    }

    return peak_pos[N_id_2];

  } else {
    return -1;
  }
}