moving some arrays to the heap, fixing formatting, setting dft norm

master
yagoda 4 years ago committed by Justin Tallon
parent f6ea431555
commit 59082770d3

@ -46,6 +46,12 @@
* Based on 3GPP TS 36.211 version 10.7.0 Release 10. * Based on 3GPP TS 36.211 version 10.7.0 Release 10.
*/ */
typedef struct {
int idx;
float factor;
cf_t phase_array[2 * 839];
} srslte_prach_cancellation_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
// Parameters from higher layers (extracted from SIB2) // Parameters from higher layers (extracted from SIB2)
uint32_t config_idx; uint32_t config_idx;
@ -90,14 +96,17 @@ typedef struct SRSLTE_API {
cf_t* signal_fft; cf_t* signal_fft;
float detect_factor; float detect_factor;
uint32_t deadzone; uint32_t deadzone;
float peak_values[65]; float peak_values[65];
uint32_t peak_offsets[65]; uint32_t peak_offsets[65];
uint32_t num_ra_preambles; uint32_t num_ra_preambles;
bool successive_cancellation; bool successive_cancellation;
bool freq_domain_offset_calc; bool freq_domain_offset_calc;
srslte_tdd_config_t tdd_config; srslte_tdd_config_t tdd_config;
uint32_t current_prach_idx; uint32_t current_prach_idx;
cf_t* cross;
cf_t* corr_freq;
srslte_prach_cancellation_t prach_cancel;
} srslte_prach_t; } srslte_prach_t;
@ -123,11 +132,6 @@ typedef struct {
bool enable_freq_domain_offset_calc; bool enable_freq_domain_offset_calc;
} srslte_prach_cfg_t; } srslte_prach_cfg_t;
typedef struct {
int idx;
float factor;
cf_t phase_array[2 * 839];
} srslte_prach_cancellation_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t f; uint32_t f;
@ -218,7 +222,6 @@ SRSLTE_API int srslte_prach_process(srslte_prach_t* p,
float* peak_to_avg, float* peak_to_avg,
uint32_t* n_indices, uint32_t* n_indices,
int cancellation_idx, int cancellation_idx,
srslte_prach_cancellation_t prach_cancel,
uint32_t begin, uint32_t begin,
uint32_t sig_len); uint32_t sig_len);

