dlsch_demodulation.c 164 KB
Newer Older
1 2 3 4
/*! \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
5
 * \version 0.1
6 7 8 9 10 11 12 13 14 15
 * \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"
16
#include "PHY/sse_intrin.h"
17 18 19 20 21


#ifndef USER_MODE
#define NOCYGWIN_STATIC static
#else
22
#define NOCYGWIN_STATIC
23 24 25
#endif

//#define DEBUG_PHY 1
26
//#define DEBUG_DLSCH_DEMOD 1
27

knopp's avatar
knopp committed
28
int avg[4]; 
29 30

// [MCS][i_mod (0,1,2) = (2,4,6)]
31 32 33 34
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
35 36
{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
37
*/
38 39 40 41 42 43 44 45
 /*
 //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
 */
46
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}};
47

48

49
extern void print_shorts(char *s,int16_t *x);
50

51

52
int rx_pdsch(PHY_VARS_UE *ue,
53 54
             PDSCH_t type,
             unsigned char eNB_id,
55
             unsigned char eNB_id_i, //if this == ue->n_connected_eNB, we assume MU interference
gauthier's avatar
gauthier committed
56
             uint8_t subframe,
57 58 59 60
             unsigned char symbol,
             unsigned char first_symbol_flag,
             unsigned char dual_stream_flag,
             unsigned char i_mod,
61 62 63
             unsigned char harq_pid)
{

64 65 66 67 68
  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;
69

70
  unsigned char aatx,aarx;
71
  unsigned short nb_rb;
72
  int avgs, rb;
73
  LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
74
  uint32_t *rballoc;
75

76 77
  switch (type) {
  case SI_PDSCH:
78 79 80
    pdsch_vars = &ue->pdsch_vars_SI[eNB_id];
    dlsch          = &ue->dlsch_SI[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
81
    break;
82

83
  case RA_PDSCH:
84 85 86
    pdsch_vars = &ue->pdsch_vars_ra[eNB_id];
    dlsch          = &ue->dlsch_ra[eNB_id];
    dlsch0_harq       = dlsch[0]->harq_processes[harq_pid];
87
    break;
88

89
  case PDSCH:
90 91 92 93
    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];
94 95 96
    break;

  default:
97
    LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",ue->proc.proc_rxtx[0].frame_rx,subframe,type);
98 99 100
    return(-1);
    break;
  }
101 102


103
  if (eNB_id > 2) {
jiangx's avatar
jiangx committed
104
    LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id);
105 106
    return(-1);
  }
107

108 109
  if (!common_vars) {
    LOG_W(PHY,"dlsch_demodulation.c: Null common_vars\n");
110 111 112
    return(-1);
  }

113 114
  if (!dlsch[0]) {
    LOG_W(PHY,"dlsch_demodulation.c: Null dlsch pointer\n");
115 116 117
    return(-1);
  }

118 119
  if (!pdsch_vars) {
    LOG_W(PHY,"dlsch_demodulation.c: Null pdsch_vars pointer\n");
120 121
    return(-1);
  }
122

123
  if (!frame_parms) {
124
    LOG_W(PHY,"dlsch_demodulation.c: Null frame_parms\n");
125 126
    return(-1);
  }
127

128 129 130 131 132 133
  
  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;
134 135

  if (frame_parms->nb_antennas_tx_eNB>1) {
136
#ifdef DEBUG_DLSCH_MOD
137
    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]);
138
#endif
139 140 141 142
    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,
143
                                   dlsch0_harq->pmi_alloc,
144
                                   pdsch_vars[eNB_id]->pmi_ext,
145
                                   rballoc,
146 147
                                   symbol,
                                   subframe,
148
                                   ue->high_speed_flag,
149
                                   frame_parms);
150 151

    if (dual_stream_flag==1) {
152 153 154 155 156
      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,
157
                                       dlsch0_harq->pmi_alloc,
158
                                       pdsch_vars[eNB_id_i]->pmi_ext,
159
                                       rballoc,
160 161
                                       symbol,
                                       subframe,
162
                                       ue->high_speed_flag,
163 164
                                       frame_parms);
      else
165 166 167 168
        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,
169
                                       dlsch0_harq->pmi_alloc,
170
                                       pdsch_vars[eNB_id_i]->pmi_ext,
171
                                       rballoc,
172 173
                                       symbol,
                                       subframe,
174
                                       ue->high_speed_flag,
175
                                       frame_parms);
