dlsch_demodulation.c 203 KB
Newer Older
1
/******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5 6 7 8
    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.
9 10


ghaddab's avatar
ghaddab committed
11 12 13 14
    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.
15

ghaddab's avatar
ghaddab committed
16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
ghaddab's avatar
ghaddab committed
22 23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

28
*******************************************************************************/
29 30 31 32 33

/*! \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
34
 * \version 0.1
35 36 37 38 39 40 41 42 43 44
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,ankit.bhamri@eurecom.fr,sebastien.aubert@eurecom.fr
 * \note
 * \warning
 */

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
45
#include "PHY/sse_intrin.h"
46 47 48 49 50


#ifndef USER_MODE
#define NOCYGWIN_STATIC static
#else
51
#define NOCYGWIN_STATIC
52 53 54
#endif

//#define DEBUG_PHY 1
55
//#define DEBUG_DLSCH_DEMOD 1
56

knopp's avatar
knopp committed
57
int avg[4]; 
58 59

// [MCS][i_mod (0,1,2) = (2,4,6)]
60 61 62 63
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
64 65
{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
66
*/
67 68 69 70 71 72 73 74
 /*
 //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
 */
75
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}};
76

77

78
extern void print_shorts(char *s,int16_t *x);
79

80 81 82 83
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
gauthier's avatar
gauthier committed
84
             uint8_t subframe,
85 86 87 88
             unsigned char symbol,
             unsigned char first_symbol_flag,
             unsigned char dual_stream_flag,
             unsigned char i_mod,
89 90 91
             unsigned char harq_pid)
{

92 93 94 95 96 97
  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;

98
  unsigned char aatx,aarx;
99
  unsigned short nb_rb;
100
  int avgs, rb;
101
  LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
102
  
103
  uint8_t beamforming_mode;
104
  uint32_t *rballoc;
105

106 107 108 109
  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];
110
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
111
    beamforming_mode  = 0;
112
    break;
113

114 115 116
  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];
117
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
118
    beamforming_mode  = 0;
119
    break;
120

121 122 123
  case PDSCH:
    lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars[eNB_id];
    dlsch_ue          = phy_vars_ue->dlsch_ue[eNB_id];
124 125
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
    dlsch1_harq       = dlsch_ue[1]->harq_processes[harq_pid];
126
    beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]<7?0:phy_vars_ue->transmission_mode[eNB_id];
127 128 129
    break;

  default:
130
    LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",phy_vars_ue->frame_rx,subframe,type);
131 132 133
    return(-1);
    break;
  }
134 135


136
  if (eNB_id > 2) {
jiangx's avatar
jiangx committed
137
    LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id);
138 139
    return(-1);
  }
140

141
  if (!lte_ue_common_vars) {
jiangx's avatar
jiangx committed
142
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_common_vars\n");
143 144 145 146
    return(-1);
  }

  if (!dlsch_ue[0]) {
jiangx's avatar
jiangx committed
147
    LOG_W(PHY,"dlsch_demodulation.c: Null dlsch_ue pointer\n");
148 149 150 151
    return(-1);
  }

  if (!lte_ue_pdsch_vars) {
jiangx's avatar
jiangx committed
152
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_pdsch_vars pointer\n");
153 154
    return(-1);
  }
155

156
  if (!frame_parms) {
jiangx's avatar
jiangx committed
157
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_frame_parms\n");
158 159
    return(-1);
  }
160

161 162 163 164 165 166
  
  if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) ||
      ((frame_parms->Ncp == EXTENDED) && (symbol>=6)))
    rballoc = dlsch0_harq->rb_alloc_odd;
  else
    rballoc = dlsch0_harq->rb_alloc_even;
167

Xiwen JIANG's avatar
Xiwen JIANG committed
168
  if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
169
#ifdef DEBUG_DLSCH_MOD
170
    LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch_ue[0],dlsch0_harq->rb_alloc_even[0]);
171 172
#endif
    nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF,
