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

/*! \file PHY/LTE_TRANSPORT/pbch.c
* \brief Top-level routines for generating and decoding  the PBCH/BCH physical/transport channel V8.6 2009-03
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger.fr
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "defs.h"
#include "extern.h"
#include "PHY/extern.h"
38
#include "PHY/sse_intrin.h"
39 40 41

//#define DEBUG_PBCH 1
//#define DEBUG_PBCH_ENCODING
xuhl's avatar
xuhl committed
42
//#define INTERFERENCE_MITIGATION 1
43 44 45 46


#define PBCH_A 24

47
int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
48
                            int32_t **txdataF,
49 50 51 52 53 54 55 56
                            uint32_t *jj,
                            uint16_t re_offset,
                            uint32_t symbol_offset,
                            uint8_t *x0,
                            uint8_t pilots,
                            int16_t amp,
                            uint32_t *re_allocated)
{
57

58
  MIMO_mode_t mimo_mode   = (frame_parms->nb_antenna_ports_eNB==1)?SISO:ALAMOUTI;
59 60


61
  uint32_t tti_offset;
62 63 64 65 66 67 68 69 70 71 72 73
  uint8_t re;
  int16_t gain_lin_QPSK;
  int16_t re_off=re_offset;

  uint8_t first_re,last_re;
  int32_t tmp_sample1,tmp_sample2;

  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);

  first_re=0;
  last_re=12;

74 75
  for (re=first_re; re<last_re; re++) {

76
    tti_offset = symbol_offset + re_off + re;
77

78 79
    // check that RE is not from Cell-specific RS

80
    if (is_not_pilot(pilots,re,frame_parms->nushift,0)==1) {
81 82
      //      printf("re %d (jj %d)\n",re,*jj);
      if (mimo_mode == SISO) {  //SISO mapping
83 84 85
        *re_allocated = *re_allocated + 1;

        //    printf("%d(%d) : %d,%d => ",tti_offset,*jj,((int16_t*)&txdataF[0][tti_offset])[0],((int16_t*)&txdataF[0][tti_offset])[1]);
86
        ((int16_t*)&txdataF[0][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
87 88 89

        *jj = *jj + 1;

90
        ((int16_t*)&txdataF[0][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133

        *jj = *jj + 1;
      } else if (mimo_mode == ALAMOUTI) {
        *re_allocated = *re_allocated + 1;

        ((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
        *jj=*jj+1;
        ((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
        *jj=*jj+1;

        // second antenna position n -> -x1*

        ((int16_t*)&tmp_sample2)[0] = (x0[*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
        *jj=*jj+1;
        ((int16_t*)&tmp_sample2)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
        *jj=*jj+1;

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

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

        re++;  // adjacent carriers are taken care of by precoding
        *re_allocated = *re_allocated + 1;

        if (is_not_pilot(pilots,re,frame_parms->nushift,0)==0) { // skip pilots
          re++;
          *re_allocated = *re_allocated + 1;
        }
134 135 136
      }
    }
  }
137

138 139
  return(0);
}
140

gauthier's avatar
gauthier committed
141
//uint8_t pbch_d[96+(3*(16+PBCH_A))], pbch_w[3*3*(16+PBCH_A)],pbch_e[1920];  //one bit per byte
142
int generate_pbch(LTE_eNB_PBCH *eNB_pbch,
143
                  int32_t **txdataF,
144 145 146 147 148
                  int amp,
                  LTE_DL_FRAME_PARMS *frame_parms,
                  uint8_t *pbch_pdu,
                  uint8_t frame_mod4)
{
149 150 151

  int i, l;

gauthier's avatar
gauthier committed
152 153 154
  uint32_t  pbch_D,pbch_E;//,pbch_coded_bytes;
  uint8_t pbch_a[PBCH_A>>3];
  uint8_t RCC;
155

gauthier's avatar
gauthier committed
156 157
  uint32_t nsymb = (frame_parms->Ncp==NORMAL) ? 14:12;
  uint32_t pilots;
158
#ifdef INTERFERENCE_MITIGATION
gauthier's avatar
gauthier committed
159
  uint32_t pilots_2;
160
#endif
gauthier's avatar
gauthier committed
161 162 163 164 165
  uint32_t second_pilot = (frame_parms->Ncp==NORMAL) ? 4 : 3;
  uint32_t jj=0;
  uint32_t re_allocated=0;
  uint32_t rb, re_offset, symbol_offset;
  uint16_t amask=0;
166 167 168 169 170 171

  pbch_D    = 16+PBCH_A;

  pbch_E  = (frame_parms->Ncp==NORMAL) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK)
  //  pbch_E_bytes = pbch_coded_bits>>3;

172 173
  LOG_D(PHY,"%s(eNB_pbch:%p txdataF:%p amp:%d frame_parms:%p pbch_pdu:%p frame_mod4:%d)\n", __FUNCTION__, eNB_pbch, txdataF, amp, frame_parms, pbch_pdu, frame_mod4==0);

174 175 176 177 178
  if (frame_mod4==0) {
    bzero(pbch_a,PBCH_A>>3);
    bzero(eNB_pbch->pbch_e,pbch_E);
    memset(eNB_pbch->pbch_d,LTE_NULL,96);
    // Encode data
179

180
    // CRC attachment
181 182
    //  crc = (uint16_t) (crc16(pbch_pdu, pbch_crc_bits-16) >> 16);

183 184
    /*
    // scramble crc with PBCH CRC mask (Table 5.3.1.1-1 of 3GPP 36.212-860)
Xiwen JIANG's avatar
Xiwen JIANG committed
185
    switch (frame_parms->nb_antenna_ports_eNB) {
186
    case 1:
gauthier's avatar
gauthier committed
187
    crc = crc ^ (uint16_t) 0;
188 189
    break;
    case 2:
gauthier's avatar
gauthier committed
190
    crc = crc ^ (uint16_t) 0xFFFF;
191 192
    break;
    case 4:
gauthier's avatar
gauthier committed
193
    crc = crc ^ (uint16_t) 0xAAAA;
194 195 196 197 198 199
    break;
    default:
    msg("[PBCH] Unknown number of TX antennas!\n");
    break;
    }
    */
