nr_pbch.c 19.8 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"
36
#include "PHY/INIT/nr_phy_init.h"
cig's avatar
cig committed
37
#include "openair1/SCHED_NR_UE/defs.h"
38
#include <openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h>
39
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
40
#include "openair1/PHY/NR_REFSIG/nr_refsig_common.h"
41
//#define DEBUG_PBCH
Hongzhi Wang's avatar
Hongzhi Wang committed
42 43 44
//#define DEBUG_PBCH_ENCODING

#define PBCH_A 24
45
#define PBCH_MAX_RE (PBCH_MAX_RE_PER_SYMBOL*4)
Raymond Knopp's avatar
Raymond Knopp committed
46
#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
47

48
static uint16_t nr_pbch_extract(uint32_t rxdataF_sz,
49
                                const c16_t rxdataF[][rxdataF_sz],
50 51
                                const int estimateSz,
                                struct complex16 dl_ch_estimates[][estimateSz],
52 53
                                struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
                                struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
54 55
                                uint32_t symbol,
                                uint32_t s_offset,
56
                                int ssb_start_subcarrier,
57 58
                                const NR_DL_FRAME_PARMS *frame_parms,
                                int nid)
59
{
Hongzhi Wang's avatar
Hongzhi Wang committed
60
  uint16_t rb;
61
  uint8_t i, j, aarx;
62
  int nushiftmod4 = nid % 4;
63 64 65
  AssertFatal(symbol>=1 && symbol<5,
              "symbol %d illegal for PBCH extraction\n",
              symbol);
Raymond Knopp's avatar
Raymond Knopp committed
66

Hongzhi Wang's avatar
Hongzhi Wang committed
67
  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
68
    unsigned int rx_offset = frame_parms->first_carrier_offset + ssb_start_subcarrier;
69
    rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size);
70
    const struct complex16 *rxF = &rxdataF[aarx][(symbol + s_offset) * frame_parms->ofdm_symbol_size];
francescomani's avatar
francescomani committed
71
    struct complex16 *rxF_ext = rxdataF_ext[aarx];
hongzhi wang's avatar
hongzhi wang committed
72
#ifdef DEBUG_PBCH
francescomani's avatar
francescomani committed
73 74 75 76
    printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n",
           nushiftmod4,
           (rx_offset + ((symbol+s_offset) * (frame_parms->ofdm_symbol_size))),
           symbol);
77 78 79
    int16_t *p = (int16_t *)rxF;

    for (int i =0; i<8; i++) {
francescomani's avatar
francescomani committed
80
      printf("rxF.r [%d]= %d rxF.i [%d]= %d\n", i, rxF[i].r, i, rxF[i].i);
81 82 83
      printf("pbch extract rxF  %d %d addr %p\n", p[2*i], p[2*i+1], &p[2*i]);
    }

hongzhi wang's avatar
hongzhi wang committed
84
#endif
Hongzhi Wang's avatar
Hongzhi Wang committed
85 86

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

89
      if (symbol==1 || symbol==3) {
Hongzhi Wang's avatar
Hongzhi Wang committed
90 91 92 93
        for (i=0; i<12; i++) {
          if ((i!=nushiftmod4) &&
              (i!=(nushiftmod4+4)) &&
              (i!=(nushiftmod4+8))) {
Raymond Knopp's avatar
Raymond Knopp committed
94 95
            rxF_ext[j]=rxF[rx_offset];
#ifdef DEBUG_PBCH
96
            printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",
francescomani's avatar
francescomani committed
97 98 99
		   (9 * rb) + j,
                   rxF_ext[j].r,
                   rxF_ext[j].i,
100
                   rx_offset,
francescomani's avatar
francescomani committed
101 102
                   rxF[rx_offset].r,
                   rxF[rx_offset].i);
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
francescomani's avatar
francescomani committed
120 121 122 123
              printf("rxF ext[%d] = (%d,%d) rxF [%u]= (%d,%d)\n",
                     (rb < 4) ? (9 * rb) + j : (9 * (rb - 12)) + j,
		     rxF_ext[j].r,
                     rxF_ext[j].i,
124
                     rx_offset,
francescomani's avatar
francescomani committed
125 126
		     rxF[rx_offset].r,
                     rxF[rx_offset].i);
127 128 129 130
#endif
              j++;
            }

Rakesh's avatar
Rakesh committed
131 132
            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);
