nr_pbch.c 24.1 KB
Newer Older
Wang's avatar
Wang committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*
 * 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
 */

/*! \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_nr_UE.h"
#include "PHY/CODING/coding_extern.h"
#include "PHY/phy_extern_nr_ue.h"
#include "PHY/sse_intrin.h"
hongzhi wang's avatar
hongzhi wang committed
36
#include "SIMULATION/TOOLS/sim.h"
hongzhi wang's avatar
hongzhi wang committed
37
#include "PHY/LTE_REFSIG/lte_refsig.h"
Wang's avatar
Wang committed
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

//#define DEBUG_PBCH 1
//#define DEBUG_PBCH_ENCODING

#ifdef OPENAIR2
//#include "PHY_INTERFACE/defs.h"
#endif

#define PBCH_A 24


uint16_t nr_pbch_extract(int **rxdataF,
                      int **dl_ch_estimates,
                      int **rxdataF_ext,
                      int **dl_ch_estimates_ext,
                      uint32_t symbol,
                      uint32_t high_speed_flag,
                      NR_DL_FRAME_PARMS *frame_parms)
{


  uint16_t rb;
  uint8_t i,j,aarx,aatx;
hongzhi wang's avatar
hongzhi wang committed
61
  int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
Wang's avatar
Wang committed
62

Hongzhi Wang's avatar
Hongzhi Wang committed
63
  int rx_offset = frame_parms->ofdm_symbol_size-10*12;
hongzhi wang's avatar
hongzhi wang committed
64
  int nushiftmod4 = frame_parms->nushift;
Wang's avatar
Wang committed
65 66

  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
hongzhi wang's avatar
hongzhi wang committed
67
        
Wang's avatar
Wang committed
68 69
    rxF        = &rxdataF[aarx][(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))];
    rxF_ext    = &rxdataF_ext[aarx][symbol*(20*12)];
hongzhi wang's avatar
hongzhi wang committed
70
#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
71 72
     printf("extract_rbs (nushift %d): rx_offset=%d, symbol %d\n",frame_parms->nushift,
     (rx_offset + (symbol*(frame_parms->ofdm_symbol_size))),symbol);
hongzhi wang's avatar
hongzhi wang committed
73
     int16_t *p = (int16_t *)rxF;
hongzhi wang's avatar
hongzhi wang committed
74
     for (int i =0; i<8;i++){
hongzhi wang's avatar
hongzhi wang committed
75
        printf("rxF [%d]= %d\n",i,rxF[i]);
hongzhi wang's avatar
hongzhi wang committed
76 77
        printf("pbch extract rxF  %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]);
        printf("rxF ext addr %p\n", &rxF_ext[i]);
hongzhi wang's avatar
hongzhi wang committed
78 79
     }
#endif
Wang's avatar
Wang committed
80 81

    for (rb=0; rb<20; rb++) {
hongzhi wang's avatar
hongzhi wang committed
82 83 84
      if (rb==10) {
        rxF       = &rxdataF[aarx][((symbol*(frame_parms->ofdm_symbol_size)))];
      }
Wang's avatar
Wang committed
85

hongzhi wang's avatar
hongzhi wang committed
86
      j=0;
hongzhi wang's avatar
hongzhi wang committed
87
      if ((symbol==5) || (symbol==7)) {
Wang's avatar
Wang committed
88 89 90 91
        for (i=0; i<12; i++) {
          if ((i!=nushiftmod4) &&
              (i!=(nushiftmod4+4)) &&
              (i!=(nushiftmod4+8))) {
hongzhi wang's avatar
hongzhi wang committed
92 93 94
            rxF_ext[j]=rxF[i];
	    //printf("rxF ext[%d] = %d rxF [%d]= %d\n",j,rxF_ext[j],i,rxF[i]);
	    j++;
Wang's avatar
Wang committed
95 96 97 98
          }
        }

        rxF+=12;
hongzhi wang's avatar
hongzhi wang committed
99
        rxF_ext+=9;
Wang's avatar
Wang committed
100
      } else { //symbol 2
hongzhi wang's avatar
hongzhi wang committed
101
    	if ((rb < 4) || (rb >15)){
Wang's avatar
Wang committed
102 103 104 105
    	  for (i=0; i<12; i++) {
        	if ((i!=nushiftmod4) &&
        	    (i!=(nushiftmod4+4)) &&
        	    (i!=(nushiftmod4+8))) {
hongzhi wang's avatar
hongzhi wang committed
106
        	  rxF_ext[j]=rxF[i];
hongzhi wang's avatar
hongzhi wang committed
107
		  //printf("symbol2 rxF ext[%d] = %d at %p\n",j,rxF_ext[j],&rxF[i]);
hongzhi wang's avatar
hongzhi wang committed
108
		  j++;
Wang's avatar
Wang committed
109 110
        	}
    	  }
hongzhi wang's avatar
hongzhi wang committed
111
	}
Wang's avatar
Wang committed
112 113

        rxF+=12;
hongzhi wang's avatar
hongzhi wang committed
114
        rxF_ext+=9;
Wang's avatar
Wang committed
115 116 117
      }
    }

hongzhi wang's avatar
hongzhi wang committed
118
    for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++) {
Wang's avatar
Wang committed
119
      if (high_speed_flag == 1)
hongzhi wang's avatar
hongzhi wang committed
120
        dl_ch0     = &dl_ch_estimates[(aatx<<1)+aarx][(symbol*(frame_parms->ofdm_symbol_size))];
Wang's avatar
Wang committed
121
      else
hongzhi wang's avatar
hongzhi wang committed
122 123
        dl_ch0     = &dl_ch_estimates[(aatx<<1)+aarx][0];

hongzhi wang's avatar
hongzhi wang committed
124
      //printf("dl_ch0 addr %p\n",dl_ch0);
Wang's avatar
Wang committed
125 126 127 128

      dl_ch0_ext = &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*(20*12)];

      for (rb=0; rb<20; rb++) {
hongzhi wang's avatar
hongzhi wang committed
129
	j=0;
hongzhi wang's avatar
hongzhi wang committed
130
        if ((symbol==5) || (symbol==7)) {
hongzhi wang's avatar
hongzhi wang committed
131
              	  for (i=0; i<12; i++) {
Wang's avatar
Wang committed
132 133 134
                    if ((i!=nushiftmod4) &&
                        (i!=(nushiftmod4+4)) &&
                        (i!=(nushiftmod4+8))) {
hongzhi wang's avatar
hongzhi wang committed
135
                           dl_ch0_ext[j]=dl_ch0[i];
hongzhi wang's avatar
hongzhi wang committed
136 137
			   if ((rb==0) && (i<2))
			     printf("dl ch0 ext[%d] = %d dl_ch0 [%d]= %d\n",j,dl_ch0_ext[j],i,dl_ch0[i]);
hongzhi wang's avatar
hongzhi wang committed
138
		           j++;
Wang's avatar
Wang committed
139 140 141 142
                    }
          	  }

          dl_ch0+=12;
hongzhi wang's avatar
hongzhi wang committed
143
          dl_ch0_ext+=9;
Wang's avatar
Wang committed
144
        }
hongzhi wang's avatar
hongzhi wang committed
145
        else { 
hongzhi wang's avatar
hongzhi wang committed
146
              if ((rb < 4) || (rb >15)){
Wang's avatar
Wang committed
147
              	  for (i=0; i<12; i++) {
hongzhi wang's avatar
hongzhi wang committed
148 149 150 151
                    if ((i!=nushiftmod4) &&
                        (i!=(nushiftmod4+4)) &&
                        (i!=(nushiftmod4+8))) {
		           dl_ch0_ext[j]=dl_ch0[i];
hongzhi wang's avatar
hongzhi wang committed
152
			   //printf("symbol2 dl ch0 ext[%d] = %d dl_ch0 [%d]= %d\n",j,dl_ch0_ext[j],i,dl_ch0[i]);
hongzhi wang's avatar
hongzhi wang committed
153
			   j++;
Wang's avatar
Wang committed
154 155 156 157 158
                       	}
               	  }
              }

              dl_ch0+=12;
hongzhi wang's avatar
hongzhi wang committed
159
              dl_ch0_ext+=9;
Wang's avatar
Wang committed
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

         }
      }
    }  //tx antenna loop

  }

  return(0);
}

//__m128i avg128;

//compute average channel_level on each (TX,RX) antenna pair
int nr_pbch_channel_level(int **dl_ch_estimates_ext,
                       NR_DL_FRAME_PARMS *frame_parms,
                       uint32_t symbol)
{

hongzhi wang's avatar
hongzhi wang committed
178
  int16_t rb, nb_rb=20;
Wang's avatar
Wang committed
179 180 181 182 183 184 185 186 187 188 189
  uint8_t aatx,aarx;

#if defined(__x86_64__) || defined(__i386__)
  __m128i avg128;
  __m128i *dl_ch128;
#elif defined(__arm__)
  int32x4_t avg128;
  int16x8_t *dl_ch128;
#endif
  int avg1=0,avg2=0;

hongzhi wang's avatar
hongzhi wang committed
190
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++)
Wang's avatar
Wang committed
191 192 193 194 195
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
      //clear average level

#if defined(__x86_64__) || defined(__i386__)
      avg128 = _mm_setzero_si128();
hongzhi wang's avatar
hongzhi wang committed
196
      dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12];
Wang's avatar
Wang committed
197 198
#elif defined(__arm__)
      avg128 = vdupq_n_s32(0);
hongzhi wang's avatar
hongzhi wang committed
199
      dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12];
Wang's avatar
Wang committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250

#endif
      for (rb=0; rb<nb_rb; rb++) {
#if defined(__x86_64__) || defined(__i386__)
        avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
        avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
        avg128 = _mm_add_epi32(avg128,_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
#elif defined(__arm__)
// to be filled in
#endif
        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]);
          }
        */
      }

      avg1 = (((int*)&avg128)[0] +
              ((int*)&avg128)[1] +
              ((int*)&avg128)[2] +
              ((int*)&avg128)[3])/(nb_rb*12);

      if (avg1>avg2)
        avg2 = avg1;

      //msg("Channel level : %d, %d\n",avg1, avg2);
    }
