dlsch_modulation.c 53.8 KB
Newer Older
1
/*******************************************************************************
2 3
  OpenAirInterface
  Copyright(c) 1999 - 2014 Eurecom
4

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


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

16 17 18 19
  You should have received a copy of the GNU General Public License
  along with OpenAirInterface.The full GNU General Public License is
  included in this distribution in the file called "COPYING". If not,
  see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
ghaddab's avatar
ghaddab committed
22 23 24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
25

26
Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29 30

/*! \file PHY/LTE_TRANSPORT/dlsch_modulation.c
31 32 33 34 35 36 37 38 39
 * \brief Top-level routines for generating the PDSCH physical channel from 36-211, V8.6 2009-03
 * \author R. Knopp, F. Kaltenberger
 * \date 2011
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
 * \note
 * \warning
 */
40 41 42 43 44 45 46
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "PHY/CODING/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "PHY/LTE_TRANSPORT/defs.h"
#include "defs.h"
47
#include "UTIL/LOG/vcd_signal_dumper.h"
48

49
//#define DEBUG_DLSCH_MODULATION
50 51 52

//#define is_not_pilot(pilots,re,nushift,use2ndpilots) ((pilots==0) || ((re!=nushift) && (re!=nushift+6)&&((re!=nushift+3)||(use2ndpilots==1))&&((re!=nushift+9)||(use2ndpilots==1)))?1:0)

53 54
uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2ndpilots)
{
55 56 57

  uint8_t offset = (pilots==2)?3:0;
  int nushiftmod3 = nushift%3;
58

59 60 61 62 63 64
  if (pilots==0)
    return(1);

  if (use2ndpilots==1) {  // This is for SISO (mode 1)
    if ((re!=nushift+offset) && (re!=((nushift+6+offset)%12)))
      return(1);
65
  } else { // 2 antenna pilots
66 67 68
    if ((re!=nushiftmod3) && (re!=nushiftmod3+6) && (re!=nushiftmod3+3) && (re!=nushiftmod3+9))
      return(1);
  }
69

70 71 72
  return(0);
}

