nr_initial_sync.c 14.2 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
/*
 * 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/initial_sync.c
* \brief Routines for initial UE synchronization procedure (PSS,SSS,PBCH and frame format detection)
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,kaltenberger@eurecom.fr
* \note
* \warning
*/
#include "PHY/types.h"
#include "PHY/defs_nr_UE.h"
#include "PHY/phy_extern_nr_ue.h"
hongzhi wang's avatar
hongzhi wang committed
35 36 37
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "nr_transport_proto_ue.h"
Wang's avatar
Wang committed
38 39 40 41
//#include "SCHED/defs.h"
//#include "SCHED/extern.h"

#include "common_lib.h"
42
#include <math.h>
Wang's avatar
Wang committed
43 44 45

#include "PHY/NR_REFSIG/pss_nr.h"
#include "PHY/NR_REFSIG/sss_nr.h"
Hongzhi Wang's avatar
Hongzhi Wang committed
46
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
Wang's avatar
Wang committed
47 48

extern openair0_config_t openair0_cfg[];
hongzhi wang's avatar
hongzhi wang committed
49 50
//static  nfapi_nr_config_request_t config_t;
//static  nfapi_nr_config_request_t* config =&config_t;
51
int cnt=0;
Wang's avatar
Wang committed
52

53
#define DEBUG_INITIAL_SYNCH
Wang's avatar
Wang committed
54

hongzhi wang's avatar
hongzhi wang committed
55
int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode)
Wang's avatar
Wang committed
56 57
{
  NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
Hongzhi Wang's avatar
Hongzhi Wang committed
58
  int ret =-1;
59 60
  int ar, n;
  double im, re;
Wang's avatar
Wang committed
61 62 63 64 65 66

#ifdef DEBUG_INITIAL_SYNCH
  LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id,
        ue->rx_offset);
#endif

knopp's avatar
knopp committed
67
  // save the nb_prefix_samples0 since we are not synchronized to subframes yet and the SSB has all symbols with nb_prefix_samples
hongzhi wang's avatar
hongzhi wang committed
68
  int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
knopp's avatar
knopp committed
69
  frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples;
hongzhi wang's avatar
hongzhi wang committed
70

71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
  // digital compensation of FFO for PBCH symbols
  if(abs(2*ue->common_vars.freq_offset)<frame_parms->subcarrier_spacing){  // this FFO compensation seems to work only for FFO between -0.5 and 0.5
  
   int size_wp = (frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples0);  // symbol size including prefix
   double s_time = 1/(1.0e3*frame_parms->samples_per_subframe);  // sampling time
   double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset);  // offset rotation angle compensation per sample

   int start = ue->ssb_offset + size_wp;  // start for offset correction is one symbol after ssb_offset (pss time position), including prefix
   int end = start + (3*size_wp);  // loop over samples in 3 symbols, including prefix
  
   for(n=start; n<end; n++){  	
	for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
		re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]);
		im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]);
		((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); 
		((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle)));
	}
   }
  }


Wang's avatar
Wang committed
92
  //symbol 1
93
  nr_slot_fep(ue,
knopp's avatar
knopp committed
94 95 96 97 98 99 100
	      1,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);
  
Wang's avatar
Wang committed
101
  //symbol 2
102
  nr_slot_fep(ue,
knopp's avatar
knopp committed
103 104 105 106 107 108
	      2,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);
Wang's avatar
Wang committed
109 110

  //symbol 3
111
  nr_slot_fep(ue,
knopp's avatar
knopp committed
112 113 114 115 116 117 118 119
	      3,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);

  //put back nb_prefix_samples0
hongzhi wang's avatar
hongzhi wang committed
120
  frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
hongzhi wang's avatar
hongzhi wang committed
121 122
  
  
knopp's avatar
knopp committed
123 124 125 126 127 128 129 130 131
  ret = nr_rx_pbch(ue,
		   &ue->proc.proc_rxtx[0],
		   ue->pbch_vars[0],
		   frame_parms,
		   0,
		   SISO,
		   ue->high_speed_flag);
  
  