176 177
    }
  } // if n_tx>1
178
  else {
179 180 181 182
    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,
183
                                     dlsch0_harq->pmi_alloc,
184
                                     pdsch_vars[eNB_id]->pmi_ext,
185
                                     rballoc,
186 187
                                     symbol,
                                     subframe,
188
                                     ue->high_speed_flag,
189 190
                                     frame_parms);

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

  //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
220
  if (nb_rb==0) {
221 222
    LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n");
    return(-1);
223
  }
224

knopp's avatar
 
knopp committed
225
  /*
226
  // DL power control: Scaling of Channel estimates for PDSCH
227
  dlsch_scale_channel(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
228
  frame_parms,
229
  dlsch,
230 231
  symbol,
  nb_rb);
knopp's avatar
 
knopp committed
232
  */
233
  if (first_symbol_flag==1) {
234
    dlsch_channel_level(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
235 236 237 238
                        frame_parms,
                        avg,
                        symbol,
                        nb_rb);
239
#ifdef DEBUG_PHY
jiangx's avatar
jiangx committed
240
    LOG_D(PHY,"[DLSCH] avg[0] %d\n",avg[0]);
241
#endif
242

243 244 245 246
    // 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;
247 248 249 250 251 252 253 254

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


255
    pdsch_vars[eNB_id]->log2_maxh = (log2_approx(avgs)/2)+1;
256 257
    // + 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);
258

259
    if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
260 261
        (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
        (dlsch0_harq->dl_power_off==1)) // we are in TM 6
262
      pdsch_vars[eNB_id]->log2_maxh++;
263 264

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
265
    /* K = Nb_rx         in TM1
266 267 268 269
       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
270 271 272
      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
273 274
      K *= frame_parms->nb_antennas_tx_eNB;

275
      pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
276 277 278
    */

#ifdef DEBUG_PHY
279
    LOG_D(PHY,"[DLSCH] log2_maxh = %d (%d,%d)\n",pdsch_vars[eNB_id]->log2_maxh,avg[0],avgs);
jiangx's avatar
jiangx committed
280
    LOG_D(PHY,"[DLSCH] mimo_mode = %d\n", dlsch0_harq->mimo_mode);
281 282
#endif
  }
283

284 285 286
  aatx = frame_parms->nb_antennas_tx_eNB;
  aarx = frame_parms->nb_antennas_rx;

287
  if (dlsch0_harq->mimo_mode<LARGE_CDD) {// SISO or ALAMOUTI
288

289 290 291 292 293 294
    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,
295 296 297
                               frame_parms,
                               symbol,
                               first_symbol_flag,
298
                               dlsch0_harq->Qm,
299
                               nb_rb,
300
                               pdsch_vars[eNB_id]->log2_maxh,
301
                               phy_measurements); // log2_maxh+I0_shift
302
#ifdef DEBUG_PHY
303

304
    if (symbol==5)
305
      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);
306

307
#endif
308 309

    if ((dual_stream_flag==1) &&
310
        (eNB_id_i<ue->n_connected_eNB)) {
311
      // get MF output for interfering stream
312 313 314 315 316 317
      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,
318 319 320 321 322
                                 frame_parms,
                                 symbol,
                                 first_symbol_flag,
                                 i_mod,
                                 nb_rb,
323
                                 pdsch_vars[eNB_id]->log2_maxh,
324
                                 phy_measurements); // log2_maxh+I0_shift
325
#ifdef DEBUG_PHY
326

327
      if (symbol == 5) {
328 329
        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);
330
      }
331 332 333

#endif

334 335
      // compute correlation between signal and interference channels
      dlsch_dual_stream_correlation(frame_parms,
336 337
                                    symbol,
                                    nb_rb,
338 339 340 341
                                    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);
342
    }
343
  } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3
344 345 346
    //   LOG_I(PHY,"Running PDSCH RX for TM3\n");
    if (frame_parms->nb_antennas_tx_eNB == 2) {
      if (first_symbol_flag==1) {
347
        // effective channel of desired user is always stronger than interfering eff. channel
348
        dlsch_channel_level_TM3(pdsch_vars[eNB_id]->dl_ch_estimates_ext,
349 350 351 352
                                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]);
353
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1];
354

355 356
        pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",pdsch_vars[eNB_id]->log2_maxh);
