/** * 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; }
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); } }
/** * 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; }
/** 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; }
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; } }