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->proc.proc_rxtx[0].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

793
  return(0);
794
795
796
797
798
799
800
801
802
803
804
805
806
807
}

//==============================================================================================
// 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
808
                                uint8_t first_symbol_flag,
809
810
811
                                unsigned char mod_order,
                                unsigned short nb_rb,
                                unsigned char output_shift,
812
813
                                PHY_MEASUREMENTS *phy_measurements)
{
814

815
#if defined(__i386) || defined(__x86_64)
816

817
818
819
  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;
820
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
821
822
823
824

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

  if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) {
825
826

    if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size
827
      nb_rb=1+(5*nb_rb/6);
828
829
    else
      pilots=1;
830
831
  }

832
  for (aatx=0; aatx<frame_parms->nb_antennas_tx_eNB; aatx++) {
833
834
    if (mod_order == 4) {
      QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
835
      QAM_amp128b = _mm_setzero_si128();
836
837
    } else if (mod_order == 6) {
      QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
838
839
      QAM_amp128b = _mm_set1_epi16(QAM64_n2);
    }
840

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

843
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {