Ejemplo n.º 1
0
/**
 * Resets the PHICH symbols
 *
 * Returns the number of written symbols, or -1 on error
 */
int regs_phich_reset(regs_t *h, cf_t *slot_symbols) {
  uint32_t i;
  uint32_t ngroup, ng;
  for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cell.cp)?ngroup+=2:ngroup++) {
    if (CP_ISEXT(h->cell.cp)) {
      ng = ngroup/2;
    } else {
      ng = ngroup;
    }
    regs_ch_t *rch = &h->phich[ng];
    for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) {
      regs_reset_reg(rch->regs[i], slot_symbols, h->cell.nof_prb);
    }
  }
  return LIBLTE_SUCCESS;
}
Ejemplo n.º 2
0
void regs_phich_free(regs_t *h) {
  uint32_t i;
  if (h->phich) {
    if (CP_ISEXT(h->cell.cp)) {
      h->ngroups_phich /= 2;
    }
    for (i=0;i<h->ngroups_phich;i++) {
      if (h->phich[i].regs) {
        free(h->phich[i].regs);
      }
    }
    free(h->phich);
  }
}
Ejemplo n.º 3
0
/**
 * Gets the PHICH symbols from the resource grid pointed by slot_symbols
 *
 * Returns the number of written symbols, or -1 on error
 */
int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngroup) {
  uint32_t i;
  if (ngroup >= h->ngroups_phich) {
    fprintf(stderr, "Error invalid ngroup %d\n", ngroup);
    return LIBLTE_ERROR_INVALID_INPUTS;
  }
  if (CP_ISEXT(h->cell.cp)) {
    ngroup /= 2;
  }
  regs_ch_t *rch = &h->phich[ngroup];
  for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) {
    regs_get_reg(rch->regs[i], slot_symbols, &phich_symbols[i*REGS_RE_X_REG], h->cell.nof_prb);
  }
  return i*REGS_RE_X_REG;
}
Ejemplo n.º 4
0
/** Initialize REGs for PHICH
 * 36.211 10.3 section 6.9.3
 */
int regs_phich_init(regs_t *h) {
  float ng;
  uint32_t i, ni, li, n[3], nreg, mi;
  regs_reg_t **regs_phich[3];
  int ret = LIBLTE_ERROR;

  switch(h->phich_res) {
  case R_1_6:
    ng = (float) 1/6;
    break;
  case R_1_2:
    ng = (float) 1/2;
    break;
  case R_1:
    ng = 1;
    break;
  case R_2:
    ng = 2;
    break;
  default:
    ng = 0;
    break;
  }
  h->ngroups_phich = (int) ceilf(ng * ((float) h->cell.nof_prb/8));
  h->phich = malloc(sizeof(regs_ch_t) * h->ngroups_phich);
  if (!h->phich) {
    perror("malloc");
    return -1;
  }
  INFO("Creating %d PHICH mapping units. %s length, Ng=%.2f\n",h->ngroups_phich,
      h->phich_len==PHICH_EXT?"Extended":"Normal",ng);
  for (i=0;i<h->ngroups_phich;i++) {
    h->phich[i].nof_regs = REGS_PHICH_REGS_X_GROUP;
    h->phich[i].regs = malloc(sizeof(regs_reg_t*) * REGS_PHICH_REGS_X_GROUP);
    if (!h->phich[i].regs) {
      perror("malloc");
      goto clean_and_exit;
    }
  }

  /** Here begins the mapping algorithm */

  /* Step 2. Count REGs not assigned to PCFICH */
  bzero(n, 3*sizeof(int));
  for (i=0;i<h->nof_regs;i++) {
    if (h->regs[i].l < 3 && !h->regs[i].assigned) {
      n[h->regs[i].l]++;
    }
  }

  bzero(regs_phich, sizeof(regs_reg_t*) * 3);
  for (i=0;i<3;i++) {
    regs_phich[i] = malloc(n[i] * sizeof(regs_reg_t*));
    if (!regs_phich[i]) {
      perror("malloc");
      goto clean_and_exit;
    }
  }

  bzero(n, 3 * sizeof(int));
  /* Step 3. Number REGs not assigned to PCFICH */
  for (i=0;i<h->nof_regs;i++) {
    // they are already sorted starting from the REG with the lowest frequency-domain index
    if (h->regs[i].l < 3 && !h->regs[i].assigned) {
      regs_phich[h->regs[i].l][n[h->regs[i].l]++] = &h->regs[i];
    }
  }

  nreg=0;
  for (mi=0;mi<h->ngroups_phich;mi++) { // here ngroups is the number of mapping units
    for (i=0;i<3;i++) {
      li=h->phich_len==PHICH_EXT?i:0; // Step 7
      ni=((h->cell.id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8
      h->phich[mi].regs[i] = regs_phich[li][ni];
      h->phich[mi].regs[i]->assigned = true;
      INFO("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li);
      nreg++;
    }
  }

  // now the number of mapping units = number of groups for normal cp. For extended cp
  // ngroups = 2 * number mapping units
  if (CP_ISEXT(h->cell.cp)) {
    h->ngroups_phich *= 2;
  }
  ret = LIBLTE_SUCCESS;

clean_and_exit:
  if (ret == LIBLTE_ERROR) {
    if (h->phich) {
      for (i=0;i<h->ngroups_phich;i++) {
        if (h->phich[i].regs) {
          free(h->phich[i].regs);
        }
      }
      free(h->phich);
    }
  }
  for (i=0;i<3;i++) {
    if (regs_phich[i]) {
      free(regs_phich[i]);
    }
  }
  return ret;
}
Ejemplo n.º 5
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;
  }
}