nr_pbch.c 21.7 KB
Newer Older
Hongzhi Wang's avatar
Hongzhi 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 "PHY/LTE_REFSIG/lte_refsig.h"
37
#include "PHY/INIT/phy_init.h"
cig's avatar
cig committed
38
#include "openair1/SCHED_NR_UE/defs.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
39

Rakesh's avatar
Rakesh committed
40
//#define DEBUG_PBCH 
Hongzhi Wang's avatar
Hongzhi Wang committed
41 42 43
//#define DEBUG_PBCH_ENCODING

#ifdef OPENAIR2
44
  //#include "PHY_INTERFACE/defs.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
45 46 47 48
#endif

#define PBCH_A 24

Raymond Knopp's avatar
Raymond Knopp committed
49
#define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7])
Hongzhi Wang's avatar
Hongzhi Wang committed
50 51

uint16_t nr_pbch_extract(int **rxdataF,
52 53 54 55 56 57 58
                         int **dl_ch_estimates,
                         int **rxdataF_ext,
                         int **dl_ch_estimates_ext,
                         uint32_t symbol,
                         uint32_t s_offset,
                         uint32_t high_speed_flag,
                         NR_DL_FRAME_PARMS *frame_parms) {
Hongzhi Wang's avatar
Hongzhi Wang committed
59
  uint16_t rb;
Raymond Knopp's avatar
Raymond Knopp committed
60
  uint8_t i,j,aarx;
hongzhi wang's avatar
hongzhi wang committed
61 62
  int32_t *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
  int nushiftmod4 = frame_parms->nushift;
63 64 65 66

  AssertFatal(symbol>=1 && symbol<5,
              "symbol %d illegal for PBCH extraction\n",
              symbol);
Raymond Knopp's avatar
Raymond Knopp committed
67

Hongzhi Wang's avatar
Hongzhi Wang committed
68
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
69 70 71
    unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier;
    rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);

72
    rxF        = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size];
73
    rxF_ext    = &rxdataF_ext[aarx][symbol*20*12];
hongzhi wang's avatar
hongzhi wang committed
74
#ifdef DEBUG_PBCH
75
    printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",frame_parms->nushift,
76 77 78 79 80 81 82 83 84
           (rx_offset + ((symbol+s_offset)*(frame_parms->ofdm_symbol_size))),symbol);
    int16_t *p = (int16_t *)rxF;

    for (int i =0; i<8; i++) {
      printf("rxF [%d]= %d\n",i,rxF[i]);
      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
85
#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
86 87

    for (rb=0; rb<20; rb++) {
hongzhi wang's avatar
hongzhi wang committed
88
      j=0;
Raymond Knopp's avatar
Raymond Knopp committed
89

90
      if (symbol==1 || symbol==3) {
Hongzhi Wang's avatar
Hongzhi Wang committed
91 92 93 94
        for (i=0; i<12; i++) {
          if ((i!=nushiftmod4) &&
              (i!=(nushiftmod4+4)) &&
              (i!=(nushiftmod4+8))) {
Raymond Knopp's avatar
Raymond Knopp committed
95 96
            rxF_ext[j]=rxF[rx_offset];
#ifdef DEBUG_PBCH
yilmazt's avatar
yilmazt committed
97
            printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(9*rb) + j,
98 99 100 101 102
                   ((int16_t *)&rxF_ext[j])[0],
                   ((int16_t *)&rxF_ext[j])[1],
                   rx_offset,
                   ((int16_t *)&rxF[rx_offset])[0],
                   ((int16_t *)&rxF[rx_offset])[1]);
Raymond Knopp's avatar
Raymond Knopp committed
103
#endif
104
            j++;
Hongzhi Wang's avatar
Hongzhi Wang committed
105
          }
106

Rakesh's avatar
Rakesh committed
107 108
          rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size);
          //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1);
109
	}
110

hongzhi wang's avatar
hongzhi wang committed
111
        rxF_ext+=9;
Hongzhi Wang's avatar
Hongzhi Wang committed
112
      } else { //symbol 2
113 114 115 116 117 118
        if ((rb < 4) || (rb >15)) {
          for (i=0; i<12; i++) {
            if ((i!=nushiftmod4) &&
                (i!=(nushiftmod4+4)) &&
                (i!=(nushiftmod4+8))) {
              rxF_ext[j]=rxF[rx_offset];
Raymond Knopp's avatar
Raymond Knopp committed
119
#ifdef DEBUG_PBCH
yilmazt's avatar
yilmazt committed
120
              printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",(rb<4) ? (9*rb) + j : (9*(rb-12))+j,
121 122 123 124 125 126 127 128 129
                     ((int16_t *)&rxF_ext[j])[0],
                     ((int16_t *)&rxF_ext[j])[1],
                     rx_offset,
                     ((int16_t *)&rxF[rx_offset])[0],
                     ((int16_t *)&rxF[rx_offset])[1]);
#endif
              j++;
            }

Rakesh's avatar
Rakesh committed
130 131
            rx_offset=(rx_offset+1)%(frame_parms->ofdm_symbol_size);
            //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 1) : (rx_offset+1);
132 133 134
          }

          rxF_ext+=9;
Rakesh's avatar
Rakesh committed
135 136 137
        } else{ //rx_offset = (rx_offset >= frame_parms->ofdm_symbol_size) ? (rx_offset - frame_parms->ofdm_symbol_size + 12) : (rx_offset+12);
                rx_offset = (rx_offset+12)%(frame_parms->ofdm_symbol_size);
          }
Hongzhi Wang's avatar
Hongzhi Wang committed
138 139 140
      }
    }

Raymond Knopp's avatar
Raymond Knopp committed
141
    if (high_speed_flag == 1)
142
      dl_ch0     = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
Raymond Knopp's avatar
Raymond Knopp committed
143 144
    else
      dl_ch0     = &dl_ch_estimates[aarx][0];
145

Raymond Knopp's avatar
Raymond Knopp committed
146
    //printf("dl_ch0 addr %p\n",dl_ch0);
147
    dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*20*12];
148

Raymond Knopp's avatar
Raymond Knopp committed
149 150
    for (rb=0; rb<20; rb++) {
      j=0;
151

152
      if (symbol==1 || symbol==3) {
153 154 155 156 157
        for (i=0; i<12; i++) {
          if ((i!=nushiftmod4) &&
              (i!=(nushiftmod4+4)) &&
              (i!=(nushiftmod4+8))) {
            dl_ch0_ext[j]=dl_ch0[i];
Raymond Knopp's avatar
Raymond Knopp committed
158
#ifdef DEBUG_PBCH
159 160 161 162 163 164 165 166 167

            if ((rb==0) && (i<2))
              printf("dl ch0 ext[%d] = (%d,%d)  dl_ch0 [%d]= (%d,%d)\n",j,
                     ((int16_t *)&dl_ch0_ext[j])[0],
                     ((int16_t *)&dl_ch0_ext[j])[1],
                     i,
                     ((int16_t *)&dl_ch0[i])[0],
                     ((int16_t *)&dl_ch0[i])[1]);

Raymond Knopp's avatar
Raymond Knopp committed
168
#endif
169 170 171 172 173 174 175 176 177 178 179 180 181
            j++;
          }
        }

        dl_ch0+=12;
        dl_ch0_ext+=9;
      } else {
        if ((rb < 4) || (rb >15)) {
          for (i=0; i<12; i++) {
            if ((i!=nushiftmod4) &&
                (i!=(nushiftmod4+4)) &&
                (i!=(nushiftmod4+8))) {
              dl_ch0_ext[j]=dl_ch0[i];
Raymond Knopp's avatar
Raymond Knopp committed
182
#ifdef DEBUG_PBCH
183 184 185 186 187 188
              printf("dl ch0 ext[%d] = (%d,%d)  dl_ch0 [%d]= (%d,%d)\n",j,
                     ((int16_t *)&dl_ch0_ext[j])[0],
                     ((int16_t *)&dl_ch0_ext[j])[1],
                     i,
                     ((int16_t *)&dl_ch0[i])[0],
                     ((int16_t *)&dl_ch0[i])[1]);
Raymond Knopp's avatar
Raymond Knopp committed
189
#endif
190 191 192 193 194 195 196 197
              j++;
            }
          }

          dl_ch0_ext+=9;
        }

        dl_ch0+=12;
Raymond Knopp's avatar
Raymond Knopp committed
198 199
      }
    }
