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

/*! \file PHY/LTE_TRANSPORT/dci.c
* \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03.
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
35 36 37 38
#include "PHY/defs_eNB.h"
#include "PHY/phy_extern.h"
#include "SCHED/sched_eNB.h"
#include "SIMULATION/TOOLS/sim.h" // for taus
39
#include "PHY/sse_intrin.h"
40 41
#include "transport_proto.h"
#include "transport_common_proto.h"
Cedric Roux's avatar
Cedric Roux committed
42
#include "assertions.h"
43
#include "T.h"
44 45
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
46
#include "PHY/LTE_TRANSPORT/transport_extern.h"
47
#include "PHY/LTE_REFSIG/lte_refsig.h"
48 49 50 51

//#define DEBUG_DCI_ENCODING 1
//#define DEBUG_DCI_DECODING 1
//#define DEBUG_PHY
52

53 54
//#undef ALL_AGGREGATION

55 56
//extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3];
//extern uint16_t pcfich_reg[4];
57

58

59

60 61
//static uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96];
//static uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)];
62

63
void dci_encoding(uint8_t *a,
64 65 66 67 68
                  uint8_t A,
                  uint16_t E,
                  uint8_t *e,
                  uint16_t rnti)
{
69 70


71 72
  uint8_t D = (A + 16);
  uint32_t RCC;
73 74
  uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96];
  uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)];
75 76

#ifdef DEBUG_DCI_ENCODING
77
  int32_t i;
78
#endif
79
  // encode dci
80 81

#ifdef DEBUG_DCI_ENCODING
82
  printf("Doing DCI encoding for %d bits, e %p, rnti %x, E %d\n",A,e,rnti,E);
83 84 85 86 87 88 89
#endif

  memset((void *)d,LTE_NULL,96);

  ccodelte_encode(A,2,a,d+96,rnti);

#ifdef DEBUG_DCI_ENCODING
90 91

  for (i=0; i<16+A; i++)
92
    printf("%d : (%d,%d,%d)\n",i,*(d+96+(3*i)),*(d+97+(3*i)),*(d+98+(3*i)));
93

94
#endif
95

96
#ifdef DEBUG_DCI_ENCODING
97
  printf("Doing DCI interleaving for %d coded bits, e %p\n",D*3,e);
98 99 100 101
#endif
  RCC = sub_block_interleaving_cc(D,d+96,w);

#ifdef DEBUG_DCI_ENCODING
102
  printf("Doing DCI rate matching for %d channel bits, RCC %d, e %p\n",E,RCC,e);
103 104 105 106 107 108 109
#endif
  lte_rate_matching_cc(RCC,E,w,e);


}


110
uint8_t *generate_dci0(uint8_t *dci,
111 112 113 114 115 116
                       uint8_t *e,
                       uint8_t DCI_LENGTH,
                       uint8_t aggregation_level,
                       uint16_t rnti)
{

117 118
  uint16_t coded_bits;
  uint8_t dci_flip[8];
119

Cedric Roux's avatar
Cedric Roux committed
120 121 122 123
  AssertFatal((aggregation_level==1) ||
	      (aggregation_level==2) ||
	      (aggregation_level==4) ||
	      (aggregation_level==8)
124
#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0)) // Added for EPDCCH/MPDCCH
125 126 127 128 129 130
	      ||
	      (aggregation_level==16) ||
	      (aggregation_level==24) ||
	      (aggregation_level==32)
#endif
	      ,
131
	      "generate_dci FATAL, illegal aggregation_level %d\n",aggregation_level);
Cedric Roux's avatar
Cedric Roux committed
132

133

134
  coded_bits = 72 * aggregation_level;
135

Cedric Roux's avatar
Cedric Roux committed
136

137 138

  #ifdef DEBUG_DCI_ENCODING
139
  for (int i=0;i<1+((DCI_LENGTH+16)/8);i++)
140
    printf("i %d : %x\n",i,dci[i]);
141
  #endif
Cedric Roux's avatar
Cedric Roux committed
142

143
  if (DCI_LENGTH<=32) {
144 145 146
    dci_flip[0] = dci[3];
    dci_flip[1] = dci[2];
    dci_flip[2] = dci[1];
147
    dci_flip[3] = dci[0];
148 149 150 151 152
#ifdef DEBUG_DCI_ENCODING
    printf("DCI => %x,%x,%x,%x\n",
	   dci_flip[0],dci_flip[1],dci_flip[2],dci_flip[3]);

#endif
153
  } else {
154 155 156 157 158 159 160 161
    dci_flip[0] = dci[7];
    dci_flip[1] = dci[6];
    dci_flip[2] = dci[5];
    dci_flip[3] = dci[4];
    dci_flip[4] = dci[3];
    dci_flip[5] = dci[2];
    dci_flip[6] = dci[1];
    dci_flip[7] = dci[0];
162
#ifdef DEBUG_DCI_ENCODING
163
    printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n",
164 165
        dci_flip[0],dci_flip[1],dci_flip[2],dci_flip[3],
        dci_flip[4],dci_flip[5],dci_flip[6],dci_flip[7]);
166
#endif
167
  }
168

169 170 171 172 173
  dci_encoding(dci_flip,DCI_LENGTH,coded_bits,e,rnti);

  return(e+coded_bits);
}

174
//uint32_t Y;
175 176


177 178 179



180

181
void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi)
182
{
183

184
  int32_t *wptr,*wptr2,*zptr;
185 186 187 188
  uint32_t Mquad = get_nquad(n_symbols_pdcch,frame_parms,mi);
  uint32_t RCC = (Mquad>>5), ND;
  uint32_t row,col,Kpi,index;
  int32_t i,k,a;
189
#ifdef RM_DEBUG
190
  int32_t nulled=0;
191
#endif
192 193
  uint32_t Msymb=(DCI_BITS_MAX/2);
  int32_t wtemp[2][Msymb];
194

195
  //  printf("[PHY] PDCCH Interleaving Mquad %d (Nsymb %d)\n",Mquad,n_symbols_pdcch);
196 197
  if ((Mquad&0x1f) > 0)
    RCC++;
198

199 200 201 202
  Kpi = (RCC<<5);
  ND = Kpi - Mquad;

  k=0;
203 204

  for (col=0; col<32; col++) {
205 206
    index = bitrev_cc_dci[col];

207
    for (row=0; row<RCC; row++) {
208
      //printf("col %d, index %d, row %d\n",col,index,row);
209
      if (index>=ND) {
Xiwen JIANG's avatar
Xiwen JIANG committed
210
        for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
211
          //printf("a %d k %d\n",a,k);
212 213 214

          wptr = &wtemp[a][k<<2];
          zptr = &z[a][(index-ND)<<2];
215

216
          //printf("wptr=%p, zptr=%p\n",wptr,zptr);
217

218 219 220 221 222
          wptr[0] = zptr[0];
          wptr[1] = zptr[1];
          wptr[2] = zptr[2];
          wptr[3] = zptr[3];
        }
223

224
        k++;
225
      }
226

227 228 229 230 231
      index+=32;
    }
  }

  // permutation
232 233
  for (i=0; i<Mquad; i++) {

Xiwen JIANG's avatar
Xiwen JIANG committed
234
    for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
235 236 237 238 239 240 241 242 243 244 245 246 247 248

      //wptr  = &wtemp[a][i<<2];
      //wptr2 = &wbar[a][((i+frame_parms->Nid_cell)%Mquad)<<2];
      wptr = &wtemp[a][((i+frame_parms->Nid_cell)%Mquad)<<2];
      wptr2 = &wbar[a][i<<2];
      wptr2[0] = wptr[0];
      wptr2[1] = wptr[1];
      wptr2[2] = wptr[2];
      wptr2[3] = wptr[3];
    }
  }
}

void pdcch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
249 250 251 252
                      uint8_t subframe,
                      uint8_t *e,
                      uint32_t length)
{
253
  int i;
254 255
  uint8_t reset;
  uint32_t x1, x2, s=0;
256 257

  //LOG_D(PHY, "%s(fp, subframe:%d, e, length:%d)\n", __FUNCTION__, subframe, length);
258 259

  reset = 1;
260
  // x1 is set in lte_gold_generic
261 262 263 264

  x2 = (subframe<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.8.2

  for (i=0; i<length; i++) {
265
    if ((i&0x1f)==0) {
266
      s = lte_gold_generic(&x1, &x2, reset);
267
      //printf("lte_gold[%d]=%x\n",i,s);
268 269
      reset = 0;
    }
270

271 272 273
    //    printf("scrambling %d : e %d, c %d\n",i,e[i],((s>>(i&0x1f))&1));
    if (e[i] != 2) // <NIL> element is 2
      e[i] = (e[i]&1) ^ ((s>>(i&0x1f))&1);
274 275
  }
}
276

277 278
uint8_t generate_dci_top(uint8_t num_pdcch_symbols,
			 uint8_t num_dci,
279 280 281 282
                         DCI_ALLOC_t *dci_alloc,
                         uint32_t n_rnti,
                         int16_t amp,
                         LTE_DL_FRAME_PARMS *frame_parms,
283
                         int32_t **txdataF,
284 285
                         uint32_t subframe)
{
286

287

288
  uint8_t *e_ptr;
289 290 291 292 293
  int8_t L;
  uint32_t i, lprime;
  uint32_t gain_lin_QPSK,kprime,kprime_mod12,mprime,nsymb,symbol_offset,tti_offset;
  int16_t re_offset;
  uint8_t mi = get_mi(frame_parms,subframe);
294 295 296
  uint8_t e[DCI_BITS_MAX];
  uint32_t Msymb=(DCI_BITS_MAX/2);
  int32_t yseq0[Msymb],yseq1[Msymb],wbar0[Msymb],wbar1[Msymb];
297

298 299
  int32_t *y[2];
  int32_t *wbar[2];
300

301 302 303 304 305 306 307 308 309
  int nushiftmod3 = frame_parms->nushift%3;

  int Msymb2;
  int split_flag=0;

  switch (frame_parms->N_RB_DL) {
  case 100:
    Msymb2 = Msymb;
    break;
310

311 312 313
  case 75:
    Msymb2 = 3*Msymb/4;
    break;
314

315 316 317
  case 50:
    Msymb2 = Msymb>>1;
    break;
318

319 320 321
  case 25:
    Msymb2 = Msymb>>2;
    break;
322

323 324 325
  case 15:
    Msymb2 = Msymb*15/100;
    break;
326

327 328 329
  case 6:
    Msymb2 = Msymb*6/100;
    break;
330

331 332 333 334 335
  default:
    Msymb2 = Msymb>>2;
    break;
  }

336

337
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PCFICH,1);
338
  generate_pcfich(num_pdcch_symbols,
339 340 341 342
                  amp,
                  frame_parms,
                  txdataF,
                  subframe);
343
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_PCFICH,0);
344 345 346 347 348
  wbar[0] = &wbar0[0];
  wbar[1] = &wbar1[0];
  y[0] = &yseq0[0];
  y[1] = &yseq1[0];

349
#if 1
350
  // reset all bits to <NIL>, here we set <NIL> elements as 2
351 352 353 354
  // memset(e, 2, DCI_BITS_MAX);
  // here we interpret NIL as a random QPSK sequence. That makes power estimation easier.
  for (i=0; i<DCI_BITS_MAX; i++)
    e[i]=taus()&1;
355 356 357 358 359
#endif

  /* clear all bits, the above code may generate too much false detections
   * (not sure about this, to be checked somehow)
   */
