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 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
gauthier's avatar
gauthier committed
77
             uint8_t subframe,
78 79 80 81
             unsigned char symbol,
             unsigned char first_symbol_flag,
             unsigned char dual_stream_flag,
             unsigned char i_mod,
82 83 84
             unsigned char harq_pid)
{

85 86 87 88 89
  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;
90

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

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

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

114
  case PDSCH:
115 116 117 118
    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];
119
    beamforming_mode  = ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id];
120 121 122
    break;

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


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

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

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

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

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

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

Xiwen JIANG's avatar
Xiwen JIANG committed
161
  if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
162
#ifdef DEBUG_DLSCH_MOD
163
    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]);
164
#endif
165 166 167 168
    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,
169
                                   dlsch0_harq->pmi_alloc,
170
                                   pdsch_vars[eNB_id]->pmi_ext,
171
                                   rballoc,
172 173
                                   symbol,
                                   subframe,
174
                                   ue->high_speed_flag,
175
                                   frame_parms);
176 177

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

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

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

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

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

Xiwen JIANG's avatar
Xiwen JIANG committed
294
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
295 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
    pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1;
Xiwen JIANG's avatar
Xiwen JIANG committed
302
    // + log2_approx(frame_parms->nb_antenna_ports_eNB-1) //-1 because log2_approx counts the number of bits
303
    //      + log2_approx(frame_parms->nb_antennas_rx-1);
304

305
    if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
306 307
        (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
        (dlsch0_harq->dl_power_off==1)) // we are in TM 6
308
      pdsch_vars[eNB_id]->log2_maxh++;
309 310

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
311
    /* K = Nb_rx         in TM1
312 313 314
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
Xiwen JIANG's avatar
Xiwen JIANG committed
315
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
316 317 318
      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
319
      K *= frame_parms->nb_antenna_ports_eNB;
320

321
      pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
322 323 324
    */

#ifdef DEBUG_PHY
325
    LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs);
jiangx's avatar
jiangx committed
326
    LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode);
327 328
#endif
  }
329

Xiwen JIANG's avatar
Xiwen JIANG committed
330
  aatx = frame_parms->nb_antenna_ports_eNB;
331 332
  aarx = frame_parms->nb_antennas_rx;

333
  if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI
334

335 336 337 338 339 340
    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,
341 342 343
                               frame_parms,
                               symbol,
                               first_symbol_flag,
344
                               dlsch0_harq->Qm,
345
                               nb_rb,
346
                               pdsch_vars[eNB_id]->log2_maxh,
347
                               phy_measurements); // log2_maxh+I0_shift
348
#ifdef DEBUG_PHY
349

350
    if (symbol==5)
351
      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);
352

353
#endif
354 355

    if ((dual_stream_flag==1) &&
356
        (eNB_id_i<ue->n_connected_eNB)) {
357
      // get MF output for interfering stream
358 359 360 361 362 363
      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,
364 365 366 367 368
                                 frame_parms,
                                 symbol,
                                 first_symbol_flag,
                                 i_mod,
                                 nb_rb,
369
                                 pdsch_vars[eNB_id]->log2_maxh,
370
                                 phy_measurements); // log2_maxh+I0_shift
371
#ifdef DEBUG_PHY
372

373
      if (symbol == 5) {
374 375
        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);
376
      }
377 378 379

#endif

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

401 402
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
403 404 405
      }

      dlsch_channel_compensation_TM3(frame_parms,
406
                                     pdsch_vars[eNB_id],
407 408 409
                                     phy_measurements,
                                     eNB_id,
                                     symbol,
410 411
                                     dlsch0_harq->Qm,
                                     dlsch1_harq->Qm,
412 413
                                     dlsch0_harq->round,
                                     nb_rb,
414
                                     pdsch_vars[eNB_id]->log2_maxh);
415
      // compute correlation between signal and interference channels (rho12 and rho21)
416
      dlsch_dual_stream_correlation(frame_parms,
417 418
                                    symbol,
                                    nb_rb,
419 420 421 422
                                    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);
423
      dlsch_dual_stream_correlation(frame_parms,
424 425
                                    symbol,
                                    nb_rb,
426 427 428 429 430
                                    &(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);
431

432
    } else {
433
      LOG_E(PHY, "only 2 tx antennas supported for TM3\n");
434
    }
