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

92
93
94
95
96
97
  LTE_UE_COMMON *lte_ue_common_vars  = &phy_vars_ue->lte_ue_common_vars;
  LTE_UE_PDSCH **lte_ue_pdsch_vars;
  LTE_DL_FRAME_PARMS *frame_parms    = &phy_vars_ue->lte_frame_parms;
  PHY_MEASUREMENTS *phy_measurements = &phy_vars_ue->PHY_measurements;
  LTE_UE_DLSCH_t   **dlsch_ue;

98
  unsigned char aatx,aarx;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
99
  unsigned short nb_rb=0;
100
  int avgs, rb;
101
  LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq = 0;
102
  
103
  uint8_t beamforming_mode;
104
  uint32_t *rballoc;
105

106
107
108
109
  switch (type) {
  case SI_PDSCH:
    lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id];
    dlsch_ue          = &phy_vars_ue->dlsch_ue_SI[eNB_id];
110
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
111
    beamforming_mode  = 0;
112
    break;
113

114
115
116
  case RA_PDSCH:
    lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars_ra[eNB_id];
    dlsch_ue          = &phy_vars_ue->dlsch_ue_ra[eNB_id];
117
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
118
    beamforming_mode  = 0;
119
    break;
120

121
122
123
  case PDSCH:
    lte_ue_pdsch_vars = &phy_vars_ue->lte_ue_pdsch_vars[eNB_id];
    dlsch_ue          = phy_vars_ue->dlsch_ue[eNB_id];
124
125
    dlsch0_harq       = dlsch_ue[0]->harq_processes[harq_pid];
    dlsch1_harq       = dlsch_ue[1]->harq_processes[harq_pid];
126
    beamforming_mode = phy_vars_ue->transmission_mode[eNB_id]<7?0:phy_vars_ue->transmission_mode[eNB_id];
127
128
129
    break;

  default:
130
    LOG_E(PHY,"[UE %d][FATAL] Frame %d subframe %d: Unknown PDSCH format %d\n",phy_vars_ue->frame_rx,subframe,type);
131
132
133
    return(-1);
    break;
  }
134
135


136
  if (eNB_id > 2) {
jiangx's avatar
jiangx committed
137
    LOG_W(PHY,"dlsch_demodulation.c: Illegal eNB_id %d\n",eNB_id);
138
139
    return(-1);
  }
140

141
  if (!lte_ue_common_vars) {
jiangx's avatar
jiangx committed
142
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_common_vars\n");
143
144
145
146
    return(-1);
  }

  if (!dlsch_ue[0]) {
jiangx's avatar
jiangx committed
147
    LOG_W(PHY,"dlsch_demodulation.c: Null dlsch_ue pointer\n");
148
149
150
151
    return(-1);
  }

  if (!lte_ue_pdsch_vars) {
jiangx's avatar
jiangx committed
152
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_ue_pdsch_vars pointer\n");
153
154
    return(-1);
  }
155

156
  if (!frame_parms) {
jiangx's avatar
jiangx committed
157
    LOG_W(PHY,"dlsch_demodulation.c: Null lte_frame_parms\n");
158
159
    return(-1);
  }
160

161
162
163
164
165
166
  
  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;
167

Xiwen JIANG's avatar
Xiwen JIANG committed
168
  if (frame_parms->nb_antenna_ports_eNB>1 && beamforming_mode==0) {
169
#ifdef DEBUG_DLSCH_MOD
170
    LOG_I(PHY,"dlsch: using pmi %x (%p), rb_alloc %x\n",pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),dlsch_ue[0],dlsch0_harq->rb_alloc_even[0]);
171
172
#endif
    nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF,
173
174
175
176
177
                                   lte_ue_common_vars->dl_ch_estimates[eNB_id],
                                   lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
                                   lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                   dlsch0_harq->pmi_alloc,
                                   lte_ue_pdsch_vars[eNB_id]->pmi_ext,
178
                                   rballoc,
179
180
181
182
                                   symbol,
                                   subframe,
                                   phy_vars_ue->high_speed_flag,
                                   frame_parms);