73
//uint8_t is_not_UEspecRS(int first_layer,int re)
74
uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode)
75
{
76 77
  uint8_t offset = (lprime==1||lprime==3)?2:0;
  if (lprime==-1)
78 79
    return(1);

80
  switch (beamforming_mode) {
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
    case 7:
      if (Ncp == NORMAL){
        if ((re!=nushift+offset) && (re!=((nushift+4+offset)%12)) &&  (re!=((nushift+8+offset)%12))) 
          return(1);
        /*else{
          printf("(is_no_UEspec_RS):lprime=%d, re=%d, nushift=%d, offset=%d\n",lprime, re,nushift,offset);
        }*/
      } else { 
        if ((re!=nushift+offset) && (re!=((nushift+3+offset)%12)) && (re!=((nushift+6+offset)%12)) && (re!=((nushift+9+offset)%12)))
          return(1);
      }
      break;

    default:
      msg("is_not_UEspecRS() [dlsch_modulation.c] : ERROR, unknown beamforming_mode %d\n",beamforming_mode);
      return(-1);
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
98

99
  return(0);
Raymond Knopp's avatar
 
Raymond Knopp committed
100 101
}

102 103
void generate_64qam_table(void)
{
104 105 106 107

  int a,b,c,index;


108 109 110 111 112 113
  for (a=-1; a<=1; a+=2)
    for (b=-1; b<=1; b+=2)
      for (c=-1; c<=1; c+=2) {
        index = (1+a)*2 + (1+b) + (1+c)/2;
        qam64_table[index] = -a*(QAM64_n1 + b*(QAM64_n2 + (c*QAM64_n3))); // 0 1 2
      }
114 115
}

116 117
void generate_16qam_table(void)
{
118 119 120

  int a,b,index;

121 122 123 124 125
  for (a=-1; a<=1; a+=2)
    for (b=-1; b<=1; b+=2) {
      index = (1+a) + (1+b)/2;
      qam16_table[index] = -a*(QAM16_n1 + (b*QAM16_n2));
    }
126 127 128 129 130
}




131 132
void layer1prec2A(int32_t *antenna0_sample, int32_t *antenna1_sample, uint8_t precoding_index)
{
133 134 135

  switch (precoding_index) {

136 137 138
    case 0: // 1 1
      *antenna1_sample=*antenna0_sample;
      break;
139

140 141 142 143
    case 1: // 1 -1
      ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[0];
      ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[1];
      break;
144

145 146 147 148
    case 2: // 1 j
      ((int16_t *)antenna1_sample)[0] = -((int16_t *)antenna0_sample)[1];
      ((int16_t *)antenna1_sample)[1] = ((int16_t *)antenna0_sample)[0];
      break;
149

150 151 152 153
    case 3: // 1 -j
      ((int16_t *)antenna1_sample)[0] = ((int16_t *)antenna0_sample)[1];
      ((int16_t *)antenna1_sample)[1] = -((int16_t *)antenna0_sample)[0];
      break;
154 155 156
  }

  // normalize
157
  /*  ((int16_t *)antenna0_sample)[0] = (int16_t)((((int16_t *)antenna0_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
158 159
      ((int16_t *)antenna0_sample)[1] = (int16_t)((((int16_t *)antenna0_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  ((int16_t *)antenna1_sample)[0] = (int16_t)((((int16_t *)antenna1_sample)[0]*ONE_OVER_SQRT2_Q15)>>15);
      ((int16_t *)antenna1_sample)[1] = (int16_t)((((int16_t *)antenna1_sample)[1]*ONE_OVER_SQRT2_Q15)>>15);  */
160
}
161

162
int allocate_REs_in_RB(PHY_VARS_eNB *phy_vars_eNB,
163 164 165 166 167 168 169 170 171 172 173 174 175 176
                       mod_sym_t **txdataF,
                       uint32_t *jj,
                       uint32_t *jj2,
                       uint16_t re_offset,
                       uint32_t symbol_offset,
                       LTE_DL_eNB_HARQ_t *dlsch0_harq,
                       LTE_DL_eNB_HARQ_t *dlsch1_harq,
                       uint8_t pilots,
                       int16_t amp,
                       uint8_t precoder_index,
                       int16_t *qam_table_s0,
                       int16_t *qam_table_s1,
                       uint32_t *re_allocated,
                       uint8_t skip_dc,
177 178 179 180 181
                       uint8_t skip_half,
                       uint8_t lprime,
                       uint8_t mprime,
                       uint8_t Ns,
                       int32_t **beamforming_weights)
182
{
183

184
  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
185 186 187 188
  uint8_t *x0             = dlsch0_harq->e;
  MIMO_mode_t mimo_mode   = dlsch0_harq->mimo_mode;

  int first_layer0        = dlsch0_harq->first_layer;
189
  int Nlayers0            = dlsch0_harq->Nlayers;
190 191 192
  uint8_t mod_order0      = get_Qm(dlsch0_harq->mcs);


Raymond Knopp's avatar
 
Raymond Knopp committed
193 194
  uint8_t *x1=NULL;
  uint8_t mod_order1=2;
195 196
  uint8_t nb_antennas_tx_phy = phy_vars_eNB->nb_antennas_tx_phy;

Raymond Knopp's avatar
 
Raymond Knopp committed
197 198 199
  // Fill these in later for TM8-10
  //  int Nlayers1;
  //  int first_layer1;
200
  int use2ndpilots = (frame_parms->mode1_flag==1)?1:0;
201 202 203 204 205 206 207

  uint32_t tti_offset,aa;
  uint8_t re;
  uint8_t qam64_table_offset_re = 0;
  uint8_t qam64_table_offset_im = 0;
  uint8_t qam16_table_offset_re = 0;
  uint8_t qam16_table_offset_im = 0;
208 209 210 211 212 213 214 215 216 217 218
  uint8_t qam64_table_offset_re0 = 0;
  uint8_t qam64_table_offset_im0 = 0;
  uint8_t qam16_table_offset_re0 = 0;
  uint8_t qam16_table_offset_im0 = 0;
  uint8_t qam64_table_offset_re1 = 0;
  uint8_t qam64_table_offset_im1 = 0;
  uint8_t qam16_table_offset_re1 = 0;
  uint8_t qam16_table_offset_im1 = 0;
  int16_t xx0_re,xx1_re;
  int16_t xx0_im,xx1_im;

219 220
  int16_t gain_lin_QPSK;//,gain_lin_16QAM1,gain_lin_16QAM2;
  int16_t re_off=re_offset;
221

222 223 224
  uint8_t first_re,last_re;
  int32_t tmp_sample1,tmp_sample2;
  int16_t tmp_amp=amp;
225
  uint8_t layer;
226
  int s=1;
227
        
228
  int mprime2 = mprime,ind,ind_dword,ind_qpsk_symb;
229
  mod_sym_t qpsk[4];
230 231 232

  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
  //  if (mimo_mode == LARGE_CDD) gain_lin_QPSK>>=1;
233 234 235 236 237 238 239 240 241
  ((int16_t *)&qpsk[0])[0] = gain_lin_QPSK;
  ((int16_t *)&qpsk[0])[1] = gain_lin_QPSK;
  ((int16_t *)&qpsk[1])[0] = -gain_lin_QPSK;
  ((int16_t *)&qpsk[1])[1] = gain_lin_QPSK;;
  ((int16_t *)&qpsk[2])[0] = gain_lin_QPSK;;
  ((int16_t *)&qpsk[2])[1] = -gain_lin_QPSK;;
  ((int16_t *)&qpsk[3])[0] = -gain_lin_QPSK;;
  ((int16_t *)&qpsk[3])[1] = -gain_lin_QPSK;

242 243 244

  if (dlsch1_harq) {
    x1             = dlsch1_harq->e;
Raymond Knopp's avatar
 
Raymond Knopp committed
245
    // Fill these in later for TM8-10
246
    //    Nlayers1       = dlsch1_harq->Nlayers;
Raymond Knopp's avatar
 
Raymond Knopp committed
247
    //    first_layer1   = dlsch1_harq->first_layer;
248 249 250
    mod_order1     = get_Qm(dlsch1_harq->mcs);

  }
251

252
  /*
253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
     switch (mod_order) {
     case 2:
// QPSK single stream

break;
case 4:
//16QAM Single stream
gain_lin_16QAM1 = (int16_t)(((int32_t)amp*QAM16_n1)>>15);
gain_lin_16QAM2 = (int16_t)(((int32_t)amp*QAM16_n2)>>15);

break;

case 6:
//64QAM Single stream
break;
default:
break;
}
   */
272

273 274 275
//#ifdef DEBUG_DLSCH_MODULATION
// printf("allocate_re (mod %d): symbol_offset %d re_offset %d (%d,%d), jj %d -> %d,%d\n",mod_order0,symbol_offset,re_offset,skip_dc,skip_half,*jj, x0[*jj], x0[1+*jj]);
//#endif
276 277 278

  first_re=0;
  last_re=12;
279
  
280
  if (skip_half==1)
281 282 283
    last_re=6;
  else if (skip_half==2)
    first_re=6;
284 285 286
  
    for (re=first_re; re<last_re; re++) {
  
287 288
    if ((skip_dc == 1) && (re==6))
      re_off=re_off - frame_parms->ofdm_symbol_size+1;
289 290


291 292
    tti_offset = symbol_offset + re_off + re;
    // printf("tti_offset = %d\n", tti_offset);
Raymond Knopp's avatar
 
Raymond Knopp committed
293 294
    // check that RE is not from Cell-specific RS

295
    if (is_not_pilot(pilots,re,frame_parms->nushift,use2ndpilots)==1) {
296
     //  printf("re %d (jj %d)\n",re,*jj);
Raymond Knopp's avatar
 
Raymond Knopp committed
297

298

299
      if (mimo_mode == SISO) {  //SISO mapping
300 301 302
        *re_allocated = *re_allocated + 1;

        switch (mod_order0) {
303
          case 2:  //QPSK
304

305 306 307 308
            //printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
            for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
              ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
            }
309

310
            *jj = *jj + 1;
311

312 313 314
            for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
              ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
            }
315

316
            *jj = *jj + 1;
317

318 319
            //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
            break;
320

321
          case 4:  //16QAM
322

323 324
            qam16_table_offset_re = 0;
            qam16_table_offset_im = 0;
325

326 327
            if (x0[*jj] == 1)
              qam16_table_offset_re+=2;
328

329
            *jj=*jj+1;
330

331 332
            if (x0[*jj] == 1)
              qam16_table_offset_im+=2;
333

334
            *jj=*jj+1;
335 336


337 338
            if (x0[*jj] == 1)
              qam16_table_offset_re+=1;
339

340
            *jj=*jj+1;
341

342 343
            if (x0[*jj] == 1)
              qam16_table_offset_im+=1;
344

345
            *jj=*jj+1;
346

347 348 349 350 351 352
            for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
              ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam16_table_offset_re];
              ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam16_table_offset_im];
              //      ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
              //      ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
            }
353

354
            break;
355

356
          case 6:  //64QAM
357 358


359 360
            qam64_table_offset_re = 0;
            qam64_table_offset_im = 0;
361

362 363
            if (x0[*jj] == 1)
              qam64_table_offset_re+=4;
364

365
            *jj=*jj+1;
366

367 368
            if (x0[*jj] == 1)
              qam64_table_offset_im+=4;
369

370
            *jj=*jj+1;
371

372 373
            if (x0[*jj] == 1)
              qam64_table_offset_re+=2;
374

375
            *jj=*jj+1;
376

377 378
            if (x0[*jj] == 1)
              qam64_table_offset_im+=2;
379

380
            *jj=*jj+1;
381

382 383
            if (x0[*jj] == 1)
              qam64_table_offset_re+=1;
384

385
            *jj=*jj+1;
386

387 388
            if (x0[*jj] == 1)
              qam64_table_offset_im+=1;
389

390
            *jj=*jj+1;
391

392 393 394 395
            for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
              ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s0[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
              ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s0[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
            }
396

397
            break;
398 399

        }
400
      }
