void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) { float gain_db = 10*log10(q->gain); float gain_uhd_db = 1.0; //float gain_uhd = 1.0; float y = 0; // Apply current gain to input signal if (!q->uhd_handler) { srslte_vec_sc_prod_cfc(signal, q->gain, signal, len); } else { if (q->gain < 1) { q->gain = 1.0; } if (isinf(gain_db) || isnan(gain_db)) { q->gain = 10.0; } else { gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db); q->gain = pow(10, gain_uhd_db/10); } } float *t; switch(q->mode) { case SRSLTE_AGC_MODE_ENERGY: y = sqrtf(crealf(srslte_vec_dot_prod_conj_ccc(signal, signal, len))/len); break; case SRSLTE_AGC_MODE_PEAK_AMPLITUDE: t = (float*) signal; y = t[srslte_vec_max_fi(t, 2*len)];// take only positive max to avoid abs() (should be similar) break; default: fprintf(stderr, "Unsupported AGC mode\n"); return; } if (q->nof_frames > 0) { q->y_tmp[q->frame_cnt++] = y; if (q->frame_cnt == q->nof_frames) { q->frame_cnt = 0; switch(q->mode) { case SRSLTE_AGC_MODE_ENERGY: y = srslte_vec_acc_ff(q->y_tmp, q->nof_frames)/q->nof_frames; break; case SRSLTE_AGC_MODE_PEAK_AMPLITUDE: y = q->y_tmp[srslte_vec_max_fi(q->y_tmp, q->nof_frames)]; break; default: fprintf(stderr, "Unsupported AGC mode\n"); return; } } } double gg = 1.0; if (q->isfirst) { q->y_out = y; q->isfirst = false; } else { if (q->frame_cnt == 0) { q->y_out = (1-q->bandwidth) * q->y_out + q->bandwidth * y; if (!q->lock) { gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target)); q->gain *= gg; } INFO("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg); } } }
int srslte_prach_detect_offset(srslte_prach_t *p, uint32_t freq_offset, cf_t *signal, uint32_t sig_len, uint32_t *indices, float *t_offsets, float *peak_to_avg, uint32_t *n_indices) { int ret = SRSLTE_ERROR; if(p != NULL && signal != NULL && sig_len > 0 && indices != NULL) { if(sig_len < p->N_ifft_prach){ fprintf(stderr, "srslte_prach_detect: Signal length is %d and should be %d\n", sig_len, p->N_ifft_prach); return SRSLTE_ERROR_INVALID_INPUTS; } // FFT incoming signal srslte_dft_run(p->fft, signal, p->signal_fft); *n_indices = 0; // Extract bins of interest uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul); uint32_t k_0 = freq_offset*N_RB_SC - N_rb_ul*N_RB_SC/2 + p->N_ifft_ul/2; uint32_t K = DELTA_F/DELTA_F_RA; uint32_t begin = PHI + (K*k_0) + (K/2); memcpy(p->prach_bins, &p->signal_fft[begin], p->N_zc*sizeof(cf_t)); for(int i=0;i<p->N_roots;i++){ cf_t *root_spec = p->dft_seqs[p->root_seqs_idx[i]]; srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc); srslte_dft_run(p->zc_ifft, p->corr_spec, p->corr_spec); srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc); float corr_ave = srslte_vec_acc_ff(p->corr, p->N_zc)/p->N_zc; uint32_t winsize = 0; if(p->N_cs != 0){ winsize = p->N_cs; }else{ winsize = p->N_zc; } uint32_t n_wins = p->N_zc/winsize; float max_peak = 0; for(int j=0;j<n_wins;j++) { uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc; uint32_t end = start+winsize; if (end>p->deadzone) { end-=p->deadzone; } start += p->deadzone; p->peak_values[j] = 0; for(int k=start;k<end;k++) { if(p->corr[k] > p->peak_values[j]) { p->peak_values[j] = p->corr[k]; p->peak_offsets[j] = k-start; if (p->peak_values[j] > max_peak) { max_peak = p->peak_values[j]; } } } } if (max_peak > p->detect_factor*corr_ave) { for (int j=0;j<n_wins;j++) { if(p->peak_values[j] > p->detect_factor*corr_ave) { printf("ncs=%d, nzc=%d, nwins=%d, Nroot=%d, i=%d, j=%d, start=%d, peak_value=%f, peak_offset=%d, tseq=%f\n", p->N_cs, p->N_zc, n_wins, p->N_roots, i, j, (p->N_zc-(j*p->N_cs))%p->N_zc, p->peak_values[j], p->peak_offsets[j], p->T_seq*1e6); memcpy(save_corr, p->corr, p->N_zc*sizeof(float)); if (indices) { indices[*n_indices] = (i*n_wins)+j; } if (peak_to_avg) { peak_to_avg[*n_indices] = p->peak_values[j]/corr_ave; } if (t_offsets) { t_offsets[*n_indices] = (float) p->peak_offsets[j]*p->T_seq/p->N_zc; } (*n_indices)++; } } } } ret = SRSLTE_SUCCESS; } return ret; }