#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
  return(avg2);

}

#if defined(__x86_64__) || defined(__i386__)
__m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
#elif defined(__arm__)
int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
#endif
void nr_pbch_channel_compensation(int **rxdataF_ext,
                               int **dl_ch_estimates_ext,
                               int **rxdataF_comp,
                               NR_DL_FRAME_PARMS *frame_parms,
                               uint8_t symbol,
                               uint8_t output_shift)
{

hongzhi wang's avatar
hongzhi wang committed
251
  uint16_t rb,nb_rb=20;
Hongzhi Wang's avatar
Hongzhi Wang committed
252
  uint8_t aatx,aarx;
Wang's avatar
Wang committed
253 254 255 256 257 258
#if defined(__x86_64__) || defined(__i386__)
  __m128i *dl_ch128,*rxdataF128,*rxdataF_comp128;
#elif defined(__arm__)

#endif

hongzhi wang's avatar
hongzhi wang committed
259
  for (aatx=0; aatx<frame_parms->nb_antenna_ports_eNB;aatx++)
Wang's avatar
Wang committed
260 261 262
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {

#if defined(__x86_64__) || defined(__i386__)
hongzhi wang's avatar
hongzhi wang committed
263 264 265 266 267 268
      dl_ch128          = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12];
      rxdataF128        = (__m128i *)&rxdataF_ext[aarx][symbol*20*12];
      rxdataF_comp128   = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12];
      //printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*20*12]);
      //printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol);
      //printf("rxdataf_comp addr %p\n",&rxdataF_comp[(aatx<<1)+aarx][symbol*20*12]); 
