phich.c 45.8 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


ghaddab's avatar
ghaddab committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

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

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

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

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55

/*! \file PHY/LTE_TRANSPORT/phich.c
* \brief Top-level routines for generating and decoding  the PHICH/HI physical/transport channel V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/

#include "PHY/defs.h"
#include "PHY/extern.h"
#include "SCHED/defs.h"
#include "defs.h"
#ifndef USER_MODE
#include "ARCH/CBMIMO1/DEVICE_DRIVER/extern.h"
#endif

//#define DEBUG_PHICH 1

//extern unsigned short pcfich_reg[4];
//extern unsigned char pcfich_first_reg_idx;

//unsigned short phich_reg[MAX_NUM_PHICH_GROUPS][3];

knopp's avatar
 
knopp committed
56 57

uint8_t rv_table[4] = {0, 2, 3, 1};
58

59 60
uint8_t get_mi(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
{
61 62

  // for FDD
knopp's avatar
 
knopp committed
63
  if (frame_parms->frame_type == FDD)
64 65 66 67 68
    return 1;

  // for TDD
  switch (frame_parms->tdd_config) {

69
  case 0:
70 71 72
    if ((subframe==0) || (subframe==5))
      return(2);
    else return(1);
73

74
    break;
75 76

  case 1:
77 78 79
    if ((subframe==0) || (subframe==5))
      return(0);
    else return(1);
80

81
    break;
82 83

  case 2:
84 85 86
    if ((subframe==3) || (subframe==8))
      return(1);
    else return(0);
87

88
    break;
89 90

  case 3:
91 92 93
    if ((subframe==0) || (subframe==8) || (subframe==9))
      return(1);
    else return(0);
94

95
    break;
96

97 98 99 100
  case 4:
    if ((subframe==8) || (subframe==9))
      return(1);
    else return(0);
101

102
    break;
103

104 105 106 107
  case 5:
    if (subframe==8)
      return(1);
    else return(0);
108

109
    break;
110

111
  case 6:
112 113 114
    return(1);
    break;

115 116 117 118 119
  default:
    return(0);
  }
}

120 121
unsigned char subframe2_ul_harq(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
122

knopp's avatar
 
knopp committed
123
  if (frame_parms->frame_type == FDD)
124
    return(subframe&7);
125

126 127
  switch (frame_parms->tdd_config) {
  case 3:
128
    if ( (subframe == 8) || (subframe == 9) ) {
129
      return(subframe-8);
130
    } else if (subframe==0)
131 132 133
      return(2);
    else {
      LOG_E(PHY,"phich.c: subframe2_ul_harq, illegal subframe %d for tdd_config %d\n",
134
            subframe,frame_parms->tdd_config);
135 136
      return(0);
    }
137

138
    break;
139

140
  }
141

142 143 144
  return(0);
}

145 146
uint8_t phich_frame2_pusch_frame(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame,uint8_t subframe)
{
knopp's avatar
 
knopp committed
147
  if (frame_parms->frame_type == FDD) {
148
    return((subframe<4) ? (frame - 1) : frame);
149
  } else {
150 151 152 153 154
    // Note this is not true, but it doesn't matter, the frame number is irrelevant for TDD!
    return(frame);
  }
}

155 156
uint8_t phich_subframe2_pusch_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
{
157

knopp's avatar
 
knopp committed
158
  if (frame_parms->frame_type == FDD)
159
    return(subframe<4 ? (subframe+6) : (subframe-4));
160

161 162 163 164 165 166
  switch (frame_parms->tdd_config) {
  case 0:
    if (subframe == 0)
      return(3);
    else if (subframe == 5) {
      return (8);
167
    } else if (subframe == 6)
168 169 170 171 172
      return (2);
    else if (subframe == 1)
      return (7);
    else {
      LOG_E(PHY, "phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
173
            subframe,frame_parms->tdd_config);
174 175
      return(0);
    }
176

177
    break;
178

179 180 181
  case 1:
    if (subframe == 6)
      return(2);
182
    else if (subframe == 9)
183 184 185 186 187 188 189
      return (3);
    else if (subframe == 1)
      return (7);
    else if (subframe == 4)
      return (8);
    else {
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
190
            subframe,frame_parms->tdd_config);
191 192
      return(0);
    }
193

194
    break;
195

196 197 198 199 200 201 202
  case 2:
    if (subframe == 8)
      return(2);
    else if (subframe == 3)
      return (7);
    else {
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
203
            subframe,frame_parms->tdd_config);
204 205
      return(0);
    }
206

207
    break;
208

209
  case 3:
210
    if ( (subframe == 8) || (subframe == 9) ) {
211
      return(subframe-6);
212
    } else if (subframe==0)
213 214 215
      return(4);
    else {
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
216
            subframe,frame_parms->tdd_config);
217 218
      return(0);
    }
219

220
    break;
221

222
  case 4:
223
    if ( (subframe == 8) || (subframe == 9) ) {
224
      return(subframe-6);
225
    } else {
226
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
227
            subframe,frame_parms->tdd_config);
228 229
      return(0);
    }
230 231 232

    break;

233
  case 5:
234
    if (subframe == 8) {
235
      return(2);
236
    } else {
237
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
238
            subframe,frame_parms->tdd_config);
239 240
      return(0);
    }
241

242 243 244
    break;

  case 6:
245
    if (subframe == 6) {
246
      return(2);
247
    } else if (subframe == 9) {
248
      return(3);
249
    } else if (subframe == 0) {
250
      return(4);
251
    } else if (subframe == 1) {
252
      return(7);
253
    } else if (subframe == 5) {
254
      return(8);
255
    } else {
256
      LOG_E(PHY,"phich.c: phich_subframe2_pusch_subframe, illegal subframe %d for tdd_config %d\n",
257
            subframe,frame_parms->tdd_config);
258 259
      return(0);
    }
260

261
    break;
262

263
  }
264

265 266 267
  return(0);
}

268 269
int check_pcfich(LTE_DL_FRAME_PARMS *frame_parms,uint16_t reg)
{
270 271 272 273 274 275

  if ((reg == frame_parms->pcfich_reg[0]) ||
      (reg == frame_parms->pcfich_reg[1]) ||
      (reg == frame_parms->pcfich_reg[2]) ||
      (reg == frame_parms->pcfich_reg[3]))
    return(1);
276

277 278 279
  return(0);
}

280 281
void generate_phich_reg_mapping(LTE_DL_FRAME_PARMS *frame_parms)
{
282 283 284 285 286 287

  unsigned short n0 = (frame_parms->N_RB_DL * 2) - 4;  // 2 REG per RB less the 4 used by PCFICH in first symbol
  unsigned short n1 = (frame_parms->N_RB_DL * 3);      // 3 REG per RB in second and third symbol
  unsigned short n2 = n1;
  unsigned short mprime = 0;
  unsigned short Ngroup_PHICH;
gauthier's avatar
gauthier committed
288 289
  //  uint16_t *phich_reg = frame_parms->phich_reg;
  uint16_t *pcfich_reg = frame_parms->pcfich_reg;
290 291 292

  // compute Ngroup_PHICH (see formula at beginning of Section 6.9 in 36-211
  Ngroup_PHICH = (frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)/48;
293

294 295
  if (((frame_parms->phich_config_common.phich_resource*frame_parms->N_RB_DL)%48) > 0)
    Ngroup_PHICH++;
296

297 298 299 300
  // check if Extended prefix
  if (frame_parms->Ncp == 1) {
    Ngroup_PHICH<<=1;
  }
301

302
#ifdef DEBUG_PHICH
303 304 305
  LOG_D(PHY,"Ngroup_PHICH %d (phich_config_common.phich_resource %d,NidCell %d,Ncp %d, frame_type %d)\n",((frame_parms->Ncp == 0)?Ngroup_PHICH:(Ngroup_PHICH>>1)),
        frame_parms->phich_config_common.phich_resource,
        frame_parms->Nid_cell,frame_parms->Ncp,frame_parms->frame_type);
306 307 308
#endif

  // This is the algorithm from Section 6.9.3 in 36-211
309
  for (mprime=0; mprime<((frame_parms->Ncp == 0)?Ngroup_PHICH:(Ngroup_PHICH>>1)); mprime++) {
310

311
    if (frame_parms->Ncp==0) { // normal prefix
312 313 314 315

      frame_parms->phich_reg[mprime][0] = (frame_parms->Nid_cell + mprime)%n0;

      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
316 317
        frame_parms->phich_reg[mprime][0]++;

318
      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
319 320
        frame_parms->phich_reg[mprime][0]++;

321
      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
322 323
        frame_parms->phich_reg[mprime][0]++;

324
      if (frame_parms->phich_reg[mprime][0]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
325
        frame_parms->phich_reg[mprime][0]++;
326 327 328 329

      frame_parms->phich_reg[mprime][1] = (frame_parms->Nid_cell + mprime + (n0/3))%n0;

      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
330 331
        frame_parms->phich_reg[mprime][1]++;

332
      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
333 334
        frame_parms->phich_reg[mprime][1]++;

335
      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
336 337
        frame_parms->phich_reg[mprime][1]++;

338
      if (frame_parms->phich_reg[mprime][1]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
339 340 341 342
        frame_parms->phich_reg[mprime][1]++;

      frame_parms->phich_reg[mprime][2] = (frame_parms->Nid_cell + mprime + (2*n0/3))%n0;

343
      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[frame_parms->pcfich_first_reg_idx])
344 345
        frame_parms->phich_reg[mprime][2]++;

346
      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+1)&3])
347 348
        frame_parms->phich_reg[mprime][2]++;

349
      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+2)&3])
350 351
        frame_parms->phich_reg[mprime][2]++;

352
      if (frame_parms->phich_reg[mprime][2]>=pcfich_reg[(frame_parms->pcfich_first_reg_idx+3)&3])
353
        frame_parms->phich_reg[mprime][2]++;
354 355 356 357

#ifdef DEBUG_PHICH
      LOG_D(PHY,"phich_reg :%d => %d,%d,%d\n",mprime,frame_parms->phich_reg[mprime][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]);
#endif
358
    } else { // extended prefix
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
      frame_parms->phich_reg[mprime<<1][0] = (frame_parms->Nid_cell + mprime)%n0;
      frame_parms->phich_reg[1+(mprime<<1)][0] = (frame_parms->Nid_cell + mprime)%n0;

      frame_parms->phich_reg[mprime<<1][1] = ((frame_parms->Nid_cell*n1/n0) + mprime + (n1/3))%n1;
      frame_parms->phich_reg[mprime<<1][2] = ((frame_parms->Nid_cell*n2/n0) + mprime + (2*n2/3))%n2;

      frame_parms->phich_reg[1+(mprime<<1)][1] = ((frame_parms->Nid_cell*n1/n0) + mprime + (n1/3))%n1;
      frame_parms->phich_reg[1+(mprime<<1)][2] = ((frame_parms->Nid_cell*n2/n0) + mprime + (2*n2/3))%n2;
#ifdef DEBUG_PHICH
      LOG_D(PHY,"phich_reg :%d => %d,%d,%d\n",mprime<<1,frame_parms->phich_reg[mprime<<1][0],frame_parms->phich_reg[mprime][1],frame_parms->phich_reg[mprime][2]);
      LOG_D(PHY,"phich_reg :%d => %d,%d,%d\n",1+(mprime<<1),frame_parms->phich_reg[1+(mprime<<1)][0],frame_parms->phich_reg[1+(mprime<<1)][1],frame_parms->phich_reg[1+(mprime<<1)][2]);
#endif
    }
  } // mprime loop
}  // num_pdcch_symbols loop


void generate_phich_emul(LTE_DL_FRAME_PARMS *frame_parms,
377 378 379
                         uint8_t HI,
                         uint8_t subframe)
{
380 381 382 383 384


}

mod_sym_t alam_bpsk_perm1[4] = {2,1,4,3}; // -conj(x) 1 (-1-j) -> 2 (1-j), 2->1, 3 (-1+j) -> (4) 1+j, 4->3
385
mod_sym_t alam_bpsk_perm2[4] = {3,4,2,1}; // conj(x) 1 (-1-j) -> 3 (-1+j), 3->1, 2 (1-j) -> 4 (1+j), 4->2
386

387
// This routine generates the PHICH
388 389

void generate_phich(LTE_DL_FRAME_PARMS *frame_parms,
390 391 392 393 394 395 396 397
                    int16_t amp,
                    uint8_t nseq_PHICH,
                    uint8_t ngroup_PHICH,
                    uint8_t HI,
                    uint8_t subframe,
                    mod_sym_t **y)
{

398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
  int16_t d[24],*dp;
  //  unsigned int i,aa;
  unsigned int re_offset;
  int16_t y0_16[8],y1_16[8];
  int16_t *y0,*y1;
  // scrambling
  uint32_t x1, x2, s=0;
  uint8_t reset = 1;
  int16_t cs[12];
  uint32_t i,i2,i3,m,j;
  int16_t gain_lin_QPSK;
  uint32_t subframe_offset=((frame_parms->Ncp==0)?14:12)*frame_parms->ofdm_symbol_size*subframe;

  memset(d,0,24*sizeof(int16_t));

413 414
  if (frame_parms->mode1_flag==1)
    gain_lin_QPSK = (int16_t)(((int32_t)amp*ONE_OVER_SQRT2_Q15)>>15);
415
  else
416
    gain_lin_QPSK = amp/2;
417 418 419 420 421 422

  //printf("PHICH : gain_lin_QPSK %d\n",gain_lin_QPSK);

  // BPSK modulation of HI input (to be repeated 3 times, 36-212 Section 5.3.5, p. 56 in v8.6)
  if (HI>0)
    HI=1;
423

424 425
  //  c = (1-(2*HI))*SSS_AMP;
  // x1 is set in lte_gold_generic
426 427
  x2 = (((subframe+1)*(frame_parms->Nid_cell+1))<<9) + frame_parms->Nid_cell;

428
  s = lte_gold_generic(&x1, &x2, reset);
429

430
  // compute scrambling sequence
431
  for (i=0; i<12; i++) {
432 433 434 435 436 437 438 439
    cs[i] = (uint8_t)((s>>(i&0x1f))&1);
    cs[i] = (cs[i] == 0) ? (1-(HI<<1)) : ((HI<<1)-1);
  }

  if (frame_parms->Ncp == 0) { // Normal Cyclic Prefix

    //    printf("Doing PHICH : Normal CP, subframe %d\n",subframe);
    // 12 output symbols (Msymb)
440
    for (i=0,i2=0,i3=0; i<3; i++,i2+=4,i3+=8) {
441 442
      switch (nseq_PHICH) {
      case 0: // +1 +1 +1 +1
443 444 445 446 447 448 449 450 451 452
        d[i3]   = cs[i2];
        d[1+i3] = cs[i2];
        d[2+i3] = cs[1+i2];
        d[3+i3] = cs[1+i2];
        d[4+i3] = cs[2+i2];
        d[5+i3] = cs[2+i2];
        d[6+i3] = cs[3+i2];
        d[7+i3] = cs[3+i2];
        break;

453
      case 1: // +1 -1 +1 -1
454 455 456 457 458 459 460 461 462 463
        d[i3] = cs[i2];
        d[1+i3] = cs[i2];
        d[2+i3] = -cs[1+i2];
        d[3+i3] = -cs[1+i2];
        d[4+i3] = cs[2+i2];
        d[5+i3] = cs[2+i2];
        d[6+i3] = -cs[3+i2];
        d[7+i3] = -cs[3+i2];
        break;

464
      case 2: // +1 +1 -1 -1
465 466 467 468 469 470 471 472 473 474
        d[i3]   = cs[i2];
        d[1+i3]   = cs[i2];
        d[2+i3] = cs[1+i2];
        d[3+i3] = cs[1+i2];
        d[4+i3] = -cs[2+i2];
        d[5+i3] = -cs[2+i2];
        d[6+i3] = -cs[3+i2];
        d[7+i3] = -cs[3+i2];
        break;

475
      case 3: // +1 -1 -1 +1
476 477 478 479 480 481 482 483 484 485
        d[i3]   = cs[i2];
        d[1+i3]   = cs[i2];
        d[2+i3] = -cs[1+i2];
        d[3+i3] = -cs[1+i2];
        d[4+i3] = -cs[2+i2];
        d[5+i3] = -cs[2+i2];
        d[6+i3] = cs[3+i2];
        d[7+i3] = cs[3+i2];
        break;

486
      case 4: // +j +j +j +j
487 488 489 490 491 492 493 494 495 496
        d[i3]   = -cs[i2];
        d[1+i3] = cs[i2];
        d[2+i3] = -cs[1+i2];
        d[3+i3] = cs[1+i2];
        d[4+i3] = -cs[2+i2];
        d[5+i3] = cs[2+i2];
        d[6+i3] = -cs[3+i2];
        d[7+i3] = cs[3+i2];
        break;

497
      case 5: // +j -j +j -j
498 499 500 501 502 503 504 505 506 507
        d[1+i3] = cs[i2];
        d[3+i3] = -cs[1+i2];
        d[5+i3] = cs[2+i2];
        d[7+i3] = -cs[3+i2];
        d[i3]   = -cs[i2];
        d[2+i3] = cs[1+i2];
        d[4+i3] = -cs[2+i2];
        d[6+i3] = cs[3+i2];
        break;

508
      case 6: // +j +j -j -j
509 510 511 512 513 514 515 516 517 518
        d[1+i3] = cs[i2];
        d[3+i3] = cs[1+i2];
        d[5+i3] = -cs[2+i2];
        d[7+i3] = -cs[3+i2];
        d[i3]   = -cs[i2];
        d[2+i3] = -cs[1+i2];
        d[4+i3] = cs[2+i2];
        d[6+i3] = cs[3+i2];
        break;

519
      case 7: // +j -j -j +j
520 521 522 523 524 525 526 527 528 529
        d[1+i3] = cs[i2];
        d[3+i3] = -cs[1+i2];
        d[5+i3] = -cs[2+i2];
        d[7+i3] = cs[3+i2];
        d[i3]   = -cs[i2];
        d[2+i3] = cs[1+i2];
        d[4+i3] = cs[2+i2];
        d[6+i3] = -cs[3+i2];
        break;

530
      default:
531
        LOG_E(PHY,"phich_coding.c: Illegal PHICH Number\n");
532 533
      } // nseq_PHICH
    }
534

535 536
#ifdef DEBUG_PHICH
    LOG_D(PHY,"[PUSCH 0]PHICH d = ");
537 538

    for (i=0; i<24; i+=2)
539
      LOG_D(PHY,"(%d,%d)",d[i],d[i+1]);
540

541 542
    LOG_D(PHY,"\n");
#endif
543 544

    // modulation here
545 546
    if (frame_parms->mode1_flag == 0) {
      // do Alamouti precoding here
547

548 549 550 551
      // Symbol 0
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][0]*6);

      if (re_offset > frame_parms->ofdm_symbol_size)
552
        re_offset -= (frame_parms->ofdm_symbol_size-1);
553 554 555

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];
556

557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
      // first antenna position n -> x0
      y0_16[0]   = d[0]*gain_lin_QPSK;
      y0_16[1]   = d[1]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[2]*gain_lin_QPSK;
      y1_16[1]   = d[3]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[4]*gain_lin_QPSK;
      y0_16[5]   = d[5]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[6]*gain_lin_QPSK;
      y1_16[5]   = d[7]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

581 582 583 584 585 586 587
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m];
          y1[j]   += y1_16[m++];
          y0[j+1] += y0_16[m];
          y1[j+1] += y1_16[m++];
        }
588
      }
589

590 591 592 593
      // Symbol 1
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][1]*6);

      if (re_offset > frame_parms->ofdm_symbol_size)
594
        re_offset -= (frame_parms->ofdm_symbol_size-1);
595 596 597

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];
598

599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622
      // first antenna position n -> x0
      y0_16[0]   = d[8]*gain_lin_QPSK;
      y0_16[1]   = d[9]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[10]*gain_lin_QPSK;
      y1_16[1]   = d[11]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[12]*gain_lin_QPSK;
      y0_16[5]   = d[13]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[14]*gain_lin_QPSK;
      y1_16[5]   = d[15]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

623 624 625 626 627 628 629
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m];
          y1[j]   += y1_16[m++];
          y0[j+1] += y0_16[m];
          y1[j+1] += y1_16[m++];
        }
630 631 632 633 634 635
      }

      // Symbol 2
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][2]*6);

      if (re_offset > frame_parms->ofdm_symbol_size)
636
        re_offset -= (frame_parms->ofdm_symbol_size-1);
637 638 639

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];
640

641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664
      // first antenna position n -> x0
      y0_16[0]   = d[16]*gain_lin_QPSK;
      y0_16[1]   = d[17]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[18]*gain_lin_QPSK;
      y1_16[1]   = d[19]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[20]*gain_lin_QPSK;
      y0_16[5]   = d[21]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[22]*gain_lin_QPSK;
      y1_16[5]   = d[23]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

665 666 667 668 669 670 671
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m];
          y1[j]   += y1_16[m++];
          y0[j+1] += y0_16[m];
          y1[j+1] += y1_16[m++];
        }
672 673 674 675 676 677 678 679 680 681
      }

    } // mode1_flag

    else {
      // Symbol 0
      //      printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][0]);
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][0]*6);

      if (re_offset > frame_parms->ofdm_symbol_size)
682
        re_offset -= (frame_parms->ofdm_symbol_size-1);
683 684 685 686 687 688 689 690 691 692 693 694 695

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      //      printf("y0 %p\n",y0);

      y0_16[0]   = d[0]*gain_lin_QPSK;
      y0_16[1]   = d[1]*gain_lin_QPSK;
      y0_16[2]   = d[2]*gain_lin_QPSK;
      y0_16[3]   = d[3]*gain_lin_QPSK;
      y0_16[4]   = d[4]*gain_lin_QPSK;
      y0_16[5]   = d[5]*gain_lin_QPSK;
      y0_16[6]   = d[6]*gain_lin_QPSK;
      y0_16[7]   = d[7]*gain_lin_QPSK;

696 697 698 699 700
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m++];
          y0[j+1] += y0_16[m++];
        }
701
      }
702

703 704 705 706 707
      // Symbol 1
      //      printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][1]);
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][1]*6);

      if (re_offset > frame_parms->ofdm_symbol_size)
708
        re_offset -= (frame_parms->ofdm_symbol_size-1);
709 710

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
711

712 713 714 715 716 717 718 719 720
      y0_16[0]   = d[8]*gain_lin_QPSK;
      y0_16[1]   = d[9]*gain_lin_QPSK;
      y0_16[2]   = d[10]*gain_lin_QPSK;
      y0_16[3]   = d[11]*gain_lin_QPSK;
      y0_16[4]   = d[12]*gain_lin_QPSK;
      y0_16[5]   = d[13]*gain_lin_QPSK;
      y0_16[6]   = d[14]*gain_lin_QPSK;
      y0_16[7]   = d[15]*gain_lin_QPSK;

721 722 723 724 725
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m++];
          y0[j+1] += y0_16[m++];
        }
726 727 728 729 730 731 732
      }

      // Symbol 2
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][2]*6);

      //      printf("[PUSCH 0]PHICH REG %d\n",frame_parms->phich_reg[ngroup_PHICH][2]);
      if (re_offset > frame_parms->ofdm_symbol_size)
733 734
        re_offset -= (frame_parms->ofdm_symbol_size-1);

735
      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
736

737 738 739 740 741 742 743 744 745
      y0_16[0]   = d[16]*gain_lin_QPSK;
      y0_16[1]   = d[17]*gain_lin_QPSK;
      y0_16[2]   = d[18]*gain_lin_QPSK;
      y0_16[3]   = d[19]*gain_lin_QPSK;
      y0_16[4]   = d[20]*gain_lin_QPSK;
      y0_16[5]   = d[21]*gain_lin_QPSK;
      y0_16[6]   = d[22]*gain_lin_QPSK;
      y0_16[7]   = d[23]*gain_lin_QPSK;

746 747 748 749 750
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j]   += y0_16[m++];
          y0[j+1] += y0_16[m++];
        }
751
      }
752

753 754
      /*
      for (i=0;i<512;i++)
755
      printf("re %d (%d): %d,%d\n",i,subframe_offset+i,((int16_t*)&y[0][subframe_offset+i])[0],((int16_t*)&y[0][subframe_offset+i])[1]);
756 757
      */
    } // mode1_flag