Hongzhi Wang's avatar
Hongzhi Wang committed
200 201 202 203 204 205 206 207 208
  }

  return(0);
}

//__m128i avg128;

//compute average channel_level on each (TX,RX) antenna pair
int nr_pbch_channel_level(int **dl_ch_estimates_ext,
209 210
                          NR_DL_FRAME_PARMS *frame_parms,
                          uint32_t symbol) {
hongzhi wang's avatar
hongzhi wang committed
211
  int16_t rb, nb_rb=20;
Raymond Knopp's avatar
Raymond Knopp committed
212
  uint8_t aarx;
Hongzhi Wang's avatar
Hongzhi Wang committed
213 214 215 216 217 218 219 220 221
#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;

Raymond Knopp's avatar
Raymond Knopp committed
222 223
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
    //clear average level
Hongzhi Wang's avatar
Hongzhi Wang committed
224
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
Raymond Knopp committed
225 226
    avg128 = _mm_setzero_si128();
    dl_ch128=(__m128i *)&dl_ch_estimates_ext[aarx][symbol*20*12];
Hongzhi Wang's avatar
Hongzhi Wang committed
227
#elif defined(__arm__)
Raymond Knopp's avatar
Raymond Knopp committed
228 229
    avg128 = vdupq_n_s32(0);
    dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[aarx][symbol*20*12];
Hongzhi Wang's avatar
Hongzhi Wang committed
230
#endif
231

Raymond Knopp's avatar
Raymond Knopp committed
232
    for (rb=0; rb<nb_rb; rb++) {
Hongzhi Wang's avatar
Hongzhi Wang committed
233
#if defined(__x86_64__) || defined(__i386__)
Raymond Knopp's avatar
Raymond Knopp committed
234 235 236
      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]));
Hongzhi Wang's avatar
Hongzhi Wang committed
237
#elif defined(__arm__)
238
      // to be filled in
Hongzhi Wang's avatar
Hongzhi Wang committed
239
#endif
Raymond Knopp's avatar
Raymond Knopp committed
240 241 242
      dl_ch128+=3;
      /*
      if (rb==0) {
243 244 245 246
      print_shorts("dl_ch128",&dl_ch128[0]);
      print_shorts("dl_ch128",&dl_ch128[1]);
      print_shorts("dl_ch128",&dl_ch128[2]);
      }*/
Hongzhi Wang's avatar
Hongzhi Wang committed
247
    }
248 249 250 251 252 253

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

Raymond Knopp's avatar
Raymond Knopp committed
254 255
    if (avg1>avg2)
      avg2 = avg1;
256

Raymond Knopp's avatar
Raymond Knopp committed
257 258
    //LOG_I(PHY,"Channel level : %d, %d\n",avg1, avg2);
  }
259

Hongzhi Wang's avatar
Hongzhi Wang committed
260 261 262 263 264 265 266 267
#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
  return(avg2);
}