Hongzhi Wang's avatar
Hongzhi Wang committed
132
  if (ret==0) {
knopp's avatar
knopp committed
133
    
Hongzhi Wang's avatar
Hongzhi Wang committed
134
    frame_parms->nb_antenna_ports_eNB = 1; //pbch_tx_ant;
knopp's avatar
knopp committed
135
    
Wang's avatar
Wang committed
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    // set initial transmission mode to 1 or 2 depending on number of detected TX antennas
    //frame_parms->mode1_flag = (pbch_tx_ant==1);
    // openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1;


    // flip byte endian on 24-bits for MIB
    //    dummy = ue->pbch_vars[0]->decoded_output[0];
    //    ue->pbch_vars[0]->decoded_output[0] = ue->pbch_vars[0]->decoded_output[2];
    //    ue->pbch_vars[0]->decoded_output[2] = dummy;

    for(int i=0; i<RX_NB_TH;i++)
    {

        ue->proc.proc_rxtx[i].frame_tx = ue->proc.proc_rxtx[0].frame_rx;
    }
#ifdef DEBUG_INITIAL_SYNCH
152
    LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id);
Wang's avatar
Wang committed
153 154 155 156 157 158 159 160 161 162 163 164 165 166
#endif
    return(0);
  } else {
    return(-1);
  }

}

char duplex_string[2][4] = {"FDD","TDD"};
char prefix_string[2][9] = {"NORMAL","EXTENDED"};

int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
{

yilmazt's avatar
yilmazt committed
167
  int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2,
knopp's avatar
knopp committed
168 169
  int32_t metric_tdd_ncp=0;
  uint8_t phase_tdd_ncp;
Wang's avatar
Wang committed
170

knopp's avatar
knopp committed
171
  NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
Wang's avatar
Wang committed
172
  int ret=-1;
hongzhi wang's avatar
hongzhi wang committed
173
  int rx_power=0; //aarx,
Guy De Souza's avatar
Guy De Souza committed
174
  //nfapi_nr_config_request_t* config;
Wang's avatar
Wang committed
175

176
  int n_ssb_crb=(fp->N_RB_DL-20);
knopp's avatar
knopp committed
177
  // First try TDD normal prefix, mu 1
knopp's avatar
knopp committed
178 179
  fp->Ncp=NORMAL;
  fp->frame_type=TDD;
180 181
  // FK: added N_RB_DL paramter here as this function shares code with the gNB where it is needed. We should rewrite this function for the UE. 
  nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,fp->N_RB_DL,n_ssb_crb,0);
knopp's avatar
knopp committed
182
  LOG_D(PHY,"nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
Wolfgang A. Mozart's avatar
Wolfgang A. Mozart committed
183

Wang's avatar
Wang committed
184
  /*
185
  write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1);
Wang's avatar
Wang committed
186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
  exit(-1);
  */

  /*   Initial synchronisation
   *
  *                                 1 radio frame = 10 ms
  *     <--------------------------------------------------------------------------->
  *     -----------------------------------------------------------------------------
  *     |                                 Received UE data buffer                    |
  *     ----------------------------------------------------------------------------
  *                     --------------------------
  *     <-------------->| pss | pbch | sss | pbch |
  *                     --------------------------
  *          sync_pos            SS/PBCH block
  */
knopp's avatar
knopp committed
201

202
  cnt++;
203
  if (1){ // (cnt>100)
204
    cnt =0;
205

Wang's avatar
Wang committed
206 207 208
  /* process pss search on received buffer */
  sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE);

hongzhi wang's avatar
hongzhi wang committed
209
  sync_pos_slot = (fp->samples_per_subframe/fp->slots_per_subframe) - 10*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
210

hongzhi wang's avatar
hongzhi wang committed
211 212 213 214 215 216
  if (sync_pos >= fp->nb_prefix_samples){
    ue->ssb_offset = sync_pos - fp->nb_prefix_samples;}
  else{
    ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;}
    
    ue->rx_offset = ue->ssb_offset - sync_pos_slot;
217

218
  //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1);
Wang's avatar
Wang committed
219 220 221

#ifdef DEBUG_INITIAL_SYNCH
  LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos,ue->common_vars.eNb_id);
hongzhi wang's avatar
hongzhi wang committed
222
  LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot);
Wang's avatar
Wang committed
223 224 225
#endif

  /* check that SSS/PBCH block is continuous inside the received buffer */
