dlsch_demodulation.c 166 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
int rx_pdsch(PHY_VARS_UE *ue,
82 83
             PDSCH_t type,
             unsigned char eNB_id,
84
             unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference
gauthier's avatar
gauthier committed
85
             uint8_t subframe,
86 87 88 89
             unsigned char symbol,
             unsigned char first_symbol_flag,
             unsigned char dual_stream_flag,
             unsigned char i_mod,
90 91 92
             unsigned char harq_pid)
{

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

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

105 106
  switch (type) {
  case SI_PDSCH:
107 108 109
    pdsch_vars = &ue->pdsch_vars_SI[eNB_id];
    dlsch          = &ue->dlsch_SI[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
110
    break;
111

112
  case RA_PDSCH:
113 114 115
    pdsch_vars = &ue->pdsch_vars_ra[eNB_id];
    dlsch          = &ue->dlsch_ra[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
116
    break;
117

118
  case PDSCH:
119 120 121 122
    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];
123 124 125
    break;

  default:
126
    LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->frame_rx,subframe,type);
127 128 129
    return(-1);
    break;
  }
130 131


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

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

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

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

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

157 158 159 160 161 162
  
  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;
163 164

  if (frame_parms->nb_antennas_tx_eNB>1) {
165
#ifdef DEBUG_DLSCH_MOD
166
    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]);
167
#endif
168 169 170 171
    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,
172
                                   dlsch0_harq->pmi_alloc,
173
                                   pdsch_vars[eNB_id]->pmi_ext,
174
                                   rballoc,
175 176
                                   symbol,
                                   subframe,
177
                                   ue->high_speed_flag,
178
                                   frame_parms);
179 180

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

220
    if (dual_stream_flag==1) {
221 222 223 224 225
      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,
226
                                         dlsch0_harq->pmi_alloc,
227
                                         pdsch_vars[eNB_id_i]->pmi_ext,
228
                                         rballoc,
229 230
                                         symbol,
                                         subframe,
231
                                         ue->high_speed_flag,
232
                                         frame_parms);
233
      
234 235 236 237
        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,
238
                                         dlsch0_harq->pmi_alloc,
239
                                         pdsch_vars[eNB_id_i]->pmi_ext,
240
                                         rballoc,
241 242
                                         symbol,
                                         subframe,
243
					 ue->high_speed_flag,
244
                                         frame_parms);
245 246
    }
  } //else n_tx>1
247 248

  //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
249
  if (nb_rb==0) {
250 251
    LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n");
    return(-1);
252
  }
253

knopp's avatar
 
knopp committed
254
  /*
255
  // DL power control: Scaling of Channel estimates for PDSCH
256
  dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
257
  frame_parms,
258
  dlsch,
259 260
  symbol,
  nb_rb);
knopp's avatar
 
knopp committed
261
  */
262
  if (first_symbol_flag==1) {
263
    dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
264 265 266 267
                        frame_parms,
                        avg,
                        symbol,
                        nb_rb);
268
#ifdef DEBUG_PHY
jiangx's avatar
jiangx committed
269
    LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]);
270
#endif
271

272 273 274 275
    // 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;
276 277 278 279 280 281 282 283

    for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++)
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
        avgs = cmax(avgs,avg[(aatx<<1)+aarx]);

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


284
    pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1;
285 286
    // + log2_approx(frame_parms->nb_antennas_tx_eNB-1) //-1 because log2_approx counts the number of bits
    //      + log2_approx(frame_parms->nb_antennas_rx-1);
287

288
    if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
289 290
        (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
        (dlsch0_harq->dl_power_off==1)) // we are in TM 6
291
      pdsch_vars[eNB_id]->log2_maxh++;
292 293

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
294
    /* K = Nb_rx         in TM1
295 296 297 298
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antennas_tx_eNB; //that also covers TM1 since Nb_tx=1
299 300 301
      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
302 303
      K *= frame_parms->nb_antennas_tx_eNB;

304
      pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
305 306 307
    */

#ifdef DEBUG_PHY
308
    LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs);