void nr_pbch_channel_compensation(int **rxdataF_ext,
268 269 270 271 272
                                  int **dl_ch_estimates_ext,
                                  int **rxdataF_comp,
                                  NR_DL_FRAME_PARMS *frame_parms,
                                  uint32_t symbol,
                                  uint8_t output_shift) {
laurent's avatar
laurent committed
273
  const uint16_t nb_re=symbol == 2 ? 72 : 180;
274
  AssertFatal((symbol > 0 && symbol < 4),
275 276
              "symbol %d is illegal for PBCH DM-RS\n",
              symbol);
Hongzhi Wang's avatar
Hongzhi Wang committed
277

278 279
  //  printf("comp: symbol %d : nb_re %d\n",symbol,nb_re);

laurent's avatar
laurent committed
280 281 282 283
  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
    vect128 *dl_ch128          = (vect128 *)&dl_ch_estimates_ext[aarx][symbol*20*12];
    vect128 *rxdataF128        = (vect128 *)&rxdataF_ext[aarx][symbol*20*12];
    vect128 *rxdataF_comp128   = (vect128 *)&rxdataF_comp[aarx][symbol*20*12];
Raymond Knopp's avatar
Raymond Knopp committed
284 285 286
    /*
    printf("ch compensation dl_ch ext addr %p \n", &dl_ch_estimates_ext[aarx][symbol*20*12]);
    printf("rxdataf ext addr %p symbol %d\n", &rxdataF_ext[aarx][symbol*20*12], symbol);
287
    printf("rxdataf_comp addr %p\n",&rxdataF_comp[aarx][symbol*20*12]);
Raymond Knopp's avatar
Raymond Knopp committed
288
    */
Hongzhi Wang's avatar
Hongzhi Wang committed
289

Raymond Knopp's avatar
Raymond Knopp committed
290
    for (int re=0; re<nb_re; re+=12) {
laurent's avatar
laurent committed
291 292 293
      *rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
      *rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
      *rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
Hongzhi Wang's avatar
Hongzhi Wang committed
294
    }
Raymond Knopp's avatar
Raymond Knopp committed
295
  }
Hongzhi Wang's avatar
Hongzhi Wang committed
296 297 298
}

void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
299 300
                           int **rxdataF_comp,
                           uint8_t symbol) {
Raymond Knopp's avatar
Raymond Knopp committed
301
  uint8_t symbol_mod;
Hongzhi Wang's avatar
Hongzhi Wang committed
302 303 304 305 306 307 308 309 310 311
  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) {
#if defined(__x86_64__) || defined(__i386__)
312 313
    rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[0][symbol_mod*6*12];
    rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[1][symbol_mod*6*12];
Hongzhi Wang's avatar
Hongzhi Wang committed
314
#elif defined(__arm__)
315 316
    rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[0][symbol_mod*6*12];
    rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[1][symbol_mod*6*12];
Hongzhi Wang's avatar
Hongzhi Wang committed
317
#endif
318 319 320

    // 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++) {
Hongzhi Wang's avatar
Hongzhi Wang committed
321
#if defined(__x86_64__) || defined(__i386__)
322
      rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
Hongzhi Wang's avatar
Hongzhi Wang committed
323
#elif defined(__arm__)
324
      rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
Hongzhi Wang's avatar
Hongzhi Wang committed
325 326
#endif
    }
327
  }
Raymond Knopp's avatar
Raymond Knopp committed
328

Hongzhi Wang's avatar
Hongzhi Wang committed
329 330 331 332 333 334
#if defined(__x86_64__) || defined(__i386__)
  _mm_empty();
  _m_empty();
#endif
}