200

201
    // Fix byte endian of PBCH (bit 23 goes in first)
202
    for (i=0; i<(PBCH_A>>3); i++)
203
      pbch_a[(PBCH_A>>3)-i-1] = pbch_pdu[i];
204

205 206
    //  pbch_data[i] = ((char*) &crc)[0];
    //  pbch_data[i+1] = ((char*) &crc)[1];
207
    //#ifdef DEBUG_PBCH
208 209

    for (i=0; i<(PBCH_A>>3); i++)
210
      LOG_D(PHY,"[PBCH] pbch_data[%d] = %x\n",i,pbch_a[i]);
211

212
    //#endif
213

214
    if (frame_parms->nb_antenna_ports_eNB == 1)
215 216
      amask = 0x0000;
    else {
Xiwen JIANG's avatar
Xiwen JIANG committed
217
      switch (frame_parms->nb_antenna_ports_eNB) {
218
      case 1:
219 220 221
        amask = 0x0000;
        break;

222
      case 2:
223 224 225
        amask = 0xffff;
        break;

226
      case 4:
227
        amask = 0x5555;
228 229
      }
    }
230

231 232
    ccodelte_encode(PBCH_A,2,pbch_a,eNB_pbch->pbch_d+96,amask);

233

234
#ifdef DEBUG_PBCH_ENCODING
235 236

    for (i=0; i<16+PBCH_A; i++)
237
      LOG_D(PHY,"%d : (%d,%d,%d)\n",i,*(eNB_pbch->pbch_d+96+(3*i)),*(eNB_pbch->pbch_d+97+(3*i)),*(eNB_pbch->pbch_d+98+(3*i)));
238

239
#endif //DEBUG_PBCH_ENCODING
240

241 242 243 244 245 246 247 248 249 250 251
    // Bit collection
    /*
      j2=0;
      for (j=0;j<pbch_crc_bits*3+12;j++) {
      if ((pbch_coded_data[j]&0x80) > 0) { // bit is to be transmitted
      pbch_coded_data2[j2++] = pbch_coded_data[j]&1;
      //Bit is repeated
      if ((pbch_coded_data[j]&0x40)>0)
      pbch_coded_data2[j2++] = pbch_coded_data[j]&1;
      }
      }
252 253

      #ifdef DEBUG_PBCH
254 255
      msg("[PBCH] rate matched bits=%d, pbch_coded_bits=%d, pbch_crc_bits=%d\n",j2,pbch_coded_bits,pbch_crc_bits);
      #endif
256

257 258 259 260 261 262 263 264 265
      #ifdef DEBUG_PBCH
      write_output("pbch_encoded_output2.m","pbch_encoded_out2",
      pbch_coded_data2,
      pbch_coded_bits,
      1,
      4);
      #endif //DEBUG_PBCH
    */
#ifdef DEBUG_PBCH_ENCODING
266
    LOG_D(PHY,"Doing PBCH interleaving for %d coded bits, e %p\n",pbch_D,eNB_pbch->pbch_e);
