dlsch_demodulation.c 201 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23

/*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c
 * \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03
24
 * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, X. Xiang
25
 * \date 2011
26
 * \version 0.1
27 28 29 30 31 32 33 34 35 36
 * \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"
37
#include "PHY/sse_intrin.h"
38
#include "T.h"
39 40 41 42

#ifndef USER_MODE
#define NOCYGWIN_STATIC static
#else
43
#define NOCYGWIN_STATIC
44 45 46
#endif

//#define DEBUG_PHY 1
47
//#define DEBUG_DLSCH_DEMOD 1
48

knopp's avatar
knopp committed
49
int avg[4]; 
50 51

// [MCS][i_mod (0,1,2) = (2,4,6)]
52 53 54 55
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
56 57
{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
58
*/
59 60 61 62 63 64 65 66
 /*
 //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
 */
67
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}};
68

69

70
extern void print_shorts(char *s,int16_t *x);
71

72

73
int rx_pdsch(PHY_VARS_UE *ue,
74 75
             PDSCH_t type,
             unsigned char eNB_id,
76
             unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference
77
             uint32_t frame,
78
             uint8_t subframe,
79 80 81 82
             unsigned char symbol,
             unsigned char first_symbol_flag,
             unsigned char dual_stream_flag,
             unsigned char i_mod,
83 84 85
             unsigned char harq_pid)
{

86 87 88 89 90
  LTE_UE_COMMON *common_vars  = &ue->common_vars;
  LTE_UE_PDSCH **pdsch_vars;
  LTE_DL_FRAME_PARMS *frame_parms    = &ue->frame_parms;
  PHY_MEASUREMENTS *phy_measurements = &ue->measurements;
  LTE_UE_DLSCH_t   **dlsch;
91

92
  unsigned char aatx,aarx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
93
  unsigned short nb_rb=0;
94
  int avgs, rb;
95
  LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
96
  
97
  uint8_t beamforming_mode;
98
  uint32_t *rballoc;
99

100 101
  switch (type) {
  case SI_PDSCH:
102 103 104
    pdsch_vars = &ue->pdsch_vars_SI[eNB_id];
    dlsch          = &ue->dlsch_SI[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
105
    beamforming_mode  = 0;
106
    break;
107

108
  case RA_PDSCH:
109 110 111
    pdsch_vars = &ue->pdsch_vars_ra[eNB_id];
    dlsch          = &ue->dlsch_ra[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
112
    beamforming_mode  = 0;
113
    break;
114

115
  case PDSCH:
116 117 118 119
    pdsch_vars = &ue->pdsch_vars[eNB_id];
    dlsch          = ue->dlsch[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
    dlsch1_harq       = dlsch[1]->harq_processes[harq_pid];
120
    beamforming_mode  = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id];
121 122 123
    break;

  default:
Cedric Roux's avatar
Cedric Roux committed
124
    LOG_E(PHY,"[UE][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,subframe,type);
125 126 127
    return(-1);
    break;
  }
128 129


130
  if (eNB_id > 2) {
jiangx's avatar
jiangx committed
131
    LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id);
132 133
    return(-1);
  }
134

135 136
  if (!common_vars) {
    LOG_W(PHY,"dlsch_demodulation.c: Null common_vars\n");
137 138 139
    return(-1);
  }

140 141
  if (!dlsch[0]) {
    LOG_W(PHY,"dlsch_demodulation.c: Null dlsch pointer\n");
142 143 144
    return(-1);
  }

145 146
  if (!pdsch_vars) {
    LOG_W(PHY,"dlsch_demodulation.c: Null pdsch_vars pointer\n");
147 148
    return(-1);
  }
149

150
  if (!frame_parms) {
151
    LOG_W(PHY,"dlsch_demodulation.c: Null frame_parms\n");
152 153
    return(-1);
  }
154

155 156 157 158 159 160
  
  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;
161

Xiwen JIANG's avatar
Xiwen JIANG committed
162
  if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
163
#ifdef DEBUG_DLSCH_MOD
164
    LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch[0],dlsch0_harq->rb_alloc_even[0]);
165
#endif
166 167 168 169
    nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF,
                                   common_vars->dl_ch_estimates[eNB_id],
                                   pdsch_vars[eNB_id]->rxdataF_ext,
                                   pdsch_vars[eNB_id]->dl_ch_estimates_ext,
170
                                   dlsch0_harq->pmi_alloc,
171
                                   pdsch_vars[eNB_id]->pmi_ext,
172
                                   rballoc,
173 174
                                   symbol,
                                   subframe,
175
                                   ue->high_speed_flag,
176
                                   frame_parms);
177 178

    if (dual_stream_flag==1) {
179 180 181 182 183
      if (eNB_id_i<ue->n_connected_eNB)
        nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF,
                                       common_vars->dl_ch_estimates[eNB_id_i],
                                       pdsch_vars[eNB_id_i]->rxdataF_ext,
                                       pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
184
                                       dlsch0_harq->pmi_alloc,
185
                                       pdsch_vars[eNB_id_i]->pmi_ext,
186
                                       rballoc,
187 188
                                       symbol,
                                       subframe,
189
                                       ue->high_speed_flag,
190 191
                                       frame_parms);
      else
192 193 194 195
        nb_rb = dlsch_extract_rbs_dual(common_vars->rxdataF,
                                       common_vars->dl_ch_estimates[eNB_id],
                                       pdsch_vars[eNB_id_i]->rxdataF_ext,
                                       pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
196
                                       dlsch0_harq->pmi_alloc,
197
                                       pdsch_vars[eNB_id_i]->pmi_ext,
198
                                       rballoc,
199 200
                                       symbol,
                                       subframe,
201
                                       ue->high_speed_flag,
202
                                       frame_parms);
203
    }
