/* 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; } }
/* In this function, input points to the beginning of the subframe. Saves result in subframe_idx and N_id_1 * Return 1 if the sequence was found, 0 if the peak is not found, -1 if the subframe_sz or symbol_sz are * invalid or not configured. * Before calling this function, the correlation threshold and symbol size duration need to be set * using sss_synch_set_threshold() and sss_synch_set_symbol_sz(). */ int sss_synch_frame(sss_synch_t *q, cf_t *input, int *subframe_idx, int *N_id_1) { int m0,m1; float m0_value, m1_value; if (q->subframe_sz <= 0 || q->symbol_sz <= 0) { return -1; } sss_synch_m0m1(q, &input[SSS_SYMBOL_ST(q->subframe_sz, q->symbol_sz)], &m0, &m0_value, &m1, &m1_value); if (m0_value > q->corr_peak_threshold && m1_value > q->corr_peak_threshold) { if (subframe_idx) { *subframe_idx = sss_synch_subframe(m0, m1); } if (N_id_1) { *N_id_1 = sss_synch_N_id_1(q, m0, m1); } return 1; } else { return 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; } }