free5GRAN  V1.0
synchronization.cpp
Go to the documentation of this file.
1 /*
2  * Copyright 2020 Telecom Paris
3 
4  Licensed under the Apache License, Version 2.0 (the "License");
5  you may not use this file except in compliance with the License.
6  You may obtain a copy of the License at
7 
8  http://www.apache.org/licenses/LICENSE-2.0
9 
10  Unless required by applicable law or agreed to in writing, software
11  distributed under the License is distributed on an "AS IS" BASIS,
12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  See the License for the specific language governing permissions and
14  limitations under the License.
15  */
16 
17 #include "synchronization.h"
18 #include "../../utils/sequence_generator/sequence_generator.h"
19 #include "../../variables/common_variables/common_variables.h"
20 #include <fftw3.h>
21 #include <thread>
22 #include <fstream>
23 #include <complex>
24 #include <vector>
25 #include <iostream>
26 using namespace std;
27 
28 
29 /*
30  * get_pss method: try to synchronize PSS for both short and extended cyclic prefix
31  */
32 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) {
52  /*
53  * Generate complex arrays to store IFFT signals for the three different PSS sequence
54  */
55  fftw_complex *pss_in_0 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
56  fftw_complex *pss_out_0 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
57  fftw_complex *pss_in_1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
58  fftw_complex *pss_out_1 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
59  fftw_complex *pss_in_2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
60  fftw_complex *pss_out_2 = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
61 
62  /*
63  * Generate IFFT plans for the three different PSS sequence
64  */
65  fftw_plan ifft_plan_0 = fftw_plan_dft_1d(fft_size, pss_in_0, pss_out_0, FFTW_BACKWARD, FFTW_MEASURE);
66  fftw_plan ifft_plan_1 = fftw_plan_dft_1d(fft_size, pss_in_1, pss_out_1, FFTW_BACKWARD, FFTW_MEASURE);
67  fftw_plan ifft_plan_2 = fftw_plan_dft_1d(fft_size, pss_in_2, pss_out_2, FFTW_BACKWARD, FFTW_MEASURE);
68 
69  /*
70  * Initialize arrays
71  */
72  for (int i = 0; i < fft_size; i++){
73  pss_in_0[i][0] = 0;
74  pss_in_0[i][1] = 0;
75 
76  pss_in_1[i][0] = 0;
77  pss_in_1[i][1] = 0;
78 
79  pss_in_2[i][0] = 0;
80  pss_in_2[i][1] = 0;
81  }
82 
83 
84  /*
85  * Generate and get PSS sequences
86  */
88 
92 
93 
94  /*
95  * Generate frequency domain signal (PSS is BPSK modulated, real part is the pss sequence value and imaginary part is 0)
96  */
97  for (int i = 0; i < fft_size/2; i++){
98  if (i < 63){
99  pss_in_0[i][0] = pss_0_seq[i + 64];
100  pss_in_0[i][1] = 0;
101 
102  pss_in_1[i][0] = pss_1_seq[i + 64];
103  pss_in_1[i][1] = 0;
104 
105  pss_in_2[i][0] = pss_2_seq[i + 64];
106  pss_in_2[i][1] = 0;
107  }
108  if (i < 64){
109  pss_in_0[fft_size - i - 1][0] = pss_0_seq[64 - i - 1];
110  pss_in_0[fft_size - i - 1][1] = 0;
111 
112  pss_in_1[fft_size - i - 1][0] = pss_1_seq[64 - i - 1];
113  pss_in_1[fft_size - i - 1][1] = 0;
114 
115  pss_in_2[fft_size - i - 1][0] = pss_2_seq[64 - i - 1];
116  pss_in_2[fft_size - i - 1][1] = 0;
117  }
118  }
119 
120  /*
121  * Execute the IFFT
122  */
123  fftw_execute(ifft_plan_0);
124  fftw_execute(ifft_plan_1);
125  fftw_execute(ifft_plan_2);
126 
127  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);
128  /*
129  * Transform fftw complex signals into vectors of complex values and add cyclic prefix
130  */
131  for (int i = 0; i < cp_length + fft_size; i++){
132  if (i < cp_length){
133  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]);
134 
135  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]);
136 
137  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]);
138  }
139  else {
140  time_signal_pss_0[i] = complex<float>(pss_out_0[i - cp_length][0], pss_out_0[i - cp_length][1]);
141 
142  time_signal_pss_1[i] = complex<float>(pss_out_1[i - cp_length][0], pss_out_1[i - cp_length][1]);
143 
144  time_signal_pss_2[i] = complex<float>(pss_out_2[i - cp_length][0], pss_out_2[i - cp_length][1]);
145  }
146 
147  }
148 
149  size_t num_samples = buff.size();
150  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];
151 
152  /*
153  * Correlate different PSS signals with different CP length with signal obtained from PHY layer
154  */
155 
156  thread correlation_thread_0(cross_correlation, buff,time_signal_pss_0,&corr_0[0],num_samples,fft_size + cp_length);
157  thread correlation_thread_1(cross_correlation, buff,time_signal_pss_1,&corr_1[0],num_samples,fft_size + cp_length);
158  thread correlation_thread_2(cross_correlation, buff,time_signal_pss_2,&corr_2[0],num_samples,fft_size + cp_length);
159  correlation_thread_0.join();
160  correlation_thread_1.join();
161  correlation_thread_2.join();
162 
163  float max_value = -1;
164  n_id_2 = -1;
165  synchronisation_index = -1;
166 
167  /*
168  * Search for the max value and index
169  */
170  for (int i = 0; i < num_samples + fft_size + cp_length - 1; i++){
171  float abs_0_short = abs(corr_0[i]);
172  float abs_1_short = abs(corr_1[i]);
173  float abs_2_short = abs(corr_2[i]);
174 
175  if (abs_0_short > max_value){
176  max_value = abs_0_short;
177  n_id_2 = 0;
178  synchronisation_index = i;
179  } else if (abs_1_short > max_value){
180  max_value = abs_1_short ;
181  n_id_2 = 1;
182  synchronisation_index = i;
183  } else if (abs_2_short > max_value){
184  max_value = abs_2_short;
185  n_id_2 = 2;
186  synchronisation_index = i;
187  }
188  }
189  peak_value = max_value;
190 
191 }
192 
193 /*
194  * cross_correlation method: cross-correlate two signals in1 and in2 which size are size1 and size2 and put the result in out
195  */
196 void free5GRAN::phy::synchronization::cross_correlation(vector<complex<float>> in1, vector<complex<float>> in2, complex<float> *out, int size1, int size2) {
206  int common = 0;
207  int base_id1, base_id2;
208  for (int m = 0; m < size1 + size2 - 1; m++){
209  if (m < size2){
210  common++;
211 
212  base_id1 = 0;
213  base_id2 = size2 - common;
214 
215  }else if (m > size1 - 1) {
216  common--;
217 
218  base_id1 = size1 - common;
219  base_id2 = 0;
220  }else {
221  base_id1 = m + 1 - size2;
222  base_id2 = 0;
223  }
224  out[m] = 0;
225 
226  for (int n = 0; n < common; n++){
227  out[m] += in1[base_id1 + n] * conj(in2[base_id2 + n]);
228  }
229  }
230 
231 }
232 
233 void free5GRAN::phy::synchronization::get_sss(int &n_id_1, float &peak_value, vector<complex<float>> &buff, int fft_size, int n_id_2) {
250  /*
251  * Create fftw complex arrays
252  */
253  fftw_complex *fft_in = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
254  fftw_complex *fft_out = (fftw_complex*) fftw_malloc(sizeof(fftw_complex) * fft_size);
255 
256  /*
257  * Create a FFT plan
258  */
259  fftw_plan fft_plan = fftw_plan_dft_1d(fft_size, fft_in, fft_out, FFTW_FORWARD, FFTW_MEASURE);
260 
261  /*
262  * Put the buff into the fft_in array
263  */
264  for (int i = 0; i < fft_size; i++){
265  fft_in[i][0] = real(buff[i]);
266  fft_in[i][1] = imag(buff[i]);
267  }
268 
269  /*
270  * Execute the FFT
271  */
272  fftw_execute(fft_plan);
273 
274  vector<complex<float>> frequency_sss(free5GRAN::SIZE_PSS_SSS_SIGNAL);
275 
276  /*
277  * Build frequency domain signal (frequency_sss) from FFT out signal
278  */
279  for (int i = 0; i < 64; i++){
280  if (i < 63){
281  frequency_sss[i + 64] = complex<float>(fft_out[i][0], fft_out[i][1]);
282  }
283  frequency_sss[64 - i - 1] = complex<float>(fft_out[fft_size - i - 1][0], fft_out[fft_size - i - 1][1]);
284  }
285  float max_value = -1;
286  n_id_1 = -1;
287  complex<float> correlation_value;
288 
289  /*
290  * Trying to correlate frequency domain signal to SSS sequences to find n_id_2
291  * TODO: use mutlithreading instead of basic loop
292  */
293  for (int i = 0; i < free5GRAN::MAX_N_ID_1; i ++){
294  int sss_seq[free5GRAN::SIZE_PSS_SSS_SIGNAL];
296  correlation_value = correlate(frequency_sss, sss_seq, free5GRAN::SIZE_PSS_SSS_SIGNAL);
297  float abs_value = abs(correlation_value);
298  if (abs_value > max_value){
299  max_value = abs_value;
300  n_id_1 = i;
301  }
302  }
303  peak_value = max_value;
304 }
305 
306 complex<float> free5GRAN::phy::synchronization::correlate(vector<complex<float>> in1, int *in2, int size) {
316  complex<float> out = 0;
317  for (int i = 0; i < size; i ++){
318  out += in1[i] * conj(complex<float>(in2[i],0));
319  }
320  return out;
321 }
void search_pss(int &n_id_2, int &synchronisation_index, float &peak_value, int cp_length, vector< complex< float >> &buff, int fft_size)
void cross_correlation(vector< complex< float >> in1, vector< complex< float >> in2, complex< float > *out, int size1, int size2)
void generate_sss_sequence(int n_id_1, int n_id_2, int *output_sequence)
void get_sss(int &n_id_1, float &peak_value, vector< complex< float >> &buff, int fft_size, int n_id_2)
complex< float > correlate(vector< complex< float >> in1, int *in2, int size)
void generate_pss_sequence(int n_id_2, int *output_sequence)