335
void nr_pbch_unscrambling(NR_UE_PBCH *pbch,
336 337 338 339 340 341
                          uint16_t Nid,
                          uint8_t nushift,
                          uint16_t M,
                          uint16_t length,
                          uint8_t bitwise,
                          uint32_t unscrambling_mask) {
342
  uint8_t reset, offset;
Hongzhi Wang's avatar
Hongzhi Wang committed
343
  uint32_t x1, x2, s=0;
Guy De Souza's avatar
Guy De Souza committed
344
  uint8_t k=0;
345
  int16_t *demod_pbch_e = pbch->llr;
Hongzhi Wang's avatar
Hongzhi Wang committed
346 347
  reset = 1;
  // x1 is set in first call to lte_gold_generic
348
  x2 = Nid; //this is c_init
Hongzhi Wang's avatar
Hongzhi Wang committed
349

350
  // The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
351
  for (int i=0; i<(uint16_t)ceil(((float)nushift*M)/32); i++) {
352 353 354
    s = lte_gold_generic(&x1, &x2, reset);
    reset = 0;
  }
355

356 357 358 359
  // Scrambling is now done with offset (nushift*M)%32
  offset = (nushift*M)&0x1f;

  for (int i=0; i<length; i++) {
360 361 362 363 364
    /*if (((i+offset)&0x1f)==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
    }*/
    if (bitwise) {
365
      if (((k+offset)&0x1f)==0 && (!((unscrambling_mask>>i)&1))) {
366 367 368
        s = lte_gold_generic(&x1, &x2, reset);
        reset = 0;
      }
369 370 371

      (pbch->pbch_a_interleaved) ^= ((unscrambling_mask>>i)&1)? ((pbch->pbch_a_prime>>i)&1)<<i : (((pbch->pbch_a_prime>>i)&1) ^ ((s>>((k+offset)&0x1f))&1))<<i;
      k += (!((unscrambling_mask>>i)&1));
Raymond Knopp's avatar
Raymond Knopp committed
372
#ifdef DEBUG_PBCH_ENCODING
373 374
      printf("i %d k %d offset %d (unscrambling_mask>>i)&1) %d s: %08x\t  pbch_a_interleaved 0x%08x (!((unscrambling_mask>>i)&1)) %d\n", i, k, offset, (unscrambling_mask>>i)&1, s, pbch->pbch_a_interleaved,
             (!((unscrambling_mask>>i)&1)));
Raymond Knopp's avatar
Raymond Knopp committed
375
#endif
376
    } else {
377 378 379 380
      if (((i+offset)&0x1f)==0) {
        s = lte_gold_generic(&x1, &x2, reset);
        reset = 0;
      }
381 382 383 384

      if (((s>>((i+offset)&0x1f))&1)==1)
        demod_pbch_e[i] = -demod_pbch_e[i];

385
#ifdef DEBUG_PBCH_ENCODING
386 387 388 389

      if (i<8)
        printf("s %d demod_pbch_e[i] %d\n", ((s>>((i+offset)&0x1f))&1), demod_pbch_e[i]);

390
#endif
391
    }
Hongzhi Wang's avatar
Hongzhi Wang committed
392 393 394
  }
}

395 396
void nr_pbch_quantize(int16_t *pbch_llr8,
                      int16_t *pbch_llr,
397
                      uint16_t len) {
Hongzhi Wang's avatar
Hongzhi Wang committed
398 399 400
  uint16_t i;

  for (i=0; i<len; i++) {
401 402 403 404
    if (pbch_llr[i]>31)
      pbch_llr8[i]=32;
    else if (pbch_llr[i]<-31)
      pbch_llr8[i]=-32;
405
    else
hongzhi wang's avatar
hongzhi wang committed
406
      pbch_llr8[i] = (char)(pbch_llr[i]);
Hongzhi Wang's avatar
Hongzhi Wang committed
407 408
  }
}
409
/*
hongzhi wang's avatar
hongzhi wang committed
410 411
unsigned char sign(int8_t x) {
  return (unsigned char)x >> 7;
hongzhi wang's avatar
hongzhi wang committed
412
}
413
*/
hongzhi wang's avatar
hongzhi wang committed
414

Guy De Souza's avatar
Guy De Souza committed
415
uint8_t pbch_deinterleaving_pattern[32] = {28,0,31,30,7,29,25,27,5,8,24,9,10,11,12,13,1,4,3,14,15,16,17,2,26,18,19,20,21,22,6,23};
Hongzhi Wang's avatar
Hongzhi Wang committed
416