758 759
  } else { // extended prefix

760 761 762
    // 6 output symbols
    if ((ngroup_PHICH & 1) == 1)
      dp = &d[4];
763
    else
764 765 766
      dp = d;

    switch (nseq_PHICH) {
767
    case 0: // +1 +1
768 769 770 771 772 773 774 775 776 777 778 779 780
      dp[0]  = cs[0];
      dp[2]  = cs[1];
      dp[8]  = cs[2];
      dp[10] = cs[3];
      dp[16] = cs[4];
      dp[18] = cs[5];
      dp[1]  = cs[0];
      dp[3]  = cs[1];
      dp[9]  = cs[2];
      dp[11] = cs[3];
      dp[17] = cs[4];
      dp[19] = cs[5];
      break;
781

782 783 784 785 786 787 788 789 790 791 792 793 794 795
    case 1: // +1 -1
      dp[0]  = cs[0];
      dp[2]  = -cs[1];
      dp[8]  = cs[2];
      dp[10] = -cs[3];
      dp[16] = cs[4];
      dp[18] = -cs[5];
      dp[1]  = cs[0];
      dp[3]  = -cs[1];
      dp[9]  = cs[2];
      dp[11] = -cs[3];
      dp[17] = cs[4];
      dp[19] = -cs[5];
      break;
796 797

    case 2: // +j +j
798 799 800 801 802 803 804 805 806 807 808 809
      dp[1]  = cs[0];
      dp[3]  = cs[1];
      dp[9]  = cs[2];
      dp[11] = cs[3];
      dp[17] = cs[4];
      dp[19] = cs[5];
      dp[0]  = -cs[0];
      dp[2]  = -cs[1];
      dp[8]  = -cs[2];
      dp[10] = -cs[3];
      dp[16] = -cs[4];
      dp[18] = -cs[5];
810

811
      break;
812 813

    case 3: // +j -j
814 815 816 817 818 819 820 821 822 823 824 825 826
      dp[1]  = cs[0];
      dp[3]  = -cs[1];
      dp[9]  = cs[2];
      dp[11] = -cs[3];
      dp[17] = cs[4];
      dp[19] = -cs[5];
      dp[0]  = -cs[0];
      dp[2]  = cs[1];
      dp[8]  = -cs[2];
      dp[10] = cs[3];
      dp[16] = -cs[4];
      dp[18] = cs[5];
      break;
827

828 829 830
    default:
      LOG_E(PHY,"phich_coding.c: Illegal PHICH Number\n");
    }
831 832 833



834 835 836 837
    if (frame_parms->mode1_flag == 0) {
      // do Alamouti precoding here
      // Symbol 0
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][0]*6);
838