@ -43,7 +43,7 @@ float save_corr[4096];
#define PHI 7 // PRACH phi parameter #define PHI 7 // PRACH phi parameter
#define PHI_4 2 // PRACH phi parameter for format 4 #define PHI_4 2 // PRACH phi parameter for format 4
#define MAX_ROOTS 838 // Max number of root sequences #define MAX_ROOTS 838 // Max number of root sequences
#define PRACH_CANCELLATION_HARD //#define PRACH_CANCELLATION_HARD
#define PRACH_AMP 1.0 #define PRACH_AMP 1.0
int srslte_prach_set_cell_(srslte_prach_t* p, int srslte_prach_set_cell_(srslte_prach_t* p,
@ -341,6 +341,8 @@ int srslte_prach_init(srslte_prach_t* p, uint32_t max_N_ifft_ul)
p->prach_bins = srslte_vec_cf_malloc(MAX_N_zc); p->prach_bins = srslte_vec_cf_malloc(MAX_N_zc);
p->corr_spec = srslte_vec_cf_malloc(MAX_N_zc); p->corr_spec = srslte_vec_cf_malloc(MAX_N_zc);
p->corr = srslte_vec_f_malloc(MAX_N_zc); p->corr = srslte_vec_f_malloc(MAX_N_zc);
p->cross = srslte_vec_cf_malloc(MAX_N_zc);
p->corr_freq = srslte_vec_cf_malloc(MAX_N_zc);
// Set up ZC FFTS // Set up ZC FFTS
if (srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) { if (srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) {
@ -378,7 +380,7 @@ int srslte_prach_init(srslte_prach_t* p, uint32_t max_N_ifft_ul)
} }
srslte_dft_plan_set_mirror(&p->fft, true); srslte_dft_plan_set_mirror(&p->fft, true);
srslte_dft_plan_set_norm(&p->fft, false); srslte_dft_plan_set_norm(&p->fft, true);
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
@ -574,19 +576,18 @@ int srslte_prach_detect(srslte_prach_t* p,
/// this function subtracts the detected prach preamble from the signal so as to allow for lower power prach signals to /// this function subtracts the detected prach preamble from the signal so as to allow for lower power prach signals to
/// be detected more easily in the subsequent searches /// be detected more easily in the subsequent searches
void srslte_prach_cancellation (srslte_prach_t* p, cf_t *signal, uint32_t begin, int sig_len, srslte_prach_cancellation_t prach_cancel) void srslte_prach_cancellation(srslte_prach_t* p)
{ {
cf_t sub[p->N_zc * 2]; cf_t sub[p->N_zc * 2];
memcpy(sub, &p->dft_seqs[p->root_seqs_idx[prach_cancel.idx]][0], p->N_zc * sizeof(cf_t)); srslte_vec_cf_copy(sub, &p->dft_seqs[p->root_seqs_idx[p->prach_cancel.idx]][0], p->N_zc);
srslte_vec_prod_ccc(sub, prach_cancel.phase_array, sub, p->N_zc); srslte_vec_prod_ccc(sub, p->prach_cancel.phase_array, sub, p->N_zc);
#ifdef PRACH_CANCELLATION_HARD #ifdef PRACH_CANCELLATION_HARD
cf_t res[p->N_zc * 2]; srslte_vec_prod_conj_ccc(p->prach_bins, sub, p->corr_spec, p->N_zc);
srslte_vec_prod_conj_ccc(p->prach_bins, sub, res, p->N_zc);
srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec); 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); srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);
prach_cancel.factor = sqrt(p->corr[0] / (p->N_zc * p->N_zc)); prach_cancel->factor = sqrt(p->corr[0] / (p->N_zc * p->N_zc));
#endif #endif
srslte_vec_sc_prod_cfc(sub, prach_cancel.factor, sub, p->N_zc); srslte_vec_sc_prod_cfc(sub, p->prach_cancel.factor, sub, p->N_zc);
srslte_vec_sub_ccc(p->prach_bins, sub, p->prach_bins, p->N_zc); srslte_vec_sub_ccc(p->prach_bins, sub, p->prach_bins, p->N_zc);
} }
@ -623,14 +624,12 @@ int srslte_prach_calculate_time_offset(srslte_prach_t* p, cf_t* cross)
} }
// calculates the aggregate phase offset of the incomming PRACH signal so it can be applied to the reference signal // calculates the aggregate phase offset of the incomming PRACH signal so it can be applied to the reference signal
// before it is subtracted from the input // before it is subtracted from the input
void srslte_prach_calculate_correction_array(srslte_prach_t* p, void srslte_prach_calculate_correction_array(srslte_prach_t* p, cf_t* corr_freq)
cf_t* corr_freq,
srslte_prach_cancellation_t* prach_cancel)
{ {
float phase[p->N_zc]; float phase[p->N_zc];
srslte_vec_arg_deg_cf(corr_freq, 0, phase, p->N_zc); srslte_vec_arg_deg_cf(corr_freq, 0, phase, p->N_zc);
for (int i = 0; i < p->N_zc; i++) { for (int i = 0; i < p->N_zc; i++) {
prach_cancel->phase_array[i] = cexpf(_Complex_I * (phase[i] / (180.0f / M_PI))); p->prach_cancel.phase_array[i] = cexpf(_Complex_I * (phase[i] / (180.0f / M_PI)));
} }
} }
@ -642,25 +641,22 @@ int srslte_prach_process(srslte_prach_t* p,
float* peak_to_avg, float* peak_to_avg,
uint32_t* n_indices, uint32_t* n_indices,
int cancellation_idx, int cancellation_idx,
srslte_prach_cancellation_t prach_cancel,
uint32_t begin, uint32_t begin,
uint32_t sig_len) uint32_t sig_len)
{ {
float max_to_cancel = 0; float max_to_cancel = 0;
cancellation_idx = -1; cancellation_idx = -1;
int max_idx = 0; int max_idx = 0;
cf_t cross[p->N_zc]; srslte_vec_cf_zero(p->cross, p->N_zc);
cf_t corr_freq[p->N_zc]; srslte_vec_cf_zero(p->corr_freq, p->N_zc);
bzero(cross, sizeof(cf_t) * p->N_zc);
bzero(corr_freq, sizeof(cf_t) * p->N_zc);
for (int i = 0; i < p->num_ra_preambles; i++) { 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 = 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_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc);
srslte_vec_prod_conj_ccc(p->corr_spec, &p->corr_spec[1], cross, p->N_zc - 1); srslte_vec_prod_conj_ccc(p->corr_spec, &p->corr_spec[1], p->cross, p->N_zc - 1);
if (p->successive_cancellation) { if (p->successive_cancellation) {
memcpy(corr_freq, p->corr_spec, p->N_zc * sizeof(cf_t)); srslte_vec_cf_copy(p->corr_freq, p->corr_spec, p->N_zc);
} }
srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec); srslte_dft_run(&p->zc_ifft, p->corr_spec, p->corr_spec);
@ -702,14 +698,11 @@ int srslte_prach_process(srslte_prach_t* p,
if (indices) { if (indices) {
if (p->successive_cancellation) { if (p->successive_cancellation) {
if (max_peak > max_to_cancel) { if (max_peak > max_to_cancel) {
cancellation_idx = (i * n_wins) + j; cancellation_idx = (i * n_wins) + j;
max_to_cancel = max_peak; max_to_cancel = max_peak;
prach_cancel.idx = cancellation_idx; // this stores the best candidate for the successive cancellation p->prach_cancel.idx = cancellation_idx;
prach_cancel.factor = (sqrt( p->prach_cancel.factor = (sqrt(max_peak / (p->N_zc * p->N_zc)));
max_peak / (p->N_zc * p->N_zc))); // this is the scaling factor for the successive cancellation srslte_prach_calculate_correction_array(p, p->corr_freq);
srslte_prach_calculate_correction_array(
p, corr_freq, &prach_cancel); // this calculates the correction array for the PRACH sig before it is
// used to cancel
} }
if (srslte_prach_have_stored(p, ((i * n_wins) + j), indices, *n_indices)) { if (srslte_prach_have_stored(p, ((i * n_wins) + j), indices, *n_indices)) {
break; break;
@ -723,7 +716,7 @@ int srslte_prach_process(srslte_prach_t* p,
if (t_offsets) { if (t_offsets) {
t_offsets[*n_indices] = t_offsets[*n_indices] =
(p->freq_domain_offset_calc) (p->freq_domain_offset_calc)
? (((float)srslte_prach_calculate_time_offset(p, cross)) / ((float)p->N_ifft_ul * DELTA_F)) ? (((float)srslte_prach_calculate_time_offset(p, p->cross)) / ((float)p->N_ifft_ul * DELTA_F))
: (srslte_prach_set_offset(p, j)); : (srslte_prach_set_offset(p, j));
} }
(*n_indices)++; (*n_indices)++;
@ -733,7 +726,7 @@ int srslte_prach_process(srslte_prach_t* p,
} }
if (cancellation_idx != -1) { if (cancellation_idx != -1) {
// if a peak has been found, this applies cancellation, if many found, subtracts strongest // if a peak has been found, this applies cancellation, if many found, subtracts strongest
srslte_prach_cancellation(p, signal, begin, sig_len, prach_cancel); srslte_prach_cancellation(p);
} else { } else {
return 1; return 1;
} }
@ -757,7 +750,7 @@ int srslte_prach_detect_offset(srslte_prach_t* p,
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
int cancellation_idx = -2; int cancellation_idx = -2;
srslte_prach_cancellation_t prach_cancel = {}; bzero(&p->prach_cancel, sizeof(srslte_prach_cancellation_t));
// FFT incoming signal // FFT incoming signal
srslte_dft_run(&p->fft, signal, p->signal_fft); srslte_dft_run(&p->fft, signal, p->signal_fft);
@ -776,7 +769,7 @@ int srslte_prach_detect_offset(srslte_prach_t* p,
// the highest power PRACH preamble each time. // the highest power PRACH preamble each time.
for (int l = 0; l < loops; l++) { for (int l = 0; l < loops; l++) {
if (srslte_prach_process( if (srslte_prach_process(
p, signal, indices, t_offsets, peak_to_avg, n_indices, cancellation_idx, prach_cancel, begin, sig_len)) { p, signal, indices, t_offsets, peak_to_avg, n_indices, cancellation_idx, begin, sig_len)) {
break; break;
} }
} }

@ -44,12 +44,11 @@ uint32_t zero_corr_zone = 1;
uint32_t n_seqs = 64; uint32_t n_seqs = 64;
uint32_t num_ra_preambles = 0; // use default uint32_t num_ra_preambles = 0; // use default
bool test_successive_cancellation = bool freq_domain_offset_calc = false;
false; // this enables the successive cancellation algorithm, computationally complex bool test_successive_cancellation = false;
bool test_offset_calculation = false; // this should not be enabled in make test, only for use in manual testing bool test_offset_calculation = false;
bool stagger_prach_power_and_phase = bool stagger_prach_power_and_phase = false;
false; // this will make the prachs have different power and phases, more realistic scenario // this will work best with one or two simultaenous prach
bool freq_domain_offset_calc = false; // this will work best with one or two simultaenous prach
srslte_filesource_t fsrc; srslte_filesource_t fsrc;
void usage(char* prog) void usage(char* prog)
@ -105,11 +104,11 @@ void stagger_prach_powers(srslte_prach_t prach, cf_t *preamble, cf_t* preamble_s
} }
if (seq_index == 1) { 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_ccc(preamble, cexpf(_Complex_I * 1), 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_cfc(preamble, 0.8, preamble, prach.N_cp + prach.N_seq);
} }
if (seq_index == 2) { 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_ccc(preamble, cexpf(_Complex_I * 0.1), preamble, prach.N_cp + prach.N_seq);
srslte_vec_sc_prod_cfc(preamble, 0.2, 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) { 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_ccc(preamble, cexpf(_Complex_I * 0.9), preamble, prach.N_cp + prach.N_seq);
@ -163,7 +162,9 @@ int main(int argc, char** argv)
int srate = srslte_sampling_freq_hz(nof_prb); int srate = srslte_sampling_freq_hz(nof_prb);
int divisor = srate / PRACH_SRATE; int divisor = srate / PRACH_SRATE;
if (test_offset_calculation || test_successive_cancellation || stagger_prach_power_and_phase) { if (test_offset_calculation || test_successive_cancellation || stagger_prach_power_and_phase) {
n_seqs = 6; if (n_seqs > 6) {
n_seqs = 6;
}
prach_cfg.zero_corr_zone = 0; prach_cfg.zero_corr_zone = 0;
prach_cfg.num_ra_preambles = 8; prach_cfg.num_ra_preambles = 8;
printf("limiting number of preambles to 6\n"); printf("limiting number of preambles to 6\n");

Loading…
Cancel
Save