Wang's avatar
Wang committed
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336

#elif defined(__arm__)
// to be filled in
#endif

      for (rb=0; rb<nb_rb; rb++) {
        //printf("rb %d\n",rb);
#if defined(__x86_64__) || defined(__i386__)
        // multiply by conjugated channel
        mmtmpP0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]);
        //  print_ints("re",&mmtmpP0);
        // mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
        mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
        mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
        //  print_ints("im",&mmtmpP1);
        mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[0]);
        // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
        //  print_ints("re(shift)",&mmtmpP0);
        mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
        //  print_ints("im(shift)",&mmtmpP1);
        mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
        mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
        //      print_ints("c0",&mmtmpP2);
        //  print_ints("c1",&mmtmpP3);
        rxdataF_comp128[0] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
        //  print_shorts("rx:",rxdataF128);
        //  print_shorts("ch:",dl_ch128);
        //  print_shorts("pack:",rxdataF_comp128);

        // multiply by conjugated channel
        mmtmpP0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]);
        // mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
        mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
        mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
        mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
        mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[1]);
        // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
        mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
        mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
        mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
        mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
        rxdataF_comp128[1] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
        //  print_shorts("rx:",rxdataF128+1);
        //  print_shorts("ch:",dl_ch128+1);
        //  print_shorts("pack:",rxdataF_comp128+1);

          // multiply by conjugated channel
          mmtmpP0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]);
          // mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
          mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1));
          mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
          mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
          mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[2]);
          // mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
          mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
          mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
          mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
          mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
          rxdataF_comp128[2] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
          //  print_shorts("rx:",rxdataF128+2);
          //  print_shorts("ch:",dl_ch128+2);
          //      print_shorts("pack:",rxdataF_comp128+2);

          dl_ch128+=3;
          rxdataF128+=3;
          rxdataF_comp128+=3;
