From 4e55c9da6df0f1258354355f3589335924fa4b70 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Mon, 14 Jan 2019 18:16:20 +0100 Subject: [PATCH 01/11] CFO included in pbchsim --- openair1/SIMULATION/NR_PHY/pbchsim.c | 55 ++++++++++++++++++++++++++-- openair1/SIMULATION/RF/rf.c | 4 +- 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 8d847787e6..7b0b8c02ee 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -87,10 +87,12 @@ int main(int argc, char **argv) int i,l,aa; double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0; + double cfo=0; uint8_t snr1set=0; int **txdata; double **s_re,**s_im,**r_re,**r_im; double iqim = 0.0; + double ip =0.0; unsigned char pbch_pdu[6]; // int sync_pos, sync_pos_slot; // FILE *rx_frame_file; @@ -118,7 +120,7 @@ int main(int argc, char **argv) double pbch_sinr; int pbch_tx_ant; - int N_RB_DL=273,mu=1; + int N_RB_DL=106,mu=1; unsigned char frame_type = 0; unsigned char pbch_phase = 0; @@ -144,7 +146,7 @@ int main(int argc, char **argv) randominit(0); - while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { + while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) { switch (c) { case 'f': write_output_file=1; @@ -210,6 +212,11 @@ int main(int argc, char **argv) n_trials = atoi(optarg); break; + case 'o': + cfo = atof(optarg); + msg("Setting CFO to %f Hz\n",cfo); + break; + case 's': snr0 = atof(optarg); msg("Setting SNR0 to %f\n",snr0); @@ -323,6 +330,7 @@ int main(int argc, char **argv) printf("-z Number of RX antennas used in UE\n"); printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n"); printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n"); + printf("-o Carrier frequency offset in Hz\n"); printf("-N Nid_cell\n"); printf("-R N_RB_DL\n"); printf("-O oversampling factor (1,2,4,8,16)\n"); @@ -358,26 +366,43 @@ int main(int argc, char **argv) nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu); phy_init_nr_gNB(gNB,0,0); - double fs,bw; + double fs,bw,scs,eps; if (mu == 1 && N_RB_DL == 217) { fs = 122.88e6; bw = 80e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 245) { fs = 122.88e6; bw = 90e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 273) { fs = 122.88e6; bw = 100e6; + scs = 30000; } else if (mu == 1 && N_RB_DL == 106) { fs = 61.44e6; bw = 40e6; + scs = 30000; } else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL); + // cfo with respect to sub-carrier spacing + eps = cfo/scs; + int IFO; + + if(eps!=0.0){ + printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000)); + if (eps>0) + IFO=(int)(eps+0.5); + else + IFO=(int)(eps-0.5); + printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO); + } + gNB2UE = new_channel_desc_scm(n_tx, n_rx, channel_model, @@ -490,6 +515,7 @@ int main(int argc, char **argv) // printf("txlev %d (%f)\n",txlev,10*log10(txlev)); + for (i=0; inb_antennas_tx; aa++) { r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); @@ -511,7 +537,30 @@ int main(int argc, char **argv) sigma2_dB = 10*log10((double)txlev)-SNR; sigma2 = pow(10,sigma2_dB/10); // printf("sigma2 %f (%f dB)\n",sigma2,sigma2_dB); + + if(eps!=0.0) + rf_rx(r_re, // real part of txdata + r_im, // imag part of txdata + NULL, // interference real part + NULL, // interference imag part + 0, // interference power + frame_parms->nb_antennas_rx, // number of rx antennas + frame_length_complex_samples, // number of samples in frame + 1.0e7/frame_length_complex_samples, //sampling time (ns) + cfo, // frequency offset in Hz + 0.0, // drift (not implemented) + 0.0, // noise figure (not implemented) + 0.0, // rx gain in dB ? + 200, // 3rd order non-linearity in dB ? + &ip, // initial phase + 30.0e3, // phase noise cutoff in kHz + -500.0, // phase noise amplitude in dBc + 0.0, // IQ imbalance (dB), + 0.0); // IQ phase imbalance (rad) + + + for (i=0; inb_antennas_rx; aa++) { diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c index e317fbd154..bff3453de0 100644 --- a/openair1/SIMULATION/RF/rf.c +++ b/openair1/SIMULATION/RF/rf.c @@ -107,10 +107,10 @@ void rf_rx(double **r_re, exit(-1); } - if (fabs(f_off) > 10000.0) { +/* if (fabs(f_off) > 10000.0) { printf("rf.c: Illegal f_off %f\n",f_off); exit(-1); - } + }*/ if (fabs(drift) > 1000.0) { printf("rf.c: Illegal drift %f\n",drift); From 70f973b57f4f5643a327b5cca6f44dbe97d870ee Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 17 Jan 2019 11:29:44 +0100 Subject: [PATCH 02/11] 1st version of CFO estimation --- openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 19 +++++++++++++++---- openair1/PHY/TOOLS/cdot_prod.c | 12 ++++-------- openair1/SIMULATION/NR_PHY/pbchsim.c | 7 +++---- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 5ac83b5280..43c1de71a2 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -33,6 +33,7 @@ #include #include #include +#include #include "PHY/defs_nr_UE.h" @@ -751,6 +752,15 @@ static inline int64_t abs64(int64_t x) return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t)((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1])); } +static inline double angle64(int64_t x) +{ + + double re=((int32_t*)&x)[0]; + double im=((int32_t*)&x)[1]; + return (atan2(im,re)); +} + + /******************************************************************* * * NAME : pss_search_time_nr @@ -811,6 +821,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain int64_t peak_value; int64_t result; int64_t avg[NUMBER_PSS_SEQUENCE]; + double ffo_est; unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */ @@ -859,7 +870,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain frame_parms->ofdm_symbol_size, shift); pss_corr_ue[pss_index][n] += abs64(result); - //((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0]; /* real part */ //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */ //((short*)&synchro_out)[0] += ((short*) &result)[0]; /* real part */ @@ -874,10 +884,11 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain peak_value = pss_corr_ue[pss_index][n]; peak_position = n; pss_source = pss_index; + ffo_est = angle64(result)/M_PI; -#ifdef DEBUG_PSS_NR - printf("pss_index %d: n %6d peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n]); -#endif +//#ifdef DEBUG_PSS_NR + printf("pss_index %d: n %6d peak_value %15llu ffo %lf\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n],ffo_est); +//#endif } } } diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index 63b74afe6d..2e23247141 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -19,6 +19,7 @@ * contact@openairinterface.org */ +#include #include "tools_defs.h" #include "PHY/sse_intrin.h" @@ -169,7 +170,7 @@ int64_t dot_product64(int16_t *x, #if defined(__x86_64__) || defined(__i386__) __m128i *x128,*y128,mmtmp1,mmtmp2,mmtmp3,mmcumul,mmcumul_re,mmcumul_im; __m128i minus_i = _mm_set_epi16(-1,1,-1,1,-1,1,-1,1); - int32_t result; + int64_t result; x128 = (__m128i*) x; y128 = (__m128i*) y; @@ -180,14 +181,13 @@ int64_t dot_product64(int16_t *x, for (n=0; n<(N>>2); n++) { // printf("n=%d, x128=%p, y128=%p\n",n,x128,y128); - // print_shorts("x",&x128[0]); - // print_shorts("y",&y128[0]); + // print_shorts("x",&x128[0]); + // print_shorts("y",&y128[0]); // this computes Re(z) = Re(x)*Re(y) + Im(x)*Im(y) mmtmp1 = _mm_madd_epi16(x128[0],y128[0]); // print_ints("retmp",&mmtmp1); // mmtmp1 contains real part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp1 = _mm_srai_epi32(mmtmp1,output_shift); mmcumul_re = _mm_add_epi32(mmcumul_re,mmtmp1); @@ -205,7 +205,6 @@ int64_t dot_product64(int16_t *x, mmtmp3 = _mm_madd_epi16(x128[0],mmtmp2); //print_ints("imtmp",&mmtmp3); // mmtmp3 contains imag part of 4 consecutive outputs (32-bit) - // shift and accumulate results mmtmp3 = _mm_srai_epi32(mmtmp3,output_shift); mmcumul_im = _mm_add_epi32(mmcumul_im,mmtmp3); @@ -218,13 +217,10 @@ int64_t dot_product64(int16_t *x, // this gives Re Re Im Im mmcumul = _mm_hadd_epi32(mmcumul_re,mmcumul_im); //print_ints("cumul1",&mmcumul); - // this gives Re Im Re Im mmcumul = _mm_hadd_epi32(mmcumul,mmcumul); - //print_ints("cumul2",&mmcumul); - //mmcumul = _mm_srai_epi32(mmcumul,output_shift); // extract the lower half result = _mm_extract_epi64(mmcumul,0); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 7b0b8c02ee..a717b820d8 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -392,8 +392,9 @@ int main(int argc, char **argv) // cfo with respect to sub-carrier spacing eps = cfo/scs; - int IFO; + // computation of integer and fractional FO to compare with estimation results + int IFO; if(eps!=0.0){ printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000)); if (eps>0) @@ -546,7 +547,7 @@ int main(int argc, char **argv) 0, // interference power frame_parms->nb_antennas_rx, // number of rx antennas frame_length_complex_samples, // number of samples in frame - 1.0e7/frame_length_complex_samples, //sampling time (ns) + 1.0e9/fs, //sampling time (ns) cfo, // frequency offset in Hz 0.0, // drift (not implemented) 0.0, // noise figure (not implemented) @@ -558,8 +559,6 @@ int main(int argc, char **argv) 0.0, // IQ imbalance (dB), 0.0); // IQ phase imbalance (rad) - - for (i=0; inb_antennas_rx; aa++) { From 35dc0857c4d9bb0a2b2e46cd2765a7da262f0052 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Tue, 22 Jan 2019 10:46:45 +0100 Subject: [PATCH 03/11] working version of FFO estimation --- openair1/PHY/NR_REFSIG/pss_nr.h | 3 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 5 +- openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 53 +++++++++++++++---- openair1/PHY/TOOLS/cdot_prod.c | 1 - openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 +-- openair1/SIMULATION/NR_PHY/pbchsim.c | 3 +- targets/RT/USER/nr-ue.c | 7 +-- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 2f39f26ee4..279f9e417a 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -137,7 +137,8 @@ int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id); + int *eNB_id, + int *f_off); #endif #undef EXTERN diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 50a283f465..c7c66bc7b5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -244,7 +244,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) ret = -1; } - /* Consider this is a false detection if the offset is > 1000 Hz */ + /* Consider this is a false detection if the offset is > 1000 Hz + Not to be used now that offest estimation is in place if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) { ret=-1; @@ -253,7 +254,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) #else LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); #endif - } + }*/ if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 43c1de71a2..38beb6f539 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -706,7 +706,9 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, - (int *)&PHY_vars_UE->common_vars.eNb_id); + (int *)&PHY_vars_UE->common_vars.eNb_id, + (int *)&PHY_vars_UE->common_vars.freq_offset); + #if TEST_SYNCHRO_TIMING_PSS @@ -815,11 +817,12 @@ static inline double angle64(int64_t x) int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id) + int *eNB_id, + int *f_off) { unsigned int n, ar, peak_position, pss_source; int64_t peak_value; - int64_t result; + int64_t result,result1,result2; int64_t avg[NUMBER_PSS_SEQUENCE]; double ffo_est; @@ -842,7 +845,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain maxval = max(maxval,-primary_synchro_time_nr[1][i]); maxval = max(maxval,primary_synchro_time_nr[2][i]); maxval = max(maxval,-primary_synchro_time_nr[2][i]); - } int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2); @@ -877,27 +879,58 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } - + /* calculate the absolute value of sync_corr[n] */ avg[pss_index]+=pss_corr_ue[pss_index][n]; if (pss_corr_ue[pss_index][n] > peak_value) { peak_value = pss_corr_ue[pss_index][n]; peak_position = n; pss_source = pss_index; - ffo_est = angle64(result)/M_PI; -//#ifdef DEBUG_PSS_NR - printf("pss_index %d: n %6d peak_value %15llu ffo %lf\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n],ffo_est); -//#endif +#ifdef DEBUG_PSS_NR + printf("pss_index %d: n %6d peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n]); +#endif } } } + + // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + + // Computing cross-correlation at peak on half the symbol size for first half of data + result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], + (short*) &(rxdata[0][peak_position]), + frame_parms->ofdm_symbol_size>>1, + shift); + // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size + // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift + result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), + (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), + frame_parms->ofdm_symbol_size>>1, + shift); + + int64_t re1,re2,im1,im2; + re1=((int*) &result1)[0]; + re2=((int*) &result2)[0]; + im1=((int*) &result1)[1]; + im2=((int*) &result2)[1]; + + // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; + +#ifdef DBG_PSS_NR + printf("ffo %lf\n",ffo_est); +#endif + + // computing absolute value of frequency offset + *f_off = ffo_est*frame_parms->subcarrier_spacing; + for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4); *eNB_id = pss_source; - LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source])); + LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est); if (peak_value < 5*avg[pss_source]) return(-1); diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index 2e23247141..843a9605f1 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -19,7 +19,6 @@ * contact@openairinterface.org */ -#include #include "tools_defs.h" #include "PHY/sse_intrin.h" diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index a9bc8cd62b..e232a0b5c9 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -139,20 +139,20 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) { LOG_D(PHY,"SS TX: frame %d, subframe %d, start_symbol %d\n",frame,subframe, ssb_start_symbol); nr_generate_pss(gNB->d_pss, txdataF, AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(gNB->d_sss, txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_sss(gNB->d_sss, txdataF, AMP, ssb_start_symbol, cfg, fp); if (!(frame&7)){ LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,subframe,gNB->pbch_configured); if (gNB->pbch_configured != 1)return; gNB->pbch_configured = 0; } - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP, ssb_start_symbol, cfg, fp); nr_generate_pbch(&gNB->pbch, gNB->nrPolar_params, pbch_pdu, gNB->nr_pbch_interleaver, txdataF, - AMP_OVER_2, + AMP, ssb_start_symbol, n_hf,Lmax,ssb_index, frame, cfg, fp); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index a717b820d8..94d1e7dc42 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -120,7 +120,7 @@ int main(int argc, char **argv) double pbch_sinr; int pbch_tx_ant; - int N_RB_DL=106,mu=1; + int N_RB_DL=273,mu=1; unsigned char frame_type = 0; unsigned char pbch_phase = 0; @@ -538,7 +538,6 @@ int main(int argc, char **argv) sigma2_dB = 10*log10((double)txlev)-SNR; sigma2 = pow(10,sigma2_dB/10); // printf("sigma2 %f (%f dB)\n",sigma2,sigma2_dB); - if(eps!=0.0) rf_rx(r_re, // real part of txdata r_im, // imag part of txdata diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index ed55e15d3c..a81d428992 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -444,6 +444,7 @@ static void *UE_thread_synch(void *arg) { //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_subframe), 1, 1); + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe; printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", hw_slot_offset, @@ -459,13 +460,13 @@ static void *UE_thread_synch(void *arg) { openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; if (UE->UE_scan_carrier == 1) { if (freq_offset >= 0) - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); else - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - freq_offset=0; + //freq_offset=0; } } From 7405eec0f159c31394713684accf04cd9ea26ced Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 23 Jan 2019 11:40:52 +0100 Subject: [PATCH 04/11] USRP now takes ffo estimation into account --- openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 4 ++-- targets/RT/USER/nr-ue.c | 3 --- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index c7c66bc7b5..5999bab5bb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -330,13 +330,13 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); # else LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", ue->Mod_id, ue->proc.proc_rxtx[0].frame_rx, - openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset, + openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset, ue->common_vars.freq_offset); # endif #endif diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index a81d428992..034098a6ca 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -458,7 +458,6 @@ static void *UE_thread_synch(void *arg) { // rerun with new cell parameters and frequency-offset for (i=0; irf_map.card].rx_num_channels; i++) { openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - if (UE->UE_scan_carrier == 1) { if (freq_offset >= 0) openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); else @@ -466,8 +465,6 @@ static void *UE_thread_synch(void *arg) { openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - //freq_offset=0; - } } // reconfigure for potentially different bandwidth From 832eb3dc50df4cf5b5f0da51efa7a518264c09aa Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Fri, 1 Feb 2019 16:42:11 +0100 Subject: [PATCH 05/11] digital compensation of FFO on PBCH symbols (works only for FFO less than 0.5) --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 28 +++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index af23474609..f8f6045620 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -39,6 +39,7 @@ //#include "SCHED/extern.h" #include "common_lib.h" +#include #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" @@ -55,6 +56,8 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; + int ar, n; + double im, re; #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, @@ -65,6 +68,27 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples; + // digital compensation of FFO for PBCH symbols + if(abs(2*ue->common_vars.freq_offset)subcarrier_spacing){ // this FFO compensation seems to work only for FFO between -0.5 and 0.5 + + int size_wp = (frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0); // symbol size including prefix + double s_time = 1/(1.0e3*frame_parms->samples_per_subframe); // sampling time + double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample + + int start = ue->ssb_offset + size_wp; // start for offset correction is one symbol after ssb_offset (pss time position), including prefix + int end = start + (3*size_wp); // loop over samples in 3 symbols, including prefix + + for(n=start; nnb_antennas_rx; ar++) { + re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); + im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); + ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); + ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); + } + } + } + + //symbol 1 nr_slot_fep(ue, 1, @@ -183,14 +207,14 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE); sync_pos_slot = (fp->samples_per_subframe/fp->slots_per_subframe) - 10*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - + if (sync_pos >= fp->nb_prefix_samples){ ue->ssb_offset = sync_pos - fp->nb_prefix_samples;} else{ ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;} ue->rx_offset = ue->ssb_offset - sync_pos_slot; - + //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); #ifdef DEBUG_INITIAL_SYNCH From 5c1c45dfe76a4202fd49f40ec5997b8f47c7d074 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Wed, 6 Feb 2019 17:03:09 +0100 Subject: [PATCH 06/11] digital compensation of FFO moved before SSS detection --- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index f8f6045620..78a2f0c82d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -56,8 +56,7 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) { NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int ret =-1; - int ar, n; - double im, re; + #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, @@ -68,26 +67,6 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode) int nb_prefix_samples0 = frame_parms->nb_prefix_samples0; frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples; - // digital compensation of FFO for PBCH symbols - if(abs(2*ue->common_vars.freq_offset)subcarrier_spacing){ // this FFO compensation seems to work only for FFO between -0.5 and 0.5 - - int size_wp = (frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0); // symbol size including prefix - double s_time = 1/(1.0e3*frame_parms->samples_per_subframe); // sampling time - double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample - - int start = ue->ssb_offset + size_wp; // start for offset correction is one symbol after ssb_offset (pss time position), including prefix - int end = start + (3*size_wp); // loop over samples in 3 symbols, including prefix - - for(n=start; nnb_antennas_rx; ar++) { - re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); - im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); - ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); - ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); - } - } - } - //symbol 1 nr_slot_fep(ue, @@ -167,6 +146,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2, int32_t metric_tdd_ncp=0; uint8_t phase_tdd_ncp; + double im, re; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; int ret=-1; @@ -213,7 +193,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) else{ ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;} - ue->rx_offset = ue->ssb_offset - sync_pos_slot; + ue->rx_offset = ue->ssb_offset - sync_pos_slot; //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); @@ -222,6 +202,23 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot); #endif + // digital compensation of FFO for SSB symbols + double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time + double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample + + int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position) + int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix + + for(int n=start; nnb_antennas_rx; ar++) { + re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); + im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); + ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); + ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); + } + } + + /* check that SSS/PBCH block is continuous inside the received buffer */ if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) { From df0b95536d206dbd2e625ff62b62c3f420682aae Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Tue, 5 Feb 2019 11:59:46 +0100 Subject: [PATCH 07/11] Fix debugging of nr_dlsch_coding --- openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c index 0d59207480..20b087facd 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c +++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c @@ -280,7 +280,7 @@ int nr_dlsch_encoding(unsigned char *a, uint32_t A, Z; uint32_t *pz = &Z; uint8_t mod_order = rel15.modulation_order; - uint16_t Kr=0,r,r_offset=0;//Kr_bytes + uint16_t Kr=0,r,r_offset=0,Kr_bytes; uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS]; uint8_t kb,BG=1; uint32_t E; @@ -346,7 +346,7 @@ int nr_dlsch_encoding(unsigned char *a, } Kr = dlsch->harq_processes[harq_pid]->K; - //Kr_bytes = Kr>>3; + Kr_bytes = Kr>>3; //printf("segment Z %d kb %d k %d Kr %d BG %d\n", *pz,kb,dlsch->harq_processes[harq_pid]->K,Kr,BG); @@ -403,7 +403,7 @@ int nr_dlsch_encoding(unsigned char *a, //start_meas(rm_stats); #ifdef DEBUG_DLSCH_CODING - printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx); + printf("rvidx in encoding = %d\n", rel15.redundancy_version); #endif E = nr_rate_matching_ldpc(Ilbrm, @@ -421,7 +421,7 @@ int nr_dlsch_encoding(unsigned char *a, #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i], r_offset); + printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset); #endif //stop_meas(rm_stats); @@ -432,18 +432,15 @@ int nr_dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->f+r_offset); //stop_meas(i_stats); - r_offset += E; #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) - printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r*r_offset], r_offset); -#endif - -#ifdef DEBUG_DLSCH_CODING + printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset); if (r==dlsch->harq_processes[harq_pid]->C-1) - write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,r_offset,1,4); - + write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4); #endif + + r_offset += E; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT); From 268d1c8d1708647dd63d9eddc8001715d7748c81 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 7 Feb 2019 11:14:16 +0100 Subject: [PATCH 08/11] Fix order of DLSCH deinterleaving and rate matching On the gNB side tha data are first rate-matched and then interleaved. So on the UE side, the received LLRs have to be deinterleaved first before rate-matching. This significantly improved the performance, especially for MCS values > 3. --- openair1/PHY/CODING/coding_defs.h | 33 +-- openair1/PHY/CODING/nr_rate_matching.c | 104 +++----- openair1/PHY/NR_TRANSPORT/nr_dlsch.h | 2 + openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c | 23 +- openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c | 15 ++ .../PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c | 246 +++++++++--------- 6 files changed, 198 insertions(+), 225 deletions(-) diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h index 2040faf4a2..0f316e7869 100644 --- a/openair1/PHY/CODING/coding_defs.h +++ b/openair1/PHY/CODING/coding_defs.h @@ -467,33 +467,26 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f); void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f); -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r); +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E); int nr_rate_matching_ldpc_rx(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, int16_t *w, int16_t *soft_input, uint8_t C, uint8_t rvidx, uint8_t clear, - uint8_t Qm, - uint8_t Nl, - uint8_t r, - uint32_t *E_out); + uint32_t E); decoder_if_t phy_threegpplte_turbo_decoder; decoder_if_t phy_threegpplte_turbo_decoder8; diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c index 01390f1f2f..0bce31630f 100644 --- a/openair1/PHY/CODING/nr_rate_matching.c +++ b/openair1/PHY/CODING/nr_rate_matching.c @@ -63,55 +63,39 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f) } -uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm, - uint32_t Tbslbrm, - uint8_t BG, - uint16_t Z, - uint32_t G, - uint8_t *w, - uint8_t *e, - uint8_t C, - uint8_t rvidx, - uint8_t Qm, - uint8_t Nl, - uint8_t r) +int nr_rate_matching_ldpc(uint8_t Ilbrm, + uint32_t Tbslbrm, + uint8_t BG, + uint16_t Z, + uint8_t *w, + uint8_t *e, + uint8_t C, + uint8_t rvidx, + uint32_t E) { - uint8_t Cprime; - uint32_t Ncb,E,ind,k,Nref,N; - //uint8_t *e2; + uint32_t Ncb,ind,k,Nref,N; - AssertFatal(Nl>0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); + if (C==0) { + printf("nr_rate_matching: invalid parameters (C %d\n",C); + return -1; + } //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3 Ncb = min(N, Nref); } -#ifdef RM_DEBUG - printf("nr_rate_matching: Ncb %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,rvidx, G, Qm,Nl,r); -#endif - - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching: E %d, k0 %d Cprime %d modcprime %d\n",E,ind, Cprime,((G/(Nl*Qm))%Cprime)); + printf("nr_rate_matching_ldpc: E %d, k0 %d, Ncb %d, rvidx %d\n", E, ind, Ncb, rvidx); #endif - //e2 = e; - k=0; for (; (ind0,"Nl is 0\n"); - AssertFatal(Qm>0,"Qm is 0\n"); - //Bit selection N = (BG==1)?(66*Z):(50*Z); if (Ilbrm == 0) - Ncb = N; + Ncb = N; else { Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3 Ncb = min(N, Nref); } - Cprime = C; //assume CBGTI not present - - if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) - E = Nl*Qm*(G/(Nl*Qm*Cprime)); - else - E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); - ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z; #ifdef RM_DEBUG - printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, Ncb %d,rvidx %d, G %d, Qm %d, Nl%d, r %d\n",clear,E,Ncb,rvidx, G, Qm,Nl,r); + printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx); #endif if (clear==1) memset(w,0,Ncb*sizeof(int16_t)); - soft_input2 = soft_input; k=0; for (; (indharq_processes[harq_pid]->d[r], - dlsch->harq_processes[harq_pid]->e+r_offset, - dlsch->harq_processes[harq_pid]->C, - rel15.redundancy_version, - mod_order, - rel15.nb_layers, - r); + E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15.nb_layers, r); + + nr_rate_matching_ldpc(Ilbrm, + Tbslbrm, + BG, + *pz, + dlsch->harq_processes[harq_pid]->d[r], + dlsch->harq_processes[harq_pid]->e+r_offset, + dlsch->harq_processes[harq_pid]->C, + rel15.redundancy_version, + E); #ifdef DEBUG_DLSCH_CODING for (int i =0; i<16; i++) diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c index 0b8ab56329..f8b7454067 100644 --- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c +++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c @@ -176,3 +176,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16 G = ((NR_NB_SC_PER_RB*nb_symb_sch)-(nb_re_dmrs*length_dmrs))*nb_rb*Qm*Nl; return(G); } + +uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) { + uint32_t E; + uint8_t Cprime = C; //assume CBGTI not present + + AssertFatal(Nl>0,"Nl is 0\n"); + AssertFatal(Qm>0,"Qm is 0\n"); + + if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1) + E = Nl*Qm*(G/(Nl*Qm*Cprime)); + else + E = Nl*Qm*((G/(Nl*Qm*Cprime))+1); + + return E; +} diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c index 610b8305df..2888a59606 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c @@ -376,6 +376,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, for (r=0; rC; r++) { //printf("start rx segment %d\n",r); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); @@ -394,20 +410,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, #endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { - + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -419,27 +430,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue, stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + r_offset += E; - //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); - -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); - - //for (int i =0; i<16; i++) - // printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING - if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -979,6 +976,30 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, dlsch_llr %p, w %p\n", + dlsch_llr+r_offset, + &harq_process->w[r]); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + +#ifdef DEBUG_DLSCH_DECODING + for (int i =0; i<16; i++) + printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); +#endif + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -995,23 +1016,16 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1023,34 +1037,18 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; //printf("main thread r_offset %d\n",r_offset); #ifdef DEBUG_DLSCH_DECODING for (int i =0; i<16; i++) - printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); #endif - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#ifdef DEBUG_DLSCH_DECODING - for (int i =0; i<16; i++) - printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); -#endif - -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { @@ -1526,6 +1524,23 @@ void *nr_dlsch_decoding_2thread0(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -1542,23 +1557,16 @@ void *nr_dlsch_decoding_2thread0(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, - Tbslbrm, - p_decParams->BG, - p_decParams->Z, - G, - harq_process->w[r], - dlsch_llr+r_offset, - harq_process->C, - harq_process->rvidx, - (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + Tbslbrm, + p_decParams->BG, + p_decParams->Z, + harq_process->d[r], + harq_process->w[r], + harq_process->C, + harq_process->rvidx, + (harq_process->round==0)?1:0, + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -1570,23 +1578,13 @@ void *nr_dlsch_decoding_2thread0(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } - //r_offset += E; //for (int i =0; i<16; i++) - // printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + + //r_offset += E; -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING - if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0); @@ -2043,6 +2041,28 @@ void *nr_dlsch_decoding_2thread1(void *arg) Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl); + E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r); + + /* + printf("Subblock deinterleaving, d %p w %p\n", + harq_process->d[r], + harq_process->w); + */ +#if UE_TIMING_TRACE + start_meas(dlsch_deinterleaving_stats); +#endif + nr_deinterleaving_ldpc(E, + harq_process->Qm, + harq_process->w[r], + dlsch_llr+r_offset); + + //for (int i =0; i<16; i++) + // printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset); + +#if UE_TIMING_TRACE + stop_meas(dlsch_deinterleaving_stats); +#endif + #if UE_TIMING_TRACE start_meas(dlsch_rate_unmatching_stats); #endif @@ -2059,23 +2079,16 @@ void *nr_dlsch_decoding_2thread1(void *arg) harq_process->round); #endif -#ifdef DEBUG_DLSCH_DECODING - printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx); -#endif if (nr_rate_matching_ldpc_rx(Ilbrm, Tbslbrm, p_decParams->BG, p_decParams->Z, - G, + harq_process->d[r], harq_process->w[r], - dlsch_llr+r_offset, harq_process->C, harq_process->rvidx, (harq_process->round==0)?1:0, - harq_process->Qm, - harq_process->Nl, - r, - &E)==-1) { + E)==-1) { #if UE_TIMING_TRACE stop_meas(dlsch_rate_unmatching_stats); #endif @@ -2087,23 +2100,12 @@ void *nr_dlsch_decoding_2thread1(void *arg) stop_meas(dlsch_rate_unmatching_stats); #endif } + + //for (int i =0; i<16; i++) + // printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset); + //r_offset += E; - /* - printf("Subblock deinterleaving, d %p w %p\n", - harq_process->d[r], - harq_process->w); - */ -#if UE_TIMING_TRACE - start_meas(dlsch_deinterleaving_stats); -#endif - nr_deinterleaving_ldpc(E, - harq_process->Qm, - harq_process->d[r], - harq_process->w[r]); -#if UE_TIMING_TRACE - stop_meas(dlsch_deinterleaving_stats); -#endif #ifdef DEBUG_DLSCH_DECODING if (r==0) { write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0); From 682bc151177d89d4cd0293c4dacd5f2c708f5192 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Thu, 7 Feb 2019 17:06:46 +0100 Subject: [PATCH 09/11] FFO estimation and compensation optional via command line --- openair1/PHY/NR_REFSIG/pss_nr.h | 1 + .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 16 ++++---- openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 41 +++++++++++-------- openair1/PHY/defs_nr_UE.h | 2 + openair1/SIMULATION/NR_PHY/pbchsim.c | 3 ++ targets/RT/USER/nr-uesoftmodem.c | 2 + targets/RT/USER/nr-uesoftmodem.h | 2 + 7 files changed, 42 insertions(+), 25 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 279f9e417a..dc20ab24d7 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -137,6 +137,7 @@ int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, + int fo_flag, int *eNB_id, int *f_off); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 78a2f0c82d..e5f079ebc3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -202,19 +202,21 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot); #endif - // digital compensation of FFO for SSB symbols - double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time - double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample + // digital compensation of FFO for SSB symbols + if (ue->UE_fo_compensation){ + double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time + double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample - int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position) - int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix + int start = ue->ssb_offset; // start for offset correction is at ssb_offset (pss time position) + int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples); // loop over samples in 4 symbols (ssb size), including prefix - for(int n=start; nnb_antennas_rx; ar++) { + for(int n=start; nnb_antennas_rx; ar++) { re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]); im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]); ((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); + } } } diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 30fb4bfc0f..9b09a846bb 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -663,6 +663,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int synchro_position; int **rxdata = NULL; + int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation #ifdef DBG_PSS_NR @@ -706,6 +707,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, + fo_flag, (int *)&PHY_vars_UE->common_vars.eNb_id, (int *)&PHY_vars_UE->common_vars.freq_offset); @@ -817,14 +819,15 @@ static inline double angle64(int64_t x) int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, + int fo_flag, int *eNB_id, int *f_off) { unsigned int n, ar, peak_position, pss_source; int64_t peak_value; - int64_t result,result1,result2; + int64_t result; int64_t avg[NUMBER_PSS_SEQUENCE]; - double ffo_est; + double ffo_est=0; unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */ @@ -894,34 +897,36 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } - - // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS - // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + if (fo_flag){ + // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. - // Computing cross-correlation at peak on half the symbol size for first half of data - result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], + int64_t result1,result2; + // Computing cross-correlation at peak on half the symbol size for first half of data + result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], (short*) &(rxdata[0][peak_position]), frame_parms->ofdm_symbol_size>>1, shift); - // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size - // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift - result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), + // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size + // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift + result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), frame_parms->ofdm_symbol_size>>1, shift); - int64_t re1,re2,im1,im2; - re1=((int*) &result1)[0]; - re2=((int*) &result2)[0]; - im1=((int*) &result1)[1]; - im2=((int*) &result2)[1]; + int64_t re1,re2,im1,im2; + re1=((int*) &result1)[0]; + re2=((int*) &result2)[0]; + im1=((int*) &result1)[1]; + im2=((int*) &result2)[1]; - // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi - ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; + // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; #ifdef DBG_PSS_NR - printf("ffo %lf\n",ffo_est); + printf("ffo %lf\n",ffo_est); #endif + } // computing absolute value of frequency offset *f_off = ffo_est*frame_parms->subcarrier_spacing; diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index c11ba8933f..54aed7adb1 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -983,6 +983,8 @@ typedef struct { int UE_scan; /// \brief Indicator that UE should perform coarse scanning around carrier int UE_scan_carrier; + /// \brief Indicator that UE should enable estimation and compensation of frequency offset + int UE_fo_compensation; /// \brief Indicator that UE is synchronized to an eNB int is_synchronized; /// Data structure for UE process scheduling diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 386b0b3140..214a33fb73 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -462,6 +462,9 @@ int main(int argc, char **argv) UE->perfect_ce = 0; + if(eps!=0.0) + UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation + if (init_nr_ue_signal(UE, 1, 0) != 0) { printf("Error at UE NR initialisation\n"); diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c index 81f46d31b3..d3d660e7f5 100644 --- a/targets/RT/USER/nr-uesoftmodem.c +++ b/targets/RT/USER/nr-uesoftmodem.c @@ -130,6 +130,7 @@ static char *itti_dump_file = NULL; int UE_scan = 0; int UE_scan_carrier = 0; +int UE_fo_compensation = 0; runmode_t mode = normal_txrx; FILE *input_fd=NULL; @@ -978,6 +979,7 @@ int main( int argc, char **argv ) { UE[CC_id]->UE_scan = UE_scan; UE[CC_id]->UE_scan_carrier = UE_scan_carrier; + UE[CC_id]->UE_fo_compensation = UE_fo_compensation; UE[CC_id]->mode = mode; printf("UE[%d]->mode = %d\n",CC_id,mode); diff --git a/targets/RT/USER/nr-uesoftmodem.h b/targets/RT/USER/nr-uesoftmodem.h index 816e753086..7f96480b2b 100644 --- a/targets/RT/USER/nr-uesoftmodem.h +++ b/targets/RT/USER/nr-uesoftmodem.h @@ -55,6 +55,7 @@ #define CONFIG_HLP_UENANTR "set UE number of rx antennas\n" #define CONFIG_HLP_UENANTT "set UE number of tx antennas\n" #define CONFIG_HLP_UESCAN "set UE to scan around carrier\n" +#define CONFIG_HLP_UEFO "set UE to enable estimation and compensation of frequency offset\n" #define CONFIG_HLP_DUMPFRAME "dump UE received frame to rxsig_frame0.dat and exit\n" #define CONFIG_HLP_DLSHIFT "dynamic shift for LLR compuation for TM3/4 (default 0)\n" #define CONFIG_HLP_UELOOP "get softmodem (UE) to loop through memory instead of acquiring from HW\n" @@ -135,6 +136,7 @@ {"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, u8ptr:&nb_antenna_rx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, u8ptr:&nb_antenna_tx, defuintval:1, TYPE_UINT8, 0}, \ {"ue-scan-carrier", CONFIG_HLP_UESCAN, PARAMFLAG_BOOL, iptr:&UE_scan_carrier, defintval:0, TYPE_INT, 0}, \ +{"ue-fo-compensation", CONFIG_HLP_UEFO, PARAMFLAG_BOOL, iptr:&UE_fo_compensation, defintval:0, TYPE_INT, 0}, \ {"ue-max-power", NULL, 0, iptr:&(tx_max_power[0]), defintval:90, TYPE_INT, 0}, \ {"r" , CONFIG_HLP_PRB, 0, iptr:&(frame_parms[0]->N_RB_DL), defintval:25, TYPE_UINT, 0}, \ {"dlsch-demod-shift", CONFIG_HLP_DLSHIFT, 0, iptr:(int32_t *)&dlsch_demod_shift, defintval:0, TYPE_INT, 0}, \ From 7cb58c9a31f0e0d6ff7eec7f3769b12d2ae6c099 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Wed, 13 Feb 2019 11:47:26 +0100 Subject: [PATCH 10/11] reverting some changes in the UE that were introduced by nr_polar_encoder_optimizations to make UE work again on real-time testbench. Now at least the PDCCH can be detected and used for time tracking. However, the DCI is not yet decoded (this will be fixed on branch nr_pdcch_fixes). The reverted changes are most notably passing the correct slot number to slot_fep in phy_procedures_nrUE. This will have to be changed as well in the future when we pass to slot-based processing at the UE. --- openair1/PHY/MODULATION/slot_fep_nr.c | 4 ++-- openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c | 6 +++--- openair1/PHY/NR_UE_TRANSPORT/dci_nr.c | 4 ++-- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 5 +---- openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c | 8 ++++---- 5 files changed, 12 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 8ef29d016d..22eb395da9 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -130,8 +130,8 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, #ifdef DEBUG_FEP // if (ue->frame <100) - /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol, - nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples); + /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol, + nb_prefix_samples,nb_prefix_samples0,slot_offset,sample_offset,rx_offset,frame_length_samples); #endif if (l==0) { diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 942bf8c0ba..145c779be9 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -28,7 +28,7 @@ #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "filt16a_32.h" #include "T.h" -//#define DEBUG_PDSCH +//#define DEBUG_PDCCH int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, @@ -297,7 +297,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, // generate pilot - nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns][symbol], &pilot[0],2000,nb_rb_coreset); + nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns>>1][symbol], &pilot[0],2000,nb_rb_coreset); for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { @@ -459,7 +459,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, break; } - if( (Ns== 2) && (l == 0)) + //if( (Ns== 2) && (l == 0)) { // do ifft of channel estimate for (aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c index cf419b0904..3d481a0468 100755 --- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c @@ -821,8 +821,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue, #ifdef NR_PDCCH_DCI_DEBUG printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol); - printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) \n", - coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R); + printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n", + coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id); #endif // diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index a4d627823f..5eee7b9c0c 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2781,8 +2781,6 @@ void nr_ue_measurement_procedures( */ eNB_id = 0; - - LOG_D(PHY,"start adjust sync l = %d slot = %d no timing %d\n",l, slot, ue->no_timing_correction); if (ue->no_timing_correction==0) nr_adjust_synch_ue(&ue->frame_parms, @@ -2791,7 +2789,6 @@ void nr_ue_measurement_procedures( nr_tti_rx, 0, 16384); - } @@ -5064,7 +5061,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN); nr_slot_fep(ue, l, - nr_tti_rx, + nr_tti_rx<<1, 0, 0, 1, diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 1ea888eeb9..4e8b72614d 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -268,11 +268,11 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { // Type0 PDCCH search space dl_config->number_pdus = 1; dl_config->dl_config_list[0].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI; - dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa; // to be set + dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0x1234; // to be set uint64_t mask = 0x0; - uint16_t num_rbs=48; - uint16_t rb_offset=47; + uint16_t num_rbs=24; + uint16_t rb_offset=0; uint16_t cell_id=0; uint16_t num_symbols=2; for(int i=0; i<(num_rbs/6); ++i){ // 38.331 Each bit corresponds a group of 6 RBs @@ -292,7 +292,7 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) { uint32_t number_of_search_space_per_slot=1; uint32_t first_symbol_index=0; - uint32_t search_space_duration=1; // element of search space + uint32_t search_space_duration=0; // element of search space uint32_t coreset_duration; // element of coreset coreset_duration = num_symbols * number_of_search_space_per_slot; From af42c1094546660857a9dad42100014e9dc03ee8 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Wed, 13 Feb 2019 11:47:45 +0100 Subject: [PATCH 11/11] added visualization of PDCCH channel estimate to phy_scope_UE. --- openair1/PHY/TOOLS/nr_phy_scope.c | 77 +++++++++++++++++-------------- targets/RT/USER/nr-ue.c | 2 +- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c index 0100dd44c4..3dd16ff0da 100644 --- a/openair1/PHY/TOOLS/nr_phy_scope.c +++ b/openair1/PHY/TOOLS/nr_phy_scope.c @@ -498,10 +498,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, float **rxsig_t_dB; float *time; float *corr; - /* int16_t **chest_t; int16_t **chest_f; - */ int16_t *pdsch_llr; int16_t *pdsch_comp; //int16_t *pdsch_mag; @@ -519,10 +517,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, int coded_bits_per_codeword = num_re*Qm; int symbol, first_symbol,nb_re; int nb_rb_pdsch =50; + float ymax=1; + float **chest_t_abs; + float Re,Im; + float *chest_f_abs; + float *freq; + static int overlay = 0; /* - float Re,Im,ymax=1; - float **chest_t_abs, *chest_f_abs; - float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx; int mcs = 0; unsigned char harq_pid = 0; @@ -565,15 +566,15 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, */ I = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); Q = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float)); - /* + chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*)); for (arx=0; arxofdm_symbol_size,sizeof(float)); } - chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float)); - */ + chest_f_abs = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); + freq = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float)); llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero bit = malloc(coded_bits_per_codeword*sizeof(float)); @@ -589,10 +590,9 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, time = calloc(samples_per_frame,sizeof(float)); corr = calloc(samples_per_frame,sizeof(float)); - /* chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id]; chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id]; - */ + pbch_llr = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->llr; pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; @@ -628,29 +628,37 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } if (phy_vars_ue->is_synchronized==0) { - for (ind=0;ind<3;ind++) { - if (pss_corr_ue[ind]) { - for (i=0; ichest_t,time,corr,samples_per_frame,"","",""); + else + fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); + + overlay = 1; } - - if (ind==0) - fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","",""); - else - fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]); } - } + } + else { + + if (overlay) { //there was a previous overlay + fl_clear_xyplot(form->chest_t); + overlay = 0; } - /* - // Channel Impulse Response (still repeated format) + // Channel Impulse Response if (chest_t != NULL) { ymax = 0; if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) { - chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]); + chest_t_abs[0][i] = (float) (chest_t[0][2*i]*chest_t[0][2*i]+chest_t[0][2*i+1]*chest_t[0][2*i+1]); + time[i] = (float) i; if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; @@ -658,7 +666,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","",""); } - + /* for (arx=1; arxofdm_symbol_size>>3); i++) { @@ -672,11 +680,12 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT); } } - + */ // Avoid flickering effect // fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); // Does not always work... fl_set_xyplot_ybounds(form->chest_t,0,(double) ymax); } + } // Channel Frequency Response (includes 5 complex sample for filter) if (chest_f != NULL) { @@ -685,7 +694,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, for (atx=0; atxofdm_symbol_size; k++) { freq[ind] = (float)ind; Re = (float)(chest_f[(atx<<1)+arx][(2*k)]); Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]); @@ -698,12 +707,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, } // tx antenna 0 - fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); + //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce); //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2); // fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2); - fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); - fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","",""); + //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR); + fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","",""); + /* for (arx=1; arxchest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } @@ -722,8 +732,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]); } } + */ } - */ // PBCH LLRs if (pbch_llr != NULL) { @@ -735,10 +745,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form, fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,864,"","",""); } - if (phy_vars_ue->is_synchronized==1) - first_symbol=5; - else - first_symbol=1; + first_symbol=1; // PBCH I/Q of MF Output if (pbch_comp!=NULL) { diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index 1dfa3dbd4f..7682b098a0 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -602,7 +602,7 @@ static void *UE_thread_synch(void *arg) { phy_scope_UE(form_ue[0], PHY_vars_UE_g[0][0], - 0,0,7); + 0,0,1); } #endif