133 134 135
          }

          rxF_ext+=9;
136 137 138
        } 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
139 140 141
      }
    }

142
    struct complex16 *dl_ch0 = &dl_ch_estimates[aarx][((symbol+s_offset)*(frame_parms->ofdm_symbol_size))];
143

Raymond Knopp's avatar
Raymond Knopp committed
144
    //printf("dl_ch0 addr %p\n",dl_ch0);
145
    struct complex16 *dl_ch0_ext = dl_ch_estimates_ext[aarx];
146

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

150
      if (symbol==1 || symbol==3) {
151 152 153 154 155
        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
156
#ifdef DEBUG_PBCH
francescomani's avatar
francescomani committed
157 158 159 160 161
            if ((rb == 0) && (i < 2))
              printf("dl ch0 ext[%d] = (%d,%d)  dl_ch0 [%d]= (%d,%d)\n",
                     j,
                     dl_ch0_ext[j].r,
                     dl_ch0_ext[j].i,
162
                     i,
francescomani's avatar
francescomani committed
163 164
                     dl_ch0[j].r,
                     dl_ch0[j].i);
Raymond Knopp's avatar
Raymond Knopp committed
165
#endif
166 167 168 169 170 171 172 173 174 175 176 177 178
            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
179
#ifdef DEBUG_PBCH
francescomani's avatar
francescomani committed
180 181 182 183
              printf("dl ch0 ext[%d] = (%d,%d)  dl_ch0 [%d]= (%d,%d)\n",
                     j,
                     dl_ch0_ext[j].r,
                     dl_ch0_ext[j].i,
184
                     i,
francescomani's avatar
francescomani committed
185 186
                     dl_ch0[j].r,
                     dl_ch0[j].i);
Raymond Knopp's avatar
Raymond Knopp committed
187
#endif
188 189 190 191 192 193 194 195
              j++;
            }
          }

          dl_ch0_ext+=9;
        }

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

  return(0);
}

//__m128i avg128;

//compute average channel_level on each (TX,RX) antenna pair
206
int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
207 208 209
                          const NR_DL_FRAME_PARMS *frame_parms,
                          int nb_re)
{
210
  int16_t nb_rb=nb_re/12;
211 212
  simde__m128i avg128;
  simde__m128i *dl_ch128;
Hongzhi Wang's avatar
Hongzhi Wang committed
213 214
  int avg1=0,avg2=0;

215
  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
Raymond Knopp's avatar
Raymond Knopp committed
216
    //clear average level
217 218
    avg128 = simde_mm_setzero_si128();
    dl_ch128=(simde__m128i *)dl_ch_estimates_ext[aarx];
219

220
    for (int rb=0; rb<nb_rb; rb++) {
221 222 223
      avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[0],dl_ch128[0]));
      avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[1],dl_ch128[1]));
      avg128 = simde_mm_add_epi32(avg128, simde_mm_madd_epi16(dl_ch128[2],dl_ch128[2]));