839
      if (re_offset > frame_parms->ofdm_symbol_size)
840
        re_offset -= (frame_parms->ofdm_symbol_size-1);
841 842 843

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];
844

845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
      // first antenna position n -> x0
      y0_16[0]   = d[0]*gain_lin_QPSK;
      y0_16[1]   = d[1]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[2]*gain_lin_QPSK;
      y1_16[1]   = d[3]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[4]*gain_lin_QPSK;
      y0_16[5]   = d[5]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[6]*gain_lin_QPSK;
      y1_16[5]   = d[7]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

869 870 871 872 873 874 875
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j] += y0_16[m];
          y1[j] += y1_16[m++];
          y0[j+1] += y0_16[m];
          y1[j+1] += y1_16[m++];
        }
876 877 878 879
      }

      // Symbol 1
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][1]<<2);
880

881
      if (re_offset > frame_parms->ofdm_symbol_size)
882 883
        re_offset -= (frame_parms->ofdm_symbol_size-1);

884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912
      re_offset += (frame_parms->ofdm_symbol_size);

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];

      // first antenna position n -> x0
      y0_16[0]   = d[8]*gain_lin_QPSK;
      y0_16[1]   = d[9]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[10]*gain_lin_QPSK;
      y1_16[1]   = d[11]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[12]*gain_lin_QPSK;
      y0_16[5]   = d[13]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[14]*gain_lin_QPSK;
      y1_16[5]   = d[15]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