hongzhi wang's avatar
hongzhi wang committed
337
        
Wang's avatar
Wang committed
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389
#elif defined(__arm__)
// to be filled in
#endif
      }
    }
#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
}

void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
                        int **rxdataF_comp,
                        uint8_t symbol)
{

  uint8_t aatx, symbol_mod;
  int i, nb_rb=6;
#if defined(__x86_64__) || defined(__i386__)
  __m128i *rxdataF_comp128_0,*rxdataF_comp128_1;
#elif defined(__arm__)
  int16x8_t *rxdataF_comp128_0,*rxdataF_comp128_1;
#endif
  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;

  if (frame_parms->nb_antennas_rx>1) {
    for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
#if defined(__x86_64__) || defined(__i386__)
      rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
      rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];
#elif defined(__arm__)
      rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
      rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];

#endif
      // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
      for (i=0; i<nb_rb*3; i++) {
#if defined(__x86_64__) || defined(__i386__)
        rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
#elif defined(__arm__)
        rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);

#endif
      }
    }
  }
#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
}

390 391 392 393 394 395
void nr_pbch_unscrambling(NR_UE_PBCH *pbch,
					   uint16_t Nid,
					   uint8_t nushift,
					   uint16_t M,
					   uint16_t length,
					   uint8_t bitwise)
Wang's avatar
Wang committed
396
{
397
  uint8_t reset, offset;
Wang's avatar
Wang committed
398
  uint32_t x1, x2, s=0;
hongzhi wang's avatar
hongzhi wang committed
399
  double *demod_pbch_e = pbch->demod_pbch_e;
400
  uint32_t unscrambling_mask = 0x100006D;
Wang's avatar
Wang committed
401

hongzhi wang's avatar
hongzhi wang committed
402
  printf("unscramb nid_cell %d\n",Nid);
hongzhi wang's avatar
hongzhi wang committed
403

Wang's avatar
Wang committed
404 405
  reset = 1;
  // x1 is set in first call to lte_gold_generic
406
  x2 = Nid; //this is c_init
Wang's avatar
Wang committed
407

408
  // The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
409
  for (int i=0; i<(uint16_t)ceil(((float)nushift*M)/32); i++) {
410 411 412 413 414 415 416 417 418 419 420 421
    s = lte_gold_generic(&x1, &x2, reset);
    reset = 0;
  }
  // Scrambling is now done with offset (nushift*M)%32
  offset = (nushift*M)&0x1f;

  for (int i=0; i<length; i++) {
      if (((i+offset)&0x1f)==0) {
        s = lte_gold_generic(&x1, &x2, reset);
        reset = 0;
      }
  #ifdef DEBUG_PBCH_ENCODING
hongzhi wang's avatar
hongzhi wang committed
422
      if (i<8)
423
    printf("s: %04x\t", s);
424
    printf("pbch_a_interleaved 0x%08x\n", pbch->pbch_a_interleaved);
425 426
  #endif
      if (bitwise) {
427 428
	
        (pbch->pbch_a_interleaved) ^= ((unscrambling_mask>>i)&1)? ((pbch->pbch_a_prime>>i)&1)<<i : (((pbch->pbch_a_prime>>i)&1) ^ ((s>>((i+offset)&0x1f))&1))<<i;
429
      }
Wang's avatar
Wang committed
430

431 432
      else {
    	  if (((s>>((i+offset)&0x1f))&1)==1)
hongzhi wang's avatar
hongzhi wang committed
433
    		  demod_pbch_e[i] = -demod_pbch_e[i];
hongzhi wang's avatar
hongzhi wang committed
434 435 436 437
#ifdef DEBUG_PBCH_ENCODING
		if (i<8)
	printf("s %d demod_pbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_pbch_e[i]);
#endif
438
      }
Wang's avatar
Wang committed
439
  }
440

Wang's avatar
Wang committed
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
}

void nr_pbch_alamouti(NR_DL_FRAME_PARMS *frame_parms,
                   int **rxdataF_comp,
                   uint8_t symbol)
{


  int16_t *rxF0,*rxF1;
  //  __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b;
  uint8_t rb,re,symbol_mod;
  int jj;

  //  printf("Doing alamouti\n");
  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
  jj         = (symbol_mod*6*12);

  rxF0     = (int16_t*)&rxdataF_comp[0][jj];  //tx antenna 0  h0*y
  rxF1     = (int16_t*)&rxdataF_comp[2][jj];  //tx antenna 1  h1*y

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

    for (re=0; re<12; re+=2) {

      // Alamouti RX combining

      rxF0[0] = rxF0[0] + rxF1[2];
      rxF0[1] = rxF0[1] - rxF1[3];

      rxF0[2] = rxF0[2] - rxF1[0];
      rxF0[3] = rxF0[3] + rxF1[1];

      rxF0+=4;
      rxF1+=4;
    }

  }

}