435
  } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { // single-layer precoding (TM5, TM6), potentially TM4 (Single-codeword)
436 437
    //    printf("Channel compensation for precoding\n");
    //    if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)) {
438
    if ((dual_stream_flag==1) && (eNB_id_i==ue->n_connected_eNB)) {  // TM5 two-user
439 440 441

      // Scale the channel estimates for interfering stream

442
      dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
443
                          frame_parms,
444
                          dlsch,
445 446
                          symbol,
                          nb_rb);
447 448 449

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
450
        // effective channel of desired user is always stronger than interfering eff. channel
451
        dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);
452 453 454 455

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

456 457
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //printf("log1_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
458 459
      }

460 461 462 463 464 465
      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,
466 467 468 469
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
470
                                      dlsch0_harq->Qm,
471
                                      nb_rb,
472
                                      pdsch_vars[eNB_id]->log2_maxh,
473
                                      dlsch0_harq->dl_power_off);
474 475 476 477

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

      // calculate opposite PMI
478
      for (rb=0; rb<nb_rb; rb++) {
479
        switch(pdsch_vars[eNB_id]->pmi_ext[rb]) {
480
        case 0:
481
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=1;
482 483 484
          break;

        case 1:
485
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=0;
486 487 488
          break;

        case 2:
489
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=3;
490 491 492
          break;

        case 3:
493
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=2;
494 495 496 497
          break;
        }

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

500 501
      }

502 503 504 505 506 507
      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,
508 509 510 511 512 513
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id_i,
                                      symbol,
                                      i_mod,
                                      nb_rb,
514
                                      pdsch_vars[eNB_id]->log2_maxh,
515 516
                                      dlsch0_harq->dl_power_off);

517
#ifdef DEBUG_PHY
518

519
      if (symbol==5) {
520 521
        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);
522 523
      }

524 525 526 527 528
#endif

      dlsch_dual_stream_correlation(frame_parms,
                                    symbol,
                                    nb_rb,
529 530 531 532
                                    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);
533

534
    } else {
535 536 537 538 539 540
      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,
541 542 543 544
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
545
                                      dlsch0_harq->Qm,
546
                                      nb_rb,
547
                                      pdsch_vars[eNB_id]->log2_maxh,
548
                                      1);
549
    }
550 551
  } else if (dlsch0_harq->mimo_mode==TM7) { //TM7

552 553 554 555 556 557
    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,
558 559 560 561 562
                               frame_parms,
                               symbol,
                               first_symbol_flag,
                               get_Qm(dlsch0_harq->mcs),
                               nb_rb,
563
                               //9,
564
                               pdsch_vars[eNB_id]->log2_maxh,
565
                               phy_measurements); // log2_maxh+I0_shift
566 567 568
  }

  //  printf("MRC\n");
569 570
  if (frame_parms->nb_antennas_rx > 1) {
    if (dlsch0_harq->mimo_mode == LARGE_CDD) {
Xiwen JIANG's avatar
Xiwen JIANG committed
571
      if (frame_parms->nb_antenna_ports_eNB == 2) {
572
        dlsch_detection_mrc(frame_parms,
573 574 575 576 577 578 579 580
                            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,
581 582 583
                            symbol,
                            nb_rb,
                            dual_stream_flag);
584
      }
585 586
    } else {

587
      dlsch_detection_mrc(frame_parms,
588 589 590 591 592 593 594 595
                          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,
596 597 598
                          symbol,
                          nb_rb,
                          dual_stream_flag);
599 600
    }
  }
601

602 603 604
  //  printf("Combining");
  if ((dlsch0_harq->mimo_mode == SISO) ||
      ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
605 606
       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0)) ||
       (dlsch0_harq->mimo_mode == TM7)) {
607 608
    /*
      dlsch_siso(frame_parms,
609 610
      pdsch_vars[eNB_id]->rxdataF_comp,
      pdsch_vars[eNB_id_i]->rxdataF_comp,
611 612 613 614 615 616
      symbol,
      nb_rb);
    */
  } else if (dlsch0_harq->mimo_mode == ALAMOUTI) {

    dlsch_alamouti(frame_parms,
617 618 619
                   pdsch_vars[eNB_id]->rxdataF_comp0,
                   pdsch_vars[eNB_id]->dl_ch_mag0,
                   pdsch_vars[eNB_id]->dl_ch_magb0,
620 621 622
                   symbol,
                   nb_rb);

623
  }