173 174 175 176 177
                                   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,
                                   dlsch0_harq->pmi_alloc,
                                   lte_ue_pdsch_vars[eNB_id]->pmi_ext,
178
                                   rballoc,
179 180 181 182
                                   symbol,
                                   subframe,
                                   phy_vars_ue->high_speed_flag,
                                   frame_parms);
183 184 185

    if (dual_stream_flag==1) {
      if (eNB_id_i<phy_vars_ue->n_connected_eNB)
186 187 188 189 190 191
        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,
                                       dlsch0_harq->pmi_alloc,
                                       lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
192
                                       rballoc,
193 194 195 196 197 198 199 200 201 202 203
                                       symbol,
                                       subframe,
                                       phy_vars_ue->high_speed_flag,
                                       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,
                                       dlsch0_harq->pmi_alloc,
                                       lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
204
                                       rballoc,
205 206 207 208
                                       symbol,
                                       subframe,
                                       phy_vars_ue->high_speed_flag,
                                       frame_parms);
209
    }
210
  } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0
211
    nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF,
212 213 214 215 216
                                     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,
                                     dlsch0_harq->pmi_alloc,
                                     lte_ue_pdsch_vars[eNB_id]->pmi_ext,
217
                                     rballoc,
218 219 220 221 222
                                     symbol,
                                     subframe,
                                     phy_vars_ue->high_speed_flag,
                                     frame_parms);

223 224
    if (dual_stream_flag==1) {
      if (eNB_id_i<phy_vars_ue->n_connected_eNB)
225 226 227 228 229 230
        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,
                                         dlsch0_harq->pmi_alloc,
                                         lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
231
                                         rballoc,
232 233 234 235
                                         symbol,
                                         subframe,
                                         phy_vars_ue->high_speed_flag,
                                         frame_parms);
236
      
237 238 239 240 241 242
        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,
                                         dlsch0_harq->pmi_alloc,
                                         lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
243
                                         rballoc,
244 245
                                         symbol,
                                         subframe,
246
					 phy_vars_ue->high_speed_flag,
247
                                         frame_parms);
248
    }
249
  } else if (beamforming_mode==7) { //else if beamforming_mode == 7
250
    nb_rb = dlsch_extract_rbs_TM7(lte_ue_common_vars->rxdataF,
251
                                  lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates,
252
                                  lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
253
                                  lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
254
				  rballoc,
255 256 257 258 259 260 261 262
                                  symbol,
                                  subframe,
                                  phy_vars_ue->high_speed_flag,
                                  frame_parms);
    
  } else if(beamforming_mode>7) {
    LOG_W(PHY,"dlsch_demodulation:beamforming mode not supported yet.\n");
  }
263 264

  //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
265
  if (nb_rb==0) {
266
    LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n");
267 268
    return(-1);
  }
269

knopp's avatar
 
knopp committed
270
  /*
271 272
  // DL power control: Scaling of Channel estimates for PDSCH
  dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
273 274 275 276
  frame_parms,
  dlsch_ue,
  symbol,
  nb_rb);
knopp's avatar
 
knopp committed
277
  */
278
  if (first_symbol_flag==1) {
279 280 281 282 283 284
    if (beamforming_mode==0)
       dlsch_channel_level(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                           frame_parms,
                           avg,
                           symbol,
                           nb_rb);
Xiwen JIANG's avatar
Xiwen JIANG committed
285 286
    else if (beamforming_mode==7)
       dlsch_channel_level_TM7(lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
287 288 289 290 291
                           frame_parms,
                           avg,
                           symbol,
                           nb_rb);
       
292
#ifdef DEBUG_PHY
jiangx's avatar
jiangx committed
293
    LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]);
294
#endif
295

296 297 298 299
    // 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;
300

Xiwen JIANG's avatar
Xiwen JIANG committed
301
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
302 303 304 305 306 307
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
        avgs = cmax(avgs,avg[(aatx<<1)+aarx]);

    //  avgs = cmax(avgs,avg[(aarx<<1)+aatx]);


308
    lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2);