hongzhi wang's avatar
hongzhi wang committed
481
void nr_pbch_quantize(int8_t *pbch_llr8,
Wang's avatar
Wang committed
482 483 484 485 486 487 488
                   int16_t *pbch_llr,
                   uint16_t len)
{

  uint16_t i;

  for (i=0; i<len; i++) {
489 490 491 492 493
    if (pbch_llr[i]>127)
      pbch_llr8[i]=127;
    else if (pbch_llr[i]<-128)
      pbch_llr8[i]=-128;
    else
hongzhi wang's avatar
hongzhi wang committed
494
      pbch_llr8[i] = (char)(pbch_llr[i]);
Wang's avatar
Wang committed
495 496 497 498

  }
}

hongzhi wang's avatar
hongzhi wang committed
499 500
unsigned char sign(int8_t x) {
  return (unsigned char)x >> 7;
hongzhi wang's avatar
hongzhi wang committed
501 502
}

503 504
uint8_t pbch_deinterleaving_pattern[32] = {28,0,31,30,1,29,25,27,22,2,24,3,4,5,6,7,18,21,20,8,9,10,11,19,26,12,13,14,15,16,23,17};

Hongzhi Wang's avatar
Hongzhi Wang committed
505
int nr_rx_pbch( PHY_VARS_NR_UE *ue,
hongzhi wang's avatar
hongzhi wang committed
506 507 508 509 510
		     UE_nr_rxtx_proc_t *proc,
		     NR_UE_PBCH *nr_ue_pbch_vars,
		     NR_DL_FRAME_PARMS *frame_parms,
		     uint8_t eNB_id,
		     MIMO_mode_t mimo_mode,
hongzhi wang's avatar
hongzhi wang committed
511
		     uint32_t high_speed_flag)