183
184
185

    if (dual_stream_flag==1) {
      if (eNB_id_i<phy_vars_ue->n_connected_eNB)
186
187
188
189
190
191
        nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF,
                                       lte_ue_common_vars->dl_ch_estimates[eNB_id_i],
                                       lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext,
                                       lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                       dlsch0_harq->pmi_alloc,
                                       lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
192
                                       rballoc,
193
194
195
196
197
198
199
200
201
202
203
                                       symbol,
                                       subframe,
                                       phy_vars_ue->high_speed_flag,
                                       frame_parms);
      else
        nb_rb = dlsch_extract_rbs_dual(lte_ue_common_vars->rxdataF,
                                       lte_ue_common_vars->dl_ch_estimates[eNB_id],
                                       lte_ue_pdsch_vars[eNB_id_i]->rxdataF_ext,
                                       lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                       dlsch0_harq->pmi_alloc,
                                       lte_ue_pdsch_vars[eNB_id_i]->pmi_ext,
204
                                       rballoc,
205
206
207
208
                                       symbol,
                                       subframe,
                                       phy_vars_ue->high_speed_flag,
                                       frame_parms);
209
    }
210
  } else if (beamforming_mode==0) { //else if nb_antennas_ports_eNB==1 && beamforming_mode == 0
211
    nb_rb = dlsch_extract_rbs_single(lte_ue_common_vars->rxdataF,
212
213
214
215
216
                                     lte_ue_common_vars->dl_ch_estimates[eNB_id],
                                     lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
                                     lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                     dlsch0_harq->pmi_alloc,
                                     lte_ue_pdsch_vars[eNB_id]->pmi_ext,
217
                                     rballoc,
218
219
220
221
222
                                     symbol,
                                     subframe,
                                     phy_vars_ue->high_speed_flag,
                                     frame_parms);

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

  //  printf("nb_rb = %d, eNB_id %d\n",nb_rb,eNB_id);
265
  if (nb_rb==0) {
266
    LOG_D(PHY,"dlsch_demodulation.c: nb_rb=0\n");
267
268
    return(-1);
  }
269

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

296
297
298
299
    // 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;
300

Xiwen JIANG's avatar
Xiwen JIANG committed
301
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
302
303
304
305
306
307
      for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
        avgs = cmax(avgs,avg[(aatx<<1)+aarx]);

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


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

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

    // this version here applies the factor .5 also to the extra terms. however, it does not work so well as the one above
318
    /* K = Nb_rx         in TM1
319
320
321
       Nb_tx*Nb_rx   in TM2,4,5
       Nb_tx^2*Nb_rx in TM6 */
    /*
Xiwen JIANG's avatar
Xiwen JIANG committed
322
      K = frame_parms->nb_antennas_rx*frame_parms->nb_antenna_ports_eNB; //that also covers TM1 since Nb_tx=1
323
324
325
      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
326
      K *= frame_parms->nb_antenna_ports_eNB;
327
328
329
330
331

      lte_ue_pdsch_vars[eNB_id]->log2_maxh = (log2_approx(K*avgs)/2);
    */

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

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

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

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

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

360
#endif
361
362
363

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

380
      if (symbol == 5) {
381
382
        write_output("rxF_comp_d.m","rxF_c_d",&lte_ue_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",&lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
383
      }
384
385
386

#endif

387
388
      // compute correlation between signal and interference channels
      dlsch_dual_stream_correlation(frame_parms,
389
390
391
392
393
394
                                    symbol,
                                    nb_rb,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                    lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                                    lte_ue_pdsch_vars[eNB_id]->log2_maxh);
395
    }
396
  } else if (dlsch0_harq->mimo_mode == LARGE_CDD) { // TM3
397
    //   LOG_I(PHY,"Running PDSCH RX for TM3\n");
Xiwen JIANG's avatar
Xiwen JIANG committed
398
    if (frame_parms->nb_antenna_ports_eNB == 2) {
399
      if (first_symbol_flag==1) {
400
401
402
403
404
405
        // effective channel of desired user is always stronger than interfering eff. channel
        dlsch_channel_level_TM3(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                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]);
406
        avg[0] = log2_approx(avg[0]) - 13 + offset_mumimo_llr_drange[dlsch0_harq->mcs][(dlsch1_harq->Qm>>1)-1];
407
408
409
410
411
412
413
414
415
416

        lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //  printf("log2_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh);
      }

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

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

      // Scale the channel estimates for interfering stream

449
      dlsch_scale_channel(lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
450
451
452
453
                          frame_parms,
                          dlsch_ue,
                          symbol,
                          nb_rb);
454
455
456

      /* compute new log2_maxh for effective channel */
      if (first_symbol_flag==1) {
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
        // effective channel of desired user is always stronger than interfering eff. channel
        dlsch_channel_level_TM56(lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext, frame_parms, lte_ue_pdsch_vars[eNB_id]->pmi_ext, avg, symbol, nb_rb);

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

        lte_ue_pdsch_vars[eNB_id]->log2_maxh = cmax(avg[0],0);
        //printf("log1_maxh =%d\n",lte_ue_pdsch_vars[eNB_id]->log2_maxh);
      }

      dlsch_channel_compensation_TM56(lte_ue_pdsch_vars[eNB_id]->rxdataF_ext,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                                      lte_ue_pdsch_vars[eNB_id]->dl_ch_magb0,
                                      lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                                      lte_ue_pdsch_vars[eNB_id]->pmi_ext,
                                      frame_parms,
                                      phy_measurements,
                                      eNB_id,
                                      symbol,
477
                                      dlsch0_harq->Qm,
478
479
480
                                      nb_rb,
                                      lte_ue_pdsch_vars[eNB_id]->log2_maxh,
                                      dlsch0_harq->dl_power_off);
481
482
483
484

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

      // calculate opposite PMI
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
      for (rb=0; rb<nb_rb; rb++) {
        switch(lte_ue_pdsch_vars[eNB_id]->pmi_ext[rb]) {
        case 0:
          lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=1;
          break;

        case 1:
          lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=0;
          break;

        case 2:
          lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=3;
          break;

        case 3:
          lte_ue_pdsch_vars[eNB_id_i]->pmi_ext[rb]=2;
          break;
        }

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

507
508
      }

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

524
#ifdef DEBUG_PHY
525

526
      if (symbol==5) {
527
528
        write_output("rxF_comp_d.m","rxF_c_d",&lte_ue_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",&lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0[0][symbol*frame_parms->N_RB_DL*12],frame_parms->N_RB_DL*12,1,1);
529
530
      }

531
532
533
534
535
536
537
538
539
#endif

      dlsch_dual_stream_correlation(frame_parms,
                                    symbol,
                                    nb_rb,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_estimates_ext,
                                    lte_ue_pdsch_vars[eNB_id_i]->dl_ch_estimates_ext,
                                    lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                                    lte_ue_pdsch_vars[eNB_id]->log2_maxh);
540

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

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

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

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

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

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

630
  }
631
632
633
634

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

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

639
640
  //    printf("LLR");

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

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

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

731
732
      }
    }