Xiwen JIANG's avatar
Xiwen JIANG committed
309
    // + log2_approx(frame_parms->nb_antenna_ports_eNB-1) //-1 because log2_approx counts the number of bits
310
    //      + log2_approx(frame_parms->nb_antennas_rx-1);
311

312
    if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
313 314
        (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
        (dlsch0_harq->dl_power_off==1)) // we are in TM 6
315 316 317
      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
318
    /* K = Nb_rx         in TM1
319 320 321
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
Xiwen JIANG's avatar
Xiwen JIANG committed
322
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
323 324 325
      if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
      (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
      (dlsch0_harq->dl_power_off==1)) // we are in TM 6
Xiwen JIANG's avatar
Xiwen JIANG committed
326
      K *= frame_parms->nb_antenna_ports_eNB;
327 328 329 330 331

      lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
    */

#ifdef DEBUG_PHY
jiangx's avatar
jiangx committed
332 333
    LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs);
    LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode);
334 335
#endif
  }
336

Xiwen JIANG's avatar
Xiwen JIANG committed
337
  aatx = frame_parms->nb_antenna_ports_eNB;
338 339
  aarx = frame_parms->nb_antennas_rx;

340
  if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI
341 342

    dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
343 344 345 346 347 348 349 350
                               lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                               lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                               lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                               lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                               (aatx>1) ? lte_ue_pdsch_vars[eNB_id]->rho : NULL,
                               frame_parms,
                               symbol,
                               first_symbol_flag,
351
                               dlsch0_harq->Qm,
352 353 354
                               nb_rb,
                               lte_ue_pdsch_vars[eNB_id]->log2_maxh,
                               phy_measurements); // log2_maxh+I0_shift
355
#ifdef DEBUG_PHY
356

357
    if (symbol==5)
358
      write_output("rxF_comp_d.m","rxF_c_d",&lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
359

360
#endif
361 362 363

    if ((dual_stream_flag==1) &&
        (eNB_id_i<phy_vars_ue->n_connected_eNB)) {
364 365
      // get MF output for interfering stream
      dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext,
366 367 368 369 370 371 372 373 374 375 376 377
                                 lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                 lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                                 lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0,
                                 lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                                 (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
378
#ifdef DEBUG_PHY
379

380
      if (symbol == 5) {
381 382
        write_output("rxF_comp_d.m","rxF_c_d",&lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0[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",&lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
383
      }
384 385 386

#endif

387 388
      // compute correlation between signal and interference channels
      dlsch_dual_stream_correlation(frame_parms,
389 390 391 392 393 394
                                    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);
395
    }
396
  } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3
397
    //   LOG_I(PHY,"Running PDSCH RX for TM3\n");
Xiwen JIANG's avatar
Xiwen JIANG committed
398
    if (frame_parms->nb_antenna_ports_eNB == 2) {
399
      if (first_symbol_flag==1) {
400 401 402 403 404 405
        // effective channel of desired user is always stronger than interfering eff. channel
        dlsch_channel_level_TM3(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                frame_parms,
                                avg, symbol, nb_rb);

        //  LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->mcs>>1)-1]);
406
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1];
407 408 409 410 411 412 413 414 415 416

        lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh);
      }

      dlsch_channel_compensation_TM3(frame_parms,
                                     lte_ue_pdsch_vars[eNB_id],
                                     phy_measurements,
                                     eNB_id,
                                     symbol,
417 418
                                     dlsch0_harq->Qm,
                                     dlsch1_harq->Qm,
419 420 421
                                     dlsch0_harq->round,
                                     nb_rb,
                                     lte_ue_pdsch_vars[eNB_id]->log2_maxh);
422
      // compute correlation between signal and interference channels (rho12 and rho21)
423
      dlsch_dual_stream_correlation(frame_parms,
424 425 426 427 428 429
                                    symbol,
                                    nb_rb,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                    &(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]),
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                                    lte_ue_pdsch_vars[eNB_id]->log2_maxh);
430
      dlsch_dual_stream_correlation(frame_parms,
431 432 433 434 435 436
                                    symbol,
                                    nb_rb,
                                    &(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext[2]),
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_rho2_ext,
                                    lte_ue_pdsch_vars[eNB_id]->log2_maxh);
437 438
      //printf("TM3 log2_maxh : %d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh);

439
    } else {
440
      LOG_E(PHY, "only 2 tx antennas supported for TM3\n");
441
    }