Wang's avatar
Wang committed
512 513 514 515
{

  NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;

Hongzhi Wang's avatar
Hongzhi Wang committed
516
  uint8_t log2_maxh;
Wang's avatar
Wang committed
517 518 519
  int max_h=0;

  int symbol,i;
hongzhi wang's avatar
hongzhi wang committed
520
  //uint8_t pbch_a[64];
521
  uint8_t *pbch_a = malloc(sizeof(uint8_t) * 32);
522
  uint32_t pbch_a_prime;
hongzhi wang's avatar
hongzhi wang committed
523
  int8_t *pbch_e_rx;
Wang's avatar
Wang committed
524
  uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output;
525 526 527 528
  uint8_t nushift;
  uint16_t M;
  uint8_t Lmax=8; //to update
  uint8_t ssb_index=0;
hongzhi wang's avatar
hongzhi wang committed
529
  //uint16_t crc;
hongzhi wang's avatar
hongzhi wang committed
530
  //short nr_demod_table[8] = {0,0,0,1,1,0,1,1};
531
  double nr_demod_table[8] = {0.707,0.707,-0.707,0.707,0.707,-0.707,-0.707,-0.707};
hongzhi wang's avatar
hongzhi wang committed
532 533
  double *demod_pbch_e  = malloc (sizeof(double) * 864); 
  unsigned short idx_demod =0;
Hongzhi Wang's avatar
Hongzhi Wang committed
534 535
  int8_t decoderState=0;
  uint8_t decoderListSize = 8, pathMetricAppr = 0;
hongzhi wang's avatar
hongzhi wang committed
536
  //double aPrioriArray[frame_parms->pbch_polar_params.payloadBits];  // assume no a priori knowledge available about the payload.
hongzhi wang's avatar
hongzhi wang committed
537

Hongzhi Wang's avatar
Hongzhi Wang committed
538
  memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
hongzhi wang's avatar
hongzhi wang committed
539

Hongzhi Wang's avatar
Hongzhi Wang committed
540
  //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell);
hongzhi wang's avatar
hongzhi wang committed
541

hongzhi wang's avatar
hongzhi wang committed
542
  //for (int i=0; i<frame_parms->pbch_polar_params.payloadBits; i++) aPrioriArray[i] = NAN;
Wang's avatar
Wang committed
543 544

  int subframe_rx = proc->subframe_rx;
hongzhi wang's avatar
hongzhi wang committed
545 546
  
  printf("ue->current_thread_id[subframe_rx] %d subframe_rx %d\n",ue->current_thread_id[subframe_rx], subframe_rx);
Wang's avatar
Wang committed
547

Hongzhi Wang's avatar
Hongzhi Wang committed
548
  pbch_e_rx = &nr_ue_pbch_vars->llr[0];
Wang's avatar
Wang committed
549 550

  // clear LLR buffer
Hongzhi Wang's avatar
Hongzhi Wang committed
551
  memset(nr_ue_pbch_vars->llr,0,NR_POLAR_PBCH_E);
Wang's avatar
Wang committed
552

Hongzhi Wang's avatar
Hongzhi Wang committed
553
  for (symbol=5; symbol<8; symbol++) {
Wang's avatar
Wang committed
554

hongzhi wang's avatar
hongzhi wang committed
555
    //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF);
hongzhi wang's avatar
hongzhi wang committed
556
    //write_output("rxdataF0_pbch.m","rxF0pbch",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF,frame_parms->ofdm_symbol_size*4,2,1);
hongzhi wang's avatar
hongzhi wang committed
557
  
Wang's avatar
Wang committed
558 559 560 561 562 563 564 565
    nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF,
                 nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].dl_ch_estimates[eNB_id],
                 nr_ue_pbch_vars->rxdataF_ext,
                 nr_ue_pbch_vars->dl_ch_estimates_ext,
                 symbol,
                 high_speed_flag,
                 frame_parms);
#ifdef DEBUG_PBCH
Hongzhi Wang's avatar
Hongzhi Wang committed
566
    msg("[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
Wang's avatar
Wang committed
567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585
    msg("[PHY] PBCH starting channel_level\n");
#endif

    max_h = nr_pbch_channel_level(nr_ue_pbch_vars->dl_ch_estimates_ext,
                               frame_parms,
                               symbol);
    log2_maxh = 3+(log2_approx(max_h)/2);

#ifdef DEBUG_PBCH
    msg("[PHY] PBCH log2_maxh = %d (%d)\n",log2_maxh,max_h);
#endif

    nr_pbch_channel_compensation(nr_ue_pbch_vars->rxdataF_ext,
                              nr_ue_pbch_vars->dl_ch_estimates_ext,
                              nr_ue_pbch_vars->rxdataF_comp,
                              frame_parms,
                              symbol,
                              log2_maxh); // log2_maxh+I0_shift

hongzhi wang's avatar
hongzhi wang committed
586 587
    //write_output("rxdataF_comp.m","rxFcomp",nr_ue_pbch_vars->rxdataF_comp,180,2,1);
  
Wang's avatar
Wang committed
588 589 590 591 592 593 594 595 596 597 598 599 600
    /*if (frame_parms->nb_antennas_rx > 1)
      pbch_detection_mrc(frame_parms,
                         nr_ue_pbch_vars->rxdataF_comp,
                         symbol);*/


    if (mimo_mode == ALAMOUTI) {
      nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol);
    } else if (mimo_mode != SISO) {
      msg("[PBCH][RX] Unsupported MIMO mode\n");
      return(-1);
    }