Raymond Knopp's avatar
Raymond Knopp committed
224 225 226
      dl_ch128+=3;
      /*
      if (rb==0) {
227 228 229 230
      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
231
    }
232

233 234
    for (int i = 0; i < 4; i++)
      avg1 += ((int *)&avg128)[i] / (nb_rb * 12);
235

Raymond Knopp's avatar
Raymond Knopp committed
236 237
    if (avg1>avg2)
      avg2 = avg1;
238

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

Hongzhi Wang's avatar
Hongzhi Wang committed
242 243 244
  return(avg2);
}

245 246 247 248
void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL],
                                  struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL],
                                  int nb_re,
                                  struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL],
249
                                  const NR_DL_FRAME_PARMS *frame_parms,
250 251
                                  uint8_t output_shift)
{
laurent's avatar
laurent committed
252
  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
253 254 255
    simde__m128i *dl_ch128          = (simde__m128i *)dl_ch_estimates_ext[aarx];
    simde__m128i *rxdataF128        = (simde__m128i *)rxdataF_ext[aarx];
    simde__m128i *rxdataF_comp128   = (simde__m128i *)rxdataF_comp[aarx];
Hongzhi Wang's avatar
Hongzhi Wang committed
256

Robert Schmidt's avatar
Robert Schmidt committed
257
    for (int re = 0; re < nb_re; re += 4) {
laurent's avatar
laurent committed
258
      *rxdataF_comp128++ = mulByConjugate128(rxdataF128++, dl_ch128++, output_shift);
Hongzhi Wang's avatar
Hongzhi Wang committed
259
    }
Raymond Knopp's avatar
Raymond Knopp committed
260
  }
Hongzhi Wang's avatar
Hongzhi Wang committed
261 262 263
}

void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
264 265
                           int **rxdataF_comp,
                           uint8_t symbol) {
Raymond Knopp's avatar
Raymond Knopp committed
266
  uint8_t symbol_mod;
267 268
  int i, nb_rb = 6;
  simde__m128i *rxdataF_comp128_0, *rxdataF_comp128_1;
Hongzhi Wang's avatar
Hongzhi Wang committed
269 270
  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;

271 272 273
  if (frame_parms->nb_antennas_rx > 1) {
    rxdataF_comp128_0 = (simde__m128i *)&rxdataF_comp[0][symbol_mod * 6 * 12];
    rxdataF_comp128_1 = (simde__m128i *)&rxdataF_comp[1][symbol_mod * 6 * 12];
274 275

    // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
276 277 278
    for (i = 0; i < nb_rb * 3; i++) {
      rxdataF_comp128_0[i] =
          simde_mm_adds_epi16(simde_mm_srai_epi16(rxdataF_comp128_0[i], 1), simde_mm_srai_epi16(rxdataF_comp128_1[i], 1));
Hongzhi Wang's avatar
Hongzhi Wang committed
279
    }
280
  }
Raymond Knopp's avatar
Raymond Knopp committed
281

282 283
  simde_mm_empty();
  simde_m_empty();
Hongzhi Wang's avatar
Hongzhi Wang committed
284 285
}

286
void nr_pbch_unscrambling(int16_t *demod_pbch_e,
Robert Schmidt's avatar
Robert Schmidt committed
287 288 289 290 291 292 293 294
                          uint16_t Nid,
                          uint8_t nushift,
                          uint16_t M,
                          uint16_t length,
                          uint8_t bitwise,
                          uint32_t unscrambling_mask,
                          uint32_t pbch_a_prime,
                          uint32_t *pbch_a_interleaved)
295
{
296
  uint32_t *seq = gold_cache(Nid, (nushift * M + length + 31) / 32); // this is c_init
297
  // The Gold sequence is shifted by nushift* M, so we skip (nushift*M /32) double words
298
  int idxGold = (nushift * M + 31) / 32 - 1;
299

300
  // Scrambling is now done with offset (nushift*M)%32
301 302 303
  int offset = (nushift * M) & 0x1f;
  uint8_t k = 0;
  for (int i = 0; i < length; i++) {
304
    if (bitwise) {
305 306 307 308 309
      if (((k + offset) & 0x1f) == 0 && (!((unscrambling_mask >> i) & 1)))
        idxGold++;
      *pbch_a_interleaved ^= ((unscrambling_mask >> i) & 1)
                                 ? ((pbch_a_prime >> i) & 1) << i
                                 : (((pbch_a_prime >> i) & 1) ^ ((seq[idxGold] >> ((k + offset) & 0x1f)) & 1)) << i;
310
      k += (!((unscrambling_mask>>i)&1));
Raymond Knopp's avatar
Raymond Knopp committed
311
#ifdef DEBUG_PBCH_ENCODING
312
      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_a_interleaved,
313
             (!((unscrambling_mask>>i)&1)));
Raymond Knopp's avatar
Raymond Knopp committed
314
#endif
315
    } else {
316 317
      if (((i + offset) & 0x1f) == 0)
        idxGold++;
318

319
      if (seq[idxGold] & (1UL << ((i + offset) % 32)))
320 321
        demod_pbch_e[i] = -demod_pbch_e[i];

322
#ifdef DEBUG_PBCH_ENCODING
323 324 325 326

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

327
#endif
328
    }
Hongzhi Wang's avatar
Hongzhi Wang committed
329 330 331
  }
}

Robert Schmidt's avatar
Robert Schmidt committed
332 333
void nr_pbch_quantize(int16_t *pbch_llr8, int16_t *pbch_llr, uint16_t len)
{
334
  for (int i=0; i<len; i++) {
335 336 337 338
    if (pbch_llr[i]>31)
      pbch_llr8[i]=32;
    else if (pbch_llr[i]<-31)
      pbch_llr8[i]=-32;
339
    else
340
      pbch_llr8[i]=pbch_llr[i];
Hongzhi Wang's avatar
Hongzhi Wang committed
341 342
  }
}
343
/*
hongzhi wang's avatar
hongzhi wang committed
344 345
unsigned char sign(int8_t x) {
  return (unsigned char)x >> 7;
hongzhi wang's avatar
hongzhi wang committed
346
}
347
*/
hongzhi wang's avatar
hongzhi wang committed
348

