free5g
unknown
c_cpp
2 years ago
8.1 kB
2
Indexable
Never
void free5GRAN::phy::synchronization::search_pss(int& n_id_2, int& synchronisation_index, float& peak_value, int cp_length, vector<complex<float>>& buff, int fft_size) { /** * \fn search_pss * \brief Search for PSS correlation peak inside a signal. * \details * Details: * - Generating the three possible PSS sequences (for N_ID_2 in [0,1,2]) * - Performing iFFT to retreive Time domain PSS sequence * - Cross-correlation between received signal and three time domain PSS * signals * - Return PSS sequence with highest correlation peak. * * \param[out] n_id_2: Returned N_ID_2 * \param[out] synchronisation_index: Synchronization index corresponding to * correlation peak \param[out] peak_value: Peak height \param[in] cp_length: * Cyclic prefix length \param[in] buff: Input IQ signal \param[in] fft_size: * FFT size and symbol size */ /* * Generate complex arrays to store IFFT signals for the three different PSS * sequence */ auto* pss_in_0 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); auto* pss_out_0 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); auto* pss_in_1 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); auto* pss_out_1 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); auto* pss_in_2 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); auto* pss_out_2 = (fftw_complex*)fftw_malloc(sizeof(fftw_complex) * fft_size); /* * Generate IFFT plans for the three different PSS sequence */ fftw_plan ifft_plan_0 = fftw_plan_dft_1d(fft_size, pss_in_0, pss_out_0, FFTW_BACKWARD, FFTW_MEASURE); fftw_plan ifft_plan_1 = fftw_plan_dft_1d(fft_size, pss_in_1, pss_out_1, FFTW_BACKWARD, FFTW_MEASURE); fftw_plan ifft_plan_2 = fftw_plan_dft_1d(fft_size, pss_in_2, pss_out_2, FFTW_BACKWARD, FFTW_MEASURE); /* * Initialize arrays */ for (int i = 0; i < fft_size; i++) { pss_in_0[i][0] = 0; pss_in_0[i][1] = 0; pss_in_1[i][0] = 0; pss_in_1[i][1] = 0; pss_in_2[i][0] = 0; pss_in_2[i][1] = 0; } /* * Generate and get PSS sequences */ int pss_0_seq[free5GRAN::SIZE_PSS_SSS_SIGNAL], pss_1_seq[free5GRAN::SIZE_PSS_SSS_SIGNAL], pss_2_seq[free5GRAN::SIZE_PSS_SSS_SIGNAL]; free5GRAN::utils::sequence_generator::generate_pss_sequence(0, pss_0_seq); free5GRAN::utils::sequence_generator::generate_pss_sequence(1, pss_1_seq); free5GRAN::utils::sequence_generator::generate_pss_sequence(2, pss_2_seq); /* * Generate frequency domain signal (PSS is BPSK modulated, real part is the * pss sequence value and imaginary part is 0) */ for (int i = 0; i < fft_size / 2; i++) { if (i < 63) { pss_in_0[i][0] = pss_0_seq[i + 64]; pss_in_0[i][1] = 0; pss_in_1[i][0] = pss_1_seq[i + 64]; pss_in_1[i][1] = 0; pss_in_2[i][0] = pss_2_seq[i + 64]; pss_in_2[i][1] = 0; } if (i < 64) { pss_in_0[fft_size - i - 1][0] = pss_0_seq[64 - i - 1]; pss_in_0[fft_size - i - 1][1] = 0; pss_in_1[fft_size - i - 1][0] = pss_1_seq[64 - i - 1]; pss_in_1[fft_size - i - 1][1] = 0; pss_in_2[fft_size - i - 1][0] = pss_2_seq[64 - i - 1]; pss_in_2[fft_size - i - 1][1] = 0; } } /* * Execute the IFFT */ fftw_execute(ifft_plan_0); fftw_execute(ifft_plan_1); fftw_execute(ifft_plan_2); vector<complex<float>> time_signal_pss_0(cp_length + fft_size), time_signal_pss_1(cp_length + fft_size), time_signal_pss_2(cp_length + fft_size); /* * Transform fftw complex signals into vectors of complex values and add * cyclic prefix */ for (int i = 0; i < cp_length + fft_size; i++) { if (i < cp_length) { time_signal_pss_0[i] = complex<float>(pss_out_0[fft_size - cp_length + i][0], pss_out_0[fft_size - cp_length + i][1]); time_signal_pss_1[i] = complex<float>(pss_out_1[fft_size - cp_length + i][0], pss_out_1[fft_size - cp_length + i][1]); time_signal_pss_2[i] = complex<float>(pss_out_2[fft_size - cp_length + i][0], pss_out_2[fft_size - cp_length + i][1]); } else { time_signal_pss_0[i] = complex<float>(pss_out_0[i - cp_length][0], pss_out_0[i - cp_length][1]); time_signal_pss_1[i] = complex<float>(pss_out_1[i - cp_length][0], pss_out_1[i - cp_length][1]); time_signal_pss_2[i] = complex<float>(pss_out_2[i - cp_length][0], pss_out_2[i - cp_length][1]); } } size_t num_samples = buff.size(); complex<float> corr_0[num_samples + fft_size + cp_length - 1], corr_1[num_samples + fft_size + cp_length - 1], corr_2[num_samples + fft_size + cp_length - 1]; /* Correlate the three possible PSS sequences with the time-domain signal buff is the time-domain signal time_signal_pss_0, time_signal_pss_1 and time_signal_pss_2 are the time domain PSS signals corr_0, corr_1 and corr_2 are the cross correlation output num_samples is the size of the buffer fft_size + cp_length corresponds to the size of a symbol (in samples)*/ cross_correlation(buff, time_signal_pss_0, &corr_0[0], num_samples, fft_size + cp_length); cross_correlation(buff, time_signal_pss_1, &corr_1[0], num_samples, fft_size + cp_length); cross_correlation(buff, time_signal_pss_2, &corr_2[0], num_samples, fft_size + cp_length); float max_value = -1; n_id_2 = -1; synchronisation_index = -1; // Search for the max value and index over the cross correlation for (int i = 0; i < num_samples + fft_size + cp_length - 1; i++) { float abs_0_short = abs(corr_0[i]); float abs_1_short = abs(corr_1[i]); float abs_2_short = abs(corr_2[i]); if (abs_0_short > max_value) { max_value = abs_0_short; n_id_2 = 0; synchronisation_index = i; } else if (abs_1_short > max_value) { max_value = abs_1_short; n_id_2 = 1; synchronisation_index = i; } else if (abs_2_short > max_value) { max_value = abs_2_short; n_id_2 = 2; synchronisation_index = i; } } peak_value = max_value; } /* * cross_correlation method: cross-correlate two signals in1 and in2 which size * are size1 and size2 and put the result in out */ void free5GRAN::phy::synchronization::cross_correlation( vector<complex<float>> in1, vector<complex<float>> in2, complex<float>* out, int size1, int size2) { /** * \fn cross_correlation * \brief Perform cross correlation (i.e. moving window correlation) between * signal 1 and signal 2 \param[in] in1: Signal 1 \param[in] in2: Signal 2 * \param[out] out: Correlation result * \param[in] size1: Signal 1 size * \param[in] size2: Signal 2 size */ int common = 0; int base_id1, base_id2; for (int m = 0; m < size1 + size2 - 1; m++) { if (m < size2) { common++; base_id1 = 0; base_id2 = size2 - common; } else if (m > size1 - 1) { common--; base_id1 = size1 - common; base_id2 = 0; } else { base_id1 = m + 1 - size2; base_id2 = 0; } out[m] = 0; for (int n = 0; n < common; n++) { out[m] += in1[base_id1 + n] * conj(in2[base_id2 + n]); } } }