357 358 359
      }

      dlsch_channel_compensation_TM3(frame_parms,
360
                                     pdsch_vars[eNB_id],
361 362 363
                                     phy_measurements,
                                     eNB_id,
                                     symbol,
364 365
                                     dlsch0_harq->Qm,
                                     dlsch1_harq->Qm,
366 367
                                     dlsch0_harq->round,
                                     nb_rb,
368
                                     pdsch_vars[eNB_id]->log2_maxh);
369
      // compute correlation between signal and interference channels (rho12 and rho21)
370
      dlsch_dual_stream_correlation(frame_parms,
371 372
                                    symbol,
                                    nb_rb,
373 374 375 376
                                    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);
377
      dlsch_dual_stream_correlation(frame_parms,
378 379
                                    symbol,
                                    nb_rb,
380 381 382 383 384
                                    &(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);
385

386
    } else {
387
      LOG_E(PHY, "only 2 tx antennas supported for TM3\n");
388
    }
389
  } else if (dlsch0_harq->mimo_mode<DUALSTREAM_UNIFORM_PRECODING1) { // single-layer precoding (TM5, TM6), potentially TM4 (Single-codeword)
390 391
    //    printf("Channel compensation for precoding\n");
    //    if ((dual_stream_flag==1) && (eNB_id_i==NUMBER_OF_CONNECTED_eNB_MAX)) {
392
    if ((dual_stream_flag==1) && (eNB_id_i==ue->n_connected_eNB)) {  // TM5 two-user
393 394 395

      // Scale the channel estimates for interfering stream

396
      dlsch_scale_channel(pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
397
                          frame_parms,
398
                          dlsch,
399 400
                          symbol,
                          nb_rb);
401 402 403

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
404
        // effective channel of desired user is always stronger than interfering eff. channel
405
        dlsch_channel_level_TM56(pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);
406 407 408 409

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

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

414 415 416 417 418 419
      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,
420 421 422 423
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
424
                                      dlsch0_harq->Qm,
425
                                      nb_rb,
426
                                      pdsch_vars[eNB_id]->log2_maxh,
427
                                      dlsch0_harq->dl_power_off);
428 429 430 431

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

      // calculate opposite PMI
432
      for (rb=0; rb<nb_rb; rb++) {
433
        switch(pdsch_vars[eNB_id]->pmi_ext[rb]) {
434
        case 0:
435
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=1;
436 437 438
          break;

        case 1:
439
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=0;
440 441 442
          break;

        case 2:
443
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=3;
444 445 446
          break;

        case 3:
447
          pdsch_vars[eNB_id_i]->pmi_ext[rb]=2;
448 449 450 451
          break;
        }

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

454 455
      }

456 457 458 459 460 461
      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,
462 463 464 465 466 467
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id_i,
                                      symbol,
                                      i_mod,
                                      nb_rb,
468
                                      pdsch_vars[eNB_id]->log2_maxh,
469 470
                                      dlsch0_harq->dl_power_off);

471
#ifdef DEBUG_PHY
472

473
      if (symbol==5) {
474 475
        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);
476 477
      }

478 479 480 481 482
#endif

      dlsch_dual_stream_correlation(frame_parms,
                                    symbol,
                                    nb_rb,
483 484 485 486
                                    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);
487

488
    } else {
489 490 491 492 493 494
      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,
495 496 497 498
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
499
                                      dlsch0_harq->Qm,
500
                                      nb_rb,
501
                                      pdsch_vars[eNB_id]->log2_maxh,
502
                                      1);
503 504 505 506
    }
  }

  //  printf("MRC\n");
507 508 509
  if (frame_parms->nb_antennas_rx > 1) {
    if (dlsch0_harq->mimo_mode == LARGE_CDD) {
      if (frame_parms->nb_antennas_tx_eNB == 2) {
510
        dlsch_detection_mrc(frame_parms,
511 512 513 514 515 516 517 518
                            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,
519 520 521
                            symbol,
                            nb_rb,
                            dual_stream_flag);
522
      }
523 524
    } else {

525
      dlsch_detection_mrc(frame_parms,
526 527 528 529 530 531 532 533
                          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,
534 535 536
                          symbol,
                          nb_rb,
                          dual_stream_flag);
537 538
    }
  }
539