349 350
const 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
351

352
int nr_rx_pbch(PHY_VARS_NR_UE *ue,
353
               const UE_nr_rxtx_proc_t *proc,
354
               bool is_synchronized,
355
               int estimateSz,
356
               struct complex16 dl_ch_estimates[][estimateSz],
357
               const NR_DL_FRAME_PARMS *frame_parms,
358
               uint8_t i_ssb,
359 360
               int ssb_start_subcarrier,
               int Nid_cell,
361
               fapiPbch_t *result,
362 363 364
               int *half_frame_bit,
               int *ssb_index,
               int *ret_symbol_offset,
365 366
               int rxdataFSize,
               const struct complex16 rxdataF[][rxdataFSize])
367
{
Hongzhi Wang's avatar
Hongzhi Wang committed
368
  int max_h=0;
369
  int symbol;
370
  uint8_t Lmax=frame_parms->Lmax;
371 372
  int M = NR_POLAR_PBCH_E;
  int nushift = (Lmax == 4) ? i_ssb & 3 : i_ssb & 7;
373 374
  int16_t pbch_e_rx[960]= {0}; //Fixme: previous version erase only NR_POLAR_PBCH_E bytes
  int16_t pbch_unClipped[960]= {0};
375
  int pbch_e_rx_idx=0;
376
  int symbol_offset=1;
377

378
  if (is_synchronized)
379
    symbol_offset=nr_get_ssb_start_symbol(frame_parms, i_ssb)%(frame_parms->symbols_per_slot);
380 381
  else
    symbol_offset=0;
Hongzhi Wang's avatar
Hongzhi Wang committed
382

Florian Kaltenberger's avatar
WIP  
Florian Kaltenberger committed
383
#ifdef DEBUG_PBCH
384
  //printf("address dataf %p",nr_ue_common_vars->rxdataF);
385
  write_output("rxdataF0_pbch.m","rxF0pbch",
386
               &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
387
#endif
388
  // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot
389
  double log2_maxh = 0;
390

391
  for (symbol=1; symbol<4; symbol++) {
392
    const uint16_t nb_re=symbol == 2 ? 72 : 180;
393 394
    __attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
    __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
395
    memset(dl_ch_estimates_ext,0, sizeof  dl_ch_estimates_ext);
396
    nr_pbch_extract(frame_parms->samples_per_slot_wCP,
397
                    rxdataF,
398
                    estimateSz,
399 400 401
                    dl_ch_estimates,
                    rxdataF_ext,
                    dl_ch_estimates_ext,
402 403
                    symbol,
                    symbol_offset,
404
                    ssb_start_subcarrier,
405 406
                    frame_parms,
                    Nid_cell);
Hongzhi Wang's avatar
Hongzhi Wang committed
407
#ifdef DEBUG_PBCH
408
    LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size);
Raymond Knopp's avatar
Raymond Knopp committed
409
    LOG_I(PHY,"[PHY] PBCH starting channel_level\n");
Hongzhi Wang's avatar
Hongzhi Wang committed
410 411
#endif

412
    if (symbol == 1) {
413
      max_h = nr_pbch_channel_level(dl_ch_estimates_ext,
414
                                    frame_parms,
415
                                    nb_re);
416
      log2_maxh = 3+(log2_approx(max_h)/2);
Raymond Knopp's avatar
Raymond Knopp committed
417
    }
Hongzhi Wang's avatar
Hongzhi Wang committed
418 419

#ifdef DEBUG_PBCH
francescomani's avatar
francescomani committed
420
    LOG_I(PHY,"[PHY] PBCH log2_maxh = %f (%d)\n", log2_maxh, max_h);
Hongzhi Wang's avatar
Hongzhi Wang committed
421
#endif
422
    __attribute__ ((aligned(32))) struct complex16 rxdataF_comp[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL];
423 424
    nr_pbch_channel_compensation(rxdataF_ext,
                                 dl_ch_estimates_ext,
425
                                 nb_re,
426
                                 rxdataF_comp,
427
                                 frame_parms,
428
                                 log2_maxh); // log2_maxh+I0_shift
Hongzhi Wang's avatar
Hongzhi Wang committed
429 430 431

    /*if (frame_parms->nb_antennas_rx > 1)
      pbch_detection_mrc(frame_parms,
432
                         rxdataF_comp,
Hongzhi Wang's avatar
Hongzhi Wang committed
433 434
                         symbol);*/

435 436 437 438 439 440
    int nb=symbol==2 ? 144 : 360;
    nr_pbch_quantize(pbch_e_rx+pbch_e_rx_idx,
		     (short *)rxdataF_comp[0],
		     nb);
    memcpy(pbch_unClipped+pbch_e_rx_idx, rxdataF_comp[0], nb*sizeof(int16_t));
    pbch_e_rx_idx+=nb;
Hongzhi Wang's avatar
Hongzhi Wang committed
441 442
  }

443
  // legacy code use int16, but it is complex16
444
  if (ue) {
Bartosz Podrygajlo's avatar
Bartosz Podrygajlo committed
445 446 447
    metadata meta = {.slot = proc->nr_slot_rx, .frame = proc->frame_rx};
    UEscopeCopyWithMetadata(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0, &meta);
    UEscopeCopyWithMetadata(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0, &meta);
448
  }
Raymond Knopp's avatar
Raymond Knopp committed
449 450
#ifdef DEBUG_PBCH
  for (int cnt = 0; cnt < 864  ; cnt++)
francescomani's avatar
francescomani committed
451
    printf("pbch rx llr %d\n", *(pbch_e_rx + cnt));
Hongzhi Wang's avatar
Hongzhi Wang committed
452
#endif
453
  // un-scrambling
Guy De Souza's avatar
Guy De Souza committed
454
  uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041;
455
  uint32_t pbch_a_interleaved=0;
456
  uint32_t pbch_a_prime=0;
457
  nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_E,
458
		       0, 0,  pbch_a_prime, &pbch_a_interleaved);