733

734
    break;
735

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

780
    break;
781

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

    } else {
816
      dlsch_64qam_64qam_llr(frame_parms,
817
818
819
820
821
822
823
                            lte_ue_pdsch_vars[eNB_id]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id_i]->rxdataF_comp0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id_i]->dl_ch_mag0,
                            lte_ue_pdsch_vars[eNB_id]->dl_ch_rho_ext,
                            lte_ue_pdsch_vars[eNB_id]->llr[0],
                            symbol,first_symbol_flag,nb_rb,
824
                            adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,subframe,symbol),
825
                            lte_ue_pdsch_vars[eNB_id]->llr128);
826
    }
827

828
    break;
829

830
  default:
jiangx's avatar
jiangx committed
831
    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
832
    return(-1);
833
    break;
834
  }
835
  return(0);
836
837
838
839
840
841
842
843
844
845
846
847
848
849
}

//==============================================================================================
// 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
850
                                uint8_t first_symbol_flag,
851
852
853
                                unsigned char mod_order,
                                unsigned short nb_rb,
                                unsigned char output_shift,
854
855
                                PHY_MEASUREMENTS *phy_measurements)
{
856

857
#if defined(__i386) || defined(__x86_64)
858

859
860
861
  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;
862
  __m128i mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3,QAM_amp128,QAM_amp128b;
863
864
865
866

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

  if ((symbol_mod == 0) || (symbol_mod == (4-frame_parms->Ncp))) {
867
868

    if (frame_parms->mode1_flag==1) // 10 out of 12 so don't reduce size
869
      nb_rb=1+(5*nb_rb/6);
870
871
    else
      pilots=1;
872
873
  }

Xiwen JIANG's avatar
Xiwen JIANG committed
874
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
875
876
    if (mod_order == 4) {
      QAM_amp128 = _mm_set1_epi16(QAM16_n1);  // 2/sqrt(10)
877
      QAM_amp128b = _mm_setzero_si128();
878
879
    } else if (mod_order == 6) {
      QAM_amp128  = _mm_set1_epi16(QAM64_n1); //
880
881
      QAM_amp128b = _mm_set1_epi16(QAM64_n2);
    }
882

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

885
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
886
887
888
889
890
891
892
893

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


894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
      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[0],1);