442
  } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { // single-layer precoding (TM5, TM6), potentially TM4 (Single-codeword)
443
    //    printf("Channel compensation for precoding\n");
444
    //    if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)){
445
    if ((dual_stream_flag==1) && (eNB_id_i==phy_vars_ue->n_connected_eNB)) {  // TM5 two-user
446 447 448

      // Scale the channel estimates for interfering stream

449
      dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
450 451 452 453
                          frame_parms,
                          dlsch_ue,
                          symbol,
                          nb_rb);
454 455 456

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
        // effective channel of desired user is always stronger than interfering eff. channel
        dlsch_channel_level_TM56(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, lte_ue_pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);

        //    LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]);
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->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_TM56(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_mag0,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                                      lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                                      lte_ue_pdsch_vars[eNB_id]->pmi_ext,
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
477
                                      dlsch0_harq->Qm,
478 479 480
                                      nb_rb,
                                      lte_ue_pdsch_vars[eNB_id]->log2_maxh,
                                      dlsch0_harq->dl_power_off);
481 482 483 484

      // if interference source is MU interference, assume opposite precoder was used at eNB

      // calculate opposite PMI
485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
      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]);

507 508
      }

509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
      dlsch_channel_compensation_TM56(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_mag0,
                                      lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0,
                                      lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                                      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,
                                      dlsch0_harq->dl_power_off);

524
#ifdef DEBUG_PHY
525

526
      if (symbol==5) {
527 528
        write_output("rxF_comp_d.m","rxF_c_d",&lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0[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",&lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
529 530
      }

531 532 533 534 535 536 537 538 539
#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);
540

541
    } else {
542
      dlsch_channel_compensation_TM56(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
543 544 545 546 547 548 549 550 551
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                                      lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                                      lte_ue_pdsch_vars[eNB_id]->pmi_ext,
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
552
                                      dlsch0_harq->Qm,
553 554 555
                                      nb_rb,
                                      lte_ue_pdsch_vars[eNB_id]->log2_maxh,
                                      1);
556
    }
557 558 559
  } else if (dlsch0_harq->mimo_mode==TM7) { //TM7

    dlsch_channel_compensation(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
560
                               lte_ue_pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
561 562 563 564 565 566 567 568 569
                               lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                               lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                               lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                               (aatx>1) ? lte_ue_pdsch_vars[eNB_id]->rho : NULL,
                               frame_parms,
                               symbol,
                               first_symbol_flag,
                               get_Qm(dlsch0_harq->mcs),
                               nb_rb,
570
                               //9,
571 572
                               lte_ue_pdsch_vars[eNB_id]->log2_maxh,
                               phy_measurements); // log2_maxh+I0_shift
573 574 575
  }

  //  printf("MRC\n");
576 577
  if (frame_parms->nb_antennas_rx > 1) {
    if (dlsch0_harq->mimo_mode == LARGE_CDD) {
Xiwen JIANG's avatar
Xiwen JIANG committed
578
      if (frame_parms->nb_antenna_ports_eNB == 2) {
579 580 581 582 583 584 585 586 587 588 589 590
        dlsch_detection_mrc(frame_parms,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->rho,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_magb1,
                            symbol,
                            nb_rb,
                            dual_stream_flag);
591
      }
592 593
    } else {

594
      dlsch_detection_mrc(frame_parms,
595 596 597 598 599 600 601 602 603 604 605
                          lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                          lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                          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_mag0,
                          lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                          lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                          lte_ue_pdsch_vars[eNB_id_i]->dl_ch_magb0,
                          symbol,
                          nb_rb,
                          dual_stream_flag);
606 607
    }
  }
608