Hongzhi Wang's avatar
Hongzhi Wang committed
459
  //polar decoding de-rate matching
Laurent Thomas's avatar
Laurent Thomas committed
460
  uint64_t tmp=0;
461 462 463 464 465 466
  const uint32_t decoderState = polar_decoder_int16(pbch_e_rx,
                                                    (uint64_t *)&tmp,
                                                    0,
                                                    NR_POLAR_PBCH_MESSAGE_TYPE,
                                                    NR_POLAR_PBCH_PAYLOAD_BITS,
                                                    NR_POLAR_PBCH_AGGREGATION_LEVEL);
467 468 469
  pbch_a_prime = tmp;

  nr_downlink_indication_t dl_indication;
470
  fapi_nr_rx_indication_t rx_ind = {0};
471
  uint16_t number_pdus = 1;
472

473 474 475 476 477 478 479
  if (decoderState) {
    if (ue) { // decoding failed in synced state
      nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
      nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL);
      if (ue->if_inst && ue->if_inst->dl_indication)
        ue->if_inst->dl_indication(&dl_indication);
    }
480 481
    return(decoderState);
  }
482
  //  printf("polar decoder output 0x%08x\n",pbch_a_prime);
483
  // Decoder reversal
484
  pbch_a_prime = (uint32_t)reverse_bits(pbch_a_prime, NR_POLAR_PBCH_PAYLOAD_BITS);
