nr_initial_sync.c 13.9 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;
58
  int ret =-1;
59

Wang's avatar
Wang committed
60 61 62 63 64 65

#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
66
  // 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
67
  int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
knopp's avatar
knopp committed
68
  frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples;
hongzhi wang's avatar
hongzhi wang committed
69

70

Wang's avatar
Wang committed
71
  //symbol 1
72
  nr_slot_fep(ue,
knopp's avatar
knopp committed
73 74 75 76 77 78 79
	      1,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);
  
Wang's avatar
Wang committed
80
  //symbol 2
81
  nr_slot_fep(ue,
knopp's avatar
knopp committed
82 83 84 85 86 87
	      2,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);
Wang's avatar
Wang committed
88 89

  //symbol 3
90
  nr_slot_fep(ue,
knopp's avatar
knopp committed
91 92 93 94 95 96 97 98
	      3,
	      0,
	      ue->ssb_offset,
	      0,
	      1,
	      NR_PBCH_EST);

  //put back nb_prefix_samples0
hongzhi wang's avatar
hongzhi wang committed
99
  frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
100 101
  
  
knopp's avatar
knopp committed
102 103 104 105 106 107 108 109 110
  ret = nr_rx_pbch(ue,
		   &ue->proc.proc_rxtx[0],
		   ue->pbch_vars[0],
		   frame_parms,
		   0,
		   SISO,
		   ue->high_speed_flag);
  
  
111
  if (ret==0) {
knopp's avatar
knopp committed
112
    
113
    frame_parms->nb_antenna_ports_eNB = 1; //pbch_tx_ant;
knopp's avatar
knopp committed
114
    
Wang's avatar
Wang committed
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    // 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
131
    LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully\n",ue->Mod_id);
Wang's avatar
Wang committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145
#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)
{

146
  int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2,
knopp's avatar
knopp committed
147 148
  int32_t metric_tdd_ncp=0;
  uint8_t phase_tdd_ncp;
149
  double im, re;
Wang's avatar
Wang committed
150

knopp's avatar
knopp committed
151
  NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
Wang's avatar
Wang committed
152
  int ret=-1;
hongzhi wang's avatar
hongzhi wang committed
153
  int rx_power=0; //aarx,
Guy De Souza's avatar
Guy De Souza committed
154
  //nfapi_nr_config_request_t* config;
Wang's avatar
Wang committed
155

156
  int n_ssb_crb=(fp->N_RB_DL-20);
knopp's avatar
knopp committed
157
  // First try TDD normal prefix, mu 1
knopp's avatar
knopp committed
158 159
  fp->Ncp=NORMAL;
  fp->frame_type=TDD;
160 161
  // 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
162
  LOG_D(PHY,"nr_initial sync ue RB_DL %d\n", fp->N_RB_DL);
163

Wang's avatar
Wang committed
164
  /*
165
  write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1);
Wang's avatar
Wang committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
  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
181

182
  cnt++;
183
  if (1){ // (cnt>100)
184
    cnt =0;
185

Wang's avatar
Wang committed
186 187 188
  /* process pss search on received buffer */
  sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE);

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

hongzhi wang's avatar
hongzhi wang committed
191 192 193 194 195
  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;}
    
196
  ue->rx_offset = ue->ssb_offset - sync_pos_slot;
197

198
  //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1);
Wang's avatar
Wang committed
199 200 201

#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
202
  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
203 204
#endif

205 206 207 208
  // digital compensation of FFO for SSB symbols
  if (ue->UE_fo_compensation){  
	double s_time = 1/(1.0e3*fp->samples_per_subframe);  // sampling time
	double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset);  // offset rotation angle compensation per sample
209

210 211
	int start = ue->ssb_offset;  // start for offset correction is at ssb_offset (pss time position)
  	int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples);  // loop over samples in 4 symbols (ssb size), including prefix  
212

213 214
	for(int n=start; n<end; n++){  	
	  for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
215 216 217 218
		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)));
219
	  }
220 221 222 223
	}
  }


Wang's avatar
Wang committed
224
  /* check that SSS/PBCH block is continuous inside the received buffer */
225
  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
226 227 228 229 230

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

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

233 234
    //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
235

Hongzhi Wang's avatar
Hongzhi Wang committed
236
    nr_gold_pbch(ue);
hongzhi wang's avatar
hongzhi wang committed
237
    ret = nr_pbch_detection(ue,mode);
238 239
    
    nr_gold_pdcch(ue,0, 2);
knopp's avatar
knopp committed
240
    /*
241 242
    int nb_prefix_samples0 = fp->nb_prefix_samples0;
    fp->nb_prefix_samples0 = fp->nb_prefix_samples;
knopp's avatar
knopp committed
243 244 245
	  
    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);
246
    fp->nb_prefix_samples0 = nb_prefix_samples0;	
247

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

#ifdef DEBUG_INITIAL_SYNCH
256 257
    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
258 259 260 261
#endif
  }
  else {
#ifdef DEBUG_INITIAL_SYNCH
knopp's avatar
knopp committed
262
    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
263 264
#endif
  }
265 266 267 268
  }
  else {
	  ret = -1;
  }
Wang's avatar
Wang committed
269

270 271
  /* 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
272 273 274 275 276 277 278 279
  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
280
  }*/
Wang's avatar
Wang committed
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

  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
322 323 324 325 326 327 328
	  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
329 330 331 332 333 334 335 336 337 338 339 340 341
#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
342 343 344 345 346 347 348
	  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
349 350 351 352 353 354 355
#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,
356
	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
Wang's avatar
Wang committed
357 358 359 360 361
	  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,
362
	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
Wang's avatar
Wang committed
363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
	  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
386 387 388
    //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
389 390 391 392 393 394 395 396 397

    /*
    // 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
398
    ue->measurements.rx_power_avg[0] = rx_power/fp->nb_antennas_rx;
Wang's avatar
Wang committed
399 400 401 402 403 404 405 406 407 408 409

    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
410
  //phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0);
Wang's avatar
Wang committed
411 412 413 414 415 416 417 418 419 420 421 422
#endif
#endif
#endif
#endif

  }
  else {

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

  }

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