360
  //memset(e, 0, DCI_BITS_MAX);
361

362 363
  e_ptr = e;

364
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DCI0,1);
365

366 367
  // generate DCIs in order of decreasing aggregation level, then common/ue spec
  // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization
368
  for (L=8; L>=1; L>>=1) {
369
    for (i=0; i<num_dci; i++) {
370

371
      if (dci_alloc[i].L == (uint8_t)L) {
372

373
        LOG_D(PHY,"Generating DCI %d/%d (nCCE %d) of length %d, aggregation %d (%x), rnti %x\n",
374
              i,num_dci,dci_alloc[i].firstCCE,dci_alloc[i].dci_length,dci_alloc[i].L,
375 376
		*(unsigned int*)dci_alloc[i].dci_pdu,
		dci_alloc[i].rnti);
377

378
        if (dci_alloc[i].firstCCE>=0) {
379
          e_ptr = generate_dci0(dci_alloc[i].dci_pdu,
380
                                e+(72*dci_alloc[i].firstCCE),
381 382 383 384
                                dci_alloc[i].dci_length,
                                dci_alloc[i].L,
                                dci_alloc[i].rnti);
        }
385 386 387
      }
    }
  }
388
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_GENERATE_DCI0,0);
389 390

  // Scrambling
391 392 393 394 395 396
#ifdef DEBUG_DCI_ENCODING
  printf("pdcch scrambling\n");