417
int nr_rx_pbch( PHY_VARS_NR_UE *ue,
laurent's avatar
fixes  
laurent committed
418
                UE_nr_rxtx_proc_t *proc,
419 420
                NR_UE_PBCH *nr_ue_pbch_vars,
                NR_DL_FRAME_PARMS *frame_parms,
421
                uint8_t gNB_id,
422
                uint8_t i_ssb,
423 424
                MIMO_mode_t mimo_mode,
                uint32_t high_speed_flag) {
425

Hongzhi Wang's avatar
Hongzhi Wang committed
426 427
  NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
  int max_h=0;
428
  int symbol;
hongzhi wang's avatar
hongzhi wang committed
429
  //uint8_t pbch_a[64];
430 431
//FT ?? cppcheck doesn't like pbch_a allocation because of line 525..and i don't get what this variable is for..
//uint8_t *pbch_a = malloc(sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
432
  //uint32_t pbch_a_prime;
Raymond Knopp's avatar
Raymond Knopp committed
433
  int16_t *pbch_e_rx;
Hongzhi Wang's avatar
Hongzhi Wang committed
434
  uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output;
435
  uint8_t nushift;
436
  uint16_t M;
437
  uint8_t Lmax=frame_parms->Lmax; 
hongzhi wang's avatar
hongzhi wang committed
438
  //uint16_t crc;
439
  //unsigned short idx_demod =0;
440
  uint32_t decoderState=0;
441 442 443
  //uint8_t decoderListSize = 8, pathMetricAppr = 0;
  //time_stats_t polar_decoder_init,polar_rate_matching,decoding,bit_extraction,deinterleaving;
  //time_stats_t path_metric,sorting,update_LLR;
444
// FT ?? cppcheck fix  memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS);
Hongzhi Wang's avatar
Hongzhi Wang committed
445
  //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell);
laurent's avatar
laurent committed
446

Hongzhi Wang's avatar
Hongzhi Wang committed
447
  pbch_e_rx = &nr_ue_pbch_vars->llr[0];
Hongzhi Wang's avatar
Hongzhi Wang committed
448
  // clear LLR buffer
Hongzhi Wang's avatar
Hongzhi Wang committed
449
  memset(nr_ue_pbch_vars->llr,0,NR_POLAR_PBCH_E);
450
  int symbol_offset=1;
451

452
  if (ue->is_synchronized > 0)
453
    symbol_offset=(ue->symbol_offset)%(frame_parms->symbols_per_slot);
454 455
  else
    symbol_offset=0;
Hongzhi Wang's avatar
Hongzhi Wang committed
456

457

Florian Kaltenberger's avatar
WIP  
Florian Kaltenberger committed
458
#ifdef DEBUG_PBCH
459
  //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF);
460
  write_output("rxdataF0_pbch.m","rxF0pbch",
461
               &nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1);
Florian Kaltenberger's avatar
WIP  
Florian Kaltenberger committed
462
#endif
Raymond Knopp's avatar
Raymond Knopp committed
463

464
  // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
465
  for (symbol=1; symbol<4; symbol++) {
466

467
    nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[proc->thread_id].rxdataF,
Francesco Mani's avatar
Francesco Mani committed
468
                    nr_ue_pbch_vars->dl_ch_estimates,
469 470 471 472 473 474
                    nr_ue_pbch_vars->rxdataF_ext,
                    nr_ue_pbch_vars->dl_ch_estimates_ext,
                    symbol,
                    symbol_offset,
                    high_speed_flag,
                    frame_parms);
Hongzhi Wang's avatar
Hongzhi Wang committed
475
#ifdef DEBUG_PBCH
Raymond Knopp's avatar
Raymond Knopp committed
476 477
    LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size );
    LOG_I(PHY,"[PHY] PBCH starting channel_level\n");
Hongzhi Wang's avatar
Hongzhi Wang committed
478 479
#endif

480
    if (symbol == 1) {
Raymond Knopp's avatar
Raymond Knopp committed
481
      max_h = nr_pbch_channel_level(nr_ue_pbch_vars->dl_ch_estimates_ext,
482 483
                                    frame_parms,
                                    symbol);
Raymond Knopp's avatar
Raymond Knopp committed
484 485
      nr_ue_pbch_vars->log2_maxh = 3+(log2_approx(max_h)/2);
    }
Hongzhi Wang's avatar
Hongzhi Wang committed
486 487

