/******************************************************************************* OpenAirInterface Copyright(c) 1999 - 2014 Eurecom OpenAirInterface is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenAirInterface is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenAirInterface.The full GNU General Public License is included in this distribution in the file called "COPYING". If not, see <http://www.gnu.org/licenses/>. Contact Information OpenAirInterface Admin: openair_admin@eurecom.fr OpenAirInterface Tech : openair_tech@eurecom.fr OpenAirInterface Dev : openair4g-devel@eurecom.fr Address : Eurecom, Compus SophiaTech 450, route des chappes, 06451 Biot, France. *******************************************************************************/ /*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c * \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03 * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert * \date 2011 * \version 0.1 * \company Eurecom * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,ankit.bhamri@eurecom.fr,sebastien.aubert@eurecom.fr * \note * \warning */ #ifdef __SSE2__ #include <emmintrin.h> #include <xmmintrin.h> #endif #ifdef __SSE3__ #include <pmmintrin.h> #include <tmmintrin.h> #endif #include "PHY/defs.h" #include "PHY/extern.h" #include "defs.h" #include "extern.h" #ifndef __SSE3__ __m128i zero;//,tmp_over_sqrt_10,tmp_sum_4_over_sqrt_10,tmp_sign,tmp_sign_3_over_sqrt_10; //#define _mm_abs_epi16(xmmx) _mm_xor_si128((xmmx),_mm_cmpgt_epi16(zero,(xmmx))) #define _mm_abs_epi16(xmmx) _mm_add_epi16(_mm_xor_si128((xmmx),_mm_cmpgt_epi16(zero,(xmmx))),_mm_srli_epi16(_mm_cmpgt_epi16(zero,(xmmx)),15)) #define _mm_sign_epi16(xmmx,xmmy) _mm_xor_si128((xmmx),_mm_cmpgt_epi16(zero,(xmmy))) #endif #ifndef USER_MODE #define NOCYGWIN_STATIC static #else #define NOCYGWIN_STATIC #endif //#define DEBUG_PHY 1 __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b,avg128D; int avg[4]; // [MCS][i_mod (0,1,2) = (2,4,6)] unsigned char offset_mumimo_llr_drange_fix=0; /* //original values from sebastion + same hand tuning unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{6,6,6},{6,6,6},{6,6,6},{5,5,5},{4,4,4},{1,2,4}, // QPSK {5,5,4},{5,5,5},{5,5,5},{3,3,3},{2,2,2},{2,2,2},{2,2,2}, // 16-QAM {2,2,1},{3,3,3},{3,3,3},{3,3,1},{2,2,2},{2,2,2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //64-QAM */ /* //first optimization try unsigned char offset_mumimo_llr_drange[29][3]={{7, 8, 7},{6, 6, 7},{6, 6, 7},{6, 6, 6},{5, 6, 6},{5, 5, 6},{5, 5, 6},{4, 5, 4},{4, 3, 4},{3, 2, 2},{6, 5, 5},{5, 4, 4},{5, 5, 4},{3, 3, 2},{2, 2, 1},{2, 1, 1},{2, 2, 2},{3, 3, 3},{3, 3, 2},{3, 3, 2},{3, 2, 1},{2, 2, 2},{2, 2, 2},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; */ //second optimization try /* unsigned char offset_mumimo_llr_drange[29][3]={{5, 8, 7},{4, 6, 8},{3, 6, 7},{7, 7, 6},{4, 7, 8},{4, 7, 4},{6, 6, 6},{3, 6, 6},{3, 6, 6},{1, 3, 4},{1, 1, 0},{3, 3, 2},{3, 4, 1},{4, 0, 1},{4, 2, 2},{3, 1, 2},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; w */ unsigned char offset_mumimo_llr_drange[29][3]={{0, 6, 5},{0, 4, 5},{0, 4, 5},{0, 5, 4},{0, 5, 6},{0, 5, 3},{0, 4, 4},{0, 4, 4},{0, 3, 3},{0, 1, 2},{1, 1, 0},{1, 3, 2},{3, 4, 1},{2, 0, 0},{2, 2, 2},{1, 1, 1},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}}; int rx_pdsch(PHY_VARS_UE *phy_vars_ue, PDSCH_t type, unsigned char eNB_id, unsigned char eNB_id_i, //if this == phy_vars_ue->n_connected_eNB, we assume MU interference uint8_t subframe, unsigned char symbol, unsigned char first_symbol_flag, unsigned char dual_stream_flag, unsigned char i_mod, unsigned char harq_pid) { LTE_UE_COMMON *lte_ue_common_vars = &phy_vars_ue->lte_ue_common_vars; LTE_UE_PDSCH **lte_ue_pdsch_vars; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->lte_frame_parms; PHY_MEASUREMENTS *phy_measurements = &phy_vars_ue->PHY_measurements; LTE_UE_DLSCH_t **dlsch_ue; unsigned char aatx,aarx; unsigned short nb_rb; int avgs, rb; switch (type) { case SI_PDSCH: lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]; dlsch_ue = &phy_vars_ue->dlsch_ue_SI[eNB_id]; break; case RA_PDSCH: lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_ra[eNB_id]; dlsch_ue = &phy_vars_ue->dlsch_ue_ra[eNB_id]; break; case PDSCH: lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars[eNB_id]; dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id]; break; default: //msg("[PHY][UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",phy_vars_ue->frame,subframe,type); mac_xface->macphy_exit(""); return(-1); break; } if (eNB_id > 2) { msg("dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id); return(-1); } if (!lte_ue_common_vars) { msg("dlsch_demodulation.c: Null lte_ue_common_vars\n"); return(-1); } if (!dlsch_ue[0]) { msg("dlsch_demodulation.c: Null dlsch_ue pointer\n"); return(-1); } if (!lte_ue_pdsch_vars) { msg("dlsch_demodulation.c: Null lte_ue_pdsch_vars pointer\n"); return(-1); } if (!frame_parms) { msg("dlsch_demodulation.c: Null lte_frame_parms\n"); return(-1); } // printf("rx_dlsch : eNB_id %d, eNB_id_i %d, dual_stream_flag %d\n",eNB_id,eNB_id_i,dual_stream_flag); // 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; else pilots=0; */ if (frame_parms->nb_antennas_tx_eNB>1) { #ifdef DEBUG_DLSCH_MOD LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc),dlsch_ue[0],dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc[0]); #endif nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id], lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); if (dual_stream_flag==1) { if (eNB_id_i<phy_vars_ue->n_connected_eNB) nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id_i], lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); else nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id], lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); } } // if n_tx>1 else { nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id], lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); if (dual_stream_flag==1) { if (eNB_id_i<phy_vars_ue->n_connected_eNB) nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id_i], lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); else nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF, lte_ue_common_vars->dl_ch_estimates[eNB_id], lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, dlsch_ue[0]->harq_processes[harq_pid]->pmi_alloc, lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc, symbol, subframe, frame_parms); } } //else n_tx>1 // printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id); if (nb_rb==0) { msg("dlsch_demodulation.c: nb_rb=0\n"); return(-1); } /* // DL power control: Scaling of Channel estimates for PDSCH dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, dlsch_ue, symbol, nb_rb); */ if (first_symbol_flag==1) { dlsch_channel_level(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, avg, symbol, nb_rb); #ifdef DEBUG_PHY msg("[DLSCH] avg[0] %d\n",avg[0]); #endif // the channel gain should be the effective gain of precoding + channel // however lets be more conservative and set maxh = nb_tx*nb_rx*max(h_i) // in case of precoding we add an additional factor of two for the precoding gain avgs = 0; for (aatx=0;aatx<frame_parms->nb_antennas_tx_eNB;aatx++) for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) avgs = cmax(avgs,avg[(aatx<<1)+aarx]); // avgs = cmax(avgs,avg[(aarx<<1)+aatx]); lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2); // + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits // + log2_approx(frame_parms->nb_antennas_rx-1); if ((dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode>=UNIFORM_PRECODING11) && (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) && (dlsch_ue[0]->harq_processes[harq_pid]->dl_power_off==1)) // we are in TM 6 lte_ue_pdsch_vars[eNB_id]->log2_maxh++; // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above /* K = Nb_rx in TM1 Nb_tx*Nb_rx in TM2,4,5 Nb_tx^2*Nb_rx in TM6 */ /* K = frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx_eNB; //that also covers TM1 since Nb_tx=1 if ((dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode>=UNIFORM_PRECODING11) && (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) && (dlsch_ue[0]->harq_processes[harq_pid]->dl_power_off==1)) // we are in TM 6 K *= frame_parms->nb_antennas_tx_eNB; lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2); */ #ifdef DEBUG_PHY msg("[DLSCH] log2_maxh = %d (%d,%d)\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs); msg("[DLSCH] mimo_mode = %d\n", dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode); #endif } aatx = frame_parms->nb_antennas_tx_eNB; aarx = frame_parms->nb_antennas_rx; if (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode<UNIFORM_PRECODING11) {// no precoding dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, (aatx>1) ? lte_ue_pdsch_vars[eNB_id]->rho : NULL, frame_parms, symbol, first_symbol_flag, get_Qm(dlsch_ue[0]->harq_processes[harq_pid]->mcs), nb_rb, lte_ue_pdsch_vars[eNB_id]->log2_maxh, phy_measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY if (symbol==5) write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); #endif if ((dual_stream_flag==1) && (eNB_id_i<phy_vars_ue->n_connected_eNB)) { // get MF output for interfering stream dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, (aatx>1) ? lte_ue_pdsch_vars[eNB_id_i]->rho : NULL, frame_parms, symbol, first_symbol_flag, i_mod, nb_rb, lte_ue_pdsch_vars[eNB_id]->log2_maxh, phy_measurements); // log2_maxh+I0_shift #ifdef DEBUG_PHY if (symbol == 5) { write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdsch_vars[eNB_id_i]->rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } #endif // compute correlation between signal and interference channels dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->log2_maxh); } } else if (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) {// single-layer precoding // printf("Channel compensation for precoding\n"); // if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)) { if ((dual_stream_flag==1) && (eNB_id_i==phy_vars_ue->n_connected_eNB)) { // Scale the channel estimates for interfering stream dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, frame_parms, dlsch_ue, symbol, nb_rb); /* compute new log2_maxh for effective channel */ if (first_symbol_flag==1) { // effective channel of desired user is always stronger than interfering eff. channel dlsch_channel_level_prec(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, lte_ue_pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb); // msg("llr_offset = %d\n",offset_mumimo_llr_drange[dlsch_ue[0]->harq_processes[harq_pid]->mcs][(i_mod>>1)-1]); avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch_ue[0]->harq_processes[harq_pid]->mcs][(i_mod>>1)-1]; lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0); //printf("log1_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh); } dlsch_channel_compensation_prec(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->pmi_ext, frame_parms, phy_measurements, eNB_id, symbol, get_Qm(dlsch_ue[0]->harq_processes[harq_pid]->mcs), nb_rb, lte_ue_pdsch_vars[eNB_id]->log2_maxh, dlsch_ue[0]->harq_processes[harq_pid]->dl_power_off); // if interference source is MU interference, assume opposite precoder was used at eNB // calculate opposite PMI for (rb=0;rb<nb_rb;rb++) { switch(lte_ue_pdsch_vars[eNB_id]->pmi_ext[rb]) { case 0: lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=1; break; case 1: lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=0; break; case 2: lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=3; break; case 3: lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=2; break; } // if (rb==0) // printf("pmi %d, pmi_i %d\n",lte_ue_pdsch_vars[eNB_id]->pmi_ext[rb],lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]); } dlsch_channel_compensation_prec(lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->pmi_ext, frame_parms, phy_measurements, eNB_id_i, symbol, i_mod, nb_rb, lte_ue_pdsch_vars[eNB_id]->log2_maxh, dlsch_ue[0]->harq_processes[harq_pid]->dl_power_off); #ifdef DEBUG_PHY if (symbol==5) { write_output("rxF_comp_d.m","rxF_c_d",<e_ue_pdsch_vars[eNB_id]->rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); write_output("rxF_comp_i.m","rxF_c_i",<e_ue_pdsch_vars[eNB_id_i]->rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1); } #endif dlsch_dual_stream_correlation(frame_parms, symbol, nb_rb, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->log2_maxh); } else { dlsch_channel_compensation_prec(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->pmi_ext, frame_parms, phy_measurements, eNB_id, symbol, get_Qm(dlsch_ue[0]->harq_processes[harq_pid]->mcs), nb_rb, lte_ue_pdsch_vars[eNB_id]->log2_maxh, 1); } } // printf("MRC\n"); if (frame_parms->nb_antennas_rx > 1) dlsch_detection_mrc(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->rho, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb, symbol, nb_rb, dual_stream_flag); // printf("Combining"); // Single-layer transmission formats if (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { if ((dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode == SISO) || ((dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode >= UNIFORM_PRECODING11) && (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode <= PUSCH_PRECODING0))) { /* dlsch_siso(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, symbol, nb_rb); */ } else if (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode == ALAMOUTI) { dlsch_alamouti(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, symbol, nb_rb); } else if (dlsch_ue[0]->harq_processes[harq_pid]->mimo_mode == ANTCYCLING) { dlsch_antcyc(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, symbol, nb_rb); } else { msg("dlsch_rx: Unknown MIMO mode\n"); return (-1); } // printf("LLR"); switch (get_Qm(dlsch_ue[0]->harq_processes[harq_pid]->mcs)) { case 2 : if (dual_stream_flag == 0) dlsch_qpsk_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); else if (i_mod == 2) { dlsch_qpsk_qpsk_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_qpsk_16qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else { dlsch_qpsk_64qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } break; case 4 : if (dual_stream_flag == 0) { dlsch_16qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->llr[0], lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,4,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else if (i_mod == 2) { dlsch_16qam_qpsk_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_16qam_16qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else { dlsch_16qam_64qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } break; case 6 : if (dual_stream_flag == 0) { dlsch_64qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->llr[0], lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_magb, symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,6,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else if (i_mod == 2) { dlsch_64qam_qpsk_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else if (i_mod == 4) { dlsch_64qam_16qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } else { dlsch_64qam_64qam_llr(frame_parms, lte_ue_pdsch_vars[eNB_id]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp, lte_ue_pdsch_vars[eNB_id]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag, lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext, lte_ue_pdsch_vars[eNB_id]->llr[0], symbol,first_symbol_flag,nb_rb, adjust_G2(frame_parms,dlsch_ue[0]->harq_processes[harq_pid]->rb_alloc,2,subframe,symbol), lte_ue_pdsch_vars[eNB_id]->llr128); } break; default: msg("rx_dlsch.c : Unknown mod_order!!!!\n"); return(-1); break; } } // single-layer transmission else { msg("rx_dlsch.c : Dualstream not yet implemented\n"); return(-1); } return(0); } //============================================================================================== // Pre-processing for LLR computation //============================================================================================== void dlsch_channel_compensation(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, int **rho, LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol, uint8_t first_symbol_flag, unsigned char mod_order, unsigned short nb_rb, unsigned char output_shift, PHY_MEASUREMENTS *phy_measurements) { unsigned short rb; unsigned char aatx,aarx,symbol_mod,pilots=0; __m128i *dl_ch128,*dl_ch128_2,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128,*rho128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; #ifndef __SSE3__ zero = _mm_xor_si128(zero,zero); #endif if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); else pilots=1; } for (aatx=0;aatx<frame_parms->nb_antennas_tx_eNB;aatx++) { if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); // 2/sqrt(10) QAM_amp128b = _mm_xor_si128(QAM_amp128b,QAM_amp128b); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); // QAM_amp128b = _mm_set1_epi16(QAM64_n2); } // printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol); for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128 = (__m128i *)&dl_ch_mag[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); // store channel magnitude here in a new field of dlsch dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); } dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); } } // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); dl_ch128+=3; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less dl_ch128+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=2; rxdataF_comp128+=2; } } } } if (rho) { for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { rho128 = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_2 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2); //print_shorts("ch:",dl_ch128); //print_shorts("pack:",rho128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2+1); //print_shorts("ch:",dl_ch128+1); //print_shorts("pack:",rho128+1); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); //print_shorts("rx:",dl_ch128_2+2); //print_shorts("ch:",dl_ch128+2); //print_shorts("pack:",rho128+2); dl_ch128+=3; dl_ch128_2+=3; rho128+=3; } if (first_symbol_flag==1) { phy_measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12); } } } _mm_empty(); _m_empty(); } void prec2A_128(unsigned char pmi,__m128i *ch0,__m128i *ch1) { __m128i amp; amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); switch (pmi) { case 0 : // +1 +1 // print_shorts("phase 0 :ch0",ch0); // print_shorts("phase 0 :ch1",ch1); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; case 1 : // +1 -1 // print_shorts("phase 1 :ch0",ch0); // print_shorts("phase 1 :ch1",ch1); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); // print_shorts("phase 1 :ch0-ch1",ch0); break; case 2 : // +1 +j ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_subs_epi16(ch0[0],ch1[0]); break; // +1 -j case 3 : ch1[0] = _mm_sign_epi16(ch1[0],*(__m128i*)&conjugate[0]); ch1[0] = _mm_shufflelo_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch1[0] = _mm_shufflehi_epi16(ch1[0],_MM_SHUFFLE(2,3,0,1)); ch0[0] = _mm_adds_epi16(ch0[0],ch1[0]); break; } ch0[0] = _mm_mulhi_epi16(ch0[0],amp); ch0[0] = _mm_slli_epi16(ch0[0],1); _mm_empty(); _m_empty(); } void dlsch_channel_compensation_prec(int **rxdataF_ext, int **dl_ch_estimates_ext, int **dl_ch_mag, int **dl_ch_magb, int **rxdataF_comp, unsigned char *pmi_ext, LTE_DL_FRAME_PARMS *frame_parms, PHY_MEASUREMENTS *phy_measurements, int eNB_id, unsigned char symbol, unsigned char mod_order, unsigned short nb_rb, unsigned char output_shift, unsigned char dl_power_off) { unsigned short rb,Nre; __m128i *dl_ch128_0,*dl_ch128_1,*dl_ch_mag128,*dl_ch_mag128b,*rxdataF128,*rxdataF_comp128; unsigned char aarx=0,symbol_mod,pilots=0; int precoded_signal_strength=0,rx_power_correction; 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; #ifndef NEW_FFT if ( (frame_parms->ofdm_symbol_size == 128) || (frame_parms->ofdm_symbol_size == 512) ) rx_power_correction = 2; else rx_power_correction = 1; #else rx_power_correction = 1; #endif #ifndef __SSE3__ zero = _mm_xor_si128(zero,zero); #endif //printf("comp prec: symbol %d, pilots %d\n",symbol, pilots); if (mod_order == 4) { QAM_amp128 = _mm_set1_epi16(QAM16_n1); QAM_amp128b = _mm_xor_si128(QAM_amp128b,QAM_amp128b); } else if (mod_order == 6) { QAM_amp128 = _mm_set1_epi16(QAM64_n1); QAM_amp128b = _mm_set1_epi16(QAM64_n2); } for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch128_0 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_1 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128 = (__m128i *)&dl_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128b = (__m128i *)&dl_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128 = (__m128i *)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { // combine TX channels using precoder from pmi #ifdef DEBUG_DLSCH_DEMOD printf("mode 6 prec: rb %d, pmi->%d\n",rb,pmi_ext[rb]); #endif prec2A_128(pmi_ext[rb],&dl_ch128_0[0],&dl_ch128_1[0]); prec2A_128(pmi_ext[rb],&dl_ch128_0[1],&dl_ch128_1[1]); if (pilots==0) { prec2A_128(pmi_ext[rb],&dl_ch128_0[2],&dl_ch128_1[2]); } if (mod_order>2) { // get channel amplitude if not QPSK mmtmpD0 = _mm_madd_epi16(dl_ch128_0[0],dl_ch128_0[0]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_madd_epi16(dl_ch128_0[1],dl_ch128_0[1]); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1); dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[0] = dl_ch_mag128[0]; dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128); dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128[0],1); //print_shorts("dl_ch_mag128[0]=",&dl_ch_mag128[0]); dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0); dl_ch_mag128b[1] = dl_ch_mag128[1]; dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128); dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1); if (pilots==0) { mmtmpD0 = _mm_madd_epi16(dl_ch128_0[2],dl_ch128_0[2]); mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0); dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1); dl_ch_mag128b[2] = dl_ch_mag128[2]; dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128); dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1); } dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b); dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1); //print_shorts("dl_ch_mag128b[0]=",&dl_ch_mag128b[0]); dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b); dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1); if (pilots==0) { dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b); dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1); } } // MF multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128_0[0],rxdataF128[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128_0[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128); // print_shorts("ch:",dl_ch128); // print_shorts("pack:",rxdataF_comp128); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128_0[1],rxdataF128[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128_0[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+1); // print_shorts("ch:",dl_ch128+1); // print_shorts("pack:",rxdataF_comp128+1); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128_0[2],rxdataF128[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128_0[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // print_shorts("rx:",rxdataF128+2); // print_shorts("ch:",dl_ch128+2); // print_shorts("pack:",rxdataF_comp128+2); dl_ch128_0+=3; dl_ch128_1+=3; dl_ch_mag128+=3; dl_ch_mag128b+=3; rxdataF128+=3; rxdataF_comp128+=3; } else { dl_ch128_0+=2; dl_ch128_1+=2; dl_ch_mag128+=2; dl_ch_mag128b+=2; rxdataF128+=2; rxdataF_comp128+=2; } } Nre = (pilots==0) ? 12 : 8; precoded_signal_strength += ((signal_energy_nodc(&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*Nre], (nb_rb*Nre))*rx_power_correction) - (phy_measurements->n0_power[aarx])); } // rx_antennas phy_measurements->precoded_cqi_dB[eNB_id][0] = dB_fixed2(precoded_signal_strength,phy_measurements->n0_power_tot); //printf("eNB_id %d, symbol %d: precoded CQI %d dB\n",eNB_id,symbol, // phy_measurements->precoded_cqi_dB[eNB_id][0]); _mm_empty(); _m_empty(); } void dlsch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms, unsigned char symbol, unsigned short nb_rb, int **dl_ch_estimates_ext, int **dl_ch_estimates_ext_i, int **dl_ch_rho_ext, unsigned char output_shift) { unsigned short rb; __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128; unsigned char aarx,symbol_mod,pilots=0; // printf("dlsch_dual_stream_correlation: symbol %d\n",symbol); 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;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch128 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128i = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch_rho128 = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]); // print_ints("re",&mmtmpD0); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]); // print_ints("im",&mmtmpD1); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[0]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); // print_ints("re(shift)",&mmtmpD0); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); // print_ints("im(shift)",&mmtmpD1); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); // print_ints("c0",&mmtmpD2); // print_ints("c1",&mmtmpD3); dl_ch_rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3); // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[1]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3); if (pilots==0) { // multiply by conjugated channel mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]); // mmtmpD0 contains real part of 4 consecutive outputs (32-bit) mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1)); mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate); mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128i[2]); // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit) mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift); mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift); mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1); mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1); dl_ch_rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3); dl_ch128+=3; dl_ch128i+=3; dl_ch_rho128+=3; } else { dl_ch128+=2; dl_ch128i+=2; dl_ch_rho128+=2; } } } _mm_empty(); _m_empty(); } void dlsch_detection_mrc(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **rxdataF_comp_i, int **rho, int **rho_i, int **dl_ch_mag, int **dl_ch_magb, int **dl_ch_mag_i, int **dl_ch_magb_i, unsigned char symbol, unsigned short nb_rb, unsigned char dual_stream_UE) { unsigned char aatx; int i; __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*dl_ch_mag128_0,*dl_ch_mag128_1,*dl_ch_mag128_0b,*dl_ch_mag128_1b,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1,*dl_ch_mag128_i0,*dl_ch_mag128_i1,*dl_ch_mag128_i0b,*dl_ch_mag128_i1b; if (frame_parms->nb_antennas_rx>1) { for (aatx=0;aatx<frame_parms->nb_antennas_tx_eNB;aatx++) { rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0 = (__m128i *)&dl_ch_mag[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1 = (__m128i *)&dl_ch_mag[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_0b = (__m128i *)&dl_ch_magb[(aatx<<1)][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_1b = (__m128i *)&dl_ch_magb[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12]; // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation) for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1)); dl_ch_mag128_0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0[i],1),_mm_srai_epi16(dl_ch_mag128_1[i],1)); dl_ch_mag128_0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_0b[i],1),_mm_srai_epi16(dl_ch_mag128_1b[i],1)); } } if (rho) { rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12]; rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12]; for (i=0;i<nb_rb*3;i++) { rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1)); } } if (dual_stream_UE == 1) { rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12]; rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i0 = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12]; rxdataF_comp128_i1 = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0 = (__m128i *)&dl_ch_mag_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1 = (__m128i *)&dl_ch_mag_i[1][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i0b = (__m128i *)&dl_ch_magb_i[0][symbol*frame_parms->N_RB_DL*12]; dl_ch_mag128_i1b = (__m128i *)&dl_ch_magb_i[1][symbol*frame_parms->N_RB_DL*12]; for (i=0;i<nb_rb*3;i++) { rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1)); rho128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1)); dl_ch_mag128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0[i],1),_mm_srai_epi16(dl_ch_mag128_i1[i],1)); dl_ch_mag128_i0b[i] = _mm_adds_epi16(_mm_srai_epi16(dl_ch_mag128_i0b[i],1),_mm_srai_epi16(dl_ch_mag128_i1b[i],1)); } } } _mm_empty(); _m_empty(); } void dlsch_scale_channel(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, LTE_UE_DLSCH_t **dlsch_ue, uint8_t symbol, unsigned short nb_rb){ short rb, ch_amp; unsigned char aatx,aarx,pilots=0,symbol_mod; __m128i *dl_ch128, ch_amp128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) { if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size nb_rb=1+(5*nb_rb/6); else pilots=1; } // Determine scaling amplitude based the symbol ch_amp = ((pilots) ? (dlsch_ue[0]->sqrt_rho_b) : (dlsch_ue[0]->sqrt_rho_a)); // msg("Scaling PDSCH Chest in OFDM symbol %d by %d\n",symbol_mod,ch_amp); ch_amp128 = _mm_set1_epi16(ch_amp); // Q3.13 for (aatx=0;aatx<frame_parms->nb_antennas_tx_eNB;aatx++) { for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { dl_ch128[0] = _mm_mulhi_epi16(dl_ch128[0],ch_amp128); dl_ch128[0] = _mm_slli_epi16(dl_ch128[0],3); dl_ch128[1] = _mm_mulhi_epi16(dl_ch128[1],ch_amp128); dl_ch128[1] = _mm_slli_epi16(dl_ch128[1],3); if (pilots) { dl_ch128+=2; } else { dl_ch128[2] = _mm_mulhi_epi16(dl_ch128[2],ch_amp128); dl_ch128[2] = _mm_slli_epi16(dl_ch128[2],3); dl_ch128+=3; } } } } } //compute average channel_level on each (TX,RX) antenna pair void dlsch_channel_level(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, int *avg, uint8_t symbol, unsigned short nb_rb){ short rb; unsigned char aatx,aarx,nre=12,symbol_mod; __m128i *dl_ch128; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; for (aatx=0;aatx<frame_parms->nb_antennas_tx_eNB;aatx++) for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { //clear average level avg128D = _mm_xor_si128(avg128D,avg128D); // 5 is always a symbol with no pilots for both normal and extended prefix dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { // printf("rb %d : ",rb); // print_shorts("ch",&dl_ch128[0]); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[0],dl_ch128[0])); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[1],dl_ch128[1])); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch128+=2; } else { avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128[2],dl_ch128[2])); dl_ch128+=3; } /* if (rb==0) { print_shorts("dl_ch128",&dl_ch128[0]); print_shorts("dl_ch128",&dl_ch128[1]); print_shorts("dl_ch128",&dl_ch128[2]); } */ } if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) nre=10; else nre=12; avg[(aatx<<1)+aarx] = (((int*)&avg128D)[0] + ((int*)&avg128D)[1] + ((int*)&avg128D)[2] + ((int*)&avg128D)[3])/(nb_rb*nre); // printf("Channel level : %d\n",avg[(aatx<<1)+aarx]); } _mm_empty(); _m_empty(); } //compute average channel_level of effective (precoded) channel void dlsch_channel_level_prec(int **dl_ch_estimates_ext, LTE_DL_FRAME_PARMS *frame_parms, unsigned char *pmi_ext, int *avg, uint8_t symbol, unsigned short nb_rb){ short rb; unsigned char aarx,nre=12,symbol_mod; __m128i *dl_ch128_0,*dl_ch128_1, dl_ch128_0_tmp, dl_ch128_1_tmp; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; //clear average level avg128D = _mm_xor_si128(avg128D,avg128D); avg[0] = 0; avg[1] = 0; // 5 is always a symbol with no pilots for both normal and extended prefix if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) nre=8; else if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==1)) nre=10; else nre=12; for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch128_0 = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12]; dl_ch128_1 = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12]; for (rb=0;rb<nb_rb;rb++) { dl_ch128_0_tmp = _mm_load_si128(&dl_ch128_0[0]); dl_ch128_1_tmp = _mm_load_si128(&dl_ch128_1[0]); prec2A_128(pmi_ext[rb],&dl_ch128_0_tmp,&dl_ch128_1_tmp); mmtmpD0 = _mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp)); dl_ch128_0_tmp = _mm_load_si128(&dl_ch128_0[1]); dl_ch128_1_tmp = _mm_load_si128(&dl_ch128_1[1]); prec2A_128(pmi_ext[rb],&dl_ch128_0_tmp,&dl_ch128_1_tmp); mmtmpD1 = _mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp)); if (((symbol_mod == 0) || (symbol_mod == (frame_parms->Ncp-1)))&&(frame_parms->mode1_flag==0)) { dl_ch128_0+=2; dl_ch128_1+=2; } else { dl_ch128_0_tmp = _mm_load_si128(&dl_ch128_0[2]); dl_ch128_1_tmp = _mm_load_si128(&dl_ch128_1[2]); prec2A_128(pmi_ext[rb],&dl_ch128_0_tmp,&dl_ch128_1_tmp); mmtmpD2 = _mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp); avg128D = _mm_add_epi32(avg128D,_mm_madd_epi16(dl_ch128_0_tmp,dl_ch128_0_tmp)); dl_ch128_0+=3; dl_ch128_1+=3; } } avg[aarx] = (((int*)&avg128D)[0])/(nb_rb*nre) + (((int*)&avg128D)[1])/(nb_rb*nre) + (((int*)&avg128D)[2])/(nb_rb*nre) + (((int*)&avg128D)[3])/(nb_rb*nre); } // choose maximum of the 2 effective channels avg[0] = cmax(avg[0],avg[1]); _mm_empty(); _m_empty(); } void dlsch_alamouti(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **dl_ch_mag, int **dl_ch_magb, unsigned char symbol, unsigned short nb_rb) { short *rxF0,*rxF1; __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b, amp, *rxF0_128; unsigned char rb,re; int jj = (symbol*frame_parms->N_RB_DL*12); uint8_t symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; uint8_t pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; rxF0_128 = (__m128i*) &rxdataF_comp[0][jj]; amp = _mm_set1_epi16(ONE_OVER_SQRT2_Q15); // printf("Doing alamouti!\n"); rxF0 = (short*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y rxF1 = (short*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y ch_mag0 = (__m128i *)&dl_ch_mag[0][jj]; ch_mag1 = (__m128i *)&dl_ch_mag[2][jj]; ch_mag0b = (__m128i *)&dl_ch_magb[0][jj]; ch_mag1b = (__m128i *)&dl_ch_magb[2][jj]; for (rb=0;rb<nb_rb;rb++) { for (re=0;re<((pilots==0)?12:8);re+=2) { // Alamouti RX combining rxF0[0] = rxF0[0] + rxF1[2]; rxF0[1] = rxF0[1] - rxF1[3]; rxF0[2] = rxF0[2] - rxF1[0]; rxF0[3] = rxF0[3] + rxF1[1]; rxF0+=4; rxF1+=4; } // compute levels for 16QAM or 64 QAM llr unit ch_mag0[0] = _mm_adds_epi16(ch_mag0[0],ch_mag1[0]); ch_mag0[1] = _mm_adds_epi16(ch_mag0[1],ch_mag1[1]); ch_mag0b[0] = _mm_adds_epi16(ch_mag0b[0],ch_mag1b[0]); ch_mag0b[1] = _mm_adds_epi16(ch_mag0b[1],ch_mag1b[1]); // account for 1/sqrt(2) scaling at transmission ch_mag0[0] = _mm_srai_epi16(ch_mag0[0],1); ch_mag0[1] = _mm_srai_epi16(ch_mag0[1],1); ch_mag0b[0] = _mm_srai_epi16(ch_mag0b[0],1); ch_mag0b[1] = _mm_srai_epi16(ch_mag0b[1],1); rxF0_128[0] = _mm_mulhi_epi16(rxF0_128[0],amp); rxF0_128[0] = _mm_slli_epi16(rxF0_128[0],1); rxF0_128[1] = _mm_mulhi_epi16(rxF0_128[1],amp); rxF0_128[1] = _mm_slli_epi16(rxF0_128[1],1); if (pilots==0) { ch_mag0[2] = _mm_adds_epi16(ch_mag0[2],ch_mag1[2]); ch_mag0b[2] = _mm_adds_epi16(ch_mag0b[2],ch_mag1b[2]); ch_mag0[2] = _mm_srai_epi16(ch_mag0[2],1); ch_mag0b[2] = _mm_srai_epi16(ch_mag0b[2],1); rxF0_128[2] = _mm_mulhi_epi16(rxF0_128[2],amp); rxF0_128[2] = _mm_slli_epi16(rxF0_128[2],1); ch_mag0+=3; ch_mag1+=3; ch_mag0b+=3; ch_mag1b+=3; rxF0_128+=3; } else { ch_mag0+=2; ch_mag1+=2; ch_mag0b+=2; ch_mag1b+=2; rxF0_128+=2; } } _mm_empty(); _m_empty(); } void dlsch_antcyc(LTE_DL_FRAME_PARMS *frame_parms, int **rxdataF_comp, int **dl_ch_mag, int **dl_ch_magb, unsigned char symbol, unsigned short nb_rb) { unsigned char rb,re; int jj=1+(symbol*frame_parms->N_RB_DL*12); // printf("Doing antcyc rx\n"); for (rb=0;rb<nb_rb;rb++) { for (re=0;re<12;re+=2) { rxdataF_comp[0][jj] = rxdataF_comp[2][jj]; //copy odd carriers from tx antenna 1 dl_ch_mag[0][jj] = dl_ch_mag[2][jj]; dl_ch_magb[0][jj] = dl_ch_magb[2][jj]; jj+=2; } } } //============================================================================================== // Extraction functions //============================================================================================== unsigned short dlsch_extract_rbs_single(int **rxdataF, int **dl_ch_estimates, int **rxdataF_ext, int **dl_ch_estimates_ext, unsigned short pmi, unsigned char *pmi_ext, unsigned int *rb_alloc, unsigned char symbol, unsigned char subframe, LTE_DL_FRAME_PARMS *frame_parms) { unsigned short rb,nb_rb=0; unsigned char rb_alloc_ind; unsigned char i,aarx,l,nsymb,skip_half=0,sss_symb,pss_symb=0; int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext; unsigned char symbol_mod,pilots=0,j=0,poffset=0; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; pilots = ((symbol_mod==0)||(symbol_mod==(4-frame_parms->Ncp))) ? 1 : 0; l=symbol; nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; if (frame_parms->frame_type == TDD) { // TDD sss_symb = nsymb-1; pss_symb = 2; } else { sss_symb = (nsymb>>1)-2; pss_symb = (nsymb>>1)-1; } if (symbol_mod==(4-frame_parms->Ncp)) poffset=3; for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; #ifndef NEW_FFT rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0;rb<frame_parms->N_RB_DL;rb++) { if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1; else rb_alloc_ind = 0; // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { #ifndef NEW_FFT rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif //dl_ch0++; } if (rb_alloc_ind==1) { *pmi_ext = (pmi>>((rb>>2)<<1))&3; memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { for (i=0;i<12;i++) { #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif /* printf("%d : (%d,%d)\n",(rxF+i-&rxdataF[aarx][( (symbol*(frame_parms->ofdm_symbol_size)))]), ((short*)&rxF[i])[0],((short*)&rxF[i])[1]);*/ } dl_ch0_ext+=12; rxF_ext+=12; } else { j=0; for (i=0;i<12;i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } nb_rb++; } dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { // Odd number of RBs for (rb=0;rb<frame_parms->N_RB_DL>>1;rb++) { // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[(i+6)<<1]; #else rxF_ext[i]=rxF[(i+6)]; #endif dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=12; rxF_ext+=12; } } else { // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0;i<6;i++) { if (i!=((frame_parms->nushift+poffset)%6)) { #ifdef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=5; rxF_ext+=5; } else if (skip_half==2) { for (i=0;i<6;i++) { if (i!=((frame_parms->nushift+poffset)%6)) { #ifndef NEW_FFT rxF_ext[j]=rxF[(i+6)<<1]; #else rxF_ext[j]=rxF[(i+6)]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i+6]; } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0;i<12;i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } } dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } // first half loop // Do middle RB (around DC) if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //PSS if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("DC rb %d (%p)\n",rb,rxF); if (rb_alloc_ind==1) { if (pilots==0) { for (i=0;i<6;i++) { dl_ch0_ext[i]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { dl_ch0_ext[i]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[(1+i-6)<<1]; #else rxF_ext[i]=rxF[(1+i-6)]; #endif } dl_ch0_ext+=12; rxF_ext+=12; } else { // pilots==1 j=0; for (i=0;i<6;i++) { if (i!=((frame_parms->nushift+poffset)%6)) { dl_ch0_ext[j]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[i<<1]; #else rxF_ext[j++]=rxF[i]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { if (i!=((frame_parms->nushift+6+poffset)%12)) { dl_ch0_ext[j]=dl_ch0[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[(1+i-6)<<1]; #else rxF_ext[j++]=rxF[(1+i-6)]; #endif // printf("**extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } dl_ch0_ext+=10; rxF_ext+=10; } // symbol_mod==0 } // rballoc==1 else { #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif } dl_ch0+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; for (;rb<frame_parms->N_RB_DL;rb++) { // printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]); // printf("rb %d (%p)\n",rb,rxF); skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=nsymb>>1) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } //PSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch0)[i<<1],((short*)dl_ch0)[1+(i<<1)]); printf("\n"); */ if (pilots==0) { // printf("Extracting w/o pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[(i+6)<<1]; #else rxF_ext[i]=rxF[(i+6)]; #endif dl_ch0_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=12; rxF_ext+=12; } } else { // printf("Extracting with pilots (symbol %d, rb %d, skip_half %d)\n",l,rb,skip_half); j=0; if (skip_half==1) { for (i=0;i<6;i++) { if (i!=((frame_parms->nushift+poffset)%6)) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=5; rxF_ext+=5; } else if (skip_half==2) { for (i=0;i<6;i++) { if (i!=((frame_parms->nushift+poffset)%6)) { #ifndef NEW_FFT rxF_ext[j]=rxF[(i+6)<<1]; #else rxF_ext[j]=rxF[(i+6)]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i+6]; } } dl_ch0_ext+=5; rxF_ext+=5; } else { for (i=0;i<12;i++) { if ((i!=(frame_parms->nushift+poffset)) && (i!=((frame_parms->nushift+poffset+6)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j++]=dl_ch0[i]; } } dl_ch0_ext+=10; rxF_ext+=10; } } // pilots=0 } dl_ch0+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } } _mm_empty(); _m_empty(); return(nb_rb/frame_parms->nb_antennas_rx); } unsigned short dlsch_extract_rbs_dual(int **rxdataF, int **dl_ch_estimates, int **rxdataF_ext, int **dl_ch_estimates_ext, unsigned short pmi, unsigned char *pmi_ext, unsigned int *rb_alloc, unsigned char symbol, unsigned char subframe, LTE_DL_FRAME_PARMS *frame_parms) { unsigned short rb,nb_rb=0; unsigned char rb_alloc_ind,skip_half=0,sss_symb,pss_symb=0,nsymb,l; unsigned char i,aarx; int *dl_ch0,*dl_ch0_ext,*dl_ch1,*dl_ch1_ext,*rxF,*rxF_ext; unsigned char symbol_mod,pilots=0,j=0; unsigned char *pmi_loc; symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol; // printf("extract_rbs: symbol_mod %d\n",symbol_mod); if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) pilots=1; nsymb = (frame_parms->Ncp==NORMAL) ? 14:12; l=symbol; if (frame_parms->frame_type == TDD) { // TDD sss_symb = nsymb-1; pss_symb = 2; } else { sss_symb = (nsymb>>1)-2; pss_symb = (nsymb>>1)-1; } for (aarx=0;aarx<frame_parms->nb_antennas_rx;aarx++) { dl_ch0 = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; dl_ch1 = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))]; dl_ch1_ext = &dl_ch_estimates_ext[2+aarx][symbol*(frame_parms->N_RB_DL*12)]; pmi_loc = pmi_ext; rxF_ext = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)]; #ifndef NEW_FFT rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif if ((frame_parms->N_RB_DL&1) == 0) // even number of RBs for (rb=0;rb<frame_parms->N_RB_DL;rb++) { skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; // For second half of RBs skip DC carrier if (rb==(frame_parms->N_RB_DL>>1)) { #ifndef NEW_FFT rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))]; #endif //dl_ch0++; //dl_ch1++; } // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { *pmi_loc = (pmi>>((rb>>2)<<1))&3; // printf("rb %d: sb %d : pmi %d\n",rb,rb>>2,*pmi_loc); pmi_loc++; if (pilots == 0) { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int)); /* printf("rb %d\n",rb); for (i=0;i<12;i++) printf("(%d %d)",((short *)dl_ch)[i<<1],((short*)dl_ch)[1+(i<<1)]); printf("\n");*/ for (i=0;i<12;i++) { #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif // printf("%d : (%d,%d)\n",(rxF+(2*i)-&rxdataF[(aatx<<1)+aarx][( (symbol*(frame_parms->ofdm_symbol_size)))*2])/2, // ((short*)&rxF[i<<1])[0],((short*)&rxF[i<<1])[0]); } nb_rb++; dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } else { j=0; for (i=0;i<12;i++) { if ((i!=frame_parms->nushift) && (i!=frame_parms->nushift+3) && (i!=frame_parms->nushift+6) && (i!=((frame_parms->nushift+9)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } nb_rb++; dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } // pilots==1 } dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } else { // Odd number of RBs for (rb=0;rb<frame_parms->N_RB_DL>>1;rb++) { skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind == 1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; //PSS in subframe 0/5 if FDD if (frame_parms->frame_type == FDD) { //FDD if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //TDD Subframe 6 if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } // printf("rb %d: alloc %d skip_half %d (rxF %p, rxF_ext %p)\n",rb,rb_alloc_ind,skip_half,rxF,rxF_ext); if (rb_alloc_ind==1) { *pmi_loc = (pmi>>((rb>>2)<<1))&3; // printf("symbol_mod %d (pilots %d) rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",symbol_mod,pilots,rb,rb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); pmi_loc++; if (pilots==0) { if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1+6,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[(i+6)<<1]; #else rxF_ext[i]=rxF[(i+6)]; #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } } else { // pilots=1 j=0; if (skip_half==1) { for (i=0;i<6;i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("(pilots,skip1)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } else if (skip_half==2) { for (i=0;i<6;i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))) { #ifndef NEW_FFT rxF_ext[j]=rxF[(i+6)<<1]; #else rxF_ext[j]=rxF[(i+6)]; #endif // printf("(pilots,skip2)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i+6]; dl_ch1_ext[j++]=dl_ch1[i+6]; } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } } else { for (i=0;i<12;i++) { if ((i!=frame_parms->nushift) && (i!=frame_parms->nushift+3) && (i!=frame_parms->nushift+6) && (i!=((frame_parms->nushift+9)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("(pilots)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j] =dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; // printf("extract rb %d, re %d => ch0 (%d,%d) ch1 (%d,%d)\n",rb,i, // *(short *)&dl_ch0_ext[j-1],*(1+(short*)&dl_ch0_ext[j-1]), // *(short *)&dl_ch1_ext[j-1],*(1+(short*)&dl_ch1_ext[j-1])); } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } } } dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } // Do middle RB (around DC) if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //PSS if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } } if (rb_alloc_ind==1) { *pmi_loc = (pmi>>((rb>>2)<<1))&3; // printf("rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",rb,rb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); pmi_loc++; if (pilots==0) { for (i=0;i<6;i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif } #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif for (;i<12;i++) { dl_ch0_ext[i]=dl_ch0[i]; dl_ch1_ext[i]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[i]=rxF[(1+i-6)<<1]; #else rxF_ext[i]=rxF[(1+i-6)]; #endif } dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } else { // pilots==1 j=0; for (i=0;i<6;i++) { if ((i!=frame_parms->nushift) && (i!=((frame_parms->nushift+3)%6))){ dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[i<<1]; #else rxF_ext[j++]=rxF[i]; #endif // printf("(pilots center)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); // printf("extract rb %d, re %d => ch0 (%d,%d) ch1 (%d,%d)\n",rb,i, // *(short *)&dl_ch0_ext[j-1],*(1+(short*)&dl_ch0_ext[j-1]), // *(short *)&dl_ch1_ext[j-1],*(1+(short*)&dl_ch1_ext[j-1])); } } #ifndef NEW_FFT rxF = &rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)*2]; #else rxF = &rxdataF[aarx][symbol*(frame_parms->ofdm_symbol_size)]; #endif for (;i<12;i++) { if ((i!=((frame_parms->nushift+6)%12)) && (i!=((frame_parms->nushift+9)%12))){ dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j]=dl_ch1[i]; #ifndef NEW_FFT rxF_ext[j++]=rxF[(1+i-6)<<1]; #else rxF_ext[j++]=rxF[(1+i-6)]; #endif // printf("(pilots center )extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j-1],*(1+(short*)&rxF_ext[j-1])); } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } } else { #ifndef NEW_FFT rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))*2]; #else rxF = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))]; #endif } dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=14; #else rxF+=7; #endif rb++; for (;rb<frame_parms->N_RB_DL;rb++) { skip_half=0; if (rb < 32) rb_alloc_ind = (rb_alloc[0]>>rb) & 1; else if (rb < 64) rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1; else if (rb < 96) rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1; else if (rb < 100) rb_alloc_ind = (rb_alloc[0]>>(rb-96)) & 1; else rb_alloc_ind = 0; if (rb_alloc_ind==1) nb_rb++; // PBCH if ((subframe==0) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) { rb_alloc_ind = 0; } //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3 if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=1; else if ((subframe==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4))) skip_half=2; //SSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb) ) { rb_alloc_ind = 0; } //SSS if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==sss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==sss_symb)) skip_half=2; if (frame_parms->frame_type == FDD) { //PSS if (((subframe==0)||(subframe==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if (((subframe==0)||(subframe==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if ((frame_parms->frame_type == TDD) && (subframe==6)){ //PSS if ((rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb) ) { rb_alloc_ind = 0; } if ((rb==((frame_parms->N_RB_DL>>1)-3)) && (l==pss_symb)) skip_half=1; else if ((rb==((frame_parms->N_RB_DL>>1)+3)) && (l==pss_symb)) skip_half=2; } if (rb_alloc_ind==1) { *pmi_loc = (pmi>>((rb>>2)<<1))&3; // printf("rb %d, sb %d, pmi %d (pmi_loc %p,rxF %p, ch00 %p, ch01 %p, rxF_ext %p dl_ch0_ext %p dl_ch1_ext %p)\n",rb,rb>>2,*pmi_loc,pmi_loc,rxF,dl_ch0, dl_ch1, rxF_ext,dl_ch0_ext,dl_ch1_ext); pmi_loc++; if (pilots==0) { if (skip_half==1) { memcpy(dl_ch0_ext,dl_ch0,6*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else if (skip_half==2) { memcpy(dl_ch0_ext,dl_ch0+6,6*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1+6,6*sizeof(int)); for (i=0;i<6;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[(i+6)<<1]; #else rxF_ext[i]=rxF[(i+6)]; #endif dl_ch0_ext+=6; dl_ch1_ext+=6; rxF_ext+=6; } else { memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int)); memcpy(dl_ch1_ext,dl_ch1,12*sizeof(int)); for (i=0;i<12;i++) #ifndef NEW_FFT rxF_ext[i]=rxF[i<<1]; #else rxF_ext[i]=rxF[i]; #endif dl_ch0_ext+=12; dl_ch1_ext+=12; rxF_ext+=12; } } else { j=0; if (skip_half==1) { for (i=0;i<6;i++) { if ((i!=(frame_parms->nushift)) && (i!=((frame_parms->nushift+3)%6))){ #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("(skip1,pilots)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; } } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } else if (skip_half==2) { for (i=0;i<6;i++) { if ((i!=(frame_parms->nushift)) && (i!=((frame_parms->nushift+3)%6))){ #ifndef NEW_FFT rxF_ext[j]=rxF[(i+6)<<1]; #else rxF_ext[j]=rxF[(i+6)]; #endif // printf("(skip2,pilots)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i+6]; dl_ch1_ext[j++]=dl_ch1[i+6]; } } dl_ch0_ext+=4; dl_ch1_ext+=4; rxF_ext+=4; } else { for (i=0;i<12;i++) { if ((i!=frame_parms->nushift) && (i!=frame_parms->nushift+3) && (i!=frame_parms->nushift+6) && (i!=((frame_parms->nushift+9)%12))) { #ifndef NEW_FFT rxF_ext[j]=rxF[i<<1]; #else rxF_ext[j]=rxF[i]; #endif // printf("(pilots)extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j])); dl_ch0_ext[j]=dl_ch0[i]; dl_ch1_ext[j++]=dl_ch1[i]; // printf("extract rb %d, re %d => ch0 (%d,%d) ch1 (%d,%d)\n",rb,i, // *(short *)&dl_ch0_ext[j-1],*(1+(short*)&dl_ch0_ext[j-1]), // *(short *)&dl_ch1_ext[j-1],*(1+(short*)&dl_ch1_ext[j-1])); } } dl_ch0_ext+=8; dl_ch1_ext+=8; rxF_ext+=8; } } } dl_ch0+=12; dl_ch1+=12; #ifndef NEW_FFT rxF+=24; #else rxF+=12; #endif } } } _mm_empty(); _m_empty(); return(nb_rb/frame_parms->nb_antennas_rx); } //============================================================================================== // Auxiliary functions //============================================================================================== #ifdef USER_MODE void dump_dlsch2(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword) { unsigned int nsymb = (phy_vars_ue->lte_frame_parms.Ncp == 0) ? 14 : 12; char fname[32],vname[32]; int N_RB_DL=phy_vars_ue->lte_frame_parms.N_RB_DL; sprintf(fname,"dlsch%d_rxF_ext0.m",eNB_id); sprintf(vname,"dl%d_rxF_ext0",eNB_id); write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_ext[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_ch_ext00.m",eNB_id); sprintf(vname,"dl%d_ch_ext00",eNB_id); write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[0],12*N_RB_DL*nsymb,1,1); /* write_output("dlsch%d_ch_ext01.m","dl01_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[1],12*N_RB_DL*nsymb,1,1); write_output("dlsch%d_ch_ext10.m","dl10_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2],12*N_RB_DL*nsymb,1,1); write_output("dlsch%d_ch_ext11.m","dl11_ch0_ext",lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[3],12*N_RB_DL*nsymb,1,1); write_output("dlsch%d_rho.m","dl_rho",lte_ue_pdsch_vars[eNB_id]->rho[0],12*N_RB_DL*nsymb,1,1); */ sprintf(fname,"dlsch%d_rxF_comp0.m",eNB_id); sprintf(vname,"dl%d_rxF_comp0",eNB_id); write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->rxdataF_comp[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_rxF_llr.m",eNB_id); sprintf(vname,"dl%d_llr",eNB_id); write_output(fname,vname, phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->llr[0],coded_bits_per_codeword,1,0); sprintf(fname,"dlsch%d_mag1.m",eNB_id); sprintf(vname,"dl%d_mag1",eNB_id); write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_mag[0],12*N_RB_DL*nsymb,1,1); sprintf(fname,"dlsch%d_mag2.m",eNB_id); sprintf(vname,"dl%d_mag2",eNB_id); write_output(fname,vname,phy_vars_ue->lte_ue_pdsch_vars[eNB_id]->dl_ch_magb[0],12*N_RB_DL*nsymb,1,1); } #endif #ifdef DEBUG_DLSCH_DEMOD void print_bytes(char *s,__m128i *x) { char *tempb = (char *)x; printf("%s : %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3],tempb[4],tempb[5],tempb[6],tempb[7], tempb[8],tempb[9],tempb[10],tempb[11],tempb[12],tempb[13],tempb[14],tempb[15] ); } void print_shorts(char *s,__m128i *x) { short *tempb = (short *)x; printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3],tempb[4],tempb[5],tempb[6],tempb[7]); } void print_shorts2(char *s,__m64 *x) { short *tempb = (short *)x; printf("%s : %d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3]); } void print_ints(char *s,__m128i *x) { int *tempb = (int *)x; printf("%s : %d,%d,%d,%d\n",s, tempb[0],tempb[1],tempb[2],tempb[3]); } #endif