609 610 611
  //  printf("Combining");
  if ((dlsch0_harq->mimo_mode == SISO) ||
      ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
612 613
       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) ||
       (dlsch0_harq->mimo_mode == TM7)) {
614 615 616 617 618 619 620 621 622 623
    /*
      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 (dlsch0_harq->mimo_mode == ALAMOUTI) {

    dlsch_alamouti(frame_parms,
624 625 626 627 628 629
                   lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                   lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                   lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                   symbol,
                   nb_rb);

630
  }
631 632 633 634

  else if (dlsch0_harq->mimo_mode == LARGE_CDD) {

  } else {
jiangx's avatar
jiangx committed
635
    LOG_W(PHY,"dlsch_rx: Unknown MIMO mode\n");
636 637
    return (-1);
  }
638

639 640
  //    printf("LLR");

641
  switch (dlsch0_harq->Qm) {
642 643
  case 2 :
    if (dlsch0_harq->mimo_mode != LARGE_CDD) {
644
      if (dual_stream_flag == 0)
645 646 647 648
        dlsch_qpsk_llr(frame_parms,
                       lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                       lte_ue_pdsch_vars[eNB_id]->llr[0],
                       symbol,first_symbol_flag,nb_rb,
649
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
650 651
                       lte_ue_pdsch_vars[eNB_id]->llr128,
                       beamforming_mode);
652
      else if (i_mod == 2) {
653 654 655 656 657 658
        dlsch_qpsk_qpsk_llr(frame_parms,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
659
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
660 661 662 663 664 665 666 667 668
                            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_comp0,
                             lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                             lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                             lte_ue_pdsch_vars[eNB_id]->llr[0],
                             symbol,first_symbol_flag,nb_rb,
669
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
670 671 672 673 674 675 676 677 678
                             lte_ue_pdsch_vars[eNB_id]->llr128);
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
                             lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                             lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                             lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                             lte_ue_pdsch_vars[eNB_id]->llr[0],
                             symbol,first_symbol_flag,nb_rb,
679
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
680 681
                             lte_ue_pdsch_vars[eNB_id]->llr128);

682
      }
683
    } else { // TM3
684
      DevAssert(dlsch1_harq);
685

686
      if (dlsch1_harq->Qm == 2) {
687
        /*  dlsch_qpsk_llr(frame_parms,
688 689 690 691 692
	    lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
	    lte_ue_pdsch_vars[eNB_id]->llr[0],
	    symbol,first_symbol_flag,nb_rb,
	    adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol),
	    lte_ue_pdsch_vars[eNB_id]->llr128);
693 694 695 696 697 698 699
        */
        dlsch_qpsk_qpsk_llr(frame_parms,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
700
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
701 702 703 704 705 706 707
                            lte_ue_pdsch_vars[eNB_id]->llr128);
        dlsch_qpsk_qpsk_llr(frame_parms,
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho2_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[1],
                            symbol,first_symbol_flag,nb_rb,
708
                            adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol),
709
                            lte_ue_pdsch_vars[eNB_id]->llr128_2ndstream);
710
      } else if (dlsch1_harq->Qm == 4) {
711 712 713 714 715 716 717
        dlsch_qpsk_16qam_llr(frame_parms,
                             lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                             lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1,
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                             lte_ue_pdsch_vars[eNB_id]->llr[0],
                             symbol,first_symbol_flag,nb_rb,
718
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
719 720 721 722 723 724 725 726 727
                             lte_ue_pdsch_vars[eNB_id]->llr128);
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
                             lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                             lte_ue_pdsch_vars[eNB_id]->rxdataF_comp1[dlsch0_harq->round],
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_mag1,
                             lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                             lte_ue_pdsch_vars[eNB_id]->llr[0],
                             symbol,first_symbol_flag,nb_rb,
728
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
729 730
                             lte_ue_pdsch_vars[eNB_id]->llr128);

731 732
      }
    }
733

734
    break;
735