hongzhi wang's avatar
hongzhi wang committed
601
    if (symbol==6) {
Wang's avatar
Wang committed
602
      nr_pbch_quantize(pbch_e_rx,
Hongzhi Wang's avatar
Hongzhi Wang committed
603
                    (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
Hongzhi Wang's avatar
Hongzhi Wang committed
604
                    144);
Wang's avatar
Wang committed
605

Hongzhi Wang's avatar
Hongzhi Wang committed
606
      pbch_e_rx+=144;
Wang's avatar
Wang committed
607 608
    } else {
      nr_pbch_quantize(pbch_e_rx,
Hongzhi Wang's avatar
Hongzhi Wang committed
609 610
                    (short*)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
                    360);
Wang's avatar
Wang committed
611

Hongzhi Wang's avatar
Hongzhi Wang committed
612
      pbch_e_rx+=360;
Wang's avatar
Wang committed
613 614 615 616 617 618
    }


  }

  pbch_e_rx = nr_ue_pbch_vars->llr;
619 620
  demod_pbch_e = nr_ue_pbch_vars->demod_pbch_e;
  pbch_a = nr_ue_pbch_vars->pbch_a;
Hongzhi Wang's avatar
Hongzhi Wang committed
621

622
#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
623
  //pbch_e_rx = &nr_ue_pbch_vars->llr[0];
Wang's avatar
Wang committed
624

hongzhi wang's avatar
hongzhi wang committed
625
  short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][5*20*12]);
626
  for (int cnt = 0; cnt < 32 ; cnt++)
hongzhi wang's avatar
hongzhi wang committed
627
    printf("pbch rx llr %d rxdata_comp %d addr %p\n",*(pbch_e_rx+cnt), p[cnt], &p[0]);
628
#endif
Wang's avatar
Wang committed
629

Hongzhi Wang's avatar
Hongzhi Wang committed
630
  for (i=0; i<NR_POLAR_PBCH_E/2; i++){
hongzhi wang's avatar
hongzhi wang committed
631 632 633
    idx_demod = (sign(pbch_e_rx[i<<1])&1) ^ ((sign(pbch_e_rx[(i<<1)+1])&1)<<1);
    demod_pbch_e[i<<1] = nr_demod_table[(idx_demod)<<1];
    demod_pbch_e[(i<<1)+1] = nr_demod_table[((idx_demod)<<1)+1];
Hongzhi Wang's avatar
Hongzhi Wang committed
634
#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
635 636 637
    if (i<16){
    printf("idx[%d]= %d\n", i , idx_demod);
    printf("sign[%d]= %d sign[%d]= %d\n", i<<1 , sign(pbch_e_rx[i<<1]), (i<<1)+1 , sign(pbch_e_rx[(i<<1)+1]));
Hongzhi Wang's avatar
Hongzhi Wang committed
638
    printf("demod_pbch_e[%d] r = %2.3f i = %2.3f\n", i<<1 , demod_pbch_e[i<<1], demod_pbch_e[(i<<1)+1]);}
Hongzhi Wang's avatar
Hongzhi Wang committed
639
#endif
hongzhi wang's avatar
hongzhi wang committed
640 641
  }

642 643 644 645
  //un-scrambling
  M =  NR_POLAR_PBCH_E;
  nushift = (Lmax==4)? ssb_index&3 : ssb_index&7;
  nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0);
Hongzhi Wang's avatar
Hongzhi Wang committed
646

647
//#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
648
    for (i=0; i<16; i++){
Hongzhi Wang's avatar
Hongzhi Wang committed
649
    printf("unscrambling demod_pbch_e[%d] r = %2.3f i = %2.3f\n", i<<1 , demod_pbch_e[i<<1], demod_pbch_e[(i<<1)+1]);}
650
//#endif
Turker YILMAZ's avatar
Turker YILMAZ committed
651
		uint32_t pbch_out;
Hongzhi Wang's avatar
Hongzhi Wang committed
652
  //polar decoding de-rate matching
hongzhi wang's avatar
hongzhi wang committed
653 654 655 656 657 658
  t_nrPolar_paramsPtr nrPolar_params = NULL, currentPtr = NULL;
   nr_polar_init(&nrPolar_params,
    		  	  	NR_POLAR_PBCH_MESSAGE_TYPE,
					NR_POLAR_PBCH_PAYLOAD_BITS,
					NR_POLAR_PBCH_AGGREGATION_LEVEL);
  currentPtr = nr_polar_params(nrPolar_params, NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL);