540 541 542 543 544 545 546
  //  printf("Combining");
  if ((dlsch0_harq->mimo_mode == SISO) ||
      ((dlsch0_harq->mimo_mode >= UNIFORM_PRECODING11) &&
       (dlsch0_harq->mimo_mode <= PUSCH_PRECODING0))) {

    /*
      dlsch_siso(frame_parms,
547 548
      pdsch_vars[eNB_id]->rxdataF_comp,
      pdsch_vars[eNB_id_i]->rxdataF_comp,
549 550 551 552 553 554
      symbol,
      nb_rb);
    */
  } else if (dlsch0_harq->mimo_mode == ALAMOUTI) {

    dlsch_alamouti(frame_parms,
555 556 557
                   pdsch_vars[eNB_id]->rxdataF_comp0,
                   pdsch_vars[eNB_id]->dl_ch_mag0,
                   pdsch_vars[eNB_id]->dl_ch_magb0,
558 559 560
                   symbol,
                   nb_rb);

561
  }
562 563 564 565

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

  } else {
jiangx's avatar
jiangx committed
566
    LOG_W(PHY,"dlsch_rx: Unknown MIMO mode\n");
567 568
    return (-1);
  }
569

570 571
  //    printf("LLR");

572
  switch (dlsch0_harq->Qm) {
573 574
  case 2 :
    if (dlsch0_harq->mimo_mode != LARGE_CDD) {
575
      if (dual_stream_flag == 0)
576
        dlsch_qpsk_llr(frame_parms,
577 578
                       pdsch_vars[eNB_id]->rxdataF_comp0,
                       pdsch_vars[eNB_id]->llr[0],
579
                       symbol,first_symbol_flag,nb_rb,
580
                       adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
581
                       pdsch_vars[eNB_id]->llr128);
582
      else if (i_mod == 2) {
583
        dlsch_qpsk_qpsk_llr(frame_parms,
584 585 586 587
                            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],
588
                            symbol,first_symbol_flag,nb_rb,
589
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
590
                            pdsch_vars[eNB_id]->llr128);
591 592
      } else if (i_mod == 4) {
        dlsch_qpsk_16qam_llr(frame_parms,
593 594 595 596 597
                             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],
598
                             symbol,first_symbol_flag,nb_rb,
599
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
600
                             pdsch_vars[eNB_id]->llr128);
601 602
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
603 604 605 606 607
                             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],
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

612
      }
613
    } else { // TM3
614
      DevAssert(dlsch1_harq);
615

616
      if (dlsch1_harq->Qm == 2) {
617
        /*  dlsch_qpsk_llr(frame_parms,
618 619
	    pdsch_vars[eNB_id]->rxdataF_comp0,
	    pdsch_vars[eNB_id]->llr[0],
620 621
	    symbol,first_symbol_flag,nb_rb,
	    adjust_G2(frame_parms,dlsch0_harq->rb_alloc,2,subframe,symbol),
622
	    pdsch_vars[eNB_id]->llr128);
623 624
        */
        dlsch_qpsk_qpsk_llr(frame_parms,
625 626 627 628
                            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],
629
                            symbol,first_symbol_flag,nb_rb,
630
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
631
                            pdsch_vars[eNB_id]->llr128);
632
        dlsch_qpsk_qpsk_llr(frame_parms,
633 634 635 636
                            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],
637
                            symbol,first_symbol_flag,nb_rb,
638
                            adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,subframe,symbol),
639
                            pdsch_vars[eNB_id]->llr128_2ndstream);
640
      } else if (dlsch1_harq->Qm == 4) {
641
        dlsch_qpsk_16qam_llr(frame_parms,
642 643 644 645 646
                             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],
647
                             symbol,first_symbol_flag,nb_rb,
648
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
649
                             pdsch_vars[eNB_id]->llr128);
650 651
      } else {
        dlsch_qpsk_64qam_llr(frame_parms,
652 653 654 655 656
                             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],
657
                             symbol,first_symbol_flag,nb_rb,
658
                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
659
                             pdsch_vars[eNB_id]->llr128);
660

661 662
      }
    }
663

664
    break;
665

666 667 668
  case 4 :
    if (dual_stream_flag == 0) {
      dlsch_16qam_llr(frame_parms,
669 670 671
                      pdsch_vars[eNB_id]->rxdataF_comp0,
                      pdsch_vars[eNB_id]->llr[0],
                      pdsch_vars[eNB_id]->dl_ch_mag0,
672
                      symbol,first_symbol_flag,nb_rb,
673
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,subframe,symbol),
674
                      pdsch_vars[eNB_id]->llr128);