912
913
914
	  //print_ints("Re(ch):",(int16_t*)&mmtmpD0);
	  //print_shorts("QAM_amp:",(int16_t*)&QAM_amp128);
	  //print_shorts("mag:",(int16_t*)&dl_ch_mag128[0]);
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
          dl_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpD0,mmtmpD0);
          dl_ch_mag128b[1] = dl_ch_mag128[1];
          dl_ch_mag128[1] = _mm_mulhi_epi16(dl_ch_mag128[1],QAM_amp128);
          dl_ch_mag128[1] = _mm_slli_epi16(dl_ch_mag128[1],1);

          if (pilots==0) {
            mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128[2]);
            mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
            mmtmpD1 = _mm_packs_epi32(mmtmpD0,mmtmpD0);

            dl_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpD1,mmtmpD1);
            dl_ch_mag128b[2] = dl_ch_mag128[2];

            dl_ch_mag128[2] = _mm_mulhi_epi16(dl_ch_mag128[2],QAM_amp128);
            dl_ch_mag128[2] = _mm_slli_epi16(dl_ch_mag128[2],1);
          }

          dl_ch_mag128b[0] = _mm_mulhi_epi16(dl_ch_mag128b[0],QAM_amp128b);
          dl_ch_mag128b[0] = _mm_slli_epi16(dl_ch_mag128b[0],1);


          dl_ch_mag128b[1] = _mm_mulhi_epi16(dl_ch_mag128b[1],QAM_amp128b);
          dl_ch_mag128b[1] = _mm_slli_epi16(dl_ch_mag128b[1],1);

          if (pilots==0) {
            dl_ch_mag128b[2] = _mm_mulhi_epi16(dl_ch_mag128b[2],QAM_amp128b);
            dl_ch_mag128b[2] = _mm_slli_epi16(dl_ch_mag128b[2],1);
          }
        }

        // multiply by conjugated channel
        mmtmpD0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]);
        //  print_ints("re",&mmtmpD0);

        // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]);
        //  print_ints("im",&mmtmpD1);
        mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[0]);
        // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
        //  print_ints("re(shift)",&mmtmpD0);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
        //  print_ints("im(shift)",&mmtmpD1);
        mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
        mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
        //        print_ints("c0",&mmtmpD2);
        //  print_ints("c1",&mmtmpD3);
        rxdataF_comp128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
        //  print_shorts("rx:",rxdataF128);
        //  print_shorts("ch:",dl_ch128);
        //  print_shorts("pack:",rxdataF_comp128);

        // multiply by conjugated channel
        mmtmpD0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]);
        // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate);
        mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[1]);
        // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
        mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
        mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);

        rxdataF_comp128[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
        //  print_shorts("rx:",rxdataF128+1);
        //  print_shorts("ch:",dl_ch128+1);
        //  print_shorts("pack:",rxdataF_comp128+1);

        if (pilots==0) {
          // multiply by conjugated channel
          mmtmpD0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]);
          // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
          mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1));
          mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
          mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate);
          mmtmpD1 = _mm_madd_epi16(mmtmpD1,rxdataF128[2]);
          // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
          mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
          mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
          mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
          mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);

          rxdataF_comp128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
          //  print_shorts("rx:",rxdataF128+2);
          //  print_shorts("ch:",dl_ch128+2);
          //        print_shorts("pack:",rxdataF_comp128+2);

          dl_ch128+=3;
          dl_ch_mag128+=3;
          dl_ch_mag128b+=3;
          rxdataF128+=3;
          rxdataF_comp128+=3;
        } else { // we have a smaller PDSCH in symbols with pilots so skip last group of 4 REs and increment less
          dl_ch128+=2;
          dl_ch_mag128+=2;
          dl_ch_mag128b+=2;
          rxdataF128+=2;
          rxdataF_comp128+=2;
        }

