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

/*! \file PHY/LTE_TRANSPORT/dlsch_demodulation.c
 * \brief Top-level routines for demodulating the PDSCH physical channel from 36-211, V8.6 2009-03
24
 * \author R. Knopp, F. Kaltenberger,A. Bhamri, S. Aubert, X. Xiang
25
 * \date 2011
26
 * \version 0.1
27
28
29
30
31
32
33
34
35
36
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,ankit.bhamri@eurecom.fr,sebastien.aubert@eurecom.fr
 * \note
 * \warning
 */

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "defs.h"
#include "extern.h"
37
#include "PHY/sse_intrin.h"
Bilel's avatar
Bilel committed
38
#include "T.h"
39
40
41
42

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

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

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

// [MCS][i_mod (0,1,2) = (2,4,6)]
52
53
54
55
unsigned char offset_mumimo_llr_drange_fix=0;
/*
//original values from sebastion + same hand tuning
unsigned char offset_mumimo_llr_drange[29][3]={{8,8,8},{7,7,7},{7,7,7},{7,7,7},{6,6,6},{6,6,6},{6,6,6},{5,5,5},{4,4,4},{1,2,4}, // QPSK
56
57
{5,5,4},{5,5,5},{5,5,5},{3,3,3},{2,2,2},{2,2,2},{2,2,2}, // 16-QAM
{2,2,1},{3,3,3},{3,3,3},{3,3,1},{2,2,2},{2,2,2},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0},{0,0,0}}; //64-QAM
58
*/
59
60
61
62
63
64
65
66
 /*
 //first optimization try
 unsigned char offset_mumimo_llr_drange[29][3]={{7, 8, 7},{6, 6, 7},{6, 6, 7},{6, 6, 6},{5, 6, 6},{5, 5, 6},{5, 5, 6},{4, 5, 4},{4, 3, 4},{3, 2, 2},{6, 5, 5},{5, 4, 4},{5, 5, 4},{3, 3, 2},{2, 2, 1},{2, 1, 1},{2, 2, 2},{3, 3, 3},{3, 3, 2},{3, 3, 2},{3, 2, 1},{2, 2, 2},{2, 2, 2},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}};
 */
 //second optimization try
 /*
   unsigned char offset_mumimo_llr_drange[29][3]={{5, 8, 7},{4, 6, 8},{3, 6, 7},{7, 7, 6},{4, 7, 8},{4, 7, 4},{6, 6, 6},{3, 6, 6},{3, 6, 6},{1, 3, 4},{1, 1, 0},{3, 3, 2},{3, 4, 1},{4, 0, 1},{4, 2, 2},{3, 1, 2},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}};  w
 */
67
unsigned char offset_mumimo_llr_drange[29][3]= {{0, 6, 5},{0, 4, 5},{0, 4, 5},{0, 5, 4},{0, 5, 6},{0, 5, 3},{0, 4, 4},{0, 4, 4},{0, 3, 3},{0, 1, 2},{1, 1, 0},{1, 3, 2},{3, 4, 1},{2, 0, 0},{2, 2, 2},{1, 1, 1},{2, 1, 0},{2, 1, 1},{1, 0, 1},{1, 0, 1},{0, 0, 0},{1, 0, 0},{0, 0, 0},{0, 1, 0},{1, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0},{0, 0, 0}};
68

69

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

72

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

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

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

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

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

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

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


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

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

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

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

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

155
156
157
158
159
160
  
  if (((frame_parms->Ncp == NORMAL) && (symbol>=7)) ||
      ((frame_parms->Ncp == EXTENDED) && (symbol>=6)))
    rballoc = dlsch0_harq->rb_alloc_odd;
  else
    rballoc = dlsch0_harq->rb_alloc_even;
161

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

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

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

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

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

290
291
292
293
    // the channel gain should be the effective gain of precoding + channel
    // however lets be more conservative and set maxh = nb_tx*nb_rx*max(h_i)
    // in case of precoding we add an additional factor of two for the precoding gain
    avgs = 0;
294

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

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

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

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

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

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
319
    /* K = Nb_rx         in TM1
320
321
322
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
Xiwen JIANG's avatar
Xiwen JIANG committed
323
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
324
325
326
      if ((dlsch0_harq->mimo_mode>=UNIFORM_PRECODING11) &&
      (dlsch0_harq->mimo_mode< DUALSTREAM_UNIFORM_PRECODING1) &&
      (dlsch0_harq->dl_power_off==1)) // we are in TM 6
Xiwen JIANG's avatar
Xiwen JIANG committed
327
      K *= frame_parms->nb_antenna_ports_eNB;
328

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

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

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

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

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

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

361
#endif
362
363

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

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

#endif

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

        //  LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->mcs>>1)-1]);
407
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1];
408

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

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

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

      // Scale the channel estimates for interfering stream

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

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

        //    LOG_D(PHY,"llr_offset = %d\n",offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1]);
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(i_mod>>1)-1];

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

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

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

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

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

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

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

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

508
509
      }

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

525
#ifdef DEBUG_PHY
526

527
      if (symbol==5) {
528
529
        write_output("rxF_comp_d.m","rxF_c_d",&pdsch_vars[eNB_id]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
        write_output("rxF_comp_i.m","rxF_c_i",&pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
530
531
      }

532
533
534
535
536
#endif

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

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

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

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

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

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

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

631
  }
632
633
634
635

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

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

640
641
  //    printf("LLR");

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

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

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

732
733
      }
    }
734

735
    break;
736

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

781
    break;
782

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