/* * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The OpenAirInterface Software Alliance licenses this file to You under * the OAI Public License, Version 1.0 (the "License"); you may not use this file * except in compliance with the License. * You may obtain a copy of the License at * * http://www.openairinterface.org/?page_id=698 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. *------------------------------------------------------------------------------- * For more information about the OpenAirInterface (OAI) Software Alliance: * contact@openairinterface.org */ /*! \file PHY/LTE_TRANSPORT/nprach_eNb_NB_IoT.c * function for NPRACH signal detection and Timing Advance estimation * \author V. Savaux * \date 2017 * \version 0.1 * \company b<>com * \email: vincent.savaux@b-com.com * \note * \warning */ //#include "PHY/sse_intrin.h" #include "PHY/defs_NB_IoT.h" #include "PHY/TOOLS/defs.h" // to take into account the dft functions //#include "PHY/extern.h" //#include "prach.h" //#include "PHY/LTE_TRANSPORT/if4_tools.h" //#include "SCHED/defs.h" //#include "SCHED/extern.h" //#include "UTIL/LOG/vcd_signal_dumper.h" uint8_t NPRACH_detection_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_sub_sampled_buffer, uint16_t sub_sampling_rate, uint32_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES){ // uint32_t P_noise ; // to uncomment when needed // needs to be defined or calculated uint16_t FFT_size=0; uint16_t delta_t=0; // size, in samples, between 2 successive FFTs uint16_t Nb_packets,n_subcarriers; uint16_t N_sample_per_sc=0; // number of samples per subcarrier int16_t **mat_from_buffer,**mat_to_detector; uint32_t **mat_energy; uint64_t energy_per_subcarrier; uint32_t threshold_gamma=0; // threshold for signal detection int k,n,m; uint8_t is_NPRACH_present = 0; switch (sub_sampling_rate){ case 16: // fs = 1.92 MHz FFT_size = 16384; //dft_size = dft16384; delta_t = 80; N_sample_per_sc = 256; break; case 32: // fs = 960 kHz FFT_size = 8192; //dft_size = dft8192; delta_t = 40; N_sample_per_sc = 128; break; case 64: // fs = 480 kHz FFT_size = 4096; //dft_size = dft4096; delta_t = 20; N_sample_per_sc = 64; break; case 128: // fs = 240 kHz FFT_size = 2048; //dft_size = dft2048; delta_t = 10; N_sample_per_sc = 32; break; } Nb_packets = (uint16_t)(FRAME_LENGTH_COMPLEX_SUB_SAMPLES-FFT_size)/delta_t + 1; // Number of sections of FFT_size complex samples n_subcarriers = FFT_size/N_sample_per_sc; // number of subcarriers on which the energy is calculated // Create matrices where lines correspond to one sample, columns are fft of inputs mat_to_detector = (int16_t **)malloc(Nb_packets*sizeof(int16_t *)); mat_from_buffer = (int16_t **)malloc(Nb_packets*sizeof(int16_t *)); mat_energy = (uint32_t **)malloc(Nb_packets*sizeof(uint32_t *)); for (k=0;k= threshold_gamma){ is_NPRACH_present = 1; } } } for (k=0;kframe_parms.nprach_config_common.nprach_CP_Length; //NB-IoT: 0: short, 1: long uint32_t fs=0; //NB-IoT: sampling frequency of Rx_buffer, must be defined somewhere uint32_t fs_sub_sampled; uint16_t length_correl_window,base_length; int64_t *vec_correlation; double max_correlation = 0; int16_t **matrix_received_signal_re, **matrix_received_signal_im; uint16_t offset_estimation, offset_start; // offset due to first coarse estimation // double *** mat_to_phase_estimation_re, *** mat_to_phase_estimation_im; double average_mat_to_phase_re, average_mat_to_phase_im; double estimated_phase, estimated_CFO; // int16_t *vec_CFO_compensation_re, *vec_CFO_compensation_im; // int16_t *vec_received_signal_re, *vec_received_signal_im; int32_t *signal_CFO_compensed_re, *signal_CFO_compensed_im; int32_t **sub_sequence_reference_re, **sub_sequence_reference_im; int32_t *sequence_reference_re, *sequence_reference_im; uint32_t TA_sample_estimated = 0; int n,k,m,o; length_seq_NPRACH = (length_CP_0+5*8192)/sub_sampling_rate; length_CP = length_CP_0/sub_sampling_rate; length_symbol = 8192/sub_sampling_rate; if (coarse){ // coarse = 1: first estimation offset_start = 0; length_correl_window = 20512/sub_sampling_rate; // corresponds to the max TA, i.e. 667.66 micro s //FRAME_LENGTH_COMPLEX_SUB_SAMPLES - 4*length_seq_NPRACH+1; }else{ offset_estimation = 8 * estimated_TA_coarse; base_length = 32; // we arbitrarily define the length of correl window as base_length samples. // Check if offset_estimation is close to zero or 1282 (max lentgh of delays) if (offset_estimation-base_length/2 <0){ offset_start = 0; length_correl_window = offset_estimation + base_length/2; } if (offset_estimation+base_length/2 >1281){ offset_start = offset_estimation-base_length/2; length_correl_window = base_length;// 512 - (1282-offset_estimation); } if ((offset_estimation-base_length/2 >=0) && (offset_estimation+base_length/2 <=1281)){ offset_start = offset_estimation-base_length/2; length_correl_window = base_length; } } fs_sub_sampled = (uint32_t)fs/sub_sampling_rate; // Method: MMSE (sub-optimal) CFO estimation -> CFO compensation -> ML (sub-optimal) TA estimation /============================================================/ matrix_received_signal_re = (int16_t **)malloc(4*sizeof(int16_t *)); matrix_received_signal_im = (int16_t **)malloc(4*sizeof(int16_t *)); for (k=0;k<4;k++){ // # sequence matrix_received_signal_re[k] = (int16_t *)malloc((length_seq_NPRACH-length_CP)*sizeof(int16_t)); // avoid CP in this process matrix_received_signal_im[k] = (int16_t *)malloc((length_seq_NPRACH-length_CP)*sizeof(int16_t)); // avoid CP in this process } signal_CFO_compensed_re = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); signal_CFO_compensed_im = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); sub_sequence_reference_re = (int32_t **)malloc(4*sizeof(int32_t *)); sub_sequence_reference_im = (int32_t **)malloc(4*sizeof(int32_t *)); for (k=0;k<4;k++){ sub_sequence_reference_re[k] = (int32_t *)calloc(length_symbol,sizeof(int32_t)); sub_sequence_reference_im[k] = (int32_t *)calloc(length_symbol,sizeof(int32_t)); } sequence_reference_re = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); sequence_reference_im = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); vec_correlation = (int64_t *)malloc(length_correl_window*sizeof(int64_t)); for (n=0;n=max_correlation){ max_correlation = vec_correlation[n]; TA_sample_estimated = n; } } free(vec_correlation); for (k=0;k<4;k++){ // # sequence free(matrix_received_signal_re[k]); free(matrix_received_signal_im[k]); free(sub_sequence_reference_re[k]); free(sub_sequence_reference_im[k]); } free(matrix_received_signal_re); free(matrix_received_signal_im); free(signal_CFO_compensed_re); free(signal_CFO_compensed_im); free(sub_sequence_reference_re); free(sub_sequence_reference_im); return TA_sample_estimated; } int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate){ int k; uint32_t L; int16_t *output_buffer; L = (uint32_t)((double)length_input / sub_sampling_rate); *length_ouput = L; output_buffer = (int16_t *)malloc(2*L*sizeof(int16_t)); for (k=0;k