#endif
  //LOG_D(PHY, "num_pdcch_symbols:%d mi:%d nquad:%d\n", num_pdcch_symbols, mi, get_nquad(num_pdcch_symbols, frame_parms, mi));

  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_SCRAMBLING,1);
397
  pdcch_scrambling(frame_parms,
398 399
                   subframe,
                   e,
400
                   8*get_nquad(num_pdcch_symbols, frame_parms, mi));
401
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_SCRAMBLING,0);
402 403
  //72*get_nCCE(num_pdcch_symbols,frame_parms,mi));

404

405

406

407
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_MODULATION,1);
408
  // Now do modulation
409
  if (frame_parms->nb_antenna_ports_eNB==1)
410
    gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
411
  else
412
    gain_lin_QPSK = amp/2;
413 414

  e_ptr = e;
415

416 417 418 419
#ifdef DEBUG_DCI_ENCODING
  printf(" PDCCH Modulation, Msymb %d, Msymb2 %d,gain_lin_QPSK %d\n",Msymb,Msymb2,gain_lin_QPSK);
#endif

420
  //LOG_D(PHY,"%s() Msymb2:%d\n", __FUNCTION__, Msymb2);
421

422
  if (frame_parms->nb_antenna_ports_eNB==1) { //SISO
423

424

425
    for (i=0; i<Msymb2; i++) {
Cedric Roux's avatar
Cedric Roux committed
426

427 428 429 430
      //((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      //((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      ((int16_t*)(&(y[0][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      ((int16_t*)(&(y[1][i])))[0] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
431
      e_ptr++;
432 433 434 435
      //((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      //((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      ((int16_t*)(&(y[0][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
      ((int16_t*)(&(y[1][i])))[1] = (*e_ptr == 2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
436 437 438

      e_ptr++;
    }
439
  } else { //ALAMOUTI
440

441

442
    for (i=0; i<Msymb2; i+=2) {
443 444

#ifdef DEBUG_DCI_ENCODING
445
      printf(" PDCCH Modulation (TX diversity): REG %d\n",i>>2);
446
#endif
447
      // first antenna position n -> x0
448
      ((int16_t*)&y[0][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
449
      e_ptr++;
450
      ((int16_t*)&y[0][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
451
      e_ptr++;
452

453
      // second antenna position n -> -x1*
454
      ((int16_t*)&y[1][i])[0] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? gain_lin_QPSK : -gain_lin_QPSK;
455
      e_ptr++;
456
      ((int16_t*)&y[1][i])[1] = (*e_ptr==2) ? 0 : (*e_ptr == 1) ? -gain_lin_QPSK : gain_lin_QPSK;
457 458 459 460 461 462 463 464 465
      e_ptr++;

      // fill in the rest of the ALAMOUTI precoding
      ((int16_t*)&y[0][i+1])[0] = -((int16_t*)&y[1][i])[0];
      ((int16_t*)&y[0][i+1])[1] = ((int16_t*)&y[1][i])[1];
      ((int16_t*)&y[1][i+1])[0] = ((int16_t*)&y[0][i])[0];
      ((int16_t*)&y[1][i+1])[1] = -((int16_t*)&y[0][i])[1];

    }
466
  }
467
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_MODULATION,0);
468 469 470


#ifdef DEBUG_DCI_ENCODING
471
  printf(" PDCCH Interleaving\n");
472 473
#endif

474
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_INTERLEAVING,1);
475
  //  printf("y %p (%p,%p), wbar %p (%p,%p)\n",y,y[0],y[1],wbar,wbar[0],wbar[1]);
476 477
  // This is the interleaving procedure defined in 36-211, first part of Section 6.8.5
  pdcch_interleaving(frame_parms,&y[0],&wbar[0],num_pdcch_symbols,mi);
478
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_INTERLEAVING,0);
479

480
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_TX,1);
481 482 483 484 485
  mprime=0;
  nsymb = (frame_parms->Ncp==0) ? 14:12;
  re_offset = frame_parms->first_carrier_offset;

  // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5
486
  //  printf("DCI (SF %d) : txdataF %p (0 %p)\n",subframe,&txdataF[0][512*14*subframe],&txdataF[0][0]);
487 488 489 490 491 492 493 494 495 496 497 498
#ifdef DEBUG_DCI_ENCODING
  printf("kprime loop - N_RB_DL:%d lprime:num_pdcch_symbols:%d Ncp:%d pcfich:%02x,%02x,%02x,%02x ofdm_symbol_size:%d first_carrier_offset:%d nb_antenna_ports_eNB:%d\n",
  frame_parms->N_RB_DL, num_pdcch_symbols,frame_parms->Ncp,
  frame_parms->pcfich_reg[0],
  frame_parms->pcfich_reg[1],
  frame_parms->pcfich_reg[2],
  frame_parms->pcfich_reg[3],
  frame_parms->ofdm_symbol_size,
  frame_parms->first_carrier_offset,
  frame_parms->nb_antenna_ports_eNB
  );
#endif
499 500
  for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) {
    for (lprime=0; lprime<num_pdcch_symbols; lprime++) {
501

502
      symbol_offset = (uint32_t)frame_parms->ofdm_symbol_size*(lprime+(subframe*nsymb));
503 504


505

506 507 508 509 510 511 512 513
      tti_offset = symbol_offset + re_offset;

      (re_offset==(frame_parms->ofdm_symbol_size-2)) ? (split_flag=1) : (split_flag=0);

      //            printf("kprime %d, lprime %d => REG %d (symbol %d)\n",kprime,lprime,(lprime==0)?(kprime/6) : (kprime>>2),symbol_offset);
      // if REG is allocated to PHICH, skip it
      if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) {
#ifdef DEBUG_DCI_ENCODING
514
        printf("generate_dci: skipping REG %d (kprime %d, lprime %d)\n",(lprime==0)?(kprime/6) : (kprime>>2),kprime,lprime);
515
#endif
516 517 518 519
      } else {
        // Copy REG to TX buffer

        if ((lprime == 0)||
Xiwen JIANG's avatar
Xiwen JIANG committed
520
            ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4))) {
521 522 523 524 525 526 527 528 529 530 531
          // first symbol, or second symbol+4 TX antennas skip pilots

          kprime_mod12 = kprime%12;

          if ((kprime_mod12 == 0) || (kprime_mod12 == 6)) {
            // kprime represents REG

            for (i=0; i<6; i++) {
              if ((i!=(nushiftmod3))&&(i!=(nushiftmod3+3))) {
                txdataF[0][tti_offset+i] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
532
                if (frame_parms->nb_antenna_ports_eNB > 1)
533 534
                  txdataF[1][tti_offset+i] = wbar[1][mprime];

535
#ifdef DEBUG_DCI_ENCODING
536
                printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime]));
537
#endif
538

539 540 541 542 543 544 545 546 547 548 549 550 551
                mprime++;
              }
            }
          }
        } else { // no pilots in this symbol
          kprime_mod12 = kprime%12;

          if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) {
            // kprime represents REG
            if (split_flag==0) {
              for (i=0; i<4; i++) {
                txdataF[0][tti_offset+i] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
552
                if (frame_parms->nb_antenna_ports_eNB > 1)
553 554
                  txdataF[1][tti_offset+i] = wbar[1][mprime];

555
#ifdef DEBUG_DCI_ENCODING
556
                LOG_I(PHY," PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+i,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime]));
557
#endif
558 559 560 561 562
                mprime++;
              }
            } else {
              txdataF[0][tti_offset+0] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
563
              if (frame_parms->nb_antenna_ports_eNB > 1)
564 565
                txdataF[1][tti_offset+0] = wbar[1][mprime];

566
#ifdef DEBUG_DCI_ENCODING
567
              printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime]));
