free5g
unknown
c_cpp
3 years ago
8.1 kB
10
Indexable
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]);
}
}
}Editor is loading...