267 268
#endif
    RCC = sub_block_interleaving_cc(pbch_D,eNB_pbch->pbch_d+96,eNB_pbch->pbch_w);
269

270 271 272
    lte_rate_matching_cc(RCC,pbch_E,eNB_pbch->pbch_w,eNB_pbch->pbch_e);

#ifdef DEBUG_PBCH_ENCODING
273
    LOG_D(PHY,"PBCH_e:\n");
274 275

    for (i=0; i<pbch_E; i++)
276
      LOG_D(PHY,"%d %d\n",i,*(eNB_pbch->pbch_e+i));
277

278
    LOG_D(PHY,"\n");
279 280 281
#endif


282

283 284 285
#ifdef DEBUG_PBCH
    if (frame_mod4==0) {
      write_output("pbch_e.m","pbch_e",
286 287 288 289 290 291 292
                   eNB_pbch->pbch_e,
                   pbch_E,
                   1,
                   4);

      for (i=0; i<16; i++)
        printf("e[%d] %d\n",i,eNB_pbch->pbch_e[i]);
293 294 295 296 297
    }
#endif //DEBUG_PBCH
    // scrambling

    pbch_scrambling(frame_parms,
298 299
                    eNB_pbch->pbch_e,
                    pbch_E);
300 301 302
#ifdef DEBUG_PBCH
    if (frame_mod4==0) {
      write_output("pbch_e_s.m","pbch_e_s",
303 304 305 306 307 308 309
                   eNB_pbch->pbch_e,
                   pbch_E,
                   1,
                   4);

      for (i=0; i<16; i++)
        printf("e_s[%d] %d\n",i,eNB_pbch->pbch_e[i]);
310 311 312 313 314
    }
#endif //DEBUG_PBCH 
  } // frame_mod4==0

  // modulation and mapping (slot 1, symbols 0..3)
315 316
  for (l=(nsymb>>1); l<(nsymb>>1)+4; l++) {

317
    pilots=0;
318
#ifdef INTERFERENCE_MITIGATION
319
    pilots_2 = 0;
320
#endif
321 322

    if ((l==0) || (l==(nsymb>>1))) {
323
      pilots=1;
324
#ifdef INTERFERENCE_MITIGATION
325
      pilots_2=1;
326
#endif
327 328
    }

329
    if ((l==1) || (l==(nsymb>>1)+1)) {
330 331 332 333 334 335 336 337
      pilots=1;
    }

    if ((l==second_pilot)||(l==(second_pilot+(nsymb>>1)))) {
      pilots=1;
    }

#ifdef DEBUG_PBCH
338
    LOG_D(PHY,"[PBCH] l=%d, pilots=%d\n",l,pilots);
339 340
#endif

341

342 343
    re_offset = frame_parms->ofdm_symbol_size-3*12;
    symbol_offset = frame_parms->ofdm_symbol_size*l;
344 345

    for (rb=0; rb<6; rb++) {
346 347

#ifdef DEBUG_PBCH
348
      LOG_D(PHY,"RB %d, jj %d, re_offset %d, symbol_offset %d, pilots %d, nushift %d\n",rb,jj,re_offset, symbol_offset, pilots,frame_parms->nushift);
349
#endif
350
      allocate_pbch_REs_in_RB(frame_parms,
351 352 353 354 355 356
                              txdataF,
                              &jj,
                              re_offset,
                              symbol_offset,
                              &eNB_pbch->pbch_e[frame_mod4*(pbch_E>>2)],
                              pilots,
357
#ifdef INTERFERENCE_MITIGATION
358
                              (pilots_2==1)?(amp/3):amp,
359
#else
360
                              amp,
361
#endif
362 363
                              &re_allocated);

364
      re_offset+=12; // go to next RB
365

366
      // check if we crossed the symbol boundary and skip DC
367

368
      if (re_offset >= frame_parms->ofdm_symbol_size)
369
        re_offset=1;
370
    }
371

372 373
    //    }
  }
374

375
#ifdef DEBUG_PBCH
376
  printf("[PBCH] txdataF=\n");
377 378

  for (i=0; i<frame_parms->ofdm_symbol_size; i++) {
379
    printf("%d=>(%d,%d)",i,((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0],
380 381
           ((short*)&txdataF[0][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]);

382
    if (frame_parms->nb_antenna_ports_eNB!=1) {
383
      printf("(%d,%d)\n",((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[0],
384 385
             ((short*)&txdataF[1][frame_parms->ofdm_symbol_size*(nsymb>>1)+i])[1]);
    } else {
386 387 388
      printf("\n");
    }
  }
389

390
#endif
391 392


393 394
  return(0);
}