Turker YILMAZ's avatar
Turker YILMAZ committed
659 660
  double aPrioriArray[currentPtr->payloadBits];
  for (int i=0; i<currentPtr->payloadBits; i++) aPrioriArray[i] = NAN;
661
  decoderState = polar_decoder_aPriori(demod_pbch_e,&nr_ue_pbch_vars->pbch_a_prime, currentPtr, decoderListSize, pathMetricAppr,aPrioriArray);
hongzhi wang's avatar
hongzhi wang committed
662
  printf("polar decoder state %d\n", decoderState);
663 664
  if(decoderState == -1)
  	return(decoderState);
Turker YILMAZ's avatar
Turker YILMAZ committed
665
  	
666
  	//printf("polar decoder output 0x%08x\n",nr_ue_pbch_vars->pbch_a_prime);
hongzhi wang's avatar
hongzhi wang committed
667
  
668
  //payload un-scrambling
669
  memset(&nr_ue_pbch_vars->pbch_a_interleaved, 0, sizeof(uint32_t) );
670
  M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
671 672
  nushift = ((nr_ue_pbch_vars->pbch_a_prime>>6)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>24)&1)<<1);
  printf("payload unscrambling nushift %d sfn3 %d sfn2 %d M %d\n",nushift, ((nr_ue_pbch_vars->pbch_a_prime>>6)&1),((nr_ue_pbch_vars->pbch_a_prime>>24)&1),M);
673 674 675 676 677 678
  nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1);

  //payload deinterleaving
  uint32_t in=0, out=0;

  for (int i=0; i<32; i++) {
679
    out |= ((nr_ue_pbch_vars->pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]);
680
#ifdef DEBUG_PBCH
681
  printf("i %d in 0x%08x out 0x%08x ilv %d (in>>i)&1) 0x%08x\n", i, nr_ue_pbch_vars->pbch_a_interleaved, out, pbch_deinterleaving_pattern[i], (in>>i)&1);
682
#endif
683 684 685
  }

  for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS>>3; i++)
hongzhi wang's avatar
hongzhi wang committed
686
	  pbch_a[i] = (uint8_t)((out>>(i<<3))&0xff);
hongzhi wang's avatar
hongzhi wang committed
687

Hongzhi Wang's avatar
Hongzhi Wang committed
688
  // Fix byte endian
689 690
  for (i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++)
     decoded_output[(NR_POLAR_PBCH_PAYLOAD_BITS>>3)-i-1] = pbch_a[i];
hongzhi wang's avatar
hongzhi wang committed
691
     
hongzhi wang's avatar
hongzhi wang committed
692
  //#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
693
  for (i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++){
hongzhi wang's avatar
hongzhi wang committed
694 695
  	  //printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]);
  	  printf("[PBCH] decoder payload[%d] = %x\n",i,decoded_output[i]);
hongzhi wang's avatar
hongzhi wang committed
696
  }
hongzhi wang's avatar
hongzhi wang committed
697
	  //#endif
698 699 700
    ue->dl_indication.rx_ind = &ue->rx_ind; //  hang on rx_ind instance
    //ue->rx_ind.sfn_slot = 0;  //should be set by higher-1-layer, i.e. clean_and_set_if_instance()
    ue->rx_ind.number_pdus = ue->rx_ind.number_pdus + 1;
701 702 703 704 705 706 707
    ue->rx_ind.rx_indication_body = (fapi_nr_rx_indication_body_t *)malloc(sizeof(fapi_nr_rx_indication_body_t));
    ue->rx_ind.rx_indication_body->pdu_type = FAPI_NR_RX_PDU_TYPE_MIB;
    ue->rx_ind.rx_indication_body->mib_pdu.pdu = &decoded_output[1];
    ue->rx_ind.rx_indication_body->mib_pdu.additional_bits = decoded_output[0];
    ue->rx_ind.rx_indication_body->mib_pdu.ssb_index = ssb_index;            //  confirm with TCL
    ue->rx_ind.rx_indication_body->mib_pdu.ssb_length = Lmax;                //  confirm with TCL
    ue->rx_ind.rx_indication_body->mib_pdu.cell_id = frame_parms->Nid_cell;  //  confirm with TCL
708

709
    ue->if_inst->dl_indication(&ue->dl_indication);
710 711

    return 0;    
Wang's avatar
Wang committed
712
}