568
#endif
569 570 571
              mprime++;
              txdataF[0][tti_offset+1] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
572
              if (frame_parms->nb_antenna_ports_eNB > 1)
573 574
                txdataF[1][tti_offset+1] = wbar[1][mprime];

575
#ifdef DEBUG_DCI_ENCODING
576
              printf("PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset+1,*(short*)&wbar[0][mprime],*(1+(short*)&wbar[0][mprime]));
577
#endif
578 579 580
              mprime++;
              txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
581
              if (frame_parms->nb_antenna_ports_eNB > 1)
582 583
                txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+3] = wbar[1][mprime];

584
#ifdef DEBUG_DCI_ENCODING
585
              printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+3,*(short*)&wbar[0][mprime],
586
                    *(1+(short*)&wbar[0][mprime]));
587
#endif
588 589 590
              mprime++;
              txdataF[0][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[0][mprime];

Xiwen JIANG's avatar
Xiwen JIANG committed
591
              if (frame_parms->nb_antenna_ports_eNB > 1)
592 593
                txdataF[1][tti_offset-frame_parms->ofdm_symbol_size+4] = wbar[1][mprime];

594
#ifdef DEBUG_DCI_ENCODING
595
              printf(" PDCCH mapping mprime %d => %d (symbol %d re %d) -> (%d,%d)\n",mprime,tti_offset,symbol_offset,re_offset-frame_parms->ofdm_symbol_size+4,*(short*)&wbar[0][mprime],
596
                    *(1+(short*)&wbar[0][mprime]));
597
#endif
598 599 600 601 602
              mprime++;

            }
          }
        }
603

604 605
        if (mprime>=Msymb2)
          return(num_pdcch_symbols);
606
      } // check_phich_reg
607

608
    } //lprime loop
609

610
    re_offset++;
611

612 613 614
    if (re_offset == (frame_parms->ofdm_symbol_size))
      re_offset = 1;
  } // kprime loop
615
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_TX,0);
616

617 618 619 620
  return(num_pdcch_symbols);
}