913 914 915 916 917
      for (i=0,j=0,m=0; i<4; i++,j+=2) {
        y0[j] += y0_16[m];
        y1[j] += y1_16[m++];
        y0[j+1] += y0_16[m];
        y1[j+1] += y1_16[m++];
918 919 920 921
      }

      // Symbol 2
      re_offset = frame_parms->first_carrier_offset +  (frame_parms->phich_reg[ngroup_PHICH][2]<<2);
922

923
      if (re_offset > frame_parms->ofdm_symbol_size)
924 925
        re_offset -= (frame_parms->ofdm_symbol_size-1);

926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
      re_offset += (frame_parms->ofdm_symbol_size<<1);

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
      y1 = (int16_t*)&y[1][re_offset+subframe_offset];

      // first antenna position n -> x0
      y0_16[0]   = d[16]*gain_lin_QPSK;
      y0_16[1]   = d[17]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[0]   = -d[18]*gain_lin_QPSK;
      y1_16[1]   = d[19]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[2] = -y1_16[0];
      y0_16[3] = y1_16[1];
      y1_16[2] = y0_16[0];
      y1_16[3] = -y0_16[1];

      // first antenna position n -> x0
      y0_16[4]   = d[20]*gain_lin_QPSK;
      y0_16[5]   = d[21]*gain_lin_QPSK;
      // second antenna position n -> -x1*
      y1_16[4]   = -d[22]*gain_lin_QPSK;
      y1_16[5]   = d[23]*gain_lin_QPSK;
      // fill in the rest of the ALAMOUTI precoding
      y0_16[6] = -y1_16[4];
      y0_16[7] = y1_16[5];
      y1_16[6] = y0_16[4];
      y1_16[7] = -y0_16[5];

