diff --git a/lib/include/srslte/phy/phch/prach.h b/lib/include/srslte/phy/phch/prach.h index 5d3219b4b..37c3f017f 100644 --- a/lib/include/srslte/phy/phch/prach.h +++ b/lib/include/srslte/phy/phch/prach.h @@ -75,6 +75,7 @@ typedef struct SRSLTE_API { // Generated tables cf_t seqs[64][839]; // Our set of 64 preamble sequences cf_t dft_seqs[64][839]; // DFT-precoded seqs + uint64_t dft_gen_bitmap; // Bitmap where each bit Indicates if the dft has been generated for sequence i. uint32_t root_seqs_idx[64]; // Indices of root seqs in seqs table uint32_t N_roots; // Number of root sequences used in this configuration cf_t* td_signals[64]; @@ -134,7 +135,6 @@ typedef struct { bool enable_freq_domain_offset_calc; } srslte_prach_cfg_t; - typedef struct SRSLTE_API { uint32_t f; uint32_t t0; @@ -217,14 +217,14 @@ SRSLTE_API int srslte_prach_free(srslte_prach_t* p); SRSLTE_API int srslte_prach_print_seqs(srslte_prach_t* p); -SRSLTE_API int srslte_prach_process(srslte_prach_t* p, - cf_t* signal, - uint32_t* indices, - float* t_offsets, - float* peak_to_avg, - uint32_t* n_indices, - int cancellation_idx, - uint32_t begin, - uint32_t sig_len); +SRSLTE_API int srslte_prach_process(srslte_prach_t* p, + cf_t* signal, + uint32_t* indices, + float* t_offsets, + float* peak_to_avg, + uint32_t* n_indices, + int cancellation_idx, + uint32_t begin, + uint32_t sig_len); #endif // SRSLTE_PRACH_H diff --git a/lib/src/phy/phch/prach.c b/lib/src/phy/phch/prach.c index faba3777a..07520a407 100644 --- a/lib/src/phy/phch/prach.c +++ b/lib/src/phy/phch/prach.c @@ -20,6 +20,7 @@ */ #include "srslte/srslte.h" +#include #include #include @@ -222,6 +223,20 @@ void print(void* d, uint32_t size, uint32_t len, char* file_str) fclose(f); } +/// Calculates the FFT of the specified sequence index if not previously done and returns a pointer to the result. +static cf_t* get_precoded_dft(srslte_prach_t* p, uint32_t idx) +{ + assert(idx < 64 && "Invalid idx value"); + // Generate FFT for this sequence if it does not exist yet. + uint64_t gen_mask = (uint64_t)1 << idx; + if (!(p->dft_gen_bitmap & gen_mask)) { + srslte_dft_run(&p->zc_fft, p->seqs[idx], p->dft_seqs[idx]); + p->dft_gen_bitmap |= gen_mask; + } + + return p->dft_seqs[idx]; +} + int srslte_prach_gen_seqs(srslte_prach_t* p) { uint32_t u = 0; @@ -410,6 +425,7 @@ int srslte_prach_set_cell_(srslte_prach_t* p, p->detect_factor = PRACH_DETECT_FACTOR; p->num_ra_preambles = cfg->num_ra_preambles; p->successive_cancellation = cfg->enable_successive_cancellation; + p->dft_gen_bitmap = 0; if (p->successive_cancellation && cfg->zero_corr_zone != 0) { printf("successive cancellation only currently supported with zero_correlation_zone_config of 0 - disabling\n"); p->successive_cancellation = false; @@ -464,10 +480,6 @@ int srslte_prach_set_cell_(srslte_prach_t* p, if (p->num_ra_preambles < 4 || p->num_ra_preambles > p->N_roots) { p->num_ra_preambles = p->N_roots; } - // Generate sequence FFTs - for (int i = 0; i < N_SEQS; i++) { - srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]); - } // Create our FFT objects and buffers p->N_ifft_ul = N_ifft_ul; @@ -540,7 +552,7 @@ int srslte_prach_gen(srslte_prach_t* p, uint32_t seq_index, uint32_t freq_offset // Map dft-precoded sequence to ifft bins memset(p->ifft_in, 0, begin * sizeof(cf_t)); - memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); + memcpy(&p->ifft_in[begin], get_precoded_dft(p, seq_index), p->N_zc * sizeof(cf_t)); memset(&p->ifft_in[begin + p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t)); srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out); @@ -581,7 +593,8 @@ int srslte_prach_detect(srslte_prach_t* p, void srslte_prach_cancellation(srslte_prach_t* p) { srslte_vec_cf_zero(p->sub, p->N_zc * 2); - srslte_vec_cf_copy(p->sub, &p->dft_seqs[p->root_seqs_idx[p->prach_cancel.idx]][0], p->N_zc); + srslte_vec_cf_copy(p->sub, get_precoded_dft(p, p->root_seqs_idx[p->prach_cancel.idx]), p->N_zc); + srslte_vec_prod_ccc(p->sub, p->prach_cancel.phase_array, p->sub, p->N_zc); #ifdef PRACH_CANCELLATION_HARD srslte_vec_prod_conj_ccc(p->prach_bins, p->sub, p->corr_spec, p->N_zc); @@ -651,7 +664,7 @@ int srslte_prach_process(srslte_prach_t* p, srslte_vec_cf_zero(p->cross, p->N_zc); srslte_vec_cf_zero(p->corr_freq, p->N_zc); for (int i = 0; i < p->num_ra_preambles; i++) { - cf_t* root_spec = p->dft_seqs[p->root_seqs_idx[i]]; + cf_t* root_spec = get_precoded_dft(p, p->root_seqs_idx[i]); srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc); diff --git a/lib/src/phy/phch/test/prach_test_multi.c b/lib/src/phy/phch/test/prach_test_multi.c index 65d0def65..15ad1ad45 100644 --- a/lib/src/phy/phch/test/prach_test_multi.c +++ b/lib/src/phy/phch/test/prach_test_multi.c @@ -110,35 +110,35 @@ void parse_args(int argc, char** argv) } } // this function staggers power and phase of the different PRACH signals for more realisitc testing -void stagger_prach_powers(srslte_prach_t prach, cf_t *preamble, cf_t* preamble_sum, int freq_offset, int n_seqs, int *offsets) { +void stagger_prach_powers(srslte_prach_t *prach, cf_t *preamble, cf_t* preamble_sum, int freq_offset, int n_seqs, int *offsets) { for (int seq_index = 0; seq_index < n_seqs; seq_index++) { - srslte_prach_gen(&prach, seq_index, freq_offset, preamble); + srslte_prach_gen(prach, seq_index, freq_offset, preamble); if (seq_index == 0) { - srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.5), preamble, prach.N_cp + prach.N_seq); - srslte_vec_sc_prod_cfc(preamble, 1, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.5), preamble, prach->N_cp + prach->N_seq); + srslte_vec_sc_prod_cfc(preamble, 1, preamble, prach->N_cp + prach->N_seq); } if (seq_index == 1) { - srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 1), preamble, prach.N_cp + prach.N_seq); - srslte_vec_sc_prod_cfc(preamble, 0.8, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 1), preamble, prach->N_cp + prach->N_seq); + srslte_vec_sc_prod_cfc(preamble, 0.8, preamble, prach->N_cp + prach->N_seq); } if (seq_index == 2) { - srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.1), preamble, prach.N_cp + prach.N_seq); - srslte_vec_sc_prod_cfc(preamble, 0.05, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.1), preamble, prach->N_cp + prach->N_seq); + srslte_vec_sc_prod_cfc(preamble, 0.05, preamble, prach->N_cp + prach->N_seq); } if (seq_index == 3) { - srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.9), preamble, prach.N_cp + prach.N_seq); - srslte_vec_sc_prod_cfc(preamble, 0.7, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.9), preamble, prach->N_cp + prach->N_seq); + srslte_vec_sc_prod_cfc(preamble, 0.7, preamble, prach->N_cp + prach->N_seq); } if (seq_index == 4) { - srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.3), preamble, prach.N_cp + prach.N_seq); - srslte_vec_sc_prod_cfc(preamble, 0.15, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_ccc(preamble, cexpf(_Complex_I * 0.3), preamble, prach->N_cp + prach->N_seq); + srslte_vec_sc_prod_cfc(preamble, 0.15, preamble, prach->N_cp + prach->N_seq); } if (seq_index == 5) { - srslte_vec_sc_prod_cfc(preamble, 0.15, preamble, prach.N_cp + prach.N_seq); + srslte_vec_sc_prod_cfc(preamble, 0.15, preamble, prach->N_cp + prach->N_seq); } int off = (offset == -1) ? offsets[seq_index] : offset; - for (int i = 0; i < prach.N_cp + prach.N_seq; i++) { + for (int i = 0; i < prach->N_cp + prach->N_seq; i++) { preamble_sum[i + off] += preamble[i]; } } @@ -209,7 +209,7 @@ int main(int argc, char** argv) srslte_prach_set_detect_factor(&prach, 10); if (stagger_prach_power_and_phase) { - stagger_prach_powers(prach, preamble, preamble_sum, prach_cfg.freq_offset, n_seqs, offsets); + stagger_prach_powers(&prach, preamble, preamble_sum, prach_cfg.freq_offset, n_seqs, offsets); } else { for (seq_index = 0; seq_index < n_seqs; seq_index++) { srslte_prach_gen(&prach, seq_index, prach_cfg.freq_offset, preamble);