Wolfgang A. Mozart's avatar
Wolfgang A. Mozart committed
226
  if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) {
Wang's avatar
Wang committed
227 228 229 230 231

#ifdef DEBUG_INITIAL_SYNCH
    LOG_I(PHY,"Calling sss detection (normal CP)\n");
#endif

knopp's avatar
knopp committed
232
    rx_sss_nr(ue,&metric_tdd_ncp,&phase_tdd_ncp);
Wang's avatar
Wang committed
233

234 235
    //FK: why do we need to do this again here?
    //nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,n_ssb_crb,0);
Hongzhi Wang's avatar
Hongzhi Wang committed
236

Hongzhi Wang's avatar
Hongzhi Wang committed
237
    nr_gold_pbch(ue);
hongzhi wang's avatar
hongzhi wang committed
238
    ret = nr_pbch_detection(ue,mode);
239 240
    
    nr_gold_pdcch(ue,0, 2);
knopp's avatar
knopp committed
241
    /*
242 243
    int nb_prefix_samples0 = fp->nb_prefix_samples0;
    fp->nb_prefix_samples0 = fp->nb_prefix_samples;
knopp's avatar
knopp committed
244 245 246
	  
    nr_slot_fep(ue,0, 0, ue->ssb_offset, 0, 1, NR_PDCCH_EST);
    nr_slot_fep(ue,1, 0, ue->ssb_offset, 0, 1, NR_PDCCH_EST);
247
    fp->nb_prefix_samples0 = nb_prefix_samples0;	
248

249
    LOG_I(PHY,"[UE  %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
250 251 252 253
              ue->Mod_id,
              ue->proc.proc_rxtx[0].frame_rx,
              ue->rx_offset,
              ue->common_vars.freq_offset );
knopp's avatar
knopp committed
254
    */
Wang's avatar
Wang committed
255 256

#ifdef DEBUG_INITIAL_SYNCH
257 258
    LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, pbch %d\n",
          fp->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,ret);
Wang's avatar
Wang committed
259 260 261 262
#endif
  }
  else {
#ifdef DEBUG_INITIAL_SYNCH
knopp's avatar
knopp committed
263
    LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot);
Wang's avatar
Wang committed
264 265
#endif
  }
266 267 268 269
  }
  else {
	  ret = -1;
  }
Wang's avatar
Wang committed
270

271 272
  /* Consider this is a false detection if the offset is > 1000 Hz 
     Not to be used now that offest estimation is in place
Wang's avatar
Wang committed
273 274 275 276 277 278 279 280
  if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
  {
	  ret=-1;
#if DISABLE_LOG_X
	  printf("Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
#else
	  LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
#endif
281
  }*/
Wang's avatar
Wang committed
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

  if (ret==0) {  // PBCH found so indicate sync to higher layers and configure frame parameters

    //#ifdef DEBUG_INITIAL_SYNCH
#if DISABLE_LOG_X
    printf("[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset);
#else
    LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset);
#endif
    //#endif

    if (ue->UE_scan_carrier == 0) {

    #if UE_AUTOTEST_TRACE
      LOG_I(PHY,"[UE  %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n",
              ue->Mod_id,
              ue->proc.proc_rxtx[0].frame_rx,
              ue->rx_offset,
              ue->common_vars.freq_offset );
    #endif

// send sync status to higher layers later when timing offset converge to target timing

      ue->pbch_vars[0]->pdu_errors_conseq=0;

    }

#if DISABLE_LOG_X
    printf("[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm,  rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
	  10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB,
	  10*log10(ue->measurements.rssi),
	  ue->rx_total_gain_dB,
	  ue->measurements.n0_power_tot_dBm,
	  10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB,
	  (10*log10(ue->measurements.rsrq[0])));


    printf("[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n",
	  ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
knopp's avatar
knopp committed
323 324 325 326 327 328 329
	  duplex_string[fp->frame_type],
	  prefix_string[fp->Ncp],
	  fp->Nid_cell,
	  fp->N_RB_DL,
	  fp->phich_config_common.phich_duration,
	  phich_string[fp->phich_config_common.phich_resource],
	  fp->nb_antenna_ports_eNB);
Wang's avatar
Wang committed
330 331 332 333 334 335 336 337 338 339 340 341 342
#else
    LOG_I(PHY, "[UE %d] Frame %d RRC Measurements => rssi %3.1f dBm (dig %3.1f dB, gain %d), N0 %d dBm,  rsrp %3.1f dBm/RE, rsrq %3.1f dB\n",ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
	  10*log10(ue->measurements.rssi)-ue->rx_total_gain_dB,
	  10*log10(ue->measurements.rssi),
	  ue->rx_total_gain_dB,
	  ue->measurements.n0_power_tot_dBm,
	  10*log10(ue->measurements.rsrp[0])-ue->rx_total_gain_dB,
	  (10*log10(ue->measurements.rsrq[0])));

/*    LOG_I(PHY, "[UE %d] Frame %d MIB Information => %s, %s, NidCell %d, N_RB_DL %d, PHICH DURATION %d, PHICH RESOURCE %s, TX_ANT %d\n",
	  ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
knopp's avatar
knopp committed
343 344 345 346 347 348 349
	  duplex_string[fp->frame_type],
	  prefix_string[fp->Ncp],
	  fp->Nid_cell,
	  fp->N_RB_DL,
	  fp->phich_config_common.phich_duration,
	  phich_string[fp->phich_config_common.phich_resource],
	  fp->nb_antenna_ports_eNB);*/
Wang's avatar
Wang committed
350 351 352 353 354 355 356
#endif

#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) || defined(OAI_ADRV9371_ZC706)
#  if DISABLE_LOG_X
    printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
	  ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
357
	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
Wang's avatar
Wang committed
358 359 360 361 362
	  ue->common_vars.freq_offset);