204
  } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0
205 206 207 208
    nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF,
                                     common_vars->dl_ch_estimates[eNB_id],
                                     pdsch_vars[eNB_id]->rxdataF_ext,
                                     pdsch_vars[eNB_id]->dl_ch_estimates_ext,
209
                                     dlsch0_harq->pmi_alloc,
210
                                     pdsch_vars[eNB_id]->pmi_ext,
211
                                     rballoc,
212 213
                                     symbol,
                                     subframe,
214
                                     ue->high_speed_flag,
215 216
                                     frame_parms);

217
    if (dual_stream_flag==1) {
218 219 220 221 222
      if (eNB_id_i<ue->n_connected_eNB)
        nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF,
                                         common_vars->dl_ch_estimates[eNB_id_i],
                                         pdsch_vars[eNB_id_i]->rxdataF_ext,
                                         pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
223
                                         dlsch0_harq->pmi_alloc,
224
                                         pdsch_vars[eNB_id_i]->pmi_ext,
225
                                         rballoc,
226 227
                                         symbol,
                                         subframe,
228
                                         ue->high_speed_flag,
229
                                         frame_parms);
230
      
231 232 233 234
        nb_rb = dlsch_extract_rbs_single(common_vars->rxdataF,
                                         common_vars->dl_ch_estimates[eNB_id],
                                         pdsch_vars[eNB_id_i]->rxdataF_ext,
                                         pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
235
                                         dlsch0_harq->pmi_alloc,
236
                                         pdsch_vars[eNB_id_i]->pmi_ext,
237
                                         rballoc,
238 239
                                         symbol,
                                         subframe,
240
					 ue->high_speed_flag,
241
                                         frame_parms);
242
    }
243
  } else if (beamforming_mode==7) { //else if beamforming_mode == 7
244 245 246 247
    nb_rb = dlsch_extract_rbs_TM7(common_vars->rxdataF,
                                  pdsch_vars[eNB_id]->dl_bf_ch_estimates,
                                  pdsch_vars[eNB_id]->rxdataF_ext,
                                  pdsch_vars[eNB_id]->dl_bf_ch_estimates_ext,
248
				  rballoc,
249 250
                                  symbol,
                                  subframe,
251
                                  ue->high_speed_flag,
252 253 254 255 256
                                  frame_parms);
    
  } else if(beamforming_mode>7) {
    LOG_W(PHY,"dlsch_demodulation:beamforming mode not supported yet.\n");
  }
257 258

  //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