#ifdef DEBUG_PBCH
Raymond Knopp's avatar
Raymond Knopp committed
488
    LOG_I(PHY,"[PHY] PBCH log2_maxh = %d (%d)\n",nr_ue_pbch_vars->log2_maxh,max_h);
Hongzhi Wang's avatar
Hongzhi Wang committed
489 490
#endif
    nr_pbch_channel_compensation(nr_ue_pbch_vars->rxdataF_ext,
491 492 493 494 495
                                 nr_ue_pbch_vars->dl_ch_estimates_ext,
                                 nr_ue_pbch_vars->rxdataF_comp,
                                 frame_parms,
                                 symbol,
                                 nr_ue_pbch_vars->log2_maxh); // log2_maxh+I0_shift
Hongzhi Wang's avatar
Hongzhi Wang committed
496 497 498 499 500 501

    /*if (frame_parms->nb_antennas_rx > 1)
      pbch_detection_mrc(frame_parms,
                         nr_ue_pbch_vars->rxdataF_comp,
                         symbol);*/

502 503 504 505 506 507 508 509
    /*
        if (mimo_mode == ALAMOUTI) {
          nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol);
        } else if (mimo_mode != SISO) {
          LOG_I(PHY,"[PBCH][RX] Unsupported MIMO mode\n");
          return(-1);
        }
    */
510
    if (symbol==2) {
Hongzhi Wang's avatar
Hongzhi Wang committed
511
      nr_pbch_quantize(pbch_e_rx,
512 513
                       (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
                       144);
Hongzhi Wang's avatar
Hongzhi Wang committed
514
      pbch_e_rx+=144;
Hongzhi Wang's avatar
Hongzhi Wang committed
515 516
    } else {
      nr_pbch_quantize(pbch_e_rx,
517 518
                       (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][symbol*240]),
                       360);
Hongzhi Wang's avatar
Hongzhi Wang committed
519
      pbch_e_rx+=360;
Hongzhi Wang's avatar
Hongzhi Wang committed
520 521 522
    }
  }

Raymond Knopp's avatar
Raymond Knopp committed
523
#ifdef DEBUG_PBCH
524
  write_output("rxdataF_comp.m","rxFcomp",&nr_ue_pbch_vars->rxdataF_comp[0][240],240*3,1,1);
Raymond Knopp's avatar
Raymond Knopp committed
525
#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
526
  pbch_e_rx = nr_ue_pbch_vars->llr;
527
  //demod_pbch_e = nr_ue_pbch_vars->demod_pbch_e;
528
// FT?? cppcheck fix -  pbch_a = nr_ue_pbch_vars->pbch_a;
529
#ifdef DEBUG_PBCH
hongzhi wang's avatar
hongzhi wang committed
530
  //pbch_e_rx = &nr_ue_pbch_vars->llr[0];
531
  short *p = (short *)&(nr_ue_pbch_vars->rxdataF_comp[0][20*12]);
532

Raymond Knopp's avatar
Raymond Knopp committed
533 534
  for (int cnt = 0; cnt < 864  ; cnt++)
    printf("pbch rx llr %d\n",*(pbch_e_rx+cnt));
Hongzhi Wang's avatar
Hongzhi Wang committed
535

Hongzhi Wang's avatar
Hongzhi Wang committed
536
#endif
537 538
  //un-scrambling
  M =  NR_POLAR_PBCH_E;
539
  nushift = (Lmax==4)? i_ssb&3 : i_ssb&7;
Guy De Souza's avatar
Guy De Souza committed
540
  uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041;
541

Guy De Souza's avatar
Guy De Souza committed
542
  nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_E,0,0);
Hongzhi Wang's avatar
Hongzhi Wang committed
543
  //polar decoding de-rate matching
544
  const t_nrPolar_params *currentPtr = nr_polar_params( NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL,1,&ue->polarList);
545
  decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&nr_ue_pbch_vars->pbch_a_prime,0,currentPtr);
546

547 548
  if(decoderState) return(decoderState);

549
  //  printf("polar decoder output 0x%08x\n",nr_ue_pbch_vars->pbch_a_prime);