485

486 487
  //payload un-scrambling
  M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3);
488
  nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1);
489
  pbch_a_interleaved=0;
490
  nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS,
491
		       1, unscrambling_mask, pbch_a_prime, &pbch_a_interleaved);
492
  //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((pbch_a_prime>>6)&1), ((pbch_a_prime>>24)&1) );
493
  //payload deinterleaving
494 495
  //uint32_t in=0;
  uint32_t out=0;
496

497
  for (int i=0; i<32; i++) {
498
    out |= ((pbch_a_interleaved>>i)&1)<<(pbch_deinterleaving_pattern[i]);
499
#ifdef DEBUG_PBCH
500
    printf("i %d in 0x%08x out 0x%08x ilv %d (in>>i)&1) 0x%08x\n", i, pbch_a_interleaved, out, pbch_deinterleaving_pattern[i], (pbch_a_interleaved>>i)&1);
501
#endif
502 503
  }

504
  result->xtra_byte = (out>>24)&0xff;
Guy De Souza's avatar
Guy De Souza committed
505

506 507
  const uint64_t payload = reverse_bits(out, NR_POLAR_PBCH_PAYLOAD_BITS);

508
  for (int i=0; i<3; i++)
509
    result->decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff);
510 511 512 513

  *half_frame_bit = (result->xtra_byte >> 4) & 0x01; // computing the half frame index from the extra byte
  *ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8

514 515
  if (Lmax == 64) {   // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte
    for (int i=0; i<3; i++)
516
      *ssb_index += (((result->xtra_byte >> (7 - i)) & 0x01) << (3 + i));
517 518
  }

519
  *ret_symbol_offset = nr_get_ssb_start_symbol(frame_parms, *ssb_index);
520

521 522
  if (*half_frame_bit)
    *ret_symbol_offset += (frame_parms->slots_per_frame >> 1) * frame_parms->symbols_per_slot;
523

524
#ifdef DEBUG_PBCH
francescomani's avatar
francescomani committed
525
  printf("xtra_byte %x payload %x\n", result->xtra_byte, payload);
526

527 528
  for (int i=0; i<(NR_POLAR_PBCH_PAYLOAD_BITS>>3); i++) {
    //     printf("unscrambling pbch_a[%d] = %x \n", i,pbch_a[i]);
529
    printf("[PBCH] decoder payload[%d] = %x\n",i,result->decoded_output[i]);
530
  }
531

532
#endif
cig's avatar
cig committed
533

534 535 536
  if (ue) {
    nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
    nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL);
537

538 539 540
    if (ue->if_inst && ue->if_inst->dl_indication)
      ue->if_inst->dl_indication(&dl_indication);
  }
541 542

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