955 956 957 958 959
      for (i=0,j=0,m=0; i<4; i++,j+=2) {
        y0[j]   += y0_16[m];
        y1[j]   += y1_16[m++];
        y0[j+1] += y0_16[m];
        y1[j+1] += y1_16[m++];
960
      }
961
    } else {
962 963 964

      // Symbol 0
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][0]*6);
965

966
      if (re_offset > frame_parms->ofdm_symbol_size)
967
        re_offset -= (frame_parms->ofdm_symbol_size-1);
968 969

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
970

971 972 973 974 975 976 977 978 979
      y0_16[0]   = d[0]*gain_lin_QPSK;
      y0_16[1]   = d[1]*gain_lin_QPSK;
      y0_16[2]   = d[2]*gain_lin_QPSK;
      y0_16[3]   = d[3]*gain_lin_QPSK;
      y0_16[4]   = d[4]*gain_lin_QPSK;
      y0_16[5]   = d[5]*gain_lin_QPSK;
      y0_16[6]   = d[6]*gain_lin_QPSK;
      y0_16[7]   = d[7]*gain_lin_QPSK;

980 981 982 983 984
      for (i=0,j=0,m=0; i<6; i++,j+=2) {
        if ((i!=(frame_parms->nushift))&&(i!=(frame_parms->nushift+3))) {
          y0[j] += y0_16[m++];
          y0[j+1] += y0_16[m++];
        }
985 986 987 988
      }

      // Symbol 1
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][1]<<2);
989

