diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 245bba4f8b..df16bccfb5 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1177,6 +1177,7 @@ set(PHY_SRC_UE ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/sss_ue.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_llr_computation.c + ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dlsch_decoding.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/dci_tools_ue.c ${OPENAIR1_DIR}/PHY/LTE_UE_TRANSPORT/uci_tools_ue.c @@ -1817,11 +1818,13 @@ endif() # So, here are some hacks here. Hope this gets fixed in future! if(EXISTS "/usr/include/atlas/cblas.h" OR EXISTS "/usr/include/cblas.h") include_directories("/usr/include/atlas") + LINK_DIRECTORIES("/usr/lib/lapack") LINK_DIRECTORIES("/usr/lib64") LINK_DIRECTORIES("/usr/lib64/atlas") #Added because atlas libraries in CentOS 7 are here! if(EXISTS "/usr/lib64/libblas.so" OR EXISTS "/usr/lib/libblas.so") #Case for CentOS7 list(APPEND ATLAS_LIBRARIES blas) + else() # Case for Ubuntu list(APPEND ATLAS_LIBRARIES cblas) endif() @@ -1847,6 +1850,8 @@ else() message("No Blas/Atlas libs found, some targets will fail") endif() +list(APPEND ATLAS_LIBRARIES lapack lapacke) + if (${XFORMS}) include_directories ("/usr/include/X11") set(XFORMS_SOURCE diff --git a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c index f82ba57e69..271151f561 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c +++ b/openair1/PHY/LTE_UE_TRANSPORT/dlsch_demodulation.c @@ -36,8 +36,18 @@ #include "transport_proto_ue.h" #include "PHY/sse_intrin.h" #include "T.h" +#include +#include +#include +#include +#include +#include +#include +#include "linear_preprocessing_rec.h" #define NOCYGWIN_STATIC +//#define DEBUG_MMSE + /* dynamic shift for LLR computation for TM3/4 * set as command line argument, see lte-softmodem.c @@ -103,6 +113,7 @@ int rx_pdsch(PHY_VARS_UE *ue, int avg[4]; int avg_0[2]; int avg_1[2]; + unsigned short mmse_flag=0; #if UE_TIMING_TRACE uint8_t slot = 0; @@ -440,14 +451,15 @@ int rx_pdsch(PHY_VARS_UE *ue, ((dlsch0_harq->mimo_mode >=DUALSTREAM_UNIFORM_PRECODING1) && (dlsch0_harq->mimo_mode <=DUALSTREAM_PUSCH_PRECODING))) { - dlsch_channel_level_TM34(pdsch_vars[eNB_id]->dl_ch_estimates_ext, - frame_parms, - pdsch_vars[eNB_id]->pmi_ext, - avg_0, - avg_1, - symbol, - nb_rb, - dlsch0_harq->mimo_mode); + dlsch_channel_level_TM34(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + pdsch_vars[eNB_id]->pmi_ext, + avg_0, + avg_1, + symbol, + nb_rb, + mmse_flag, + dlsch0_harq->mimo_mode); LOG_D(PHY,"Channel Level TM34 avg_0 %d, avg_1 %d, rx_type %d, rx_standard %d, dlsch_demod_shift %d \n", avg_0[0], avg_1[0], rx_type, rx_standard, dlsch_demod_shift); @@ -547,6 +559,26 @@ int rx_pdsch(PHY_VARS_UE *ue, start_meas(&ue->generic_stat_bis[ue->current_thread_id[subframe]][slot]); #endif + if (rx_type==rx_IC_dual_stream && mmse_flag==1){ + + precode_channel_est(pdsch_vars[eNB_id]->dl_ch_estimates_ext, + frame_parms, + pdsch_vars[eNB_id], + symbol, + nb_rb, + dlsch0_harq->mimo_mode); + + mmse_processing_oai(pdsch_vars[eNB_id], + frame_parms, + measurements, + first_symbol_flag, + dlsch0_harq->mimo_mode, + mmse_flag, + 0.0, + symbol, + nb_rb); + } + // Now channel compensation if (dlsch0_harq->mimo_moderxdataF_ext, @@ -607,6 +639,7 @@ int rx_pdsch(PHY_VARS_UE *ue, dlsch0_harq->round, dlsch0_harq->mimo_mode, nb_rb, + mmse_flag, pdsch_vars[eNB_id]->log2_maxh0, pdsch_vars[eNB_id]->log2_maxh1); if (symbol == 5) { @@ -2479,6 +2512,69 @@ void dlsch_channel_compensation_TM56(int **rxdataF_ext, _m_empty(); } +void precode_channel_est(int32_t **dl_ch_estimates_ext, + LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDSCH *pdsch_vars, + unsigned char symbol, + unsigned short nb_rb, + MIMO_mode_t mimo_mode){ + + unsigned short rb; + __m128i *dl_ch0_128,*dl_ch1_128; + unsigned char aarx=0,symbol_mod,pilots=0; + unsigned char *pmi_ext = pdsch_vars->pmi_ext; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) + pilots=1; + + for (aarx=0;aarxnb_antennas_rx;aarx++) { + + dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // this is h11 + dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // this is h12 + + for (rb=0; rbnb_antennas_rx;aarx++) { - /* if (aarx==0) { - output_shift=output_shift0; - } - else { - output_shift=output_shift1; - } */ - - // printf("antenna %d\n", aarx); - // printf("symbol %d, rx antenna %d\n", symbol, aarx); - dl_ch0_128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; // this is h11 dl_ch1_128 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; // this is h12 - - dl_ch_mag0_128 = (__m128i *)&dl_ch_mag0[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x1 dl_ch_mag0_128b = (__m128i *)&dl_ch_magb0[aarx][symbol*frame_parms->N_RB_DL*12];//responsible for x1 dl_ch_mag1_128 = (__m128i *)&dl_ch_mag1[aarx][symbol*frame_parms->N_RB_DL*12]; //responsible for x2. always coming from tx2 @@ -2562,48 +2647,37 @@ void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, rxdataF_comp1_128 = (__m128i *)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; //result of multipl with MF x2 on antenna of interest for (rb=0; rb2) { @@ -2732,7 +2806,7 @@ void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch0_128); - // print_shorts("pack:",rxdataF_comp0_128); + //print_shorts("pack:",rxdataF_comp0_128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch0_128[1],rxdataF128[1]); @@ -2951,36 +3025,31 @@ void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, rxdataF_comp1_128 = (int16x8_t*)&rxdataF_comp1[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0; rb2) { @@ -3869,7 +3938,592 @@ void dlsch_channel_level_core(int **dl_ch_estimates_ext, } -//compute average channel_level of effective (precoded) channel +void mmse_processing_oai(LTE_UE_PDSCH *pdsch_vars, + LTE_DL_FRAME_PARMS *frame_parms, + PHY_MEASUREMENTS *measurements, + unsigned char first_symbol_flag, + MIMO_mode_t mimo_mode, + unsigned short mmse_flag, + int noise_power, + unsigned char symbol, + unsigned short nb_rb){ + + int **rxdataF_ext = pdsch_vars->rxdataF_ext; + int **dl_ch_estimates_ext = pdsch_vars->dl_ch_estimates_ext; + unsigned char *pmi_ext = pdsch_vars->pmi_ext; + int avg_00[frame_parms->nb_antenna_ports_eNB*frame_parms->nb_antennas_rx]; + int avg_01[frame_parms->nb_antenna_ports_eNB*frame_parms->nb_antennas_rx]; + int symbol_mod, length, start_point, nre; + + symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) + nre=8; + else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) + nre=10; + else + nre=12; + + length = nre*nb_rb; + start_point = symbol*nb_rb*12; + + + mmse_processing_core(rxdataF_ext, + dl_ch_estimates_ext, + noise_power, + frame_parms->nb_antenna_ports_eNB, + frame_parms->nb_antennas_rx, + length, + start_point); + + + /*dlsch_channel_aver_band(dl_ch_estimates_ext, + frame_parms, + chan_avg, + symbol, + nb_rb); + + + for (aatx=0; aatxnb_antenna_ports_eNB; aatx++) + for (aarx=0; aarxnb_antennas_rx; aarx++) { + H[aatx*frame_parms->nb_antennas_rx + aarx] = (float)(chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r/(32768.0)) + I*(float)(chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i/(32768.0)); + // printf("H [%d] = (%f, %f) \n", aatx*frame_parms->nb_antennas_rx + aarx, creal(H[aatx*frame_parms->nb_antennas_rx + aarx]), cimag(H[aatx*frame_parms->nb_antennas_rx + aarx])); + }*/ + + if (first_symbol_flag == 1){ + dlsch_channel_level_TM34(dl_ch_estimates_ext, + frame_parms, + pmi_ext, + avg_00, + avg_01, + symbol, + nb_rb, + mmse_flag, + mimo_mode); + + avg_00[0] = (log2_approx(avg_00[0])/2) + dlsch_demod_shift+4;// + 2 ;//+ 4; + avg_01[0] = (log2_approx(avg_01[0])/2) + dlsch_demod_shift+4;// + 2 ;//+ 4; + pdsch_vars->log2_maxh0 = cmax(avg_00[0],0); + pdsch_vars->log2_maxh1 = cmax(avg_01[0],0); + } +} + +void mmse_processing_core(int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + int noise_power, + int n_tx, + int n_rx, + int length, + int start_point){ + + int aatx, aarx, re; + float imag; + float real; + + + float complex **W_MMSE= malloc(n_tx*n_rx*sizeof(float complex*)); + for (int j=0; j max) + max = fabs(creal(W_MMSE_re[aatx*n_rx + aarx])); + if (fabs(cimag(W_MMSE_re[aatx*n_rx + aarx])) > max) + max = fabs(cimag(W_MMSE_re[aatx*n_rx + aarx])); + } + } + } + one_over_max = 1.0/max; + + for (re=0; re=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; + + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) + nre=8; + else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB==1)) + nre=10; + else + nre=12; + + for (aatx=0; aatxnb_antennas_tx; aatx++){ + for (aarx=0; aarxnb_antennas_rx; aarx++) { + dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; + avg128D = _mm_setzero_si128(); + // print_shorts("avg128D 1",&avg128D); + + for (rb=0;rbnb_antennas_rx + aarx, nb_rb*nre, rb); + print_shorts("aver dl_ch128",&dl_ch128[0]); + print_shorts("aver dl_ch128",&dl_ch128[1]); + print_shorts("aver dl_ch128",&dl_ch128[2]); + avg128D = _mm_add_epi16(avg128D, dl_ch128[0]);*/ + //print_shorts("avg128D 2",&avg128D); + + avg128D = _mm_add_epi16(avg128D, dl_ch128[1]); + // print_shorts("avg128D 3",&avg128D); + + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { + dl_ch128+=2; + }else { + avg128D = _mm_add_epi16(avg128D,dl_ch128[2]); + // print_shorts("avg128D 4",&avg128D); + dl_ch128+=3; + } + } + + chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r =(((int16_t*)&avg128D)[0] + + ((int16_t*)&avg128D)[2] + + ((int16_t*)&avg128D)[4] + + ((int16_t*)&avg128D)[6])/(nb_rb*nre); + // printf("symb %d chan_avg re [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r); + + + + chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i =(((int16_t*)&avg128D)[1] + + ((int16_t*)&avg128D)[3] + + ((int16_t*)&avg128D)[5] + + ((int16_t*)&avg128D)[7])/(nb_rb*nre); + // printf("symb %d chan_avg im [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i); + + //printf("symb %d chan_avg im [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i); + + + chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx] = (((int32_t)chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].i)<<16)|(((int32_t)chan_avg[aatx*frame_parms->nb_antennas_rx + aarx].r) & 0xffff); + + //printf("symb %d chan_est_avg [%d] = %d\n", symbol, aatx*frame_parms->nb_antennas_rx + aarx, chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); + + dl_ch128=(__m128i *)&dl_ch_estimates_ext[aatx*frame_parms->nb_antennas_rx + aarx][symbol*frame_parms->N_RB_DL*12]; + + for (rb=0;rbnb_antennas_rx + aarx]); + dl_ch128[1] = _mm_set1_epi32(chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); + if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->nb_antenna_ports_eNB!=1)) { + dl_ch128+=2; + }else { + dl_ch128[2] = _mm_set1_epi32(chan_est_avg[aatx*frame_parms->nb_antennas_rx + aarx]); + dl_ch128+=3; + } + } + } + } + + _mm_empty(); + _m_empty(); + +#elif defined(__arm__) +#endif + } + +void rxdataF_to_float(int32_t **rxdataF_ext, + float complex **rxdataF_f, + int n_rx, + int length, + int start_point) +{ + short re; + int aarx; + int16_t imag; + int16_t real; + + for (aarx=0; aarx> 16); + real = (int16_t) (rxdataF_ext[aarx][start_point + re] & 0xffff); + rxdataF_f[aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0)); +#ifdef DEBUG_MMSE + if (re==0){ + printf("rxdataF_to_float: aarx = %d, real= %d, imag = %d\n", aarx, real, imag); + //printf("rxdataF_to_float: rxdataF_ext[%d][%d] = %d\n", aarx, start_point + re, rxdataF_ext[aarx][start_point + re]); + //printf("rxdataF_to_float: ant %d, re = %d, rxdataF_f real = %f, rxdataF_f imag = %f \n", aarx, re, creal(rxdataF_f[aarx][re]), cimag(rxdataF_f[aarx][re])); + } +#endif + } + } +} + + + +void chan_est_to_float(int32_t **dl_ch_estimates_ext, + float complex **dl_ch_estimates_ext_f, + int n_tx, + int n_rx, + int length, + int start_point) +{ + short re; + int aatx,aarx; + int16_t imag; + int16_t real; + + for (aatx=0; aatx> 16); + real = (int16_t) (dl_ch_estimates_ext[aatx*n_rx + aarx][start_point+ re] & 0xffff); + dl_ch_estimates_ext_f[aatx*n_rx + aarx][re] = (float)(real/(32768.0)) + I*(float)(imag/(32768.0)); +#ifdef DEBUG_MMSE + if (re==0){ + printf("ant %d, re = %d, real = %d, imag = %d \n", aatx*n_rx + aarx, re, real, imag); + printf("ant %d, re = %d, real = %f, imag = %f \n", aatx*n_rx + aarx, re, creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])); + } +#endif + } + } + } +} + +void float_to_chan_est(int32_t **dl_ch_estimates_ext, + float complex **dl_ch_estimates_ext_f, + int n_tx, + int n_rx, + int length, + int start_point) +{ + + short re; + int aarx, aatx; + int16_t imag; + int16_t real; + + for (aatx=0; aatx=1) + imag = 0x7FFF; + else + imag = cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; + if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])<-1) + real = 0x8000; + else if (creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])>=1) + real = 0x7FFF; + else + real = creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])*32768; + + dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re] = (((int32_t)imag)<<16)|((int32_t)real & 0xffff); +#ifdef DEBUG_MMSE + if (re==0){ + printf(" float_to_chan_est: chan est real = %f, chan est imag = %f\n",creal(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re]), cimag(dl_ch_estimates_ext_f[aatx*n_rx + aarx][re])); + printf("float_to_chan_est: real fixed = %d, imag fixed = %d\n", real, imag); + printf("float_to_chan_est: ant %d, re = %d, dl_ch_estimates_ext = %d \n", aatx*n_rx + aarx, re, dl_ch_estimates_ext[aatx*n_rx + aarx][start_point + re]); + } +#endif + } + } + } +} + + +void float_to_rxdataF(int32_t **rxdataF_ext, + float complex **rxdataF_f, + int n_tx, + int n_rx, + int length, + int start_point) +{ + + short re; + int aarx; + int16_t imag; + int16_t real; + + for (aarx=0; aarx=1) + imag = 0x7FFF; + else + imag = cimag(rxdataF_f[aarx][re])*32768; + if (creal(rxdataF_f[aarx][re])<-1) + real = 0x8000; + else if (creal(rxdataF_f[aarx][re])>=1) + real = 0x7FFF; + else + real = creal(rxdataF_f[aarx][re])*32768; + rxdataF_ext[aarx][start_point + re] = (((int32_t)imag)<<16)|(((int32_t)real) & 0xffff); +#ifdef DEBUG_MMSE + if (re==0){ + printf(" float_to_rxdataF: real = %f, imag = %f\n",creal(rxdataF_f[aarx][re]), cimag(rxdataF_f[aarx][re])); + printf("float_to_rxdataF: real fixed = %d, imag fixed = %d\n", real, imag); + printf("float_to_rxdataF: ant %d, re = %d, rxdataF_ext = %d \n", aarx, re, rxdataF_ext[aarx][symbol*nb_rb*12 + re]); + } +#endif + } + } +} + + +void mult_mmse_rxdataF(float complex** Wmmse, + float complex** rxdataF_ext_f, + int n_tx, + int n_rx, + int length, + int start_point) +{ + short re; + int aarx, aatx; + + + float complex* rxdata_re = malloc(n_rx*sizeof(float complex)); + float complex* rxdata_mmse_re = malloc(n_rx*sizeof(float complex)); + float complex* Wmmse_re = malloc(n_tx*n_rx*sizeof(float complex)); + + for (re=0;re +#include +#include +#include +#include +#include +#include +#include + +//#define DEBUG_PREPROC + + +void transpose (int N, float complex *A, float complex *Result) +{ + // COnputes C := alpha*op(A)*op(B) + beta*C, + enum CBLAS_TRANSPOSE transa = CblasTrans; + enum CBLAS_TRANSPOSE transb = CblasNoTrans; + int rows_opA = N; // number of rows in op(A) and in C + int col_opB = N; //number of columns of op(B) and in C + int col_opA = N; //number of columns in op(A) and rows in op(B) + int col_B; //number of columns in B + float complex alpha = 1.0+I*0; + int lda = rows_opA; + float complex beta = 0.0+I*0; + int ldc = rows_opA; + int i; + float complex* B; + + int ldb = col_opB; + + if (transb == CblasNoTrans) { + B = (float complex*)calloc(ldb*col_opB,sizeof(float complex)); + col_B= col_opB; + } + else { + B = (float complex*)calloc(ldb*col_opA, sizeof(float complex)); + col_B = col_opA; + } + float complex* C = (float complex*)malloc(ldc*col_opB*sizeof(float complex)); + + for (i=0; i>2)*sizeof(float complex)); + float complex *H1_re = malloc(n_rx*(n_tx>>2)*sizeof(float complex)); + float complex *R_corr_col_n_0_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *R_corr_col_n_1_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *U_0_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *U_1_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *U_0_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *U_1_herm_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *D_0_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *D_1_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *W_Wh_0_re = malloc(n_rx*n_tx*sizeof(float complex)); + float complex *W_Wh_1_re = malloc(n_rx*n_tx*sizeof(float complex)); + + for (aatx=0; aatx>2), H1_re, sigma2, R_corr_col_n_0_re); + HH_herm_plus_sigma2I(n_rx, (n_tx>>2), H0_re, sigma2, R_corr_col_n_1_re); + + eigen_vectors_values(n_rx, R_corr_col_n_0_re, U_0_re, D_0_re); + eigen_vectors_values(n_rx, R_corr_col_n_1_re, U_1_re, D_1_re); + + transpose (n_rx, U_0_re, U_0_herm_re); + transpose (n_rx, U_1_re, U_1_herm_re); + + sigma = (float)(sqrt((double)(sigma2))); + + /*The inverse of a diagonal matrix is obtained by replacing each element in the diagonal with its reciprocal. + A square root of a diagonal matrix is given by the diagonal matrix, whose diagonal entries are just the square + roots of the original matrix.*/ + + + D_0_re_inv_sqrt[0] = sqrt_float(1/D_0_re_inv[0]); + D_0_re_inv_sqrt[5] = sqrt_float(1/D_0_re_inv[5]); + D_0_re_inv_sqrt[10] = sqrt_float(1/D_0_re_inv[10]); + D_0_re_inv_sqrt[15] = sqrt_float(1/D_0_re_inv[15]); + + D_1_re_inv[0] = sqrt_float(1/D_1_re_inv[0]); + D_1_re_inv[5] = sqrt_float(1/D_1_re_inv[5]); + D_1_re_inv[10] = sqrt_float(1/D_1_re_inv[10]); + D_1_re_inv[15] = sqrt_float(1/D_1_re_inv[15]); + + now only to multiply + + free(H0); + free(H1); + free(R_corr_col_n_0); + free(R_corr_col_n_1); +} +#endif + +float sqrt_float(float x, float sqrt_x) +{ + sqrt_x = (float)(sqrt((double)(x))); + return sqrt_x; +} \ No newline at end of file diff --git a/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.h b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.h new file mode 100755 index 0000000000..f38bc47556 --- /dev/null +++ b/openair1/PHY/LTE_UE_TRANSPORT/linear_preprocessing_rec.h @@ -0,0 +1,121 @@ + +#include +#include +#include +#include +#include "PHY/defs_UE.h" + + +/* FUNCTIONS FOR LINEAR PREPROCESSING: MMSE, WHITENNING, etc*/ +void transpose(int N, float complex *A, float complex *Result); + +void conjugate_transpose(int N, float complex *A, float complex *Result); + +void H_hermH_plus_sigma2I(int N, int M, float complex *A, float sigma2, float complex *Result); + +void HH_herm_plus_sigma2I(int M, int N, float complex *A, float sigma2, float complex *Result); + +void eigen_vectors_values(int N, float complex *A, float complex *Vectors, float *Values_Matrix); + +void lin_eq_solver(int N, float complex *A, float complex* B); +//float complex* lin_eq_solver (int N, float complex* A, float complex* B); + +/* mutl_matrix_matrix_row_based performs multiplications when matrix is row-oriented H[0], H[1]; H[2], H[3]*/ +void mutl_matrix_matrix_row_based(float complex* M0, float complex* M1, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex* Result ); + +/* mutl_matrix_matrix_col_based performs multiplications matrix is column-oriented H[0], H[2]; H[1], H[3]*/ +void mutl_matrix_matrix_col_based(float complex* M0, float complex* M1, int rows_M0, int col_M0, int rows_M1, int col_M1, float complex* Result ); + +void compute_MMSE(float complex* H, int order_H, float sigma2, float complex* W_MMSE); + +void compute_white_filter(float complex* H, int order_H, float sigma2, float complex* U_1, float complex* D_1); + +void mmse_processing_oai(LTE_UE_PDSCH *pdsch_vars, + LTE_DL_FRAME_PARMS *frame_parms, + PHY_MEASUREMENTS *measurements, + unsigned char first_symbol_flag, + MIMO_mode_t mimo_mode, + unsigned short mmse_flag, + int noise_power, + unsigned char symbol, + unsigned short nb_rb); + + +void precode_channel_est(int32_t **dl_ch_estimates_ext, + LTE_DL_FRAME_PARMS *frame_parms, + LTE_UE_PDSCH *pdsch_vars, + unsigned char symbol, + unsigned short nb_rb, + MIMO_mode_t mimo_mode); + + +void rxdataF_to_float(int32_t **rxdataF_ext, + float complex **rxdataF_f, + int n_rx, + int length, + int start_point); + +void chan_est_to_float(int32_t **dl_ch_estimates_ext, + float complex **dl_ch_estimates_ext_f, + int n_tx, + int n_rx, + int length, + int start_point); + +void float_to_chan_est(int32_t **dl_ch_estimates_ext, + float complex **dl_ch_estimates_ext_f, + int n_tx, + int n_rx, + int length, + int start_point); + +void float_to_rxdataF(int32_t **rxdataF_ext, + float complex **rxdataF_f, + int n_tx, + int n_rx, + int length, + int start_point); + +void mult_mmse_rxdataF(float complex** Wmmse, + float complex** rxdataF_ext_f, + int n_tx, + int n_rx, + int length, + int start_point); + +void mult_mmse_chan_est(float complex** Wmmse, + float complex** dl_ch_estimates_ext_f, + int n_tx, + int n_rx, + int length, + int start_point); + +void mmse_processing_core(int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + int sigma2, + int n_tx, + int n_rx, + int length, + int start_point); + +void mmse_processing_core_flp(float complex** rxdataF_ext_flcpx, + float complex **H, + int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + float sigma2, + int n_tx, + int n_rx, + int length, + int start_point); + +void whitening_processing_core_flp(float complex** rxdataF_ext_flcpx, + float complex **H, + int32_t **rxdataF_ext, + int32_t **dl_ch_estimates_ext, + float sigma2, + int n_tx, + int n_rx, + int length, + int start_point); + +float sqrt_float(float x, float sqrt_x); diff --git a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h index 178ed53dcc..53f593fe29 100644 --- a/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h +++ b/openair1/PHY/LTE_UE_TRANSPORT/transport_proto_ue.h @@ -925,6 +925,7 @@ void dlsch_channel_compensation_TM34(LTE_DL_FRAME_PARMS *frame_parms, int round, MIMO_mode_t mimo_mode, unsigned short nb_rb, + unsigned short mmse_flag, unsigned char output_shift0, unsigned char output_shift1); @@ -957,6 +958,7 @@ void dlsch_channel_level_TM34(int **dl_ch_estimates_ext, int *avg_1, uint8_t symbol, unsigned short nb_rb, + unsigned int mmse_flag, MIMO_mode_t mimo_mode);