550 551
  // Decoder reversal
  uint32_t a_reversed=0;
552

553 554 555 556
  for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
    a_reversed |= (((uint64_t)nr_ue_pbch_vars->pbch_a_prime>>i)&1)<<(31-i);

  nr_ue_pbch_vars->pbch_a_prime = a_reversed;
557
  //payload un-scrambling
558
  memset(&nr_ue_pbch_vars->pbch_a_interleaved, 0, sizeof(uint32_t) );
559
  M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
Guy De Souza's avatar
Guy De Souza committed
560 561
  nushift = ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) ^ (((nr_ue_pbch_vars->pbch_a_prime>>6)&1)<<1);
  nr_pbch_unscrambling(nr_ue_pbch_vars,frame_parms->Nid_cell,nushift,M,NR_POLAR_PBCH_PAYLOAD_BITS,1,unscrambling_mask);
562
  //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((nr_ue_pbch_vars->pbch_a_prime>>6)&1), ((nr_ue_pbch_vars->pbch_a_prime>>24)&1) );
563
  //payload deinterleaving
564 565
  //uint32_t in=0;
  uint32_t out=0;
566

567
  for (int i=0; i<32; i++) {
568
    out |= ((nr_ue_pbch_vars->pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]);
569
#ifdef DEBUG_PBCH
570
    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], (nr_ue_pbch_vars->pbch_a_interleaved>>i)&1);
571
#endif
572 573
  }

574
  uint32_t payload = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
575 576
  //uint8_t xtra_byte = 0;
  nr_ue_pbch_vars->xtra_byte = (out>>24)&0xff;
Guy De Souza's avatar
Guy De Souza committed
577 578

  for (int i=0; i<NR_POLAR_PBCH_PAYLOAD_BITS; i++)
579
    payload |= ((out>>i)&1)<<(NR_POLAR_PBCH_PAYLOAD_BITS-i-1);
Guy De Souza's avatar
Guy De Souza committed
580

581 582
  for (int i=0; i<3; i++)
    decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff);
hongzhi wang's avatar
hongzhi wang committed
583

584
  frame_parms->half_frame_bit = ((nr_ue_pbch_vars->xtra_byte>>4)&0x01); // computing the half frame index from the extra byte
585

586
  frame_parms->ssb_index = i_ssb;  // ssb index corresponds to i_ssb for Lmax = 4,8
587 588
  if (Lmax == 64) {   // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte
    for (int i=0; i<3; i++)
589
      frame_parms->ssb_index += (((nr_ue_pbch_vars->xtra_byte>>(7-i))&0x01)<<(3+i));
590 591
  }

francescomani's avatar
francescomani committed
592
  ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index);
593 594
  if (frame_parms->half_frame_bit)
    ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot;
595

596 597 598 599 600 601
  uint8_t frame_number_4lsb = 0;
  for (int i=0; i<4; i++)
    frame_number_4lsb |= ((nr_ue_pbch_vars->xtra_byte>>i)&1)<<(3-i);

  proc->decoded_frame_rx = frame_number_4lsb;

602
#ifdef DEBUG_PBCH
Florian Kaltenberger's avatar
Florian Kaltenberger committed
603
  printf("xtra_byte %x payload %x\n", nr_ue_pbch_vars->xtra_byte, payload);
604

605 606 607 608 609
  for (int i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++) {
    //     printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]);
    printf("[PBCH] decoder payload[%d] = %x\n",i,decoded_output[i]);
  }
#endif
610

611 612
  nr_downlink_indication_t dl_indication;
  fapi_nr_rx_indication_t rx_ind;
cig's avatar
cig committed
613 614 615 616
  uint16_t number_pdus = 1;

  nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, gNB_id);
  nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_MIB, gNB_id, ue, NULL, number_pdus);
617 618

  if (ue->if_inst && ue->if_inst->dl_indication)
619
    ue->if_inst->dl_indication(&dl_indication, NULL);
620 621

  return 0;
Hongzhi Wang's avatar
Hongzhi Wang committed
622
}