736 737 738
  case 4 :
    if (dual_stream_flag == 0) {
      dlsch_16qam_llr(frame_parms,
739 740 741 742
                      lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                      lte_ue_pdsch_vars[eNB_id]->llr[0],
                      lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                      symbol,first_symbol_flag,nb_rb,
743
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
744 745
                      lte_ue_pdsch_vars[eNB_id]->llr128,
                      beamforming_mode);
746
    } else if (i_mod == 2) {
747
      dlsch_16qam_qpsk_llr(frame_parms,
748 749 750 751 752 753
                           lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                           lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                           lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                           lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                           lte_ue_pdsch_vars[eNB_id]->llr[0],
                           symbol,first_symbol_flag,nb_rb,
754
                           adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
755 756
                           lte_ue_pdsch_vars[eNB_id]->llr128);
    } else if (i_mod == 4) {
757
      dlsch_16qam_16qam_llr(frame_parms,
758 759 760 761 762 763 764
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
765
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
766
                            lte_ue_pdsch_vars[eNB_id]->llr128);
767 768
    } else {
      dlsch_16qam_64qam_llr(frame_parms,
769 770 771 772 773 774 775
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
776
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
777
                            lte_ue_pdsch_vars[eNB_id]->llr128);
778
    }
779

780
    break;
781

782 783 784
  case 6 :
    if (dual_stream_flag == 0) {
      dlsch_64qam_llr(frame_parms,
785 786 787 788 789
                      lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                      lte_ue_pdsch_vars[eNB_id]->llr[0],
                      lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                      lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                      symbol,first_symbol_flag,nb_rb,
790
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol),
791 792
                      lte_ue_pdsch_vars[eNB_id]->llr128,
                      beamforming_mode);
793
    } else if (i_mod == 2) {
794
      dlsch_64qam_qpsk_llr(frame_parms,
795 796 797 798 799 800
                           lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                           lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                           lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                           lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                           lte_ue_pdsch_vars[eNB_id]->llr[0],
                           symbol,first_symbol_flag,nb_rb,
801
                           adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
802 803
                           lte_ue_pdsch_vars[eNB_id]->llr128);
    } else if (i_mod == 4) {
804
      dlsch_64qam_16qam_llr(frame_parms,
805 806 807 808 809 810 811
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
812
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
813 814 815
                            lte_ue_pdsch_vars[eNB_id]->llr128);

    } else {
816
      dlsch_64qam_64qam_llr(frame_parms,
817 818 819 820 821 822 823
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
824
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
825
                            lte_ue_pdsch_vars[eNB_id]->llr128);
826
    }
827

828
    break;
829

830
  default:
jiangx's avatar
jiangx committed
831
    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
832
    return(-1);
833
    break;
834
  }
835
  return(0);
836 837 838 839 840 841 842 843 844 845 846 847 848 849
}

//==============================================================================================
// 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,
gauthier's avatar
gauthier committed
850
                                uint8_t first_symbol_flag,
851 852 853
                                unsigned char mod_order,
                                unsigned short nb_rb,
                                unsigned char output_shift,
854 855
                                PHY_MEASUREMENTS *phy_measurements)
{
856

857
#if defined(__i386) || defined(__x86_64)
858

859 860 861
  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;
862
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
863 864 865 866

  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;

  if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) {
867 868

    if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size
869
      nb_rb=1+(5*nb_rb/6);
870 871
    else
      pilots=1;
872 873
  }

Xiwen JIANG's avatar
Xiwen JIANG committed
874
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
875 876
    if (mod_order == 4) {
      QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
877
      QAM_amp128b = _mm_setzero_si128();
878 879
    } else if (mod_order == 6) {
      QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
880 881
      QAM_amp128b = _mm_set1_epi16(QAM64_n2);
    }
882

883 884
    //    printf("comp: rxdataF_comp %p, symbol %d\n",rxdataF_comp[0],symbol);

885
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
886 887 888 889 890 891 892 893

      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];


894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
      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);
912 913 914
	  //print_ints("Re(ch):",(int16_t*)&mmtmpD0);
	  //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128);
	  //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]);
915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939