624 625 626 627

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

  } else {
jiangx's avatar
jiangx committed
628
    LOG_W(PHY,"dlsch_rx: Unknown MIMO mode\n");
629 630
    return (-1);
  }
631

632 633
  //    printf("LLR");

634
  switch (dlsch0_harq->Qm) {
635 636
  case 2 :
    if (dlsch0_harq->mimo_mode != LARGE_CDD) {
637
      if (dual_stream_flag == 0)
638
        dlsch_qpsk_llr(frame_parms,
639 640
                       pdsch_vars[eNB_id]->rxdataF_comp0,
                       pdsch_vars[eNB_id]->llr[0],
641
                       symbol,first_symbol_flag,nb_rb,
642
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
643
                       pdsch_vars[eNB_id]->llr128,
644
                       beamforming_mode);
645
      else if (i_mod == 2) {
646
        dlsch_qpsk_qpsk_llr(frame_parms,
647 648 649 650
                            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],
651
                            symbol,first_symbol_flag,nb_rb,
652
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
653
                            pdsch_vars[eNB_id]->llr128);
654 655
      } else if (i_mod == 4) {
        dlsch_qpsk_16qam_llr(frame_parms,
656 657 658 659 660
                             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],
661
                             symbol,first_symbol_flag,nb_rb,
662
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
663
                             pdsch_vars[eNB_id]->llr128);
664 665
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
666 667 668 669 670
                             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],
671
                             symbol,first_symbol_flag,nb_rb,
672
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
673
                             pdsch_vars[eNB_id]->llr128);
674

675
      }
676
    } else { // TM3
677
      DevAssert(dlsch1_harq);
678

679
      if (dlsch1_harq->Qm == 2) {
680
        /*  dlsch_qpsk_llr(frame_parms,
681 682
	    pdsch_vars[eNB_id]->rxdataF_comp0,
	    pdsch_vars[eNB_id]->llr[0],
683 684
	    symbol,first_symbol_flag,nb_rb,
	    adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol),
685
	    pdsch_vars[eNB_id]->llr128);
686 687
        */
        dlsch_qpsk_qpsk_llr(frame_parms,
688 689 690 691
                            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],
692
                            symbol,first_symbol_flag,nb_rb,
693
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
694
                            pdsch_vars[eNB_id]->llr128);
695
        dlsch_qpsk_qpsk_llr(frame_parms,
696 697 698 699
                            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],
700
                            symbol,first_symbol_flag,nb_rb,
701
                            adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol),
702
                            pdsch_vars[eNB_id]->llr128_2ndstream);
703
      } else if (dlsch1_harq->Qm == 4) {
704
        dlsch_qpsk_16qam_llr(frame_parms,
705 706 707 708 709
                             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],
710
                             symbol,first_symbol_flag,nb_rb,
711
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
712
                             pdsch_vars[eNB_id]->llr128);
713 714
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
715 716 717 718 719
                             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],
720
                             symbol,first_symbol_flag,nb_rb,
721
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
722
                             pdsch_vars[eNB_id]->llr128);
723

724 725
      }
    }
726

727
    break;
728

729 730 731
  case 4 :
    if (dual_stream_flag == 0) {
      dlsch_16qam_llr(frame_parms,
732 733 734
                      pdsch_vars[eNB_id]->rxdataF_comp0,
                      pdsch_vars[eNB_id]->llr[0],
                      pdsch_vars[eNB_id]->dl_ch_mag0,
735
                      symbol,first_symbol_flag,nb_rb,
736
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
737
                      pdsch_vars[eNB_id]->llr128,
738
                      beamforming_mode);
739
    } else if (i_mod == 2) {
740
      dlsch_16qam_qpsk_llr(frame_parms,
741 742 743 744 745
                           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],
746
                           symbol,first_symbol_flag,nb_rb,
747
                           adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
748
                           pdsch_vars[eNB_id]->llr128);
749
    } else if (i_mod == 4) {
750
      dlsch_16qam_16qam_llr(frame_parms,
751 752 753 754 755 756
                            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],
757
                            symbol,first_symbol_flag,nb_rb,
758
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
759
                            pdsch_vars[eNB_id]->llr128);
760 761
    } else {
      dlsch_16qam_64qam_llr(frame_parms,
762 763 764 765 766 767
                            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],
768
                            symbol,first_symbol_flag,nb_rb,
769
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),