#  else
    LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
	  ue->Mod_id,
	  ue->proc.proc_rxtx[0].frame_rx,
363
	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
Wang's avatar
Wang committed
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
	  ue->common_vars.freq_offset);
#  endif
#endif
  } else {
#ifdef DEBUG_INITIAL_SYNC
    LOG_I(PHY,"[UE%d] Initial sync : PBCH not ok\n",ue->Mod_id);
    LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n",ue->Mod_id,sync_pos,ue->common_vars.eNb_id);
    LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id,
          frame_parms->Nid_cell,frame_parms->frame_type);
#endif

    ue->UE_mode[0] = NOT_SYNCHED;
    ue->pbch_vars[0]->pdu_errors_last=ue->pbch_vars[0]->pdu_errors;
    ue->pbch_vars[0]->pdu_errors++;
    ue->pbch_vars[0]->pdu_errors_conseq++;

  }

  // gain control
  if (ret!=0) { //we are not synched, so we cannot use rssi measurement (which is based on channel estimates)
    rx_power = 0;

    // do a measurement on the best guess of the PSS
hongzhi wang's avatar
hongzhi wang committed
387 388 389
    //for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
    //  rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2],
	//			frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples);
Wang's avatar
Wang committed
390 391 392 393 394 395 396 397 398

    /*
    // do a measurement on the full frame
    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
      rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0],
				frame_parms->samples_per_subframe*10);
    */

    // we might add a low-pass filter here later
knopp's avatar
knopp committed
399
    ue->measurements.rx_power_avg[0] = rx_power/fp->nb_antennas_rx;
Wang's avatar
Wang committed
400 401 402 403 404 405 406 407 408 409 410

    ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]);

#ifdef DEBUG_INITIAL_SYNCH
  LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] );
#endif

#ifndef OAI_USRP
#ifndef OAI_BLADERF
#ifndef OAI_LMSSDR
#ifndef OAI_ADRV9371_ZC706
hongzhi wang's avatar
hongzhi wang committed
411
  //phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0);
Wang's avatar
Wang committed
412 413 414 415 416 417 418 419 420 421 422 423
#endif
#endif
#endif
#endif

  }
  else {

#ifndef OAI_USRP
#ifndef OAI_BLADERF
#ifndef OAI_LMSSDR
#ifndef OAI_ADRV9371_ZC706
hongzhi wang's avatar
hongzhi wang committed
424
  //phy_adjust_gain(ue,dB_fixed(ue->measurements.rssi),0);
Wang's avatar
Wang committed
425 426 427 428 429 430 431 432 433 434 435
#endif
#endif
#endif
#endif

  }

  //  exit_fun("debug exit");
  return ret;
}