401 402 403 404 405 406 407

      else if (mimo_mode == ALAMOUTI) {
        *re_allocated = *re_allocated + 1;
        // normalization for 2 tx antennas
        amp = (int16_t)(((int32_t)tmp_amp*ONE_OVER_SQRT2_Q15)>>15);

        switch (mod_order0) {
408
          case 2:  //QPSK
409

410
            // first antenna position n -> x0
411

412 413 414 415
            ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
            *jj=*jj+1;
            ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
            *jj=*jj+1;
416

417
            // second antenna position n -> -x1*
418

419 420 421 422
            ((int16_t*)&tmp_sample2)[0] = (x0[*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
            *jj=*jj+1;
            ((int16_t*)&tmp_sample2)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
            *jj=*jj+1;
423

424 425 426 427 428
            // normalization for 2 tx antennas
            ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
            ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
            ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
            ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
429

430
            break;
431

432
          case 4:  //16QAM
433

434
            // Antenna 0 position n
435

436 437
            qam16_table_offset_re = 0;
            qam16_table_offset_im = 0;
438

439 440
            if (x0[*jj] == 1)
              qam16_table_offset_re+=2;
441

442
            *jj=*jj+1;
443

444 445
            if (x0[*jj] == 1)
              qam16_table_offset_im+=2;
446

447
            *jj=*jj+1;
448 449


450 451
            if (x0[*jj] == 1)
              qam16_table_offset_re+=1;
452

453
            *jj=*jj+1;
454

455 456
            if (x0[*jj] == 1)
              qam16_table_offset_im+=1;
457

458
            *jj=*jj+1;
459

460 461
            ((int16_t *)&txdataF[0][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
            ((int16_t *)&txdataF[0][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
462

463
            // Antenna 1 position n Real part -> -x1*
464

465 466
            qam16_table_offset_re = 0;
            qam16_table_offset_im = 0;
467

468 469
            if (x0[*jj] == 1)
              qam16_table_offset_re+=2;
470

471
            *jj=*jj+1;
472

473 474
            if (x0[*jj] == 1)
              qam16_table_offset_im+=2;
475

476
            *jj=*jj+1;
477 478


479 480
            if (x0[*jj] == 1)
              qam16_table_offset_re+=1;
481

482
            *jj=*jj+1;
483

484 485
            if (x0[*jj] == 1)
              qam16_table_offset_im+=1;
486

487
            *jj=*jj+1;
488

489 490
            ((int16_t *)&txdataF[1][tti_offset])[0]+=-(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
            ((int16_t *)&txdataF[1][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
491 492


493
            break;
494

495
          case 6:   // 64-QAM
496

497 498 499
            // Antenna 0
            qam64_table_offset_re = 0;
            qam64_table_offset_im = 0;
500

501 502
            if (x0[*jj] == 1)
              qam64_table_offset_re+=4;
503

504
            *jj=*jj+1;
505

506 507
            if (x0[*jj] == 1)
              qam64_table_offset_im+=4;
508

509
            *jj=*jj+1;
510

511 512
            if (x0[*jj] == 1)
              qam64_table_offset_re+=2;
513

514
            *jj=*jj+1;
515

516 517
            if (x0[*jj] == 1)
              qam64_table_offset_im+=2;
518

519
            *jj=*jj+1;
520

521 522
            if (x0[*jj] == 1)
              qam64_table_offset_re+=1;
523

524
            *jj=*jj+1;
525

526 527
            if (x0[*jj] == 1)
              qam64_table_offset_im+=1;
528

529
            *jj=*jj+1;
530

531 532
            ((int16_t *)&txdataF[0][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
            ((int16_t *)&txdataF[0][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
533 534


535 536 537
            // Antenna 1 => -x1*
            qam64_table_offset_re = 0;
            qam64_table_offset_im = 0;
538

539 540
            if (x0[*jj] == 1)
              qam64_table_offset_re+=4;
541

542
            *jj=*jj+1;
543

544 545
            if (x0[*jj] == 1)
              qam64_table_offset_im+=4;
546

547
            *jj=*jj+1;
548

549 550
            if (x0[*jj] == 1)
              qam64_table_offset_re+=2;
551

552
            *jj=*jj+1;
553

554 555
            if (x0[*jj] == 1)
              qam64_table_offset_im+=2;
556

557
            *jj=*jj+1;
558

559 560
            if (x0[*jj] == 1)
              qam64_table_offset_re+=1;
561

562
            *jj=*jj+1;
563

564 565
            if (x0[*jj] == 1)
              qam64_table_offset_im+=1;
566

567
            *jj=*jj+1;
568

569 570
            ((int16_t *)&txdataF[1][tti_offset])[0]+=-(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
            ((int16_t *)&txdataF[1][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
571

572
            break;
573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592
        }

        // fill in the rest of the ALAMOUTI precoding
        if (is_not_pilot(pilots,re + 1,frame_parms->nushift,use2ndpilots)==1) {
          ((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
          ((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
          ((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
          ((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
        } else {
          ((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
          ((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
          ((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
          ((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
        }
      } else if (mimo_mode == LARGE_CDD) {

        *re_allocated = *re_allocated + 1;

        if (frame_parms->nb_antennas_tx == 2) {
          switch (mod_order0) {
593 594 595 596 597 598 599 600 601 602 603
            default:
              LOG_E(PHY,"Unknown mod_order0 %d\n",mod_order0);
              xx0_re=xx0_im=0;
              break;

            case 2:  //QPSK
              // printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              xx0_re = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
              *jj = *jj + 1;
              xx0_im = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
              *jj = *jj + 1;
604 605 606



607 608
              // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              break;
609

610
            case 4:  //16QAM
611

612 613
              qam16_table_offset_re0 = 0;
              qam16_table_offset_im0 = 0;
614

615 616
              if (x0[*jj] == 1)
                qam16_table_offset_re0+=2;
617

618
              *jj=*jj+1;
619

620 621
              if (x0[*jj] == 1)
                qam16_table_offset_im0+=2;
622

623
              *jj=*jj+1;
624

625 626
              if (x0[*jj] == 1)
                qam16_table_offset_re0+=1;
627

628
              *jj=*jj+1;
629

630 631
              if (x0[*jj] == 1)
                qam16_table_offset_im0+=1;
632

633
              *jj=*jj+1;
634

635 636
              xx0_re = qam_table_s0[qam16_table_offset_re0];
              xx0_im = qam_table_s0[qam16_table_offset_im0];
637

638
              break;
639

640
            case 6:  //64QAM
641 642


643 644
              qam64_table_offset_re0 = 0;
              qam64_table_offset_im0 = 0;
645

646 647
              if (x0[*jj] == 1)
                qam64_table_offset_re0+=4;
648

649
              *jj=*jj+1;
650

651 652
              if (x0[*jj] == 1)
                qam64_table_offset_im0+=4;
653

654
              *jj=*jj+1;
655

656 657
              if (x0[*jj] == 1)
                qam64_table_offset_re0+=2;
658

659
              *jj=*jj+1;
660

661 662
              if (x0[*jj] == 1)
                qam64_table_offset_im0+=2;
663

664
              *jj=*jj+1;
665

666 667
              if (x0[*jj] == 1)
                qam64_table_offset_re0+=1;
668

669
              *jj=*jj+1;
670

671 672
              if (x0[*jj] == 1)
                qam64_table_offset_im0+=1;
673

674
              *jj=*jj+1;
675

676 677
              xx0_re = qam_table_s0[qam64_table_offset_re0];
              xx0_im = qam_table_s0[qam64_table_offset_im0];
678 679


680
              break;
681 682 683 684

          }

          switch (mod_order1) {
685 686 687 688
            default:
              LOG_E(PHY,"Unknown mod_order1 %d\n",mod_order1);
              xx1_re=xx1_im=0;
              break;
689

690 691 692 693 694 695 696 697
            case 2:  //QPSK
              //    printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              xx1_re = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
              *jj2 = *jj2 + 1;
              xx1_im = (x1[*jj2]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
              *jj2 = *jj2 + 1;
              // printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              break;
698

699
            case 4:  //16QAM
700

701 702
              qam16_table_offset_re1 = 0;
              qam16_table_offset_im1 = 0;
703

704 705
              if (x1[*jj2] == 1)
                qam16_table_offset_re1+=2;
706

707
              *jj2 = *jj2 + 1;
708

709 710
              if (x1[*jj2] == 1)
                qam16_table_offset_im1+=2;
711

712
              *jj2 = *jj2 + 1;
713

714 715
              if (x1[*jj2] == 1)
                qam16_table_offset_re1+=1;
716

717
              *jj2 = *jj2 + 1;
718

719 720
              if (x1[*jj2] == 1)
                qam16_table_offset_im1+=1;
721

722
              *jj2 = *jj2 + 1;
723

724 725
              xx1_re = qam_table_s1[qam16_table_offset_re1];
              xx1_im = qam_table_s1[qam16_table_offset_im1];
726

727
              break;
728

729
            case 6:  //64QAM
730

731 732
              qam64_table_offset_re1 = 0;
              qam64_table_offset_im1 = 0;
733

734 735
              if (x1[*jj2] == 1)
                qam64_table_offset_re1+=4;
736

737
              *jj2 = *jj2 + 1;
738

739 740
              if (x1[*jj2] == 1)
                qam64_table_offset_im1+=4;
741

742
              *jj2 = *jj2 + 1;
743

744 745
              if (x1[*jj2] == 1)
                qam64_table_offset_re1+=2;
746

747
              *jj2 = *jj2 + 1;
748

749 750
              if (x1[*jj2] == 1)
                qam64_table_offset_im1+=2;
751

752
              *jj2 = *jj2 + 1;
753

754 755
              if (x1[*jj2] == 1)
                qam64_table_offset_re1+=1;
756

757
              *jj2 = *jj2 + 1;
758

759 760
              if (x1[*jj2] == 1)
                qam64_table_offset_im1+=1;
761

762
              *jj2 = *jj2 + 1;
763

764 765
              xx1_re = qam_table_s1[qam64_table_offset_re1];
              xx1_im = qam_table_s1[qam64_table_offset_im1];
766 767


768
              break;
769 770 771 772 773 774 775 776 777 778 779 780 781 782

          }

          // This implements the Large CDD precoding for 2 TX antennas
          // -  -        -    -  -         -  -     -  -  -       -              -
          //| y0 |      | 1  0 || 1    0    || 1   1 || x0 |     |        x0 + x1 |
          //| y1 | = .5 | 0  1 || 0  (-1)^i || 1  -1 || x1 | = .5| (-1)^i(x0 - x1)|
          // -  -        -    -  -         -  -     -  -  -       -
          // Note: Factor .5 is accounted for in amplitude when calling this function
          ((int16_t *)&txdataF[0][tti_offset])[0]+=((xx0_re+xx1_re)>>1);
          ((int16_t *)&txdataF[1][tti_offset])[0]+=(s*((xx0_re-xx1_re)>>1));
          ((int16_t *)&txdataF[0][tti_offset])[1]+=((xx0_im+xx1_im)>>1);
          ((int16_t *)&txdataF[1][tti_offset])[1]+=(s*((xx0_im-xx1_im)>>1));
          /*
783 784 785 786
             printf("CDD: xx0 (%d,%d), xx1(%d,%d), s(%d), txF[0] (%d,%d), txF[1] (%d,%d)\n",
             xx0_re,xx0_im,xx1_re,xx1_im, s, ((int16_t *)&txdataF[0][tti_offset])[0],((int16_t *)&txdataF[0][tti_offset])[1],
             ((int16_t *)&txdataF[1][tti_offset])[0],((int16_t *)&txdataF[1][tti_offset])[1]);
           */
787 788 789 790 791 792 793 794 795
          // s alternates +1/-1 for each RE
          s = -s;
        }
      } else if ((mimo_mode >= UNIFORM_PRECODING11)&&(mimo_mode <= PUSCH_PRECODING1)) {
        // this is for transmission modes 4-6 (1 layer)
        *re_allocated = *re_allocated + 1;
        amp = (int16_t)(((int32_t)tmp_amp*ONE_OVER_SQRT2_Q15)>>15);

        switch (mod_order0) {
796
          case 2:  //QPSK
797

798 799 800 801
            ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
            *jj = *jj + 1;
            ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
            *jj = *jj + 1;
802

803 804 805
            // normalization for 2 tx antennas
            ((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
            ((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
806

807 808 809 810 811
            if (frame_parms->nb_antennas_tx == 2) {
              layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
              ((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
              ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
            }
812

813
            break;
814

815
          case 4:  //16QAM
816

817 818
            qam16_table_offset_re = 0;
            qam16_table_offset_im = 0;
819

820 821
            if (x0[*jj] == 1)
              qam16_table_offset_re+=2;
822

823
            *jj=*jj+1;
824

825 826
            if (x0[*jj] == 1)
              qam16_table_offset_im+=2;
827

828
            *jj=*jj+1;
829 830


831 832
            if (x0[*jj] == 1)
              qam16_table_offset_re+=1;
833

834
            *jj=*jj+1;
835

836 837
            if (x0[*jj] == 1)
              qam16_table_offset_im+=1;
838

839
            *jj=*jj+1;
840

841 842
            ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
            ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
843

844 845
            ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
            ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
846

847 848 849 850 851
            if (frame_parms->nb_antennas_tx == 2) {
              layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
              ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
              ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
            }
852

853
            break;
854

855
          case 6:  //64QAM
856 857


858 859
            qam64_table_offset_re = 0;
            qam64_table_offset_im = 0;
860

861 862
            if (x0[*jj] == 1)
              qam64_table_offset_re+=4;
863

864
            *jj=*jj+1;
865

866 867
            if (x0[*jj] == 1)
              qam64_table_offset_im+=4;
868

869
            *jj=*jj+1;
870

871 872
            if (x0[*jj] == 1)
              qam64_table_offset_re+=2;
873

874
            *jj=*jj+1;
875

876 877
            if (x0[*jj] == 1)
              qam64_table_offset_im+=2;
878

879
            *jj=*jj+1;
880

881 882
            if (x0[*jj] == 1)
              qam64_table_offset_re+=1;
883

884
            *jj=*jj+1;
885

886 887
            if (x0[*jj] == 1)
              qam64_table_offset_im+=1;
888

889
            *jj=*jj+1;
890

891 892
            ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
            ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
893

894 895
            ((int16_t *)&txdataF[0][tti_offset])[0] += ((int16_t*)&tmp_sample1)[0];
            ((int16_t *)&txdataF[0][tti_offset])[1] += ((int16_t*)&tmp_sample1)[1];
896

897 898 899 900 901
            if (frame_parms->nb_antennas_tx == 2) {
              layer1prec2A(&tmp_sample1,&tmp_sample2,precoder_index);
              ((int16_t*)&txdataF[1][tti_offset])[0] += ((int16_t*)&tmp_sample2)[0];
              ((int16_t*)&txdataF[1][tti_offset])[1] += ((int16_t*)&tmp_sample2)[1];
            }
902

903
            break;
904 905

        }
906
      } else if(mimo_mode == TM7){
907 908
        *re_allocated = *re_allocated + 1;

909
        if (is_not_UEspecRS(lprime,re,frame_parms->Nid_cell%3,frame_parms->Ncp,7)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
910

911 912
          switch (mod_order0){
            case 2:  //QPSK
913

914
              ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
915
              *jj = *jj + 1;
916
              ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
917 918
              *jj = *jj + 1;

919 920 921 922 923 924 925 926 927 928 929 930 931 932 933
              //printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              //printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&tmp_sample1)[0],((int16_t*)&tmp_sample1)[1]);
              for (aa=0; aa<nb_antennas_tx_phy; aa++) {
                ((int16_t*)&txdataF[aa][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((uint16_t*)&beamforming_weights[re][aa])[0])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[0] +=-(int16_t)((((int16_t*)&tmp_sample1)[1]*((uint16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((uint16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*((uint16_t*)&beamforming_weights[re][aa])[0])>>15);
               /* ((int16_t*)&txdataF[aa][tti_offset])[0] = ((int16_t*)&tmp_sample1)[0];
                ((int16_t*)&txdataF[aa][tti_offset])[1] = ((int16_t*)&tmp_sample1)[1]; */
              }

              //printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
              break;

            case 4:  //16QAM
934 935 936 937 938 939 940

              qam16_table_offset_re = 0;
              qam16_table_offset_im = 0;

              if (x0[*jj] == 1)
                qam16_table_offset_re+=2;

941
              *jj=*jj+1;
942 943 944 945

              if (x0[*jj] == 1)
                qam16_table_offset_im+=2;

946 947
              *jj=*jj+1;

948 949 950 951

              if (x0[*jj] == 1)
                qam16_table_offset_re+=1;

952
              *jj=*jj+1;
953 954 955 956

              if (x0[*jj] == 1)
                qam16_table_offset_im+=1;

957 958 959 960
              *jj=*jj+1;

              ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
              ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
961

962 963 964 965 966
              for (aa=0; aa<nb_antennas_tx_phy; aa++) {
                ((int16_t*)&txdataF[aa][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((int16_t*)&beamforming_weights[re][aa])[0])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[0] +=-(int16_t)((((int16_t*)&tmp_sample1)[1]*((int16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((int16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*((int16_t*)&beamforming_weights[re][aa])[0])>>15);
967 968
              }

969
              break;
970

971
            case 6:  //64QAM
972 973


974 975
              qam64_table_offset_re = 0;
              qam64_table_offset_im = 0;
976

977 978
              if (x0[*jj] == 1)
                qam64_table_offset_re+=4;
979

980
              *jj=*jj+1;
981

982 983
              if (x0[*jj] == 1)
                qam64_table_offset_im+=4;
984

985
              *jj=*jj+1;
986

987 988
              if (x0[*jj] == 1)
                qam64_table_offset_re+=2;
989

990
              *jj=*jj+1;
991

992 993
              if (x0[*jj] == 1)
                qam64_table_offset_im+=2;
994

995
              *jj=*jj+1;
996

997 998
              if (x0[*jj] == 1)
                qam64_table_offset_re+=1;
999

1000
              *jj=*jj+1;
1001

1002 1003
              if (x0[*jj] == 1)
                qam64_table_offset_im+=1;
1004

1005
              *jj=*jj+1;
1006

1007 1008
              ((int16_t*)&tmp_sample1)[0] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
              ((int16_t*)&tmp_sample1)[1] = (int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
1009

1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
              for (aa=0; aa<nb_antennas_tx_phy; aa++) {
                ((int16_t*)&txdataF[aa][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((int16_t*)&beamforming_weights[re][aa])[0])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[0] +=-(int16_t)((((int16_t*)&tmp_sample1)[1]*((int16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((int16_t*)&beamforming_weights[re][aa])[1])>>15);
                ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*((int16_t*)&beamforming_weights[re][aa])[0])>>15);
              }

              break;

          }
        } else{
          //precoding UE spec RS
          //printf("precoding UE spec RS\n");

          for (aa=0; aa<nb_antennas_tx_phy; aa++) {
1025 1026 1027 1028
           
            ind = 3*lprime*dlsch0_harq->nb_rb+mprime2;
            ind_dword = ind>>4;
            ind_qpsk_symb = ind&0xf;
1029

1030 1031
            tmp_sample1 = qpsk[(phy_vars_eNB->lte_gold_uespec_port5_table[0][Ns][ind_dword]>>(2*ind_qpsk_symb))&3];
            //printf("lprime=%d,nb_rb=%d,mprime2=%d,ind=%d,Ns=%d,tmp_sample1=(%d,%d)\n",lprime,dlsch0_harq->nb_rb,mprime2,ind,Ns,((int16_t*)&tmp_sample1)[0],((int16_t*)&tmp_sample1)[1]);
1032

1033 1034 1035 1036 1037 1038 1039 1040
            ((int16_t*)&txdataF[aa][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((uint16_t*)&beamforming_weights[re][aa])[0])>>15);
            ((int16_t*)&txdataF[aa][tti_offset])[0] +=-(int16_t)((((int16_t*)&tmp_sample1)[1]*((uint16_t*)&beamforming_weights[re][aa])[1])>>15);
            ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[0]*((uint16_t*)&beamforming_weights[re][aa])[1])>>15);
            ((int16_t*)&txdataF[aa][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*((uint16_t*)&beamforming_weights[re][aa])[0])>>15);

            // ((int16_t*)&txdataF[aa][tti_offset])[0] = 0xffff;
            // ((int16_t*)&txdataF[aa][tti_offset])[1] = 0xffff;

1041 1042 1043 1044
            //printf("tmp_sample1=%d+i%d\n",((int16_t*)&tmp_sample1)[0],((int16_t*)&tmp_sample1)[1]);
            //printf("beamforing_weights[%d][%d]=%d+i%d\n",re,aa,((int16_t*)&beamforming_weights[re][aa])[0],((int16_t*)&beamforming_weights[re][aa])[1]);
            //printf("txdataF[%d][%d]= %d+i%d\n ",aa,tti_offset,((int16_t*)&txdataF[aa][tti_offset])[0],((int16_t*)&txdataF[aa][tti_offset])[1]);

1045
            mprime2 = mprime2++;
1046
          }
1047

1048
        }
1049
      } else if (mimo_mode == TM8) { //TM8
1050 1051
        msg("allocate_REs_in_RB() [dlsch.c] : ERROR, unknown mimo_mode %d\n",mimo_mode);
        return(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1052
      }
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
      if (mimo_mode == ALAMOUTI) {
        re++;  // adjacent carriers are taken care of by precoding
        *re_allocated = *re_allocated + 1;

        if (is_not_pilot(pilots,re,frame_parms->nushift,use2ndpilots)==0) {
          re++;
          *re_allocated = *re_allocated + 1;
        }
      }

1063
    }
1064 1065


1066
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1067

1068
return(0);
1069 1070 1071
}

int allocate_REs_in_RB_MCH(mod_sym_t **txdataF,
1072
                           uint32_t *jj,
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
                            uint16_t re_offset,
                            uint32_t symbol_offset,
                            uint8_t *x0,
                            uint8_t l,
                            uint8_t mod_order,
                            int16_t amp,
                            int16_t *qam_table_s,
                            uint32_t *re_allocated,
                            uint8_t skip_dc,
                            LTE_DL_FRAME_PARMS *frame_parms)
1083
{
1084 1085 1086 1087 1088 1089 1090 1091 1092

  uint32_t tti_offset,aa;
  uint8_t re;
  uint8_t qam64_table_offset_re = 0;
  uint8_t qam64_table_offset_im = 0;
  uint8_t qam16_table_offset_re = 0;
  uint8_t qam16_table_offset_im = 0;
  int16_t gain_lin_QPSK;//,gain_lin_16QAM1,gain_lin_16QAM2;
  int16_t re_off=re_offset;
1093
  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
1094 1095 1096
  uint8_t first_re,last_re;
  int inc;
#ifdef DEBUG_DLSCH_MODULATION
1097
  printf("allocate_re_MCH (mod %d): symbol_offset %d re_offset %d (%d), jj %d -> %d,%d\n",mod_order,symbol_offset,re_offset,skip_dc,*jj, x0[*jj], x0[1+*jj]);
1098 1099 1100 1101 1102
#endif

  last_re=12;
  first_re=0;
  inc=1;
1103

1104 1105 1106
  if ((l==2)||(l==10)) {
    inc=2;
    first_re=1;
1107
  } else if (l==6) {
1108 1109
    inc=2;
  }
1110 1111 1112

  for (re=first_re; re<last_re; re+=inc) {

1113 1114
    if ((skip_dc == 1) && (re==(6+first_re)))
      re_off=re_off - frame_parms->ofdm_symbol_size+1;
1115

1116
    tti_offset = symbol_offset + re_off + re;
1117

1118 1119
    //    printf("re %d (jj %d)\n",re,*jj);
    *re_allocated = *re_allocated + 1;
1120 1121


1122
    switch (mod_order) {
1123
      case 2:  //QPSK
1124

1125 1126 1127
        //      printf("%d : %d,%d => ",tti_offset,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
        for (aa=0; aa<frame_parms->nb_antennas_tx; aa++)
          ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
1128

1129
        *jj = *jj + 1;
1130

1131 1132
        for (aa=0; aa<frame_parms->nb_antennas_tx; aa++)
          ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
1133

1134
    *jj = *jj + 1;
1135

1136 1137
    //  printf("%d,%d\n",((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
    break;
1138

1139
      case 4:  //16QAM
1140

1141 1142
    qam16_table_offset_re = 0;
    qam16_table_offset_im = 0;
1143

1144 1145
    if (x0[*jj] == 1)
      qam16_table_offset_re+=2;
1146

1147
    *jj=*jj+1;
1148

1149 1150
    if (x0[*jj] == 1)
      qam16_table_offset_im+=2;
1151

1152
    *jj=*jj+1;
1153 1154


1155 1156
    if (x0[*jj] == 1)
      qam16_table_offset_re+=1;
1157

1158
    *jj=*jj+1;
1159

1160 1161
    if (x0[*jj] == 1)
      qam16_table_offset_im+=1;
1162

1163
    *jj=*jj+1;
1164

1165 1166 1167 1168 1169 1170
    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
      ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam16_table_offset_re];
      ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam16_table_offset_im];
      //      ((int16_t *)&txdataF[aa][tti_offset])[0]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_re])>>15);
      //      ((int16_t *)&txdataF[aa][tti_offset])[1]+=(int16_t)(((int32_t)amp*qam16_table[qam16_table_offset_im])>>15);
    }
1171

1172
    break;
1173

1174
      case 6:  //64QAM
1175 1176


1177 1178
    qam64_table_offset_re = 0;
    qam64_table_offset_im = 0;
1179

1180 1181
    if (x0[*jj] == 1)
      qam64_table_offset_re+=4;
1182

1183
    *jj=*jj+1;
1184

1185 1186
    if (x0[*jj] == 1)
      qam64_table_offset_im+=4;
1187

1188
    *jj=*jj+1;
1189

1190 1191
    if (x0[*jj] == 1)
      qam64_table_offset_re+=2;
1192

1193
    *jj=*jj+1;
1194

1195 1196
    if (x0[*jj] == 1)
      qam64_table_offset_im+=2;
1197

1198
    *jj=*jj+1;
1199

1200 1201
    if (x0[*jj] == 1)
      qam64_table_offset_re+=1;
1202

1203
    *jj=*jj+1;
1204

1205 1206
    if (x0[*jj] == 1)
      qam64_table_offset_im+=1;
1207

1208
    *jj=*jj+1;
1209

1210 1211 1212 1213
    for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
      ((int16_t *)&txdataF[aa][tti_offset])[0]+=qam_table_s[qam64_table_offset_re];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_re])>>15);
      ((int16_t *)&txdataF[aa][tti_offset])[1]+=qam_table_s[qam64_table_offset_im];//(int16_t)(((int32_t)amp*qam64_table[qam64_table_offset_im])>>15);
    }
1214

1215
    break;
1216

1217
    }
1218 1219
  }

1220 1221 1222
  return(0);
}

1223 1224
uint8_t get_pmi(uint8_t N_RB_DL,LTE_DL_eNB_HARQ_t *dlsch_harq,uint16_t rb)
{
1225 1226 1227 1228


  MIMO_mode_t mode   = dlsch_harq->mimo_mode;
  uint32_t pmi_alloc = dlsch_harq->pmi_alloc;
1229 1230

  //  printf("Getting pmi for RB %d => %d\n",rb,(pmi_alloc>>((rb>>2)<<1))&3);
Raymond Knopp's avatar
 
Raymond Knopp committed
1231
  switch (N_RB_DL) {
1232 1233 1234 1235 1236
    case 6:   // 1 PRB per subband
      if (mode <= PUSCH_PRECODING1)
        return((pmi_alloc>>(rb<<1))&3);
      else
        return((pmi_alloc>>rb)&1);
1237

1238
      break;
1239

1240 1241 1242 1243 1244 1245
    default:
    case 25:  // 4 PRBs per subband
      if (mode <= PUSCH_PRECODING1)
        return((pmi_alloc>>((rb>>2)<<1))&3);
      else
        return((pmi_alloc>>(rb>>2))&1);
1246

1247
      break;
1248

1249 1250 1251 1252 1253
    case 50: // 6 PRBs per subband
      if (mode <= PUSCH_PRECODING1)
        return((pmi_alloc>>((rb/6)<<1))&3);
      else
        return((pmi_alloc>>(rb/6))&1);
1254

1255
      break;
1256

1257 1258 1259 1260 1261
    case 100: // 8 PRBs per subband
      if (mode <= PUSCH_PRECODING1)
        return((pmi_alloc>>((rb>>3)<<1))&3);
      else
        return((pmi_alloc>>(rb>>3))&1);
1262

1263
      break;
Raymond Knopp's avatar
 
Raymond Knopp committed
1264
  }
1265 1266
}

Raymond Knopp's avatar
 
Raymond Knopp committed
1267

1268 1269
int dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
                     mod_sym_t **txdataF,
1270 1271 1272 1273
                     int16_t amp,
                     uint32_t subframe_offset,
                     uint8_t num_pdcch_symbols,
                     LTE_eNB_DLSCH_t *dlsch0,
1274 1275
                     LTE_eNB_DLSCH_t *dlsch1,
                     int32_t **beamforming_weights)
1276
{
1277
  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
1278 1279

  uint8_t nsymb;
1280 1281 1282 1283
  uint8_t harq_pid = dlsch0->current_harq_pid;
  LTE_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid];
  LTE_DL_eNB_HARQ_t *dlsch1_harq; //= dlsch1->harq_processes[harq_pid];
  uint32_t i,jj,jj2,re_allocated,symbol_offset;
1284 1285
  uint16_t l,rb,re_offset;
  uint32_t rb_alloc_ind;
1286
  uint32_t *rb_alloc = dlsch0_harq->rb_alloc;
1287
  uint8_t pilots=0,ue_spec_rs=0;
1288
  uint8_t skip_dc,skip_half;
1289
  uint8_t mod_order0 = get_Qm(dlsch0_harq->mcs);
1290
  uint8_t mod_order1 = 0;
1291
  int16_t amp_rho_a, amp_rho_b;
1292 1293 1294
  int16_t qam16_table_a0[4],qam64_table_a0[8],qam16_table_b0[4],qam64_table_b0[8];
  int16_t qam16_table_a1[4],qam64_table_a1[8],qam16_table_b1[4],qam64_table_b1[8];
  int16_t *qam_table_s0,*qam_table_s1;
1295 1296 1297
  MIMO_mode_t mimo_mode = dlsch0_harq->mimo_mode;
  uint8_t beamforming_mode = 0;
  int32_t **beamforming_weights_RB = beamforming_weights;
1298 1299
  uint8_t mprime=0,Ns;
  int8_t  lprime=-1;
1300

Raymond Knopp's avatar
 
Raymond Knopp committed
1301
#ifdef DEBUG_DLSCH_MODULATION
1302 1303
  uint8_t Nl0 = dlsch0_harq->Nl;
  uint8_t Nl1;
Raymond Knopp's avatar
 
Raymond Knopp committed
1304
#endif
1305 1306 1307 1308 1309 1310 1311 1312

  if (dlsch1) {
    dlsch1_harq = dlsch1->harq_processes[harq_pid];
    mod_order1 = get_Qm(dlsch1_harq->mcs);
#ifdef DEBUG_DLSCH_MODULATION
    Nl1 = dlsch1_harq->Nl;
#endif
  }
1313

1314
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_IN);
1315

1316
  nsymb = (frame_parms->Ncp==0) ? 14:12;
1317

1318 1319
  amp_rho_a = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_a)>>13);
  amp_rho_b = (int16_t)(((int32_t)amp*dlsch0->sqrt_rho_b)>>13);
1320

1321
  if (mod_order0 == 4)
1322
    for (i=0;i<4; i++) {
1323 1324
      qam16_table_a0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
      qam16_table_b0[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
1325
    }
1326
  else if (mod_order0 == 6)
1327
    for (i=0; i<8; i++) {
1328 1329
      qam64_table_a0[i] = (int16_t)(((int32_t)qam64_table[i]*amp_rho_a)>>15);
      qam64_table_b0[i] = (int16_t)(((int32_t)qam64_table[i]*amp_rho_b)>>15);
1330
    }
1331 1332

  if (mod_order1 == 4)
1333
    for (i=0; i<4; i++) {
1334 1335 1336
      qam16_table_a1[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_a)>>15);
      qam16_table_b1[i] = (int16_t)(((int32_t)qam16_table[i]*amp_rho_b)>>15);
    }
Raymond Knopp's avatar
Raymond Knopp committed
1337
  else if (mod_order1 == 6)
1338
    for (i=0; i<8; i++) {
1339 1340
      qam64_table_a1[i] = (int16_t)(((int32_t)qam64_table[i]*amp_rho_a)>>15);
      qam64_table_b1[i] = (int16_t)(((int32_t)qam64_table[i]*amp_rho_b)>>15);
1341 1342
    }

1343
  //Modulation mapping (difference w.r.t. LTE specs)
1344 1345 1346

  jj=0;
  jj2=0;
1347
  re_allocated=0;
1348

1349
  //  printf("num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb);
1350 1351
  for (l=num_pdcch_symbols; l<nsymb; l++) {

1352
#ifdef DEBUG_DLSCH_MODULATION
1353
    msg("Generating DLSCH (harq_pid %d,mimo %d, pmi_alloc0 %llx, mod0 %d, mod1 %d, rb_alloc[0] %d) in %d\n",
1354 1355 1356 1357 1358 1359 1360 1361
        harq_pid,
        dlsch0_harq->mimo_mode,
        pmi2hex_2Ar1(dlsch0_harq->pmi_alloc),
        mod_order0,
        mod_order1,
        rb_alloc[0],
        l);
#endif
1362 1363 1364

    if (frame_parms->Ncp==0) { // normal prefix
      if ((l==4)||(l==11))
1365
        pilots=2;   // pilots in nushift+3, nushift+9
1366
      else if (l==7)
1367
        pilots=1;   // pilots in nushift, nushift+6
1368
      else
1369 1370
        pilots=0;
    } else {
1371
      if ((l==3)||(l==9))
1372
        pilots=2;
1373
      else if (l==6)
1374
        pilots=1;
1375
      else
1376
        pilots=0;
1377 1378
    }

1379 1380 1381 1382
    if(mimo_mode==TM7){ //36.211 V8.6.0 2009-03
      beamforming_mode = 7;
      mprime = 0;
      if (frame_parms->Ncp==0) { // normal prefix
1383 1384 1385 1386 1387 1388 1389 1390
        if (l==12)
          lprime=3;   // pilots in nushift+3, nushift+9
        else if (l==9)
          lprime=2;   // pilots in nushift, nushift+6
        else if (l==6)
          lprime=1;   // pilots in nushift+3, nushift+9
        else if (l==3)
          lprime=0;   // pilots in nushift, nushift+6
1391
        else
1392
          lprime=-1;
1393
      } else {
1394
        if (l==10)
1395
          lprime=2;
1396
        else if (l==7)
1397
          lprime=1;
1398
        else if (l==4)
1399
          lprime=0;
1400 1401
        else
          lprime=-1;
1402 1403 1404 1405 1406 1407 1408
      }
    }else if(mimo_mode==TM8){
      beamforming_mode = 8;
    }else if(mimo_mode==TM9_10){
      beamforming_mode = 9;
    }
  
1409
    Ns = 2*subframe_offset+(l>=(nsymb>>1));
1410

1411 1412 1413 1414
    re_offset = frame_parms->first_carrier_offset;
    symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb));

    //for (aa=0;aa<frame_parms->nb_antennas_tx;aa++)
1415
    //  memset(&txdataF[aa][symbol_offset],0,frame_parms->ofdm_symbol_size<<2);
1416
    //printf("symbol_offset %d,subframe offset %d : pilots %d\n",symbol_offset,subframe_offset,pilots);
1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521
    for (rb=0; rb<frame_parms->N_RB_DL; rb++) {

      if (rb < 32)
        rb_alloc_ind = (rb_alloc[0]>>rb) & 1;
      else if (rb < 64)
        rb_alloc_ind = (rb_alloc[1]>>(rb-32)) & 1;
      else if (rb < 96)
        rb_alloc_ind = (rb_alloc[2]>>(rb-64)) & 1;
      else if (rb < 100)
        rb_alloc_ind = (rb_alloc[3]>>(rb-96)) & 1;
      else
        rb_alloc_ind = 0;

      // check for PBCH
      skip_half=0;

      if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL

        if (rb==(frame_parms->N_RB_DL>>1))
          skip_dc = 1;
        else
          skip_dc = 0;

        // PBCH
        if ((subframe_offset==0) &&
            (rb>((frame_parms->N_RB_DL>>1)-3)) &&
            (rb<((frame_parms->N_RB_DL>>1)+3)) &&
            (l>=(nsymb>>1)) &&
            (l<((nsymb>>1) + 4))) {
          rb_alloc_ind = 0;
        }

        //PBCH subframe 0, symbols nsymb>>1 ... nsymb>>1 + 3
        if ((subframe_offset==0) &&
            (rb==((frame_parms->N_RB_DL>>1)-3)) &&
            (l>=(nsymb>>1)) &&
            (l<((nsymb>>1) + 4)))
          skip_half=1;
        else if ((subframe_offset==0) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l>=(nsymb>>1)) && (l<((nsymb>>1) + 4)))
          skip_half=2;

        if (frame_parms->frame_type == TDD) { // TDD
          //SSS TDD
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1)) ) {
            rb_alloc_ind = 0;
          }

          //SSS TDD
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==(nsymb-1)))
            skip_half=1;
          else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(nsymb-1)))
            skip_half=2;

          //PSS TDD
          if (((subframe_offset==1) || (subframe_offset==6)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==2) ) {
            rb_alloc_ind = 0;
          }

          //PSS TDD
          if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==2))
            skip_half=1;
          else if (((subframe_offset==1)||(subframe_offset==6)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==2))
            skip_half=2;
        } else {
          //PSS FDD
          if (((subframe_offset==0)||(subframe_offset==5)) &&
              (rb>((frame_parms->N_RB_DL>>1)-3)) &&
              (rb<((frame_parms->N_RB_DL>>1)+3)) &&
              (l==((nsymb>>1)-1)) ) {
            rb_alloc_ind = 0;
          }

          //PSS FDD
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && (l==((nsymb>>1)-1)))
            skip_half=1;
          else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && (l==(((nsymb>>1)-1))))
            skip_half=2;

          //SSS FDD
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb>((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) {
            rb_alloc_ind = 0;
          }

          //SSS FDD
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)-3)) && ((l==((nsymb>>1)-2))))
            skip_half=1;
          else if (((subframe_offset==0)||(subframe_offset==5)) && (rb==((frame_parms->N_RB_DL>>1)+3)) && ((l==(nsymb>>1)-2)))
            skip_half=2;

        }

      } else { // EVEN N_RB_DL
        //PBCH
        if ((subframe_offset==0) &&
            (rb>=((frame_parms->N_RB_DL>>1)-3)) &&
            (rb<((frame_parms->N_RB_DL>>1)+3)) &&
            (l>=nsymb>>1) && (l<((nsymb>>1) + 4)))
          rb_alloc_ind = 0;

        skip_dc=0;
        skip_half=0;

        if (frame_parms->frame_type == TDD) { // TDD
          //SSS
          if (((subframe_offset==0)||
1522
                (subframe_offset==5)) &&
1523 1524 1525 1526 1527 1528 1529 1530
              (rb>=((frame_parms->N_RB_DL>>1)-3)) &&
              (rb<((frame_parms->N_RB_DL>>1)+3)) &&
              (l==nsymb-1) ) {
            rb_alloc_ind = 0;
          }

          //PSS
          if (((subframe_offset==1)||
1531
                (subframe_offset==6)) &&
1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548
              (rb>=((frame_parms->N_RB_DL>>1)-3)) &&
              (rb<((frame_parms->N_RB_DL>>1)+3)) &&
              (l==2) ) {
            rb_alloc_ind = 0;
          }
        } else { // FDD
          //SSS
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-2)) ) {
            rb_alloc_ind = 0;
          }

          //PSS
          if (((subframe_offset==0)||(subframe_offset==5)) && (rb>=((frame_parms->N_RB_DL>>1)-3)) && (rb<((frame_parms->N_RB_DL>>1)+3)) && (l==((nsymb>>1)-1)) ) {
            rb_alloc_ind = 0;
          }
        }
      }
1549

1550 1551 1552
      if (dlsch0_harq->Nlayers>1) {
        msg("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset);
        return(-1);
1553
      }
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576

      if (dlsch1) {
        if (dlsch1_harq->Nlayers>1) {
          msg("Nlayers %d: re_offset %d, symbol %d offset %d\n",dlsch0_harq->Nlayers,re_offset,l,symbol_offset);
          return(-1);
        }
      }

      if (mod_order0 == 4)
        qam_table_s0 = ((pilots) ? qam16_table_b0 : qam16_table_a0);
      else if (mod_order0 == 6)
        qam_table_s0 = ((pilots) ? qam64_table_b0 : qam64_table_a0);
      else
        qam_table_s0 = NULL;

      if (mod_order1 == 4)
        qam_table_s1 = ((pilots) ? qam16_table_b1 : qam16_table_a1);
      else if (mod_order1 == 6)
        qam_table_s1 = ((pilots) ? qam64_table_b1 : qam64_table_a1);
      else
        qam_table_s1 = NULL;

      if (rb_alloc_ind > 0) {
1577
        // printf("Allocated rb %d/symbol %d, skip_half %d, subframe_offset %d, symbol_offset %d, re_offset %d, jj %d\n",rb,l,skip_half,subframe_offset,symbol_offset,re_offset,jj);
1578
        allocate_REs_in_RB(phy_vars_eNB,
1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592
                           txdataF,
                           &jj,
                           &jj2,
                           re_offset,
                           symbol_offset,
                           dlsch0->harq_processes[harq_pid],
                           (dlsch1==NULL) ? NULL : dlsch1->harq_processes[harq_pid],
                           pilots,
                           ((pilots) ? amp_rho_b : amp_rho_a),
                           get_pmi(frame_parms->N_RB_DL,dlsch0->harq_processes[harq_pid],rb),
                           qam_table_s0,
                           qam_table_s1,
                           &re_allocated,
                           skip_dc,
1593 1594 1595 1596 1597 1598
                           skip_half,
                           lprime,
                           mprime,
                           Ns,
                           beamforming_weights_RB);

1599 1600
        if(mimo_mode==TM7 && lprime>=0)
           mprime +=3+frame_parms->Ncp;
1601

1602
      }
1603 1604

      re_offset+=12; // go to next RB
1605
      beamforming_weights_RB +=12;
1606 1607 1608 1609


      // check if we crossed the symbol boundary and skip DC
      if (re_offset >= frame_parms->ofdm_symbol_size) {
1610 1611 1612 1613 1614 1615 1616
              if (skip_dc == 0)  //even number of RBs (doesn't straddle DC)
                re_offset=1;
              else
                re_offset=7;  // odd number of RBs
          }
              beamforming_weights_RB = beamforming_weights;
               }
1617

1618
      }
1619

1620 1621 1622


#ifdef DEBUG_DLSCH_MODULATION
1623
  msg("generate_dlsch : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch0_harq->nb_rb,dlsch0_harq->rb_alloc,mod_order0,Nl0,2,0,subframe_offset));
1624
#endif
1625

1626
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
1627

1628 1629 1630 1631
  return (re_allocated);
}

int mch_modulation(mod_sym_t **txdataF,
1632 1633 1634 1635 1636 1637
                   int16_t amp,
                   uint32_t subframe_offset,
                   LTE_DL_FRAME_PARMS *frame_parms,
                   LTE_eNB_DLSCH_t *dlsch)
{

1638 1639 1640 1641 1642 1643 1644 1645 1646 1647
  uint8_t nsymb,nsymb_pmch;
  uint32_t i,jj,re_allocated,symbol_offset;
  uint16_t l,rb,re_offset;
  uint8_t skip_dc=0;
  uint8_t mod_order = get_Qm(dlsch->harq_processes[0]->mcs);
  int16_t qam16_table_a[4],qam64_table_a[8];//,qam16_table_b[4],qam64_table_b[8];
  int16_t *qam_table_s;

  nsymb_pmch = 12;
  nsymb = (frame_parms->Ncp == NORMAL) ? 14 : 12;
1648

1649
  if (mod_order == 4)
1650
    for (i=0; i<4; i++) {
1651 1652 1653
      qam16_table_a[i] = (int16_t)(((int32_t)qam16_table[i]*amp)>>15);
    }
  else if (mod_order == 6)
1654
    for (i=0; i<8; i++) {
1655
      qam64_table_a[i] = (int16_t)(((int32_t)qam64_table[i]*amp)>>15);
1656 1657 1658
    }

  jj=0;
1659
  re_allocated=0;
1660

1661
  //  printf("num_pdcch_symbols %d, nsymb %d\n",num_pdcch_symbols,nsymb);
1662 1663
  for (l=2; l<nsymb_pmch; l++) {

1664 1665
#ifdef DEBUG_DLSCH_MODULATION
    msg("Generating MCH (mod %d) in %d\n",mod_order, l);
1666
#endif
1667 1668 1669 1670

    re_offset = frame_parms->first_carrier_offset;
    symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(l+(subframe_offset*nsymb));

1671 1672
    for (rb=0; rb<frame_parms->N_RB_DL; rb++) {

1673 1674

      if ((frame_parms->N_RB_DL&1) == 1) { // ODD N_RB_DL
1675 1676 1677 1678 1679

        if (rb==(frame_parms->N_RB_DL>>1))
          skip_dc = 1;
        else
          skip_dc = 0;
1680 1681 1682

      }

1683

1684
      if (mod_order == 4)
1685
        qam_table_s = qam16_table_a;
1686
      else if (mod_order == 6)
1687
        qam_table_s = qam64_table_a;
1688
      else
1689
        qam_table_s = NULL;
1690 1691 1692

      //      printf("Allocated rb %d, subframe_offset %d\n",rb,subframe_offset);
      allocate_REs_in_RB_MCH(txdataF,
1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704
                             &jj,
                             re_offset,
                             symbol_offset,
                             dlsch->harq_processes[0]->e,
                             l,
                             mod_order,
                             amp,
                             qam_table_s,
                             &re_allocated,
                             skip_dc,
                             frame_parms);

1705
      re_offset+=12; // go to next RB
1706 1707


1708 1709
      // check if we crossed the symbol boundary and skip DC
      if (re_offset >= frame_parms->ofdm_symbol_size) {
1710 1711 1712 1713
        if (skip_dc == 0)  //even number of RBs (doesn't straddle DC)
          re_offset=1;
        else
          re_offset=7;  // odd number of RBs
1714 1715 1716 1717
      }
    }
  }

1718 1719


1720 1721 1722


#ifdef DEBUG_DLSCH_MODULATION
1723
  msg("generate_dlsch(MCH) : jj = %d,re_allocated = %d (G %d)\n",jj,re_allocated,get_G(frame_parms,dlsch->harq_processes[0]->nb_rb,dlsch->harq_processes[0]->rb_alloc,mod_order,1,2,0,subframe_offset));
1724
#endif
1725 1726

  return (re_allocated);
1727
}