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

/*! \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
*/
#ifdef USER_MODE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#endif
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
40
#include "SIMULATION/TOOLS/defs.h" // for taus 
41
#include "PHY/sse_intrin.h"
42

43
#include "assertions.h" 
Bilel's avatar
Bilel committed
44
#include "T.h"
45
#include "UTIL/LOG/log.h"
46 47 48 49

//#define DEBUG_DCI_ENCODING 1
//#define DEBUG_DCI_DECODING 1
//#define DEBUG_PHY
50

51 52
//#undef ALL_AGGREGATION

gauthier's avatar
gauthier committed
53 54
//extern uint16_t phich_reg[MAX_NUM_PHICH_GROUPS][3];
//extern uint16_t pcfich_reg[4];
55

56 57
uint32_t check_phich_reg(LTE_DL_FRAME_PARMS *frame_parms,uint32_t kprime,uint8_t lprime,uint8_t mi)
{
58

gauthier's avatar
gauthier committed
59 60 61 62
  uint16_t i;
  uint16_t Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48;
  uint16_t mprime;
  uint16_t *pcfich_reg = frame_parms->pcfich_reg;
63 64 65 66 67 68 69 70

  if ((lprime>0) && (frame_parms->Ncp==0) )
    return(0);

  //  printf("check_phich_reg : mi %d\n",mi);

  // compute REG based on symbol
  if ((lprime == 0)||
Xiwen JIANG's avatar
Xiwen JIANG committed
71
      ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)))
72 73 74 75 76
    mprime = kprime/6;
  else
    mprime = kprime>>2;

  // check if PCFICH uses mprime
77
  if ((lprime==0) &&
78 79 80 81 82
      ((mprime == pcfich_reg[0]) ||
       (mprime == pcfich_reg[1]) ||
       (mprime == pcfich_reg[2]) ||
       (mprime == pcfich_reg[3]))) {
#ifdef DEBUG_DCI_ENCODING
83
    printf("[PHY] REG %d allocated to PCFICH\n",mprime);
84 85 86 87 88 89 90 91 92 93
#endif
    return(1);
  }

  // handle Special subframe case for TDD !!!

  //  printf("Checking phich_reg %d\n",mprime);
  if (mi > 0) {
    if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0)
      Ngroup_PHICH++;
94

95 96 97
    if (frame_parms->Ncp == 1) {
      Ngroup_PHICH<<=1;
    }
98 99 100 101 102 103 104



    for (i=0; i<Ngroup_PHICH; i++) {
      if ((mprime == frame_parms->phich_reg[i][0]) ||
          (mprime == frame_parms->phich_reg[i][1]) ||
          (mprime == frame_parms->phich_reg[i][2]))  {
105
#ifdef DEBUG_DCI_ENCODING
106
        printf("[PHY] REG %d (lprime %d) allocated to PHICH\n",mprime,lprime);
107
#endif
108
        return(1);
109 110 111
      }
    }
  }
112

113 114 115
  return(0);
}

116 117
uint16_t extract_crc(uint8_t *dci,uint8_t dci_len)
{
118

gauthier's avatar
gauthier committed
119 120
  uint16_t crc16;
  //  uint8_t i;
121 122

  /*
gauthier's avatar
gauthier committed
123 124
  uint8_t crc;
  crc = ((uint16_t *)dci)[DCI_LENGTH>>4];
125 126 127
  printf("crc1: %x, shift %d (DCI_LENGTH %d)\n",crc,DCI_LENGTH&0xf,DCI_LENGTH);
  crc = (crc>>(DCI_LENGTH&0xf));
  // clear crc bits
gauthier's avatar
gauthier committed
128 129 130
  ((uint16_t *)dci)[DCI_LENGTH>>4] &= (0xffff>>(16-(DCI_LENGTH&0xf)));
  printf("crc2: %x, dci0 %x\n",crc,((int16_t *)dci)[DCI_LENGTH>>4]);
  crc |= (((uint16_t *)dci)[1+(DCI_LENGTH>>4)])<<(16-(DCI_LENGTH&0xf));
131
  // clear crc bits
gauthier's avatar
gauthier committed
132
  (((uint16_t *)dci)[1+(DCI_LENGTH>>4)]) = 0;
133 134
  printf("extract_crc: crc %x\n",crc);
  */
135
#ifdef DEBUG_DCI_DECODING
136
  LOG_I(PHY,"dci_crc (%x,%x,%x), dci_len&0x7=%d\n",dci[dci_len>>3],dci[1+(dci_len>>3)],dci[2+(dci_len>>3)],
137
      dci_len&0x7);
138
#endif
139

140
  if ((dci_len&0x7) > 0) {
gauthier's avatar
gauthier committed
141 142
    ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)]<<(dci_len&0x7) | dci[2+(dci_len>>3)]>>(8-(dci_len&0x7));
    ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)]<<(dci_len&0x7) | dci[1+(dci_len>>3)]>>(8-(dci_len&0x7));
143
  } else {
gauthier's avatar
gauthier committed
144 145
    ((uint8_t *)&crc16)[0] = dci[1+(dci_len>>3)];
    ((uint8_t *)&crc16)[1] = dci[(dci_len>>3)];
146 147
  }

148
#ifdef DEBUG_DCI_DECODING
149
  LOG_I(PHY,"dci_crc =>%x\n",crc16);
150 151 152 153 154
#endif

  //  dci[(dci_len>>3)]&=(0xffff<<(dci_len&0xf));
  //  dci[(dci_len>>3)+1] = 0;
  //  dci[(dci_len>>3)+2] = 0;
gauthier's avatar
gauthier committed
155
  return((uint16_t)crc16);
156
  
157 158 159 160
}



gauthier's avatar
gauthier committed
161 162
static uint8_t d[3*(MAX_DCI_SIZE_BITS + 16) + 96];
static uint8_t w[3*3*(MAX_DCI_SIZE_BITS+16)];
163

gauthier's avatar
gauthier committed
164
void dci_encoding(uint8_t *a,
165 166 167 168 169
                  uint8_t A,
                  uint16_t E,
                  uint8_t *e,
                  uint16_t rnti)
{
170 171


gauthier's avatar
gauthier committed
172 173
  uint8_t D = (A + 16);
  uint32_t RCC;
174 175

#ifdef DEBUG_DCI_ENCODING
gauthier's avatar
gauthier committed
176
  int32_t i;
177
#endif
178
  // encode dci
179 180

#ifdef DEBUG_DCI_ENCODING
181
  printf("Doing DCI encoding for %d bits, e %p, rnti %x\n",A,e,rnti);
182 183 184 185 186 187 188
#endif

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

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

#ifdef DEBUG_DCI_ENCODING
189 190

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

193
#endif
194

195
#ifdef DEBUG_DCI_ENCODING
196
  printf("Doing DCI interleaving for %d coded bits, e %p\n",D*3,e);
197 198 199 200
#endif
  RCC = sub_block_interleaving_cc(D,d+96,w);

#ifdef DEBUG_DCI_ENCODING
201
  printf("Doing DCI rate matching for %d channel bits, RCC %d, e %p\n",E,RCC,e);
202 203 204 205 206 207 208
#endif
  lte_rate_matching_cc(RCC,E,w,e);


}


gauthier's avatar
gauthier committed
209
uint8_t *generate_dci0(uint8_t *dci,
210 211 212 213 214 215
                       uint8_t *e,
                       uint8_t DCI_LENGTH,
                       uint8_t aggregation_level,
                       uint16_t rnti)
{

gauthier's avatar
gauthier committed
216 217
  uint16_t coded_bits;
  uint8_t dci_flip[8];
218 219

  if (aggregation_level>3) {
220
    printf("dci.c: generate_dci FATAL, illegal aggregation_level %d\n",aggregation_level);
221 222 223 224 225
    return NULL;
  }

  coded_bits = 72 * (1<<aggregation_level);

226 227 228
  /*

  #ifdef DEBUG_DCI_ENCODING
229
  for (i=0;i<1+((DCI_LENGTH+16)/8);i++)
230
    printf("i %d : %x\n",i,dci[i]);
231
  #endif
232
  */
233
  if (DCI_LENGTH<=32) {
234 235 236
    dci_flip[0] = dci[3];
    dci_flip[1] = dci[2];
    dci_flip[2] = dci[1];
237 238
    dci_flip[3] = dci[0];
  } else {
239 240 241 242 243 244 245 246
    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];
247
#ifdef DEBUG_DCI_ENCODING
248
    printf("DCI => %x,%x,%x,%x,%x,%x,%x,%x\n",
249 250
        dci_flip[0],dci_flip[1],dci_flip[2],dci_flip[3],
        dci_flip[4],dci_flip[5],dci_flip[6],dci_flip[7]);
251
#endif
252
  }
253

254 255 256 257 258
  dci_encoding(dci_flip,DCI_LENGTH,coded_bits,e,rnti);

  return(e+coded_bits);
}

gauthier's avatar
gauthier committed
259
uint32_t Y;
260 261 262 263 264 265 266 267

#define CCEBITS 72
#define CCEPERSYMBOL 33  // This is for 1200 RE
#define CCEPERSYMBOL0 22  // This is for 1200 RE
#define DCI_BITS_MAX ((2*CCEPERSYMBOL+CCEPERSYMBOL0)*CCEBITS)
#define Msymb (DCI_BITS_MAX/2)
//#define Mquad (Msymb/4)

gauthier's avatar
gauthier committed
268
static uint32_t bitrev_cc_dci[32] = {1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30};
269
static int32_t wtemp[2][Msymb];
270

271
void pdcch_interleaving(LTE_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi)
272
{
273

274
  int32_t *wptr,*wptr2,*zptr;
gauthier's avatar
gauthier committed
275 276 277 278
  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;
279
#ifdef RM_DEBUG
gauthier's avatar
gauthier committed
280
  int32_t nulled=0;
281
#endif
282

283
  //  printf("[PHY] PDCCH Interleaving Mquad %d (Nsymb %d)\n",Mquad,n_symbols_pdcch);
284 285
  if ((Mquad&0x1f) > 0)
    RCC++;
286

287 288 289 290
  Kpi = (RCC<<5);
  ND = Kpi - Mquad;

  k=0;
291 292

  for (col=0; col<32; col++) {
293 294
    index = bitrev_cc_dci[col];

295
    for (row=0; row<RCC; row++) {
296
      //printf("col %d, index %d, row %d\n",col,index,row);
297
      if (index>=ND) {
Xiwen JIANG's avatar
Xiwen JIANG committed
298
        for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
299
          //printf("a %d k %d\n",a,k);
300 301 302

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

304
          //printf("wptr=%p, zptr=%p\n",wptr,zptr);
305

306 307 308 309 310
          wptr[0] = zptr[0];
          wptr[1] = zptr[1];
          wptr[2] = zptr[2];
          wptr[3] = zptr[3];
        }
311

312
        k++;
313
      }
314

315 316 317 318 319
      index+=32;
    }
  }

  // permutation
320 321
  for (i=0; i<Mquad; i++) {

Xiwen JIANG's avatar
Xiwen JIANG committed
322
    for (a=0; a<frame_parms->nb_antenna_ports_eNB; a++) {
323 324 325 326 327 328 329 330 331 332 333 334 335

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

336 337
void pdcch_demapping(uint16_t *llr,uint16_t *wbar,LTE_DL_FRAME_PARMS *frame_parms,uint8_t num_pdcch_symbols,uint8_t mi)
{
338

gauthier's avatar
gauthier committed
339 340 341
  uint32_t i, lprime;
  uint16_t kprime,kprime_mod12,mprime,symbol_offset,tti_offset,tti_offset0;
  int16_t re_offset,re_offset0;
342 343 344 345 346 347 348 349 350

  // This is the REG allocation algorithm from 36-211, second part of Section 6.8.5

  int Msymb2;

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

352 353 354
  case 75:
    Msymb2 = 3*Msymb/4;
    break;
355

356 357 358
  case 50:
    Msymb2 = Msymb>>1;
    break;
359

360 361 362
  case 25:
    Msymb2 = Msymb>>2;
    break;
363

364 365 366
  case 15:
    Msymb2 = Msymb*15/100;
    break;
367

368 369 370
  case 6:
    Msymb2 = Msymb*6/100;
    break;
371

372 373 374 375
  default:
    Msymb2 = Msymb>>2;
    break;
  }
376

377 378 379 380 381
  mprime=0;


  re_offset = 0;
  re_offset0 = 0; // counter for symbol with pilots (extracted outside!)
382 383 384

  for (kprime=0; kprime<frame_parms->N_RB_DL*12; kprime++) {
    for (lprime=0; lprime<num_pdcch_symbols; lprime++) {
385

gauthier's avatar
gauthier committed
386
      symbol_offset = (uint32_t)frame_parms->N_RB_DL*12*lprime;
387

388 389
      tti_offset = symbol_offset + re_offset;
      tti_offset0 = symbol_offset + re_offset0;
390

391 392
      // if REG is allocated to PHICH, skip it
      if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) {
393 394 395
	//        printf("dci_demapping : skipping REG %d (RE %d)\n",(lprime==0)?kprime/6 : kprime>>2,kprime);
	if ((lprime == 0)&&((kprime%6)==0))
	  re_offset0+=4;
396
      } else { // not allocated to PHICH/PCFICH
397
	//        printf("dci_demapping: REG %d\n",(lprime==0)?kprime/6 : kprime>>2);
398 399 400 401 402 403 404 405 406
        if (lprime == 0) {
          // 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<4; i++) {
              wbar[mprime] = llr[tti_offset0+i];
407
#ifdef DEBUG_DCI_DECODING
Wilson's avatar
Wilson committed
408
              LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset0+i,symbol_offset,re_offset0,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime]));
409
#endif
410 411 412 413
              mprime++;
              re_offset0++;
            }
          }
Xiwen JIANG's avatar
Xiwen JIANG committed
414
        } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) {
415 416 417 418 419 420 421 422
          // LATER!!!!
        } else { // no pilots in this symbol
          kprime_mod12 = kprime%12;

          if ((kprime_mod12 == 0) || (kprime_mod12 == 4) || (kprime_mod12 == 8)) {
            // kprime represents REG
            for (i=0; i<4; i++) {
              wbar[mprime] = llr[tti_offset+i];
423
#ifdef DEBUG_DCI_DECODING
Wilson's avatar
Wilson committed
424
              LOG_I(PHY,"PDCCH demapping mprime %d.%d <= llr %d (symbol %d re %d) -> (%d,%d)\n",mprime/4,i,tti_offset+i,symbol_offset,re_offset+i,*(char*)&wbar[mprime],*(1+(char*)&wbar[mprime]));
425
#endif
426 427 428 429
              mprime++;
            }
          }  // is representative
        } // no pilots case
430 431 432 433
      } // not allocated to PHICH/PCFICH

      // Stop when all REGs are copied in
      if (mprime>=Msymb2)
434
        break;
435
    } //lprime loop
436

437 438 439 440 441
    re_offset++;

  } // kprime loop
}

gauthier's avatar
gauthier committed
442
static uint16_t wtemp_rx[Msymb];
443 444
void pdcch_deinterleaving(LTE_DL_FRAME_PARMS *frame_parms,uint16_t *z, uint16_t *wbar,uint8_t number_pdcch_symbols,uint8_t mi)
{
445

gauthier's avatar
gauthier committed
446
  uint16_t *wptr,*zptr,*wptr2;
447

gauthier's avatar
gauthier committed
448 449 450 451
  uint16_t Mquad=get_nquad(number_pdcch_symbols,frame_parms,mi);
  uint32_t RCC = (Mquad>>5), ND;
  uint32_t row,col,Kpi,index;
  int32_t i,k;
452 453 454 455


  //  printf("Mquad %d, RCC %d\n",Mquad,RCC);

456
  AssertFatal(z!=NULL,"dci.c: pdcch_deinterleaving: FATAL z is Null\n");
457

458
  // undo permutation
459
  for (i=0; i<Mquad; i++) {
460 461 462 463 464 465 466
    wptr = &wtemp_rx[((i+frame_parms->Nid_cell)%Mquad)<<2];
    wptr2 = &wbar[i<<2];

    wptr[0] = wptr2[0];
    wptr[1] = wptr2[1];
    wptr[2] = wptr2[2];
    wptr[3] = wptr2[3];
467 468 469 470 471 472 473 474 475 476
    /*    
    printf("pdcch_deinterleaving (%p,%p): quad %d (%d) -> (%d,%d %d,%d %d,%d %d,%d)\n",wptr,wptr2,i,(i+frame_parms->Nid_cell)%Mquad,
	   ((char*)wptr2)[0],
	   ((char*)wptr2)[1],
	   ((char*)wptr2)[2],
	   ((char*)wptr2)[3],
	   ((char*)wptr2)[4],
	   ((char*)wptr2)[5],
	   ((char*)wptr2)[6],
	   ((char*)wptr2)[7]);
477
    */
478 479 480 481 482

  }

  if ((Mquad&0x1f) > 0)
    RCC++;
483

484 485 486 487
  Kpi = (RCC<<5);
  ND = Kpi - Mquad;

  k=0;
488 489

  for (col=0; col<32; col++) {
490 491
    index = bitrev_cc_dci[col];

492
    for (row=0; row<RCC; row++) {
493 494 495 496 497
      //      printf("row %d, index %d, Nd %d\n",row,index,ND);
      if (index>=ND) {



498 499 500 501 502 503 504 505
        wptr = &wtemp_rx[k<<2];
        zptr = &z[(index-ND)<<2];

        zptr[0] = wptr[0];
        zptr[1] = wptr[1];
        zptr[2] = wptr[2];
        zptr[3] = wptr[3];

506
	/*        
507 508 509 510 511 512 513 514 515
        printf("deinterleaving ; k %d, index-Nd %d  => (%d,%d,%d,%d,%d,%d,%d,%d)\n",k,(index-ND),
               ((int8_t *)wptr)[0],
               ((int8_t *)wptr)[1],
               ((int8_t *)wptr)[2],
               ((int8_t *)wptr)[3],
               ((int8_t *)wptr)[4],
               ((int8_t *)wptr)[5],
               ((int8_t *)wptr)[6],
               ((int8_t *)wptr)[7]);
516
	*/
517
        k++;
518
      }
519

520
      index+=32;
521

522 523 524
    }
  }

525
  for (i=0; i<Mquad; i++) {
526
    zptr = &z[i<<2];
527
    /*    
528
    printf("deinterleaving ; quad %d  => (%d,%d,%d,%d,%d,%d,%d,%d)\n",i,
529 530 531 532 533 534 535 536
     ((int8_t *)zptr)[0],
     ((int8_t *)zptr)[1],
     ((int8_t *)zptr)[2],
     ((int8_t *)zptr)[3],
     ((int8_t *)zptr)[4],
     ((int8_t *)zptr)[5],
     ((int8_t *)zptr)[6],
     ((int8_t *)zptr)[7]);
537
    */  
538
  }
539

540 541 542
}


gauthier's avatar
gauthier committed
543
int32_t pdcch_qpsk_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms,
544 545 546 547 548 549 550
                            int32_t **rxdataF_comp,
                            int32_t **rxdataF_comp_i,
                            int32_t **rho_i,
                            int16_t *pdcch_llr16,
                            int16_t *pdcch_llr8in,
                            uint8_t symbol)
{
551

552 553 554 555
  int16_t *rxF=(int16_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
  int16_t *rxF_i=(int16_t*)&rxdataF_comp_i[0][(symbol*frame_parms->N_RB_DL*12)];
  int16_t *rho=(int16_t*)&rho_i[0][(symbol*frame_parms->N_RB_DL*12)];
  int16_t *llr128;
gauthier's avatar
gauthier committed
556
  int32_t i;
557
  char *pdcch_llr8;
gauthier's avatar
gauthier committed
558
  int16_t *pdcch_llr;
559 560 561 562
  pdcch_llr8 = (char *)&pdcch_llr8in[symbol*frame_parms->N_RB_DL*12];
  pdcch_llr = &pdcch_llr16[symbol*frame_parms->N_RB_DL*12];

  //  printf("dlsch_qpsk_qpsk: symbol %d\n",symbol);
563

564
  llr128 = (int16_t*)pdcch_llr;
565 566

  if (!llr128) {
567
    printf("dlsch_qpsk_qpsk_llr: llr is null, symbol %d\n",symbol);
568 569 570
    return -1;
  }

571 572 573 574
  qpsk_qpsk(rxF,
            rxF_i,
            llr128,
            rho,
575
            frame_parms->N_RB_DL*12);
576 577

  //prepare for Viterbi which accepts 8 bit, but prefers 4 bit, soft input.
578
  for (i=0; i<(frame_parms->N_RB_DL*24); i++) {
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
    if (*pdcch_llr>7)
      *pdcch_llr8=7;
    else if (*pdcch_llr<-8)
      *pdcch_llr8=-8;
    else
      *pdcch_llr8 = (char)(*pdcch_llr);

    pdcch_llr++;
    pdcch_llr8++;
  }

  return(0);
}


gauthier's avatar
gauthier committed
594
int32_t pdcch_llr(LTE_DL_FRAME_PARMS *frame_parms,
595 596 597 598
                  int32_t **rxdataF_comp,
                  char *pdcch_llr,
                  uint8_t symbol)
{
599

gauthier's avatar
gauthier committed
600 601
  int16_t *rxF= (int16_t*) &rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
  int32_t i;
602 603 604
  char *pdcch_llr8;

  pdcch_llr8 = &pdcch_llr[2*symbol*frame_parms->N_RB_DL*12];
605

606
  if (!pdcch_llr8) {
607
    printf("pdcch_qpsk_llr: llr is null, symbol %d\n",symbol);
608 609
    return(-1);
  }
610

611
  //    printf("pdcch qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),pdcch_llr8-pdcch_llr);
612

613
  for (i=0; i<(frame_parms->N_RB_DL*((symbol==0) ? 16 : 24)); i++) {
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630

    if (*rxF>31)
      *pdcch_llr8=31;
    else if (*rxF<-32)
      *pdcch_llr8=-32;
    else
      *pdcch_llr8 = (char)(*rxF);

    //    printf("%d %d => %d\n",i,*rxF,*pdcch_llr8);
    rxF++;
    pdcch_llr8++;
  }

  return(0);

}

631
//__m128i avg128P;
632 633

//compute average channel_level on each (TX,RX) antenna pair
gauthier's avatar
gauthier committed
634
void pdcch_channel_level(int32_t **dl_ch_estimates_ext,
635 636 637 638
                         LTE_DL_FRAME_PARMS *frame_parms,
                         int32_t *avg,
                         uint8_t nb_rb)
{
639

gauthier's avatar
gauthier committed
640 641
  int16_t rb;
  uint8_t aatx,aarx;
642
#if defined(__x86_64__) || defined(__i386__)
643
  __m128i *dl_ch128;
644 645 646 647 648
  __m128i avg128P;
#elif defined(__arm__)
  int16x8_t *dl_ch128;
  int32x4_t *avg128P;
#endif
Xiwen JIANG's avatar
Xiwen JIANG committed
649
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++)
650
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
651
      //clear average level
652
#if defined(__x86_64__) || defined(__i386__)
653
      avg128P = _mm_setzero_si128();
654
      dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][frame_parms->N_RB_DL*12];
655
#elif defined(__arm__)
656

657
#endif
658 659
      for (rb=0; rb<nb_rb; rb++) {

660
#if defined(__x86_64__) || defined(__i386__)
661 662 663
        avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
        avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
        avg128P = _mm_add_epi32(avg128P,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
664
#elif defined(__arm__)
665

666
#endif
667 668 669 670 671 672 673 674
        dl_ch128+=3;
        /*
          if (rb==0) {
          print_shorts("dl_ch128",&dl_ch128[0]);
          print_shorts("dl_ch128",&dl_ch128[1]);
          print_shorts("dl_ch128",&dl_ch128[2]);
          }
        */
675 676
      }

677
      DevAssert( nb_rb );
678 679 680 681
      avg[(aatx<<1)+aarx] = (((int32_t*)&avg128P)[0] +
                             ((int32_t*)&avg128P)[1] +
                             ((int32_t*)&avg128P)[2] +
                             ((int32_t*)&avg128P)[3])/(nb_rb*12);
682

683
      //            printf("Channel level : %d\n",avg[(aatx<<1)+aarx]);
684
    }
685

686
#if defined(__x86_64__) || defined(__i386__)
687 688
  _mm_empty();
  _m_empty();
689
#endif
690 691 692

}

693
#if defined(__x86_64) || defined(__i386__)
694
__m128i mmtmpPD0,mmtmpPD1,mmtmpPD2,mmtmpPD3;
695
#elif defined(__arm__)
696

697
#endif
698
void pdcch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms,
699 700 701 702 703 704
                                   uint8_t symbol,
                                   int32_t **dl_ch_estimates_ext,
                                   int32_t **dl_ch_estimates_ext_i,
                                   int32_t **dl_ch_rho_ext,
                                   uint8_t output_shift)
{
705

gauthier's avatar
gauthier committed
706
  uint16_t rb;
707
#if defined(__x86_64__) || defined(__i386__)
708
  __m128i *dl_ch128,*dl_ch128i,*dl_ch_rho128;
709 710 711
#elif defined(__arm__)

#endif
gauthier's avatar
gauthier committed
712
  uint8_t aarx;
713 714 715 716

  //  printf("dlsch_dual_stream_correlation: symbol %d\n",symbol);


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

719
#if defined(__x86_64__) || defined(__i386__)
720 721 722 723
    dl_ch128          = (__m128i *)&dl_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
    dl_ch128i         = (__m128i *)&dl_ch_estimates_ext_i[aarx][symbol*frame_parms->N_RB_DL*12];
    dl_ch_rho128      = (__m128i *)&dl_ch_rho_ext[aarx][symbol*frame_parms->N_RB_DL*12];

724 725 726
#elif defined(__arm__)

#endif
727

728
    for (rb=0; rb<frame_parms->N_RB_DL; rb++) {
729
      // multiply by conjugated channel
730
#if defined(__x86_64__) || defined(__i386__)
731
      mmtmpPD0 = _mm_madd_epi16(dl_ch128[0],dl_ch128i[0]);
732 733
      //  print_ints("re",&mmtmpPD0);

734 735 736 737
      // mmtmpD0 contains real part of 4 consecutive outputs (32-bit)
      mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)&conjugate[0]);
738
      //  print_ints("im",&mmtmpPD1);
739 740 741
      mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[0]);
      // mmtmpD1 contains imag part of 4 consecutive outputs (32-bit)
      mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift);
742
      //  print_ints("re(shift)",&mmtmpPD0);
743
      mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift);
744
      //  print_ints("im(shift)",&mmtmpPD1);
745 746
      mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1);
      mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1);
747 748
      //        print_ints("c0",&mmtmpPD2);
      //  print_ints("c1",&mmtmpPD3);
749
      dl_ch_rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3);
750

751 752 753
      //print_shorts("rx:",dl_ch128_2);
      //print_shorts("ch:",dl_ch128);
      //print_shorts("pack:",rho128);
754

755 756 757 758 759 760 761 762 763 764 765 766
      // multiply by conjugated channel
      mmtmpPD0 = _mm_madd_epi16(dl_ch128[1],dl_ch128i[1]);
      // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit)
      mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate);
      mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[1]);
      // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit)
      mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift);
      mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift);
      mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1);
      mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1);
767 768


769 770 771
      dl_ch_rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3);
      //print_shorts("rx:",dl_ch128_2+1);
      //print_shorts("ch:",dl_ch128+1);
772
      //print_shorts("pack:",rho128+1);
773 774 775 776 777 778 779 780 781 782 783 784
      // multiply by conjugated channel
      mmtmpPD0 = _mm_madd_epi16(dl_ch128[2],dl_ch128i[2]);
      // mmtmpPD0 contains real part of 4 consecutive outputs (32-bit)
      mmtmpPD1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_shufflehi_epi16(mmtmpPD1,_MM_SHUFFLE(2,3,0,1));
      mmtmpPD1 = _mm_sign_epi16(mmtmpPD1,*(__m128i*)conjugate);
      mmtmpPD1 = _mm_madd_epi16(mmtmpPD1,dl_ch128i[2]);
      // mmtmpPD1 contains imag part of 4 consecutive outputs (32-bit)
      mmtmpPD0 = _mm_srai_epi32(mmtmpPD0,output_shift);
      mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift);
      mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1);
      mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1);
785

786 787 788 789
      dl_ch_rho128[2] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3);
      //print_shorts("rx:",dl_ch128_2+2);
      //print_shorts("ch:",dl_ch128+2);
      //print_shorts("pack:",rho128+2);
790

791 792 793
      dl_ch128+=3;
      dl_ch128i+=3;
      dl_ch_rho128+=3;
794 795


796
#elif defined(__arm__)
797

798 799 800 801
#endif
     }
  }
#if defined(__x86_64__) || defined(__i386__)
802 803
  _mm_empty();
  _m_empty();
804
#endif
805

806 807 808 809
}


void pdcch_detection_mrc_i(LTE_DL_FRAME_PARMS *frame_parms,
810 811 812 813 814 815
                           int32_t **rxdataF_comp,
                           int32_t **rxdataF_comp_i,
                           int32_t **rho,
                           int32_t **rho_i,
                           uint8_t symbol)
{
816

gauthier's avatar
gauthier committed
817
  uint8_t aatx;
818

819
#if defined(__x86_64__) || defined(__i386__)
820
  __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1;
821 822 823
#elif defined(__arm__)
  int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1;
#endif
gauthier's avatar
gauthier committed
824
  int32_t i;
825 826

  if (frame_parms->nb_antennas_rx>1) {
Xiwen JIANG's avatar
Xiwen JIANG committed
827
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB; aatx++) {
828 829
      //if (frame_parms->mode1_flag && (aatx>0)) break;

830
#if defined(__x86_64__) || defined(__i386__)
831
      rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
832
      rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
833 834 835 836
#elif defined(__arm__)
      rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol*frame_parms->N_RB_DL*12];
      rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol*frame_parms->N_RB_DL*12];
#endif
837
      // MRC on each re of rb on MF output
838
      for (i=0; i<frame_parms->N_RB_DL*3; i++) {
839
#if defined(__x86_64__) || defined(__i386__)
840
        rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
841 842 843
#elif defined(__arm__)
        rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
#endif
844 845
      }
    }
846

847
#if defined(__x86_64__) || defined(__i386__)
848 849
    rho128_0 = (__m128i *) &rho[0][symbol*frame_parms->N_RB_DL*12];
    rho128_1 = (__m128i *) &rho[1][symbol*frame_parms->N_RB_DL*12];
850 851 852 853
#elif defined(__arm__)
    rho128_0 = (int16x8_t *) &rho[0][symbol*frame_parms->N_RB_DL*12];
    rho128_1 = (int16x8_t *) &rho[1][symbol*frame_parms->N_RB_DL*12];
#endif
854
    for (i=0; i<frame_parms->N_RB_DL*3; i++) {
855
#if defined(__x86_64__) || defined(__i386__)
856
      rho128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rho128_0[i],1),_mm_srai_epi16(rho128_1[i],1));
857 858 859
#elif defined(__arm__)
      rho128_0[i] = vhaddq_s16(rho128_0[i],rho128_1[i]);
#endif
860
    }
861

862
#if defined(__x86_64__) || defined(__i386__)
863 864
    rho128_i0 = (__m128i *) &rho_i[0][symbol*frame_parms->N_RB_DL*12];
    rho128_i1 = (__m128i *) &rho_i[1][symbol*frame_parms->N_RB_DL*12];
865
    rxdataF_comp128_i0   = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12];
866
    rxdataF_comp128_i1   = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12];
867 868 869 870 871
#elif defined(__arm__)
    rho128_i0 = (int16x8_t*) &rho_i[0][symbol*frame_parms->N_RB_DL*12];
    rho128_i1 = (int16x8_t*) &rho_i[1][symbol*frame_parms->N_RB_DL*12];
    rxdataF_comp128_i0   = (int16x8_t *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12];
    rxdataF_comp128_i1   = (int16x8_t *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12];
872

873
#endif
874 875
    // MRC on each re of rb on MF and rho
    for (i=0; i<frame_parms->N_RB_DL*3; i++) {
876
#if defined(__x86_64__) || defined(__i386__)
877 878
      rxdataF_comp128_i0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_i0[i],1),_mm_srai_epi16(rxdataF_comp128_i1[i],1));
      rho128_i0[i]          = _mm_adds_epi16(_mm_srai_epi16(rho128_i0[i],1),_mm_srai_epi16(rho128_i1[i],1));
879 880 881 882 883
#elif defined(__arm__)
      rxdataF_comp128_i0[i] = vhaddq_s16(rxdataF_comp128_i0[i],rxdataF_comp128_i1[i]);
      rho128_i0[i]          = vhaddq_s16(rho128_i0[i],rho128_i1[i]);

#endif
884 885
    }
  }
886

887
#if defined(__x86_64__) || defined(__i386__)
888 889
  _mm_empty();
  _m_empty();
890
#endif
891 892 893
}


gauthier's avatar
gauthier committed
894
void pdcch_extract_rbs_single(int32_t **rxdataF,
895 896 897 898 899 900 901
                              int32_t **dl_ch_estimates,
                              int32_t **rxdataF_ext,
                              int32_t **dl_ch_estimates_ext,
                              uint8_t symbol,
                              uint32_t high_speed_flag,
                              LTE_DL_FRAME_PARMS *frame_parms)
{
902 903


gauthier's avatar
gauthier committed
904 905 906
  uint16_t rb,nb_rb=0;
  uint8_t i,j,aarx;
  int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
907

908 909

  int nushiftmod3 = frame_parms->nushift%3;
gauthier's avatar
gauthier committed
910
  uint8_t symbol_mod;
911 912 913

  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
#ifdef DEBUG_DCI_DECODING
914
  LOG_I(PHY, "extract_rbs_single: symbol_mod %d\n",symbol_mod);
915
#endif
916 917

  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
918 919 920 921 922

    if (high_speed_flag == 1)
      dl_ch0     = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))];
    else
      dl_ch0     = &dl_ch_estimates[aarx][5];
923

924 925 926 927 928
    dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];

    rxF_ext   = &rxdataF_ext[aarx][symbol*(frame_parms->N_RB_DL*12)];

    rxF       = &rxdataF[aarx][(frame_parms->first_carrier_offset + (symbol*(frame_parms->ofdm_symbol_size)))];
knopp's avatar
 
knopp committed
929

930
    if ((frame_parms->N_RB_DL&1) == 0)  { // even number of RBs
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
      for (rb=0; rb<frame_parms->N_RB_DL; rb++) {

        // For second half of RBs skip DC carrier
        if (rb==(frame_parms->N_RB_DL>>1)) {
          rxF       = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];

          //dl_ch0++;
        }

        if (symbol_mod>0) {
          memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int32_t));

          for (i=0; i<12; i++) {

            rxF_ext[i]=rxF[i];

          }

          nb_rb++;
          dl_ch0_ext+=12;
          rxF_ext+=12;

          dl_ch0+=12;
          rxF+=12;
        } else {
          j=0;

          for (i=0; i<12; i++) {
            if ((i!=nushiftmod3) &&
                (i!=(nushiftmod3+3)) &&
                (i!=(nushiftmod3+6)) &&
                (i!=(nushiftmod3+9))) {
              rxF_ext[j]=rxF[i];
              //                        printf("extract rb %d, re %d => (%d,%d)\n",rb,i,*(short *)&rxF_ext[j],*(1+(short*)&rxF_ext[j]));
              dl_ch0_ext[j++]=dl_ch0[i];
              //                printf("ch %d => (%d,%d)\n",i,*(short *)&dl_ch0[i],*(1+(short*)&dl_ch0[i]));
            }
          }

          nb_rb++;
          dl_ch0_ext+=8;
          rxF_ext+=8;

          dl_ch0+=12;
          rxF+=12;
        }
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