259
  if (nb_rb==0) {
260
    LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n");
261 262
    return(-1);
  }
263

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

290 291 292 293
    // 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;
294

Xiwen JIANG's avatar
Xiwen JIANG committed
295
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
296 297 298 299 300
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
        avgs = cmax(avgs,avg[(aatx<<1)+aarx]);

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

301 302 303 304 305 306 307
#if T_TRACER
    if (type == PDSCH)
    {
      T(T_UE_PHY_PDSCH_ENERGY, T_INT(eNB_id),  T_INT(0), T_INT(frame%1024), T_INT(subframe),
                               T_INT(avg[0]), T_INT(avg[1]),    T_INT(avg[2]),             T_INT(avg[3]));
    }
#endif
308

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

313
    if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
314 315
        (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
        (dlsch0_harq->dl_power_off==1)) // we are in TM 6
316
      pdsch_vars[eNB_id]->log2_maxh++;
317 318

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
319
    /* K = Nb_rx         in TM1
320 321 322
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
Xiwen JIANG's avatar
Xiwen JIANG committed
323
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
324 325 326
      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
327
      K *= frame_parms->nb_antenna_ports_eNB;
328

329
      pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
330 331 332
    */

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

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

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

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

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

361
#endif
362 363

    if ((dual_stream_flag==1) &&
364
        (eNB_id_i<ue->n_connected_eNB)) {
365
      // get MF output for interfering stream
366 367 368 369 370 371
      dlsch_channel_compensation(pdsch_vars[eNB_id_i]->rxdataF_ext,
                                 pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                 pdsch_vars[eNB_id_i]->dl_ch_mag0,
                                 pdsch_vars[eNB_id_i]->dl_ch_magb0,
                                 pdsch_vars[eNB_id_i]->rxdataF_comp0,
                                 (aatx>1) ? pdsch_vars[eNB_id_i]->rho : NULL,
372 373 374 375 376
                                 frame_parms,
                                 symbol,
                                 first_symbol_flag,
                                 i_mod,
                                 nb_rb,
377
                                 pdsch_vars[eNB_id]->log2_maxh,
378
                                 phy_measurements); // log2_maxh+I0_shift
379
#ifdef DEBUG_PHY
380

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

#endif

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

409 410
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
411 412 413
      }

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

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

      // Scale the channel estimates for interfering stream

450
      dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
451
                          frame_parms,
452
                          dlsch,
453 454
                          symbol,
                          nb_rb);
455 456 457

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
458
        // effective channel of desired user is always stronger than interfering eff. channel
459
        dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);
460 461 462 463

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

464 465
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //printf("log1_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
466 467
      }

468 469 470 471 472 473
      dlsch_channel_compensation_TM56(pdsch_vars[eNB_id]->rxdataF_ext,
                                      pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                      pdsch_vars[eNB_id]->dl_ch_mag0,
                                      pdsch_vars[eNB_id]->dl_ch_magb0,
                                      pdsch_vars[eNB_id]->rxdataF_comp0,
                                      pdsch_vars[eNB_id]->pmi_ext,
474 475 476 477
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
478
                                      dlsch0_harq->Qm,
479
                                      nb_rb,
480
                                      pdsch_vars[eNB_id]->log2_maxh,
481
                                      dlsch0_harq->dl_power_off);
482 483 484 485

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

      // calculate opposite PMI
486
      for (rb=0; rb<nb_rb; rb++) {
487
        switch(pdsch_vars[eNB_id]->pmi_ext[rb]) {
488
        case 0:
489
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=1;
490 491 492
          break;

        case 1:
493
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=0;
494 495 496
          break;

        case 2:
497
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=3;
498 499 500
          break;

        case 3:
501
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=2;
502 503 504 505
          break;
        }

        //  if (rb==0)
506
        //    printf("pmi %d, pmi_i %d\n",pdsch_vars[eNB_id]->pmi_ext[rb],pdsch_vars[eNB_id_i]->pmi_ext[rb]);
507

508 509
      }