1019
1020
1021
      }
    }
  }
1022

1023
  if (rho) {
1024
1025
1026


    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
1027
1028
1029
      rho128        = (__m128i *)&rho[aarx][symbol*frame_parms->N_RB_DL*12];
      dl_ch128      = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
      dl_ch128_2    = (__m128i *)&dl_ch_estimates_ext[2+aarx][symbol*frame_parms->N_RB_DL*12];
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098

      for (rb=0; rb<nb_rb; rb++) {
        // multiply by conjugated channel
        mmtmpD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128_2[0]);
        //  print_ints("re",&mmtmpD0);

        // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate[0]);
        //  print_ints("im",&mmtmpD1);
        mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[0]);
        // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
        //  print_ints("re(shift)",&mmtmpD0);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
        //  print_ints("im(shift)",&mmtmpD1);
        mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
        mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
        //        print_ints("c0",&mmtmpD2);
        //  print_ints("c1",&mmtmpD3);
        rho128[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3);

        //print_shorts("rx:",dl_ch128_2);
        //print_shorts("ch:",dl_ch128);
        //print_shorts("pack:",rho128);

        // multiply by conjugated channel
        mmtmpD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128_2[1]);
        // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate);
        mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[1]);
        // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
        mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
        mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);


        rho128[1] =_mm_packs_epi32(mmtmpD2,mmtmpD3);
        //print_shorts("rx:",dl_ch128_2+1);
        //print_shorts("ch:",dl_ch128+1);
        //print_shorts("pack:",rho128+1);
        // multiply by conjugated channel
        mmtmpD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128_2[2]);
        // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
        mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)conjugate);
        mmtmpD1 = _mm_madd_epi16(mmtmpD1,dl_ch128_2[2]);
        // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
        mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
        mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
        mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);

        rho128[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
        //print_shorts("rx:",dl_ch128_2+2);
        //print_shorts("ch:",dl_ch128+2);
        //print_shorts("pack:",rho128+2);

        dl_ch128+=3;
        dl_ch128_2+=3;
        rho128+=3;

      }

1099
      if (first_symbol_flag==1) {
1100
1101
1102
        phy_measurements->rx_correlation[0][aarx] = signal_energy(&rho[aarx][symbol*frame_parms->N_RB_DL*12],rb*12);
      }
    }
1103
1104
1105
1106
  }

  _mm_empty();
  _m_empty();
1107
1108
1109
1110

#elif defined(__arm__)


1111
1112
  unsigned short rb;
  unsigned char aatx,aarx,symbol_mod,pilots=0;
1113

1114
1115
1116
1117
1118
  int16x4_t *dl_ch128,*dl_ch128_2,*rxdataF128;
  int32x4_t mmtmpD0,mmtmpD1,mmtmpD0b,</