jiangx's avatar
jiangx committed
309
    LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode);
310 311
#endif
  }
312

313 314 315
  aatx = frame_parms->nb_antennas_tx_eNB;
  aarx = frame_parms->nb_antennas_rx;

316
  if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI
317

318 319 320 321 322 323
    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,
324 325 326
                               frame_parms,
                               symbol,
                               first_symbol_flag,
327
                               dlsch0_harq->Qm,
328
                               nb_rb,
329
                               pdsch_vars[eNB_id]->log2_maxh,
330
                               phy_measurements); // log2_maxh+I0_shift
331
#ifdef DEBUG_PHY
332

333
    if (symbol==5)
334
      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);
335

336
#endif
337 338

    if ((dual_stream_flag==1) &&
339
        (eNB_id_i<ue->n_connected_eNB)) {
340
      // get MF output for interfering stream
341 342 343 344 345 346
      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,
347 348 349 350 351
                                 frame_parms,
                                 symbol,
                                 first_symbol_flag,
                                 i_mod,
                                 nb_rb,
352
                                 pdsch_vars[eNB_id]->log2_maxh,
353
                                 phy_measurements); // log2_maxh+I0_shift
354
#ifdef DEBUG_PHY
355

356
      if (symbol == 5) {
357 358
        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);
359
      }
360 361 362

#endif

363 364
      // compute correlation between signal and interference channels
      dlsch_dual_stream_correlation(frame_parms,
365 366
                                    symbol,
                                    nb_rb,
367 368 369 370
                                    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);
371
    }
372
  } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3
373 374 375
    //   LOG_I(PHY,"Running PDSCH RX for TM3\n");
    if (frame_parms->nb_antennas_tx_eNB == 2) {
      if (first_symbol_flag==1) {
376
        // effective channel of desired user is always stronger than interfering eff. channel
377
        dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
378 379 380 381
                                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]);
382
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1];
383

384 385
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
386 387 388
      }

      dlsch_channel_compensation_TM3(frame_parms,
389
                                     pdsch_vars[eNB_id],
390 391 392
                                     phy_measurements,
                                     eNB_id,
                                     symbol,
393 394
                                     dlsch0_harq->Qm,
                                     dlsch1_harq->Qm,
395 396
                                     dlsch0_harq->round,
                                     nb_rb,
397
                                     pdsch_vars[eNB_id]->log2_maxh);
398
      // compute correlation between signal and interference channels (rho12 and rho21)
399
      dlsch_dual_stream_correlation(frame_parms,
400 401
                                    symbol,
                                    nb_rb,
402 403 404 405
                                    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);
406
      dlsch_dual_stream_correlation(frame_parms,
407 408
                                    symbol,
                                    nb_rb,
409 410 411 412 413
                                    &(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);
414

415
    } else {
416
      LOG_E(PHY, "only 2 tx antennas supported for TM3\n");
417
    }
418
  } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { // single-layer precoding (TM5, TM6), potentially TM4 (Single-codeword)
419 420
    //    printf("Channel compensation for precoding\n");
    //    if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)) {
421
    if ((dual_stream_flag==1) && (eNB_id_i==ue->n_connected_eNB)) {  // TM5 two-user
422 423 424

      // Scale the channel estimates for interfering stream

425
      dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
426
                          frame_parms,
427
                          dlsch,
428 429
                          symbol,
                          nb_rb);
430 431 432

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
433
        // effective channel of desired user is always stronger than interfering eff. channel
434
        dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);
435 436 437 438

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

439 440
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //printf("log1_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
441 442
      }

443 444 445 446 447 448
      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,
449 450 451 452
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
453
                                      dlsch0_harq->Qm,
454
                                      nb_rb,
455
                                      pdsch_vars[eNB_id]->log2_maxh,
456
                                      dlsch0_harq->dl_power_off);
457 458 459 460

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

      // calculate opposite PMI
