Commit d38f75b3 authored by Matthieu Kanj's avatar Matthieu Kanj

Detection of msg1 sent from NB-IoT module

parent aa9e906b
......@@ -21,7 +21,7 @@
/*! \file PHY/LTE_TRANSPORT/nprach_eNb_NB_IoT.c
* function for NPRACH signal detection and Timing Advance estimation
* \author V. Savaux
* \date 2017
* \date 2018
* \version 0.1
* \company b<>com
* \email: vincent.savaux@b-com.com
......@@ -32,6 +32,7 @@
//#include "PHY/sse_intrin.h"
#include "PHY/defs_NB_IoT.h"
#include "PHY/TOOLS/defs.h" // to take into account the dft functions
#include "tables_nprach_NB_IoT.h"
//#include "PHY/extern.h"
//#include "prach.h"
//#include "PHY/LTE_TRANSPORT/if4_tools.h"
......@@ -39,156 +40,98 @@
//#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;
}
int filter_xx[40] = {-2161, 453, 489, 570, 688, 838, 1014, 1209, 1420, 1639,
1862, 2082, 2295, 2495, 2677, 2837, 2969, 3072, 3142, 3178,
3178, 3142, 3072, 2969, 2837, 2677, 2495, 2295, 2082, 1862,
1639, 1420, 1209, 1014, 838, 688, 570, 489, 453, -2161}; // this is a low-pass filter
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<Nb_packets;k++){
mat_to_detector[k] = (int16_t *)malloc(2*FFT_size*sizeof(int16_t));
mat_from_buffer[k] = (int16_t *)malloc(2*FFT_size*sizeof(int16_t));
mat_energy[k] = (uint32_t *)malloc(n_subcarriers*sizeof(uint32_t));
}
for (k=0;k<Nb_packets;k++){
for (n=0;n<FFT_size;n++){
mat_from_buffer[k][2*n] = Rx_sub_sampled_buffer[k*delta_t+2*n]; // Real part
mat_from_buffer[k][2*n+1] = Rx_sub_sampled_buffer[k*delta_t+2*n+1]; // Imag part
}
// dft_size(int16_t mat_from_buffer[k],int16_t mat_to_detector[k],int scale=1);
switch (sub_sampling_rate){
case 16: // fs = 1.92 MHz
printf("dft16384 not yet implemented\n");
//dft16384(int16_t mat_from_buffer[k],int16_t mat_to_detector[k],int scale=1);
break;
case 32: // fs = 960 kHz
dft8192( mat_from_buffer[k], mat_to_detector[k],1);
break;
case 64: // fs = 480 kHz
dft4096( mat_from_buffer[k], mat_to_detector[k],1);
break;
case 128: // fs = 240 kHz
dft2048( mat_from_buffer[k], mat_to_detector[k],1);
break;
}
}
int16_t buffer_nprach[153600];
int16_t filtered_buffer[153600];
int16_t signal_compensed_re[153600];
int16_t signal_compensed_im[153600];
int16_t output_buffer[4800];
// Calculate the energy of the samples of mat_to_detector
// and concatenate by N_sample_per_sc samples
uint8_t NPRACH_detection_NB_IoT(int16_t *input_buffer,uint32_t input_length){
for (k=0;k<Nb_packets;k++){
for (n=0;n<n_subcarriers;n++){
energy_per_subcarrier = 0;
for (m=0;m<N_sample_per_sc;m++){
energy_per_subcarrier += (uint64_t)mat_to_detector[k][2*n*N_sample_per_sc+2*m]*mat_to_detector[k][2*n*N_sample_per_sc+2*m]
+ (uint64_t)mat_to_detector[k][2*n*N_sample_per_sc+2*m+1]*mat_to_detector[k][2*n*N_sample_per_sc+2*m+1];
}
mat_energy[k][n] = energy_per_subcarrier/N_sample_per_sc;
uint8_t cp_type = 0; // 0: short ; 1: extended
uint32_t nb_signal_samples,nb_noise_samples,n1,n2;
uint64_t energy_signal=0,energy_noise=0;
uint32_t n;
if (energy_per_subcarrier >= threshold_gamma){
is_NPRACH_present = 1;
}
}
}
if(cp_type){
for (k=0;k<Nb_packets;k++){
free(mat_to_detector[k]);
free(mat_from_buffer[k]);
free(mat_energy[k]);
}else{
nb_signal_samples = (uint32_t)(((uint64_t) 62670*input_length)/100000);
nb_noise_samples = input_length - nb_signal_samples;
}
free(mat_to_detector);
free(mat_from_buffer);
free(mat_energy);
n1 = nb_signal_samples;
n2 = nb_noise_samples;
// printf("n samples = %i %i\n",FRAME_LENGTH_COMPLEX_SAMPLESx,nb_signal_samples);
return is_NPRACH_present;
for(n=0;n<nb_signal_samples;n++){
energy_signal += (((uint64_t)input_buffer[2*n]*input_buffer[2*n] + (uint64_t)input_buffer[2*n+1]*input_buffer[2*n+1])/n1);
//energy_signal += (uint64_t)(((uint64_t)input_buffer[2*n]*input_buffer[2*n] + (uint64_t)input_buffer[2*n+1]*input_buffer[2*n+1])/10);
}
for(n=nb_signal_samples;n<input_length;n++){
energy_noise += (((uint64_t)input_buffer[2*n]*input_buffer[2*n] + (uint64_t)input_buffer[2*n+1]*input_buffer[2*n+1])/n2);
//energy_noise += (uint64_t)(((uint64_t)input_buffer[2*n]*input_buffer[2*n] + (uint64_t)input_buffer[2*n+1]*input_buffer[2*n+1])/10);
}
//printf("energies = %ld %ld\n",energy_signal,energy_noise);
if ((uint64_t)(((uint64_t) energy_signal))<(uint64_t)energy_noise>>2){
return 1;
}else{
return 0;
}
}
uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
/*uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB *eNB,
int16_t *Rx_sub_sampled_buffer,
uint16_t sub_sampling_rate,
uint16_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES,
uint32_t estimated_TA_coarse,
char coarse){
uint8_t coarse){
uint16_t length_seq_NPRACH,length_CP,length_symbol; // in number of samples, per NPRACH preamble: 4 sequences ; length of CP in number of samples
uint16_t length_CP_0 = eNB->frame_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
uint16_t length_CP_0 = 2048;//eNB->frame_parms.prach_config_common.nprach_CP_Length; //NB-IoT: 0: short, 1: long
uint32_t fs=30720000; //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;
int64_t 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;
int64_t average_mat_to_phase_re, average_mat_to_phase_im;
float estimated_phase, estimated_CFO, CFO_correction, CFO_correction_k;
// 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;
int16_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;
int32_t A;//,B;
int n,k,m,o;
int32_t pow_n1 = 1;
uint32_t index_av_ph1, index_av_ph2;
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
if (coarse){ // coarse = 1: first estimation at 240 kHz
length_seq_NPRACH = (length_CP_0+5*8192)/128;
length_CP = length_CP_0/128;
length_symbol = 64;
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;
length_correl_window = 80; //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;
fs_sub_sampled = (uint32_t)fs/128;
}else{
length_seq_NPRACH = (length_CP_0+5*8192)/16;
length_CP = length_CP_0/16;
length_symbol = 8192/16;
offset_estimation = 8 * estimated_TA_coarse;
base_length = 32;
// we arbitrarily define the length of correl window as base_length samples.
......@@ -206,21 +149,23 @@ uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
offset_start = offset_estimation-base_length/2;
length_correl_window = base_length;
}
err
fs_sub_sampled = (uint32_t)fs/16;
}
fs_sub_sampled = (uint32_t)fs/sub_sampling_rate;
//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));
//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 = (int16_t *)malloc(4*length_seq_NPRACH*sizeof(int16_t)); /////to do : exact size of tables
signal_CFO_compensed_im = (int16_t *)malloc(4*length_seq_NPRACH*sizeof(int16_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++){
......@@ -229,98 +174,120 @@ uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
}
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));
vec_correlation = (int64_t *)calloc(length_correl_window,sizeof(int64_t));
for (n=0;n<length_correl_window;n++){ // loops over samples %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// MMSE (sub-optimal) CFO estimation /============================================================/
// for (k=0;k<4;k++){ // # sequence
// for (m=0;m<(length_seq_NPRACH-length_CP);m++){
// matrix_received_signal_re[k][m] = Rx_sub_sampled_buffer[2*(n+k*length_seq_NPRACH+length_CP+m)]; // avoid CP for CFO estimation
// matrix_received_signal_im[k][m] = Rx_sub_sampled_buffer[2*(n+k*length_seq_NPRACH+length_CP+m)+1];
// }
// }
average_mat_to_phase_re = 0;
average_mat_to_phase_im = 0;
for (k=0;k<4;k++){ // # sequence
for (o=0;o<4;o++){ // # symbol in sequence
for (m=0;m<length_symbol;m++){
// average_mat_to_phase_re = average_mat_to_phase_re
// - (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_re[k][(o+1)*length_symbol+m]
// - (double)matrix_received_signal_im[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m];
// average_mat_to_phase_im = average_mat_to_phase_im
// - (double)matrix_received_signal_im[k][o*length_symbol+m] * matrix_received_signal_re[k][(o+1)*length_symbol+m]
// + (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m];
for (m=0;m<length_symbol;m++){ ///// creation of two variables for tab indexes "n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m"
index_av_ph1 = (n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)<<1;
index_av_ph2 = index_av_ph1 + (length_symbol<<1);
average_mat_to_phase_re = average_mat_to_phase_re
- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)]
* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)]
- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)+1]
* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)+1];
// - (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_re[k][(o+1)*length_symbol+m]
// - (double)matrix_received_signal_im[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m];
- (int64_t)(Rx_sub_sampled_buffer[index_av_ph1]
* Rx_sub_sampled_buffer[index_av_ph2])
- (int64_t)(Rx_sub_sampled_buffer[index_av_ph1+1]
* Rx_sub_sampled_buffer[index_av_ph2+1]);
average_mat_to_phase_im = average_mat_to_phase_im
- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)+1]
* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)]
+ (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)]
* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)+1];
- (int64_t)(Rx_sub_sampled_buffer[index_av_ph1+1]
* Rx_sub_sampled_buffer[index_av_ph2])
+ (int64_t)(Rx_sub_sampled_buffer[index_av_ph1]
* Rx_sub_sampled_buffer[index_av_ph2+1]);
}
}
}
average_mat_to_phase_re = average_mat_to_phase_re/(16*length_symbol);
average_mat_to_phase_im = average_mat_to_phase_im/(16*length_symbol);
estimated_phase = atan2(average_mat_to_phase_im,average_mat_to_phase_re);
estimated_CFO = ((double)fs*estimated_phase)/(8192*2*M_PI);
estimated_phase = atan2f(average_mat_to_phase_im,average_mat_to_phase_re);
estimated_CFO = ((float)fs*estimated_phase)/(8192*2*(float)M_PI);
CFO_correction = 2*(float)M_PI*estimated_CFO/fs_sub_sampled;
// CFO compensation /============================================================/
for (k=0;k<4*length_seq_NPRACH;k++){
signal_CFO_compensed_re[k] = Rx_sub_sampled_buffer[2*(n+k)] * (int16_t)((double)cos(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767)
- Rx_sub_sampled_buffer[2*(n+k)+1] * (int16_t)((double)sin(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767);
signal_CFO_compensed_im[k] = Rx_sub_sampled_buffer[2*(n+k)] * (int16_t)((double)sin(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767)
+ Rx_sub_sampled_buffer[2*(n+k)+1] * (int16_t)((double)cos(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767);
for (k=0;k<4*length_seq_NPRACH;k++){ ///// creation of two variables for tab indexes /// replace "2*(float)M_PI*estimated_CFO*k/fs_sub_sampled" and "2*(n+offset_start+k)"
CFO_correction_k = (float)k*CFO_correction;
signal_CFO_compensed_re[k] = (int16_t)((Rx_sub_sampled_buffer[(n+offset_start+k)<<1] * (int32_t)(cosf(CFO_correction_k)*32767)
- Rx_sub_sampled_buffer[((n+offset_start+k)<<1)+1] * (int32_t)(sinf(CFO_correction_k)*32767))>>15);
signal_CFO_compensed_im[k] = (int16_t)((Rx_sub_sampled_buffer[(n+offset_start+k)<<1] * (int32_t)(sinf(CFO_correction_k)*32767)
+ Rx_sub_sampled_buffer[((n+offset_start+k)<<1)+1] * (int32_t)(cosf(CFO_correction_k)*32767))>>15);
}
// sub-optimal ML TA estimation /============================================================/
for (k=0;k<4;k++){ // loop over the 4 sequence of a preamble
for (k=0;k<4;k++){ // loop over the 4 sequences of a preamble
pow_n1 = 1;
for (o=0;o<5;o++){ // loop over the symbols of a sequence
for (m=0;m<length_symbol;m++){
sub_sequence_reference_re[k][m] = sub_sequence_reference_re[k][m] + (int32_t)pow(-1,o) * signal_CFO_compensed_re[k*length_seq_NPRACH + o*length_symbol + length_CP + m] / 5; // average over the 5 symbols of a group
sub_sequence_reference_im[k][m] = sub_sequence_reference_im[k][m] + (int32_t)pow(-1,o) * signal_CFO_compensed_im [k*length_seq_NPRACH + o*length_symbol + length_CP + m]/ 5; // average over the 5 symbols of a group
// mon_variable=k*length_seq_NPRACH + o*length_symbol + length_CP + m ///////////////////////////////////////////////////////////////////////////////////////////////
sub_sequence_reference_re[k][m] = sub_sequence_reference_re[k][m] + pow_n1 * signal_CFO_compensed_re[k*length_seq_NPRACH + o*length_symbol + length_CP + m] / 5; // average over the 5 symbols of a group
sub_sequence_reference_im[k][m] = sub_sequence_reference_im[k][m] + pow_n1 * signal_CFO_compensed_im [k*length_seq_NPRACH + o*length_symbol + length_CP + m]/ 5; // average over the 5 symbols of a group
}
pow_n1 = -pow_n1;
}
}
for (k=0;k<4;k++){ // re-initialize sub_sequence_reference matrices
pow_n1 = 1;
for (k=0;k<4;k++){ // loop over the 4 sequences of a preamble
pow_n1 = 1;
for (o=0;o<5;o++){ // loop over the symbols of a sequence // mon_variable=k*length_seq_NPRACH+o*length_symbol +length_CP +m///////////////////////////////////////////////
for (m=0;m<length_symbol;m++){
sequence_reference_re[k*length_seq_NPRACH+o*length_symbol +length_CP +m] = pow_n1 * sub_sequence_reference_re[k][m];
sequence_reference_im[k*length_seq_NPRACH+o*length_symbol +length_CP +m] = pow_n1 * sub_sequence_reference_im[k][m];
}
pow_n1 = -pow_n1;
}
}
for (k=0;k<4;k++){ // loop over the 4 sequences of a preamble
for (m=0;m<length_CP;m++){
sequence_reference_re[k*length_seq_NPRACH+m] = -sub_sequence_reference_re[k][length_symbol-length_CP+m];
sequence_reference_im[k*length_seq_NPRACH+m] = -sub_sequence_reference_im[k][length_symbol-length_CP+m];
}
}
// for (m=0;m<length_seq_NPRACH;m++){
// vec_correlation[n] = vec_correlation[n] + (double)signal_CFO_compensed_re[m] * sequence_reference_re[m] + (double)signal_CFO_compensed_im[m] * sequence_reference_im[m];
// printf("seq=%i\n",sequence_reference_re[m]);
// }
for (m=0;m<4*length_seq_NPRACH;m++){
A = (int64_t)((signal_CFO_compensed_re[m] * sequence_reference_re[m]
+ signal_CFO_compensed_im[m] * sequence_reference_im[m]));
//B = -(int32_t)(((int64_t)signal_CFO_compensed_re[m] * (int64_t)sequence_reference_im[m]
// - (int64_t)signal_CFO_compensed_im[m] * (int64_t)sequence_reference_re[m])>>32);
vec_correlation[n] = vec_correlation[n] + A;//(int32_t)(((int64_t)A*(int64_t)A + 2*(int64_t)B*(int64_t)B)>>32);
}
for (k=0;k<4;k++){ // re-initialize sub_sequence_reference matrices ////////////////////////////////////////////
for (m=0;m<length_symbol;m++){
sub_sequence_reference_re[k][m] = 0;
sub_sequence_reference_im[k][m] = 0;
}
}
for (m=0;m<length_seq_NPRACH;m++){
vec_correlation[n] = vec_correlation[n] + (double)signal_CFO_compensed_re[m] * sequence_reference_re[m] + (double)signal_CFO_compensed_im[m] * sequence_reference_im[m];
}
}
for (n=0;n<length_correl_window;n++){
//printf("\ncorr=%li \n",vec_correlation[n]);
if(vec_correlation[n]>=max_correlation){
max_correlation = vec_correlation[n];
TA_sample_estimated = n;
TA_sample_estimated = offset_start+ n;
}
}
free(vec_correlation);
free(vec_correlation);
for (k=0;k<4;k++){ // # sequence
free(matrix_received_signal_re[k]);
free(matrix_received_signal_im[k]);
//free(matrix_received_signal_re[k]);
err//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(matrix_received_signal_re);
//free(matrix_received_signal_im);
free(signal_CFO_compensed_re);
free(signal_CFO_compensed_im);
free(sub_sequence_reference_re);
......@@ -328,66 +295,119 @@ uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
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){
int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate){ // void function ////// adding flag for switching between output_buffers
int k;
uint32_t L;
int16_t *output_buffer;
L = (uint32_t)((double)length_input / sub_sampling_rate);
*length_ouput = L;
//int16_t *output_buffer;
int16_t *p_output_buffer;
L = (uint32_t)(length_input / sub_sampling_rate);
*length_ouput = L; ///// to remove
output_buffer = (int16_t *)malloc(2*L*sizeof(int16_t));
for (k=0;k<L;k++){
output_buffer[2*k] = input_buffer[sub_sampling_rate*(2*k)];
output_buffer[2*k+1] = input_buffer[sub_sampling_rate*(2*k)+1];
output_buffer[k<<1] = input_buffer[sub_sampling_rate*(k<<1)];
output_buffer[(k<<1)+1] = input_buffer[sub_sampling_rate*(k<<1)+1];
}
// for (k=0;k<2*L;k++){
// printf("%i\n",output_buffer[k]);
// }
p_output_buffer=output_buffer;
return p_output_buffer;
}
void filtering_signal(int16_t *input_buffer, int16_t *filtered_buffer, uint32_t FRAME_LENGTH_COMPLEX_SAMPLESx){
int n,k;
//float f_s_RB22 = 1807.5;
//float f_s = 7680;
//int16_t *signal_compensed_re, *signal_compensed_im;
int16_t *cos_x, *sin_x;
cos_x = cos_x_rb22;
sin_x = sin_x_rb22;
for (n=0;n<FRAME_LENGTH_COMPLEX_SAMPLESx;n++){
signal_compensed_re[n] = (int16_t)((input_buffer[n<<1] * (int32_t)(cos_x[n])
+ input_buffer[(n<<1)+1] * (int32_t)(sin_x[n]))>>15);
signal_compensed_im[n] = (int16_t)((- input_buffer[n<<1] * (int32_t)(sin_x[n])
+ input_buffer[(n<<1)+1] * (int32_t)(cos_x[n]))>>15);
}
return output_buffer;
for (n=0;n<FRAME_LENGTH_COMPLEX_SAMPLESx-10;n++){
if (n<20){
for (k=-n;k<20;k++){
filtered_buffer[n<<1] = filtered_buffer[n<<1] + (int16_t)(((int32_t)filter_xx[20+k]*(int32_t)signal_compensed_re[n+k])>>15);
filtered_buffer[(n<<1)+1] = filtered_buffer[(n<<1)+1] + (int16_t)(((int32_t)filter_xx[20+k]*(int32_t)signal_compensed_im[n+k])>>15);
}
}else{
for (k=-20;k<20;k++){
filtered_buffer[n<<1] = filtered_buffer[n<<1] + (int16_t)(((int32_t)filter_xx[20+k]*(int32_t)signal_compensed_re[n+k])>>15);
filtered_buffer[(n<<1)+1] = filtered_buffer[(n<<1)+1] + (int16_t)(((int32_t)filter_xx[20+k]*(int32_t)signal_compensed_im[n+k])>>15);
}
}
}
}
void RX_NPRACH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_buffer){
uint32_t RX_NPRACH_NB_IoT(PHY_VARS_eNB *eNB, int frame){
uint32_t estimated_TA =0;
uint32_t estimated_TA_coarse=0;
uint32_t estimated_TA;
int16_t *Rx_sub_sampled_buffer_128,*Rx_sub_sampled_buffer_16;
uint16_t sub_sampling_rate; //NB-IoT: to be defined somewhere
uint32_t FRAME_LENGTH_COMPLEX_SAMPLESx=0; // NB-IoT: length of input buffer, to be defined somewhere
uint32_t FRAME_LENGTH_COMPLEX_SAMPLESx; // NB-IoT: length of input buffer, to be defined somewhere
uint32_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES; // Length of buffer after sub-sampling
uint32_t *length_ouput; // Length of buffer after sub-sampling
char coarse=1; // flag that indicate the level of TA estimation
uint8_t coarse=1; // flag that indicate the level of TA estimation
int16_t *Rx_buffer;
//int16_t *filtered_buffer;
int n;
//// 1. Coarse TA estimation using sub sampling rate = 128, i.e. fs = 240 kHz
FRAME_LENGTH_COMPLEX_SAMPLESx = 10*eNB->frame_parms.samples_per_tti;
Rx_buffer = (int16_t*)&eNB->common_vars.rxdata[0][0][0]; // get the whole frame
/* 1. Coarse TA estimation using sub sampling rate = 128, i.e. fs = 240 kHz */
memcpy(&buffer_nprach[0],&Rx_buffer[0],307200);
//filtered_buffer = (int16_t *)calloc(2*FRAME_LENGTH_COMPLEX_SAMPLESx,sizeof(int16_t)); // calcule du taille exacte du tableau 76800
memset(filtered_buffer,0,307200);
filtering_signal(buffer_nprach,filtered_buffer,FRAME_LENGTH_COMPLEX_SAMPLESx);
// Sub-sampling stage /============================================================/
sub_sampling_rate = 128;
sub_sampling_rate = FRAME_LENGTH_COMPLEX_SAMPLESx/2400; // gives the sub-sampling rate leading to f=240 kHz
length_ouput = &FRAME_LENGTH_COMPLEX_SUB_SAMPLES;
Rx_sub_sampled_buffer_128 = sub_sampling_NB_IoT(Rx_buffer,FRAME_LENGTH_COMPLEX_SAMPLESx,length_ouput, sub_sampling_rate);
Rx_sub_sampled_buffer_128 = sub_sampling_NB_IoT(filtered_buffer,FRAME_LENGTH_COMPLEX_SAMPLESx,length_ouput, sub_sampling_rate);
// Detection and TA estimation stage /============================================================/
if (NPRACH_detection_NB_IoT(eNB, Rx_sub_sampled_buffer_128, sub_sampling_rate,FRAME_LENGTH_COMPLEX_SUB_SAMPLES)){
if (NPRACH_detection_NB_IoT(Rx_sub_sampled_buffer_128,*length_ouput)){
estimated_TA_coarse = TA_estimation_NB_IoT(eNB,
/*estimated_TA_coarse = TA_estimation_NB_IoT(eNB,
Rx_sub_sampled_buffer_128,
sub_sampling_rate,
FRAME_LENGTH_COMPLEX_SUB_SAMPLES,
estimated_TA_coarse,
coarse);
/* 2. Fine TA estimation using sub sampling rate = 16, i.e. fs = 240 MHz */
// 2. Fine TA estimation using sub sampling rate = 16, i.e. fs = 1.92 MHz
// Sub-sampling stage /============================================================/
sub_sampling_rate = 16;
Rx_sub_sampled_buffer_16 = sub_sampling_NB_IoT(Rx_buffer,FRAME_LENGTH_COMPLEX_SAMPLESx,length_ouput, sub_sampling_rate);
/*sub_sampling_rate = FRAME_LENGTH_COMPLEX_SAMPLESx/(2400*8);
Rx_sub_sampled_buffer_16 = sub_sampling_NB_IoT(filtered_buffer,FRAME_LENGTH_COMPLEX_SAMPLESx,length_ouput, sub_sampling_rate);
// Fine TA estimation stage /============================================================/
......@@ -398,10 +418,24 @@ void RX_NPRACH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_buffer){
sub_sampling_rate,
FRAME_LENGTH_COMPLEX_SUB_SAMPLES,
estimated_TA_coarse,
coarse);
coarse); */
// Needs to be stored in a variable in PHY_VARS_eNB_NB_IoT structure
}
//for (n=0;n<FRAME_LENGTH_COMPLEX_SAMPLESx;n++){
//printf(" buf%i= %i",n,Rx_sub_sampled_buffer_128[2*n]);
// fprintf(f," %i %i ",Rx_buffer[2*n],Rx_buffer[2*n+1]);
//fprintf(f,"%i \n",Rx_buffer[2*n+1]);
//}*/
printf("\ndetection !!! est_TA = %i ---- %i\n",estimated_TA_coarse,estimated_TA);
return 1;//estimated_TA;
}else{
return 0;
}
// }
return 0;
}
......@@ -282,18 +282,20 @@ void ulsch_extract_rbs_single_NB_IoT(int32_t **rxdataF,
void extract_CQI_NB_IoT(void *o,UCI_format_NB_IoT_t uci_format,NB_IoT_eNB_UE_stats *stats,uint8_t N_RB_DL, uint16_t * crnti, uint8_t * access_mode);
//*****************Vincent part for nprach ******************//
void RX_NPRACH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_buffer);
uint32_t RX_NPRACH_NB_IoT(PHY_VARS_eNB *eNB, int frame);
uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB *eNB,
int16_t *Rx_sub_sampled_buffer,
uint16_t sub_sampling_rate,
uint16_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES,
uint32_t estimated_TA_coarse,
char coarse);
uint8_t coarse);
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);
uint8_t NPRACH_detection_NB_IoT(int16_t *input_buffer,uint32_t FRAME_LENGTH_COMPLEX_SAMPLESx);
int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate);
int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate);
void filtering_signal(int16_t *input_buffer, int16_t *filtered_buffer, uint32_t FRAME_LENGTH_COMPLEX_SAMPLESx);
//************************************************************//
//*****************Vincent part for ULSCH demodulation ******************//
uint16_t get_UL_sc_start_NB_IoT(uint16_t I_sc);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -48,6 +48,8 @@ uint32_t is_SIB1_NB_IoT(const frame_t frameP,
NB_IoT_eNB_NDLSCH_t *ndlsch_SIB1
);
void nprach_procedures_NB_IoT(PHY_VARS_eNB *eNB);
#endif
......@@ -2022,12 +2022,12 @@ void prach_procedures(PHY_VARS_eNB *eNB) {
int frame = eNB->proc.frame_prach;
uint8_t CC_id = eNB->CC_id;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
/*VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));*/
if (eNB->abstraction_flag == 0) {
LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id,
/*LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id,
frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB);
......@@ -2035,11 +2035,13 @@ void prach_procedures(PHY_VARS_eNB *eNB) {
preamble_energy_list,
preamble_delay_list,
frame,
0);
0);*/
//usleep(100);
nprach_procedures_NB_IoT(eNB);
} else {
for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
/*LOG_D(PHY,"[RAPROC] UE_id %d (%p), generate_prach %d, UE RSI %d, eNB RSI %d preamble index %d\n",
UE_id,PHY_vars_UE_g[UE_id][CC_id],PHY_vars_UE_g[UE_id][CC_id]->generate_prach,
PHY_vars_UE_g[UE_id][CC_id]->frame_parms.prach_config_common.rootSequenceIndex,
fp->prach_config_common.rootSequenceIndex,
......@@ -2051,11 +2053,11 @@ void prach_procedures(PHY_VARS_eNB *eNB) {
preamble_energy_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 800;
preamble_delay_list[PHY_vars_UE_g[UE_id][CC_id]->prach_PreambleIndex] = 5;
}
}*/
}
}
preamble_energy_max = preamble_energy_list[0];
/*preamble_energy_max = preamble_energy_list[0];
preamble_max = 0;
for (i=1; i<64; i++) {
......@@ -2132,7 +2134,7 @@ void prach_procedures(PHY_VARS_eNB *eNB) {
eNB->Mod_id,frame, subframe);
}
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);*/
}
void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,uint8_t do_srs)
......@@ -2846,8 +2848,10 @@ void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe) {
eNB_proc_t *proc = &eNB->proc;
LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
if(frame%2==0 && subframe==9)
{
// check if we have to detect PRACH first
if (is_prach_subframe(fp,frame,subframe)>0) {
//if (is_prach_subframe(fp,frame,subframe)>0) {
/* accept some delay in processing - up to 5ms */
int i;
for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
......@@ -2879,7 +2883,8 @@ void do_prach(PHY_VARS_eNB *eNB,int frame,int subframe) {
}
pthread_mutex_unlock( &proc->mutex_prach );
}
//}
}
}
......
......@@ -1514,4 +1514,23 @@ void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
}
}
}
void nprach_procedures_NB_IoT(PHY_VARS_eNB *eNB) {
uint32_t estimated_TA;
int subframe,frame,frame_mod;
subframe = eNB->proc.subframe_prach;
frame = eNB->proc.frame_prach;
//printf("frame = %i \n sf = %i\n",frame,subframe);
frame_mod = 0;//(frame)%32;
//if (subframe==1 && frame_mod==0 && frame!=0){
if (frame_mod==0 && frame!=0){
//printf("\n frame_in = %i\n",frame);
estimated_TA = RX_NPRACH_NB_IoT(eNB,frame);
//printf("estim = %i\n",estimated_TA);
}
}
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment