dci.c 143 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
46
47
48

//#define DEBUG_DCI_ENCODING 1
//#define DEBUG_DCI_DECODING 1
//#define DEBUG_PHY
49

50
51
//#undef ALL_AGGREGATION

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

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

gauthier's avatar
gauthier committed
58
59
60
61
  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;
62
63
64
65
66
67
68
69

  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
70
      ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)))
71
72
73
74
75
    mprime = kprime/6;
  else
    mprime = kprime>>2;

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

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



    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]))  {
104
#ifdef DEBUG_DCI_ENCODING
105
        printf("[PHY] REG %d (lprime %d) allocated to PHICH\n",mprime,lprime);
106
#endif
107
        return(1);
108
109
110
      }
    }
  }
111

112
113
114
  return(0);
}

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

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

  /*
gauthier's avatar
gauthier committed
122
123
  uint8_t crc;
  crc = ((uint16_t *)dci)[DCI_LENGTH>>4];
124
125
126
  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
127
128
129
  ((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));
130
  // clear crc bits
gauthier's avatar
gauthier committed
131
  (((uint16_t *)dci)[1+(DCI_LENGTH>>4)]) = 0;
132
133
  printf("extract_crc: crc %x\n",crc);
  */
134
#ifdef DEBUG_DCI_DECODING
135
  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)],
136
      dci_len&0x7);
137
#endif
138

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

147
#ifdef DEBUG_DCI_DECODING
148
  LOG_I(PHY,"dci_crc =>%x\n",crc16);
149
150
151
152
153
#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
154
  return((uint16_t)crc16);
155
  
156
157
158
159
}



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

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


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

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

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

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

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

#ifdef DEBUG_DCI_ENCODING
188
189

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

192
#endif
193

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

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


}


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

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

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

  coded_bits = 72 * (1<<aggregation_level);

225
226
227
  /*

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

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

  return(e+coded_bits);
}

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

#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
267
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};
268
static int32_t wtemp[2][Msymb];
269

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

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

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

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

  k=0;
290
291

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

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

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

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

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

311
        k++;
312
      }
313

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

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

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

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

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

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

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

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

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

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

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

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

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

376
377
378
379
380
  mprime=0;


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

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

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

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

390
391
      // if REG is allocated to PHICH, skip it
      if (check_phich_reg(frame_parms,kprime,lprime,mi) == 1) {
392
393
394
	//        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;
395
      } else { // not allocated to PHICH/PCFICH
396
	//        printf("dci_demapping: REG %d\n",(lprime==0)?kprime/6 : kprime>>2);
397
398
399
400
401
402
403
404
405
        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];
406
#ifdef DEBUG_DCI_DECODING
407
//              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]));
408
#endif
409
410
411
412
              mprime++;
              re_offset0++;
            }
          }
Xiwen JIANG's avatar
Xiwen JIANG committed
413
        } else if ((lprime==1)&&(frame_parms->nb_antenna_ports_eNB == 4)) {
414
415
416
417
418
419
420
421
          // 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];
422
#ifdef DEBUG_DCI_DECODING
423
//              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]));
424
#endif
425
426
427
428
              mprime++;
            }
          }  // is representative
        } // no pilots case
429
430
431
432
      } // not allocated to PHICH/PCFICH

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

436
437
438
439
440
    re_offset++;

  } // kprime loop
}

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

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

gauthier's avatar
gauthier committed
447
448
449
450
  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;
451
452
453
454
455


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

  if (!z) {
456
    printf("dci.c: pdcch_deinterleaving: FATAL z is Null\n");
457
458
    return;
  }
459

460
  // undo permutation
461
  for (i=0; i<Mquad; i++) {
462
463
464
465
466
467
468
    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];
469
470
471
472
473
474
475
476
477
478
    /*    
    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]);
479
    */
480
481
482
483
484

  }

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

486
487
488
489
  Kpi = (RCC<<5);
  ND = Kpi - Mquad;

  k=0;
490
491

  for (col=0; col<32; col++) {
492
493
    index = bitrev_cc_dci[col];

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



500
501
502
503
504
505
506
507
        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];

508
	/*        
509
510
511
512
513
514
515
516
517
        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]);
518
	*/
519
        k++;
520
      }
521

522
      index+=32;
523

524
525
526
    }
  }

527
  for (i=0; i<Mquad; i++) {
528
    zptr = &z[i<<2];
529
    /*    
530
    printf("deinterleaving ; quad %d  => (%d,%d,%d,%d,%d,%d,%d,%d)\n",i,
531
532
533
534
535
536
537
538
     ((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]);
539
    */  
540
  }
541

542
543
544
}


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

554
555
556
557
  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
558
  int32_t i;
559
  char *pdcch_llr8;
gauthier's avatar
gauthier committed
560
  int16_t *pdcch_llr;
561
562
563
564
  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);
565

566
  llr128 = (int16_t*)pdcch_llr;
567
568

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

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

  //prepare for Viterbi which accepts 8 bit, but prefers 4 bit, soft input.
580
  for (i=0; i<(frame_parms->N_RB_DL*24); i++) {
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
    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
596
int32_t pdcch_llr(LTE_DL_FRAME_PARMS *frame_parms,
597
598
599
600
                  int32_t **rxdataF_comp,
                  char *pdcch_llr,
                  uint8_t symbol)
{
601

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

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

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

613
  //    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);
614

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

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

}

633
//__m128i avg128P;
634
635

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

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

659
#endif
660
661
      for (rb=0; rb<nb_rb; rb++) {

662
#if defined(__x86_64__) || defined(__i386__)
663
664
665
        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]));
666
#elif defined(__arm__)
667

668
#endif
669
670
671
672
673
674
675
676
        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]);
          }
        */
677
678
      }

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

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

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

}

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

699
#endif
700
void pdcch_dual_stream_correlation(LTE_DL_FRAME_PARMS *frame_parms,
701
702
703
704
705
706
                                   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)
{
707

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

#endif
gauthier's avatar
gauthier committed
714
  uint8_t aarx;
715
716
717
718

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


719
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
720

721
#if defined(__x86_64__) || defined(__i386__)
722
723
724
725
    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];

726
727
728
#elif defined(__arm__)

#endif
729

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

736
737
738
739
      // 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]);
740
      //  print_ints("im",&mmtmpPD1);
741
742
743
      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);
744
      //  print_ints("re(shift)",&mmtmpPD0);
745
      mmtmpPD1 = _mm_srai_epi32(mmtmpPD1,output_shift);
746
      //  print_ints("im(shift)",&mmtmpPD1);
747
748
      mmtmpPD2 = _mm_unpacklo_epi32(mmtmpPD0,mmtmpPD1);
      mmtmpPD3 = _mm_unpackhi_epi32(mmtmpPD0,mmtmpPD1);
749
750
      //        print_ints("c0",&mmtmpPD2);
      //  print_ints("c1",&mmtmpPD3);
751
      dl_ch_rho128[0] = _mm_packs_epi32(mmtmpPD2,mmtmpPD3);
752

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

757
758
759
760
761
762
763
764
765
766
767
768
      // 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);
769
770


771
772
773
      dl_ch_rho128[1] =_mm_packs_epi32(mmtmpPD2,mmtmpPD3);
      //print_shorts("rx:",dl_ch128_2+1);
      //print_shorts("ch:",dl_ch128+1);
774
      //print_shorts("pack:",rho128+1);
775
776
777
778
779
780
781
782
783
784
785
786
      // 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);
787

788
789
790
791
      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);
792

793
794
795
      dl_ch128+=3;
      dl_ch128i+=3;
      dl_ch_rho128+=3;
796
797


798
#elif defined(__arm__)
799

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

808
809
810
811
}


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

gauthier's avatar
gauthier committed
819
  uint8_t aatx;
820

821
#if defined(__x86_64__) || defined(__i386__)
822
  __m128i *rxdataF_comp128_0,*rxdataF_comp128_1,*rxdataF_comp128_i0,*rxdataF_comp128_i1,*rho128_0,*rho128_1,*rho128_i0,*rho128_i1;
823
824
825
#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
826
  int32_t i;
827
828

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

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

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

864
#if defined(__x86_64__) || defined(__i386__)
865
866
    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];
867
    rxdataF_comp128_i0   = (__m128i *)&rxdataF_comp_i[0][symbol*frame_parms->N_RB_DL*12];
868
    rxdataF_comp128_i1   = (__m128i *)&rxdataF_comp_i[1][symbol*frame_parms->N_RB_DL*12];
869
870
871
872
873
#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];
874

875
#endif
876
877
    // MRC on each re of rb on MF and rho
    for (i=0; i<frame_parms->N_RB_DL*3; i++) {
878
#if defined(__x86_64__) || defined(__i386__)
879
880
      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));
881
882
883
884
885
#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
886
887
    }
  }
888

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


gauthier's avatar
gauthier committed
896
void pdcch_extract_rbs_single(int32_t **rxdataF,
897
898
899
900
901
902
903
                              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)
{
904
905


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

910
911

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

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

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

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

926
927
928
929
930
    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
931

932
    if ((frame_parms->N_RB_DL&1) == 0)  { // even number of RBs
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
      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;
        }
979
      }
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
    } else { // Odd number of RBs
      for (rb=0; rb<frame_parms->N_RB_DL>>1; rb++) {

        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;
        }
1017
      }
1018

1019
      // Do middle RB (around DC)
1020
      //  printf("dlch_ext %d\n",dl_ch0_ext-&dl_ch_estimates_ext[aarx][0]);
1021
1022

      if (symbol_mod==0) {
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
        j=0;

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

        rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];

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


        nb_rb++;
        dl_ch0_ext+=8;
        rxF_ext+=8;
        dl_ch0+=12;
        rxF+=7;
        rb++;
      } else {
        for (i=0; i<6; i++) {
          dl_ch0_ext[i]=dl_ch0[i];
          rxF_ext[i]=rxF[i];
        }

        rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];

        for (; i<12; i++) {
          dl_ch0_ext[i]=dl_ch0[i];
          rxF_ext[i]=rxF[(1+i-6)];
        }


        nb_rb++;
        dl_ch0_ext+=12;
        rxF_ext+=12;
        dl_ch0+=12;
        rxF+=7;
        rb++;
1072
1073
      }

1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
      for (; rb<frame_parms->N_RB_DL; rb++) {
        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];
            }
          }

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

          dl_ch0+=12;
          rxF+=12;
        }
1108
1109
1110
1111
1112
      }
    }
  }
}

gauthier's avatar
gauthier committed
1113
void pdcch_extract_rbs_dual(int32_t **rxdataF,
1114
1115
1116
1117
1118
1119
1120
1121
                            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)
{

1122

gauthier's avatar
gauthier committed
1123
1124
1125
1126
  uint16_t rb,nb_rb=0;
  uint8_t i,aarx,j;
  int32_t *dl_ch0,*dl_ch0_ext,*dl_ch1,*dl_ch1_ext,*rxF,*rxF_ext;
  uint8_t symbol_mod;
1127
1128
1129
  int nushiftmod3 = frame_parms->nushift%3;

  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
1130
1131
1132
#ifdef DEBUG_DCI_DECODING
  LOG_I(PHY, "extract_rbs_dual: symbol_mod %d\n",symbol_mod);
#endif
1133

1134
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
1135
1136
1137
1138

    if (high_speed_flag==1) {
      dl_ch0     = &dl_ch_estimates[aarx][5+(symbol*(frame_parms->ofdm_symbol_size))];
      dl_ch1     = &dl_ch_estimates[2+aarx][5+(symbol*(frame_parms->ofdm_symbol_size))];
1139
    } else {