990
      if (re_offset > frame_parms->ofdm_symbol_size)
991 992
        re_offset -= (frame_parms->ofdm_symbol_size-1);

993 994 995
      re_offset += (frame_parms->ofdm_symbol_size);

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
996

997 998 999 1000 1001 1002 1003 1004 1005
      y0_16[0]   = d[8]*gain_lin_QPSK;
      y0_16[1]   = d[9]*gain_lin_QPSK;
      y0_16[2]   = d[10]*gain_lin_QPSK;
      y0_16[3]   = d[11]*gain_lin_QPSK;
      y0_16[4]   = d[12]*gain_lin_QPSK;
      y0_16[5]   = d[13]*gain_lin_QPSK;
      y0_16[6]   = d[14]*gain_lin_QPSK;
      y0_16[7]   = d[15]*gain_lin_QPSK;

1006 1007 1008
      for (i=0,j=0,m=0; i<4; i++,j+=2) {
        y0[j] += y0_16[m++];
        y0[j+1] += y0_16[m++];
1009 1010 1011 1012 1013
      }


      // Symbol 2
      re_offset = frame_parms->first_carrier_offset + (frame_parms->phich_reg[ngroup_PHICH][2]<<2);
1014

1015
      if (re_offset > frame_parms->ofdm_symbol_size)
1016 1017
        re_offset -= (frame_parms->ofdm_symbol_size-1);

1018 1019 1020
      re_offset += (frame_parms->ofdm_symbol_size<<1);

      y0 = (int16_t*)&y[0][re_offset+subframe_offset];
1021

1022 1023 1024 1025 1026 1027 1028 1029 1030
      y0_16[0]   = d[16]*gain_lin_QPSK;<