441 lines
14 KiB
C
441 lines
14 KiB
C
/*
|
|
* 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"
|
|
#include "PHY/INIT/phy_init.h"
|
|
#include "PHY/MODULATION/modulation_UE.h"
|
|
#include "nr_transport_proto_ue.h"
|
|
//#include "SCHED/defs.h"
|
|
//#include "SCHED/extern.h"
|
|
|
|
#include "common_lib.h"
|
|
|
|
#include "PHY/NR_REFSIG/pss_nr.h"
|
|
#include "PHY/NR_REFSIG/sss_nr.h"
|
|
#include "PHY/NR_REFSIG/refsig_defs_ue.h"
|
|
|
|
extern openair0_config_t openair0_cfg[];
|
|
//static nfapi_nr_config_request_t config_t;
|
|
//static nfapi_nr_config_request_t* config =&config_t;
|
|
int cnt=0;
|
|
|
|
//#define DEBUG_INITIAL_SYNCH
|
|
|
|
int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode)
|
|
{
|
|
printf("nr pbch detec RB_DL %d\n", ue->frame_parms.N_RB_DL);
|
|
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
|
|
int ret =-1;
|
|
|
|
#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
|
|
|
|
int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
|
frame_parms->nb_prefix_samples0 = 0;
|
|
|
|
//symbol 1
|
|
nr_slot_fep(ue,
|
|
5,
|
|
0,
|
|
ue->rx_offset,
|
|
0,
|
|
1,
|
|
NR_PBCH_EST);
|
|
|
|
//symbol 2
|
|
nr_slot_fep(ue,
|
|
6,
|
|
0,
|
|
ue->rx_offset,
|
|
0,
|
|
1,
|
|
NR_PBCH_EST);
|
|
|
|
//symbol 3
|
|
nr_slot_fep(ue,
|
|
7,
|
|
0,
|
|
ue->rx_offset,
|
|
0,
|
|
1,
|
|
NR_PBCH_EST);
|
|
|
|
frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
|
|
|
|
printf("pbch_detection nid_cell %d\n",frame_parms->Nid_cell);
|
|
|
|
ret = nr_rx_pbch(ue,
|
|
&ue->proc.proc_rxtx[0],
|
|
ue->pbch_vars[0],
|
|
frame_parms,
|
|
0,
|
|
SISO,
|
|
ue->high_speed_flag);
|
|
|
|
|
|
if (ret==0) {
|
|
|
|
frame_parms->nb_antenna_ports_eNB = 1; //pbch_tx_ant;
|
|
|
|
// 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
|
|
LOG_I(PHY,"[UE%d] Initial sync: pbch decoded sucessfully mode1_flag %d, tx_ant %d, frame %d\n",
|
|
ue->Mod_id,
|
|
frame_parms->mode1_flag,
|
|
pbch_tx_ant,
|
|
ue->proc.proc_rxtx[0].frame_rx,);
|
|
#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)
|
|
{
|
|
|
|
int32_t sync_pos, sync_pos2, k_ssb, N_ssb_crb, sync_pos_slot;
|
|
int32_t metric_fdd_ncp=0;
|
|
uint8_t phase_fdd_ncp;
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
|
|
int ret=-1;
|
|
int rx_power=0; //aarx,
|
|
//nfapi_nr_config_request_t* config;
|
|
|
|
/*offset parameters to be updated from higher layer */
|
|
//k_ssb =0;
|
|
//N_ssb_crb = 0;
|
|
|
|
/*#ifdef OAI_USRP
|
|
__m128i *rxdata128;
|
|
#endif*/
|
|
// LOG_I(PHY,"**************************************************************\n");
|
|
// First try FDD normal prefix
|
|
frame_parms->Ncp=NORMAL;
|
|
frame_parms->frame_type=TDD;
|
|
nr_init_frame_parms_ue(frame_parms);
|
|
printf("nr_initial sync ue RB_DL %d\n", ue->frame_parms.N_RB_DL);
|
|
/*
|
|
write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
|
exit(-1);
|
|
*/
|
|
|
|
/* Initial synchronisation
|
|
*
|
|
* 1 radio frame = 10 ms
|
|
* <--------------------------------------------------------------------------->
|
|
* -----------------------------------------------------------------------------
|
|
* | Received UE data buffer |
|
|
* ----------------------------------------------------------------------------
|
|
* --------------------------
|
|
* <-------------->| pss | pbch | sss | pbch |
|
|
* --------------------------
|
|
* sync_pos SS/PBCH block
|
|
*/
|
|
cnt++;
|
|
if (cnt >100){
|
|
cnt =0;
|
|
/* process pss search on received buffer */
|
|
sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE);
|
|
|
|
sync_pos_slot = (frame_parms->samples_per_tti>>1) - 3*(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
|
|
|
|
if (sync_pos >= frame_parms->nb_prefix_samples)
|
|
sync_pos2 = sync_pos - frame_parms->nb_prefix_samples;
|
|
else
|
|
sync_pos2 = sync_pos + FRAME_LENGTH_COMPLEX_SAMPLES - frame_parms->nb_prefix_samples;
|
|
|
|
/* offset is used by sss serach as it is returned from pss search */
|
|
if (sync_pos2 >= sync_pos_slot)
|
|
ue->rx_offset = sync_pos2 - sync_pos_slot;
|
|
else
|
|
ue->rx_offset = FRAME_LENGTH_COMPLEX_SAMPLES + sync_pos2 - sync_pos_slot;
|
|
|
|
printf("sync_pos %d sync_pos_slot %d rx_offset %d\n",sync_pos,sync_pos_slot, ue->rx_offset);
|
|
|
|
|
|
// write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
|
|
|
#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);
|
|
#endif
|
|
|
|
/* check that SSS/PBCH block is continuous inside the received buffer */
|
|
if (sync_pos < (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->ttis_per_subframe*frame_parms->samples_per_tti - (NB_SYMBOLS_PBCH * frame_parms->ofdm_symbol_size))) {
|
|
|
|
#ifdef DEBUG_INITIAL_SYNCH
|
|
LOG_I(PHY,"Calling sss detection (normal CP)\n");
|
|
#endif
|
|
|
|
rx_sss_nr(ue,&metric_fdd_ncp,&phase_fdd_ncp);
|
|
|
|
nr_init_frame_parms_ue(&ue->frame_parms);
|
|
|
|
nr_gold_pbch(ue);
|
|
ret = nr_pbch_detection(ue,mode);
|
|
|
|
nr_gold_pdcch(ue,0, 2);
|
|
int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
|
|
frame_parms->nb_prefix_samples0 = 0;
|
|
|
|
nr_slot_fep(ue,0, 0, ue->rx_offset, 0, 1, NR_PDCCH_EST);
|
|
nr_slot_fep(ue,1, 0, ue->rx_offset, 0, 1, NR_PDCCH_EST);
|
|
frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
|
|
|
|
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 );
|
|
|
|
//ret = -1; //to be deleted
|
|
// write_output("rxdata2.m","rxd2",ue->common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1);
|
|
|
|
#ifdef DEBUG_INITIAL_SYNCH
|
|
LOG_I(PHY,"FDD Normal prefix: CellId %d metric %d, phase %d, flip %d, pbch %d\n",
|
|
frame_parms->Nid_cell,metric_fdd_ncp,phase_fdd_ncp,flip_fdd_ncp,ret);
|
|
#endif
|
|
}
|
|
else {
|
|
#ifdef DEBUG_INITIAL_SYNCH
|
|
LOG_I(PHY,"FDD Normal prefix: SSS error condition: sync_pos %d, sync_pos_slot %d\n", sync_pos, sync_pos_slot);
|
|
#endif
|
|
}
|
|
}
|
|
else {
|
|
ret = -1;
|
|
}
|
|
|
|
/* Consider this is a false detection if the offset is > 1000 Hz */
|
|
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
|
|
}
|
|
|
|
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
|
|
#if OAISIM
|
|
if (ue->mac_enabled==1) {
|
|
LOG_I(PHY,"[UE%d] Sending synch status to higher layers\n",ue->Mod_id);
|
|
//mac_resynch();
|
|
mac_xface->dl_phy_sync_success(ue->Mod_id,ue->proc.proc_rxtx[0].frame_rx,0,1);//ue->common_vars.eNb_id);
|
|
ue->UE_mode[0] = PRACH;
|
|
}
|
|
else {
|
|
ue->UE_mode[0] = PUSCH;
|
|
}
|
|
#endif
|
|
|
|
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,
|
|
duplex_string[ue->frame_parms.frame_type],
|
|
prefix_string[ue->frame_parms.Ncp],
|
|
ue->frame_parms.Nid_cell,
|
|
ue->frame_parms.N_RB_DL,
|
|
ue->frame_parms.phich_config_common.phich_duration,
|
|
phich_string[ue->frame_parms.phich_config_common.phich_resource],
|
|
ue->frame_parms.nb_antenna_ports_eNB);
|
|
#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,
|
|
duplex_string[ue->frame_parms.frame_type],
|
|
prefix_string[ue->frame_parms.Ncp],
|
|
ue->frame_parms.Nid_cell,
|
|
ue->frame_parms.N_RB_DL,
|
|
ue->frame_parms.phich_config_common.phich_duration,
|
|
phich_string[ue->frame_parms.phich_config_common.phich_resource],
|
|
ue->frame_parms.nb_antenna_ports_eNB);*/
|
|
#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,
|
|
openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset,
|
|
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,
|
|
openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset,
|
|
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: (metric fdd_ncp %d (%d), metric fdd_ecp %d (%d), metric_tdd_ncp %d (%d), metric_tdd_ecp %d (%d))\n",
|
|
ue->Mod_id,
|
|
metric_fdd_ncp,Nid_cell_fdd_ncp,
|
|
metric_fdd_ecp,Nid_cell_fdd_ecp,
|
|
metric_tdd_ncp,Nid_cell_tdd_ncp,
|
|
metric_tdd_ecp,Nid_cell_tdd_ecp);*/
|
|
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
|
|
//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);
|
|
|
|
/*
|
|
// 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
|
|
ue->measurements.rx_power_avg[0] = rx_power/frame_parms->nb_antennas_rx;
|
|
|
|
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
|
|
//phy_adjust_gain(ue,ue->measurements.rx_power_avg_dB[0],0);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
else {
|
|
|
|
#ifndef OAI_USRP
|
|
#ifndef OAI_BLADERF
|
|
#ifndef OAI_LMSSDR
|
|
#ifndef OAI_ADRV9371_ZC706
|
|
//phy_adjust_gain(ue,dB_fixed(ue->measurements.rssi),0);
|
|
#endif
|
|
#endif
|
|
#endif
|
|
#endif
|
|
|
|
}
|
|
|
|
// exit_fun("debug exit");
|
|
return ret;
|
|
}
|
|
|