510 511 512 513 514 515
      dlsch_channel_compensation_TM56(pdsch_vars[eNB_id_i]->rxdataF_ext,
                                      pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                      pdsch_vars[eNB_id_i]->dl_ch_mag0,
                                      pdsch_vars[eNB_id_i]->dl_ch_magb0,
                                      pdsch_vars[eNB_id_i]->rxdataF_comp0,
                                      pdsch_vars[eNB_id_i]->pmi_ext,
516 517 518 519 520 521
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id_i,
                                      symbol,
                                      i_mod,
                                      nb_rb,
522
                                      pdsch_vars[eNB_id]->log2_maxh,
523 524
                                      dlsch0_harq->dl_power_off);

525
#ifdef DEBUG_PHY
526

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

532 533 534 535 536
#endif

      dlsch_dual_stream_correlation(frame_parms,
                                    symbol,
                                    nb_rb,
537 538 539 540
                                    pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                    pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                    pdsch_vars[eNB_id]->dl_ch_rho_ext,
                                    pdsch_vars[eNB_id]->log2_maxh);
541

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

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

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

595
      dlsch_detection_mrc(frame_parms,
596 597 598 599 600 601 602 603
                          pdsch_vars[eNB_id]->rxdataF_comp0,
                          pdsch_vars[eNB_id_i]->rxdataF_comp0,
                          pdsch_vars[eNB_id]->rho,
                          pdsch_vars[eNB_id]->dl_ch_rho_ext,
                          pdsch_vars[eNB_id]->dl_ch_mag0,
                          pdsch_vars[eNB_id]->dl_ch_magb0,
                          pdsch_vars[eNB_id_i]->dl_ch_mag0,
                          pdsch_vars[eNB_id_i]->dl_ch_magb0,
604 605 606
                          symbol,
                          nb_rb,
                          dual_stream_flag);
607 608
    }
  }
609

610 611 612
  //  printf("Combining");
  if ((dlsch0_harq->mimo_mode == SISO) ||
      ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
613 614
       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) ||
       (dlsch0_harq->mimo_mode == TM7)) {
615 616
    /*
      dlsch_siso(frame_parms,
617 618
      pdsch_vars[eNB_id]->rxdataF_comp,
      pdsch_vars[eNB_id_i]->rxdataF_comp,
619 620 621 622 623 624
      symbol,
      nb_rb);
    */
  } else if (dlsch0_harq->mimo_mode == ALAMOUTI) {

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

631
  }
632 633 634 635

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

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

640 641
  //    printf("LLR");

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

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

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

732 733
      }
    }
734

735
    break;
736

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

781
    break;
782

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

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

829
    break;
830

831
  default:
jiangx's avatar
jiangx committed
832
    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
833
    return(-1);
834
    break;
835
  }
836

837 838
#if T_TRACER
  T(T_UE_PHY_PDSCH_IQ, T_INT(eNB_id), T_INT(ue->Mod_id), T_INT(frame%1024),
839 840
    T_INT(subframe), T_INT(nb_rb),
    T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_tti),
Bilel's avatar
Bilel committed
841
    T_BUFFER(&pdsch_vars[eNB_id]->rxdataF_comp0[eNB_id][0],
842
             2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2));
843
#endif
844

845
  return(0);
846 847 848 849 850 851 852 853 854 855 856 857 858 859
}

//==============================================================================================
// 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,
860
                                uint8_t first_symbol_flag,
861 862 863
                                unsigned char mod_order,
                                unsigned short nb_rb,
                                unsigned char output_shift,
864 865
                                PHY_MEASUREMENTS *phy_measurements)
{
866

867
#if defined(__i386) || defined(__x86_64)
868

869 870 871
  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;
872
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
873 874 875 876

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

  if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) {
877 878

    if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size
879
      nb_rb=1+(5*nb_rb/6);
880 881
    else
      pilots=1;
882 883
  }

Xiwen JIANG's avatar
Xiwen JIANG committed
884
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
885 886
    if (mod_order == 4) {
      QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
887
      QAM_amp128b = _mm_setzero_si128();
888 889
    } else if (mod_order == 6) {
      QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
890 891
      QAM_amp128b = _mm_set1_epi16(QAM64_n2);
    }
892

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

895
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
896 897 898 899 900 901 902 903

      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