461
      for (rb=0; rb<nb_rb; rb++) {
462
        switch(pdsch_vars[eNB_id]->pmi_ext[rb]) {
463
        case 0:
464
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=1;
465 466 467
          break;

        case 1:
468
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=0;
469 470 471
          break;

        case 2:
472
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=3;
473 474 475
          break;

        case 3:
476
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=2;
477 478 479 480
          break;
        }

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

483 484
      }

485 486 487 488 489 490
      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,
491 492 493 494 495 496
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id_i,
                                      symbol,
                                      i_mod,
                                      nb_rb,
497
                                      pdsch_vars[eNB_id]->log2_maxh,
498 499
                                      dlsch0_harq->dl_power_off);

500
#ifdef DEBUG_PHY
501

502
      if (symbol==5) {
503 504
        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);
505 506
      }

507 508 509 510 511
#endif

      dlsch_dual_stream_correlation(frame_parms,
                                    symbol,
                                    nb_rb,
512 513 514 515
                                    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);
516

517
    } else {
518 519 520 521 522 523
      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,
524 525 526 527
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
528
                                      dlsch0_harq->Qm,
529
                                      nb_rb,
530
                                      pdsch_vars[eNB_id]->log2_maxh,
531
                                      1);
532 533 534 535
    }
  }

  //  printf("MRC\n");
536 537 538
  if (frame_parms->nb_antennas_rx > 1) {
    if (dlsch0_harq->mimo_mode == LARGE_CDD) {
      if (frame_parms->nb_antennas_tx_eNB == 2) {
539
        dlsch_detection_mrc(frame_parms,
540 541 542 543 544 545 546 547
                            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,
548 549 550
                            symbol,
                            nb_rb,
                            dual_stream_flag);
551
      }
552 553
    } else {

554
      dlsch_detection_mrc(frame_parms,
555 556 557 558 559 560 561 562
                          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,
563 564 565
                          symbol,
                          nb_rb,
                          dual_stream_flag);
566 567
    }
  }
568

569 570 571 572 573 574 575
  //  printf("Combining");
  if ((dlsch0_harq->mimo_mode == SISO) ||
      ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0))) {

    /*
      dlsch_siso(frame_parms,
576 577
      pdsch_vars[eNB_id]->rxdataF_comp,
      pdsch_vars[eNB_id_i]->rxdataF_comp,
578 579 580 581 582 583
      symbol,
      nb_rb);
    */
  } else if (dlsch0_harq->mimo_mode == ALAMOUTI) {

    dlsch_alamouti(frame_parms,
584 585 586
                   pdsch_vars[eNB_id]->rxdataF_comp0,
                   pdsch_vars[eNB_id]->dl_ch_mag0,
                   pdsch_vars[eNB_id]->dl_ch_magb0,
587 588 589
                   symbol,
                   nb_rb);

590
  }
591 592 593 594

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

  } else {
jiangx's avatar
jiangx committed
595
    LOG_W(PHY,"dlsch_rx: Unknown MIMO mode\n");
596 597
    return (-1);
  }
598

599 600
  //    printf("LLR");

601
  switch (dlsch0_harq->Qm) {
602 603
  case 2 :
    if (dlsch0_harq->mimo_mode != LARGE_CDD) {
604
      if (dual_stream_flag == 0)
605
        dlsch_qpsk_llr(frame_parms,
606 607
                       pdsch_vars[eNB_id]->rxdataF_comp0,
                       pdsch_vars[eNB_id]->llr[0],
608
                       symbol,first_symbol_flag,nb_rb,
609
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
610
                       pdsch_vars[eNB_id]->llr128);
611
      else if (i_mod == 2) {
612
        dlsch_qpsk_qpsk_llr(frame_parms,
613 614 615 616
                            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],
617
                            symbol,first_symbol_flag,nb_rb,
618
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
619
                            pdsch_vars[eNB_id]->llr128);
620 621
      } else if (i_mod == 4) {
        dlsch_qpsk_16qam_llr(frame_parms,
622 623 624 625 626
                             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],
627
                             symbol,first_symbol_flag,nb_rb,
628
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
629
                             pdsch_vars[eNB_id]->llr128);
630 631
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
632 633 634 635 636
                             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],