675
    } else if (i_mod == 2) {
676
      dlsch_16qam_qpsk_llr(frame_parms,
677 678 679 680 681
                           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],
682
                           symbol,first_symbol_flag,nb_rb,
683
                           adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
684
                           pdsch_vars[eNB_id]->llr128);
685
    } else if (i_mod == 4) {
686
      dlsch_16qam_16qam_llr(frame_parms,
687 688 689 690 691 692
                            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],
693
                            symbol,first_symbol_flag,nb_rb,
694
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
695
                            pdsch_vars[eNB_id]->llr128);
696 697
    } else {
      dlsch_16qam_64qam_llr(frame_parms,
698 699 700 701 702 703
                            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],
704
                            symbol,first_symbol_flag,nb_rb,
705
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
706
                            pdsch_vars[eNB_id]->llr128);
707
    }
708

709
    break;
710

711 712 713
  case 6 :
    if (dual_stream_flag == 0) {
      dlsch_64qam_llr(frame_parms,
714 715 716 717
                      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,
718
                      symbol,first_symbol_flag,nb_rb,
719
                      adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,subframe,symbol),
720
                      pdsch_vars[eNB_id]->llr128);
721
    } else if (i_mod == 2) {
722
      dlsch_64qam_qpsk_llr(frame_parms,
723 724 725 726 727
                           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],
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
    } else if (i_mod == 4) {
732
      dlsch_64qam_16qam_llr(frame_parms,
733 734 735 736 737 738
                            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],
739
                            symbol,first_symbol_flag,nb_rb,
740
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
741
                            pdsch_vars[eNB_id]->llr128);
742 743

    } else {
744
      dlsch_64qam_64qam_llr(frame_parms,
745 746 747 748 749 750
                            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],
751
                            symbol,first_symbol_flag,nb_rb,
752
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
753
                            pdsch_vars[eNB_id]->llr128);
754
    }
755

756
    break;
757

758
  default:
jiangx's avatar
jiangx committed
759
    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
760
    return(-1);
761
    break;
762
  }
763

764
  return(0);
765 766 767 768 769 770 771 772 773 774 775 776 777 778
}

//==============================================================================================
// Pre-processing for LLR computation
//==============================================================================================

void dlsch_channel_compensation(int **rxdataF_ext,
                                int **dl_ch_estimates_ext,
                                int **dl_ch_mag,
                                int **dl_ch_magb,
                                int **rxdataF_comp,
                                int **rho,
                                LTE_DL_FRAME_PARMS *frame_parms,
                                unsigned char symbol,
gauthier's avatar
gauthier committed
779
                                uint8_t first_symbol_flag,
780 781 782
                                unsigned char mod_order,
                                unsigned short nb_rb,
                                unsigned char output_shift,
783 784
                                PHY_MEASUREMENTS *phy_measurements)
{
785

786
#if defined(__i386) || defined(__x86_64)
787

788 789 790
  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;
791
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
792 793 794 795

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

  if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) {
796 797

    if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size
798
      nb_rb=1+(5*nb_rb/6);
799 800
    else
      pilots=1;
801 802
  }

803
  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
804 805
    if (mod_order == 4) {
      QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
806
      QAM_amp128b = _mm_setzero_si128();
807 808
    } else if (mod_order == 6) {
      QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
809 810
      QAM_amp128b = _mm_set1_epi16(QAM64_n2);
    }
811

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

814
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
815 816 817 818 819 820 821 822

      dl_ch128          = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
      dl_ch_mag128      = (__m128i *)&dl_ch_mag[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
      dl_ch_mag128b     = (__m128i *)&dl_ch_magb[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];
      rxdataF128        = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12];
      rxdataF_comp128   = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*frame_parms->N_RB_DL*12];


823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840
      for (rb=0; rb<nb_rb; rb++) {
        if (mod_order>2) {
          // get channel amplitude if not QPSK

          mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128[0]);
          mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);

          mmtmpD1 = _mm_madd_epi16(dl_ch128[1],dl_ch128[1]);
          mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);

          mmtmpD0 = _mm_packs_epi32(mmtmpD0,mmtmpD1);

          // store channel magnitude here in a new field of dlsch

          dl_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpD0,mmtmpD0);
          dl_ch_mag128b[0] = dl_ch_mag128[0];
          dl_ch_mag128[0] = _mm_mulhi_epi16(dl_ch_mag128[0],QAM_amp128);
          dl_ch_mag128[0] = _mm_slli_epi16(dl_ch_mag128