637
                             symbol,first_symbol_flag,nb_rb,
638
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
639
                             pdsch_vars[eNB_id]->llr128);
640

641
      }
642
    } else { // TM3
643
      DevAssert(dlsch1_harq);
644

645
      if (dlsch1_harq->Qm == 2) {
646
        /*  dlsch_qpsk_llr(frame_parms,
647 648
	    pdsch_vars[eNB_id]->rxdataF_comp0,
	    pdsch_vars[eNB_id]->llr[0],
649 650
	    symbol,first_symbol_flag,nb_rb,
	    adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol),
651
	    pdsch_vars[eNB_id]->llr128);
652 653
        */
        dlsch_qpsk_qpsk_llr(frame_parms,
654 655 656 657
                            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],
658
                            symbol,first_symbol_flag,nb_rb,
659
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
660
                            pdsch_vars[eNB_id]->llr128);
661
        dlsch_qpsk_qpsk_llr(frame_parms,
662 663 664 665
                            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],
666
                            symbol,first_symbol_flag,nb_rb,
667
                            adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol),
668
                            pdsch_vars[eNB_id]->llr128_2ndstream);
669
      } else if (dlsch1_harq->Qm == 4) {
670
        dlsch_qpsk_16qam_llr(frame_parms,
671 672 673 674 675
                             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],
676
                             symbol,first_symbol_flag,nb_rb,
677
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
678
                             pdsch_vars[eNB_id]->llr128);
679 680
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
681 682 683 684 685
                             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],
686
                             symbol,first_symbol_flag,nb_rb,
687
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
688
                             pdsch_vars[eNB_id]->llr128);
689

690 691
      }
    }
692

693
    break;
694

695 696 697
  case 4 :
    if (dual_stream_flag == 0) {
      dlsch_16qam_llr(frame_parms,
698 699 700
                      pdsch_vars[eNB_id]->rxdataF_comp0,
                      pdsch_vars[eNB_id]->llr[0],
                      pdsch_vars[eNB_id]->dl_ch_mag0,
701
                      symbol,first_symbol_flag,nb_rb,
702
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
703
                      pdsch_vars[eNB_id]->llr128);
704
    } else if (i_mod == 2) {
705
      dlsch_16qam_qpsk_llr(frame_parms,
706 707 708 709 710
                           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],
711
                           symbol,first_symbol_flag,nb_rb,
712
                           adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
713
                           pdsch_vars[eNB_id]->llr128);
714
    } else if (i_mod == 4) {
715
      dlsch_16qam_16qam_llr(frame_parms,
716 717 718 719 720 721
                            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],
722
                            symbol,first_symbol_flag,nb_rb,
723
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
724
                            pdsch_vars[eNB_id]->llr128);
725 726
    } else {
      dlsch_16qam_64qam_llr(frame_parms,
727 728 729 730 731 732
                            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],
733
                            symbol,first_symbol_flag,nb_rb,
734
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
735
                            pdsch_vars[eNB_id]->llr128);
736
    }
737

738
    break;
739

740 741 742
  case 6 :
    if (dual_stream_flag == 0) {
      dlsch_64qam_llr(frame_parms,
743 744 745 746
                      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,
747
                      symbol,first_symbol_flag,nb_rb,
748
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol),
749
                      pdsch_vars[eNB_id]->llr128);
750
    } else if (i_mod == 2) {
751
      dlsch_64qam_qpsk_llr(frame_parms,
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]->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
    } else if (i_mod == 4) {
761
      dlsch_64qam_16qam_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),
770
                            pdsch_vars[eNB_id]->llr128);
771 772

    } else {
773
      dlsch_64qam_64qam_llr(frame_parms,
774 775 776 777 778 779
                            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],
780
                            symbol,first_symbol_flag,nb_rb,
781
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
782
                            pdsch_vars[eNB_id]->llr128);
783
    }
784

785
    break;
786

787
  default:
jiangx's avatar
jiangx committed
788
    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
789
    return(-1);
790
    break;
791
  }
792