Commit 50a4a1fd authored by Guy De Souza's avatar Guy De Souza

Merge branch 'nr_initialsync' of...

Merge branch 'nr_initialsync' of https://gitlab.eurecom.fr/oai/openairinterface5g into nr_initialsync
parents 5da38359 0fb13383
......@@ -1271,6 +1271,9 @@ set(PHY_SRC_UE
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dmrs_nr.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_pbch.c
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/
${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
......
......@@ -928,3 +928,45 @@ void nr_lte_ue_transport(PHY_VARS_UE *ue,int abstraction_flag) {
ue->dlsch_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS_MBSFN,ue->frame_parms.N_RB_DL,0);
}*/
void phy_init_nr_top(NR_DL_FRAME_PARMS *frame_parms)
{
crcTableInit();
ccodedot11_init();
ccodedot11_init_inv();
ccodelte_init();
ccodelte_init_inv();
//treillis_table_init();
phy_generate_viterbi_tables();
phy_generate_viterbi_tables_lte();
//init_td8();
//init_td16();
#ifdef __AVX2__
//init_td16avx2();
#endif
init_context_synchro_nr(frame_parms);
generate_ul_reference_signal_sequences(SHRT_MAX);
//lte_sync_time_init(frame_parms);
//generate_ul_ref_sigs();
//generate_ul_ref_sigs_rx();
//generate_64qam_table();
//generate_16qam_table();
//generate_RIV_tables();
//init_unscrambling_lut();
//init_scrambling_lut();
//set_taus_seed(1328);
}
......@@ -34,6 +34,131 @@ int nr_init_frame_parms(nfapi_config_request_t* config,
int Ncp = config->subframe_config.dl_cyclic_prefix_type.value;
int mu = config->subframe_config.numerology_index_mu.value;
#if DISABLE_LOG_X
printf("Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, N_RB, Ncp);
#else
LOG_I(PHY,"Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, N_RB, Ncp);
#endif
if (Ncp == EXTENDED)
AssertFatal(mu == NR_MU_2,"Invalid cyclic prefix %d for numerology index %d\n", Ncp, mu);
switch(mu) {
case NR_MU_0: //15kHz scs
frame_parms->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_0];
frame_parms->slots_per_subframe = nr_slots_per_subframe[NR_MU_0];
break;
case NR_MU_1: //30kHz scs
frame_parms->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_1];
frame_parms->slots_per_subframe = nr_slots_per_subframe[NR_MU_1];
switch(N_RB){
case 11:
case 24:
case 38:
case 78:
case 51:
case 65:
case 106: //40 MHz
if (frame_parms->threequarter_fs) {
frame_parms->ofdm_symbol_size = 1536;
frame_parms->first_carrier_offset = 900; //1536 - 636
frame_parms->nb_prefix_samples0 = 132;
frame_parms->nb_prefix_samples = 108;
}
else {
frame_parms->ofdm_symbol_size = 2048;
frame_parms->first_carrier_offset = 1412; //2048 - 636
frame_parms->nb_prefix_samples0 = 176;
frame_parms->nb_prefix_samples = 144;
}
break;
case 133:
case 162:
case 189:
case 217: //80 MHz
if (frame_parms->threequarter_fs) {
frame_parms->ofdm_symbol_size = 3072;
frame_parms->first_carrier_offset = 1770; //3072 - 1302
frame_parms->nb_prefix_samples0 = 264;
frame_parms->nb_prefix_samples = 216;
}
else {
frame_parms->ofdm_symbol_size = 4096;
frame_parms->first_carrier_offset = 2794; //4096 - 1302
frame_parms->nb_prefix_samples0 = 352;
frame_parms->nb_prefix_samples = 288;
}
break;
case 245:
case 273:
default:
AssertFatal(1==0,"Number of resource blocks %d undefined for mu %d, frame parms = %p\n", N_RB, mu, frame_parms);
}
break;
case NR_MU_2: //60kHz scs
frame_parms->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_2];
frame_parms->slots_per_subframe = nr_slots_per_subframe[NR_MU_2];
switch(N_RB){ //FR1 bands only
case 11:
case 18:
case 38:
case 24:
case 31:
case 51:
case 65:
case 79:
case 93:
case 107:
case 121:
case 135:
default:
AssertFatal(1==0,"Number of resource blocks %d undefined for mu %d, frame parms = %p\n", N_RB, mu, frame_parms);
}
break;
case NR_MU_3:
frame_parms->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_3];
frame_parms->slots_per_subframe = nr_slots_per_subframe[NR_MU_3];
break;
case NR_MU_4:
frame_parms->subcarrier_spacing = nr_subcarrier_spacing[NR_MU_4];
frame_parms->slots_per_subframe = nr_slots_per_subframe[NR_MU_4];
break;
default:
AssertFatal(1==0,"Invalid numerology index %d", mu);
}
frame_parms->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe;
frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP;
frame_parms->samples_per_subframe = (frame_parms->samples_per_subframe_wCP + (frame_parms->nb_prefix_samples0 * frame_parms->slots_per_subframe) +
(frame_parms->nb_prefix_samples * frame_parms->slots_per_subframe * (frame_parms->symbols_per_slot - 1)));
frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe;
return 0;
}
int nr_init_frame_parms_ue(nfapi_config_request_t* config,
NR_DL_FRAME_PARMS *frame_parms)
{
int N_RB = 106;
int Ncp = 0;
int mu = 1;
#if DISABLE_LOG_X
printf("Initializing frame parms for mu %d, N_RB %d, Ncp %d\n",mu, N_RB, Ncp);
#else
......@@ -152,11 +277,23 @@ int nr_init_frame_parms(nfapi_config_request_t* config,
AssertFatal(1==0,"Invalid numerology index %d", mu);
}
frame_parms->nb_prefix_samples0 = 160;
frame_parms->nb_prefix_samples = 144;
frame_parms->symbols_per_tti = 14;
frame_parms->numerology_index = 0;
frame_parms->ttis_per_subframe = 1;
frame_parms->slots_per_tti = 2; //only slot config 1 is supported
frame_parms->ofdm_symbol_size = 2048;
frame_parms->samples_per_tti = 30720;
frame_parms->samples_per_subframe = 30720 * frame_parms->ttis_per_subframe;
frame_parms->first_carrier_offset = 2048-600;
frame_parms->symbols_per_slot = ((Ncp == NORMAL)? 14 : 12); // to redefine for different slot formats
frame_parms->samples_per_subframe_wCP = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_slot * frame_parms->slots_per_subframe;
frame_parms->samples_per_frame_wCP = 10 * frame_parms->samples_per_subframe_wCP;
frame_parms->samples_per_subframe = frame_parms->samples_per_subframe_wCP + (frame_parms->nb_prefix_samples0 * frame_parms->slots_per_subframe) +
(frame_parms->nb_prefix_samples * frame_parms->slots_per_subframe * (frame_parms->symbols_per_slot - 1));
//frame_parms->samples_per_subframe = (frame_parms->samples_per_subframe_wCP + (frame_parms->nb_prefix_samples0 * frame_parms->slots_per_subframe) +
// (frame_parms->nb_prefix_samples * frame_parms->slots_per_subframe * (frame_parms->symbols_per_slot - 1)));
frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe;
......
......@@ -375,6 +375,7 @@ void phy_config_request(PHY_Config_t *phy_config);
int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
int nr_init_frame_parms(nfapi_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms);
int nr_init_frame_parms_ue(nfapi_config_request_t* config, NR_DL_FRAME_PARMS *frame_parms);
void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms);
int phy_init_nr_gNB(PHY_VARS_gNB *gNB, unsigned char is_secondary_gNB, unsigned char abstraction_flag);
void nr_phy_config_request(PHY_VARS_gNB *gNB);
......
/*
* 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 "SCHED/defs.h"
//#include "SCHED/extern.h"
//#include "defs.h"
//#include "extern.h"
#include "common_lib.h"
#include "PHY/NR_REFSIG/pss_nr.h"
#include "PHY/NR_REFSIG/sss_nr.h"
extern openair0_config_t openair0_cfg[];
static nfapi_config_request_t config_t;
static nfapi_config_request_t* config =&config_t;
/* forward declarations */
void set_default_frame_parms_single(nfapi_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms);
//#define DEBUG_INITIAL_SYNCH
int pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode)
{
uint8_t l,pbch_decoded,frame_mod4,pbch_tx_ant,dummy;
NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
char phich_resource[6];
#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
//symbol 1
slot_fep_pbch(ue,
1,
0,
ue->rx_offset,
0,
1);
//symbol 2
slot_fep_pbch(ue,
2,
0,
ue->rx_offset,
0,
1);
//symbol 3
slot_fep_pbch(ue,
3,
0,
ue->rx_offset,
0,
1);
pbch_decoded = 0;
//for (frame_mod4=0; frame_mod4<4; frame_mod4++) {
pbch_tx_ant = nr_rx_pbch(ue,
&ue->proc.proc_rxtx[0],
ue->pbch_vars[0],
frame_parms,
0,
SISO,
ue->high_speed_flag,
frame_mod4);
if ((pbch_tx_ant>0) && (pbch_tx_ant<=2)) {
pbch_decoded = 1;
// break;
}
//}
if (pbch_decoded) {
frame_parms->nb_antenna_ports_eNB = 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;
// now check for Bandwidth of Cell
dummy = (ue->pbch_vars[0]->decoded_output[2]>>5)&7;
switch (dummy) {
case 0 :
frame_parms->N_RB_DL = 6;
break;
case 1 :
frame_parms->N_RB_DL = 15;
break;
case 2 :
frame_parms->N_RB_DL = 25;
break;
case 3 :
frame_parms->N_RB_DL = 50;
break;
case 4 :
frame_parms->N_RB_DL = 75;
break;
case 5:
frame_parms->N_RB_DL = 100;
break;
default:
LOG_E(PHY,"[UE%d] Initial sync: PBCH decoding: Unknown N_RB_DL\n",ue->Mod_id);
return -1;
break;
}
for(int i=0; i<RX_NB_TH;i++)
{
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
ue->proc.proc_rxtx[i].frame_rx = (((ue->pbch_vars[0]->decoded_output[2]&3)<<6) + (ue->pbch_vars[0]->decoded_output[1]>>2))<<2;
#ifndef USER_MODE
// one frame delay
ue->proc.proc_rxtx[i].frame_rx ++;
#endif
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_RB_DL %d, phich_duration %d, phich_resource %s!\n",
ue->Mod_id,
frame_parms->mode1_flag,
pbch_tx_ant,
ue->proc.proc_rxtx[0].frame_rx,
frame_parms->N_RB_DL,
frame_parms->phich_config_common.phich_duration,
phich_resource); //frame_parms->phich_config_common.phich_resource);
#endif
return(0);
} else {
return(-1);
}
}
char phich_string[13][4] = {"","1/6","","1/2","","","one","","","","","","two"};
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;
int32_t metric_fdd_ncp=0;
uint8_t phase_fdd_ncp;
NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
int ret=-1;
int aarx,rx_power=0;
//nfapi_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=FDD;
set_default_frame_parms_single(config,frame_parms);
nr_init_frame_parms_ue(config,frame_parms);
/*
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
*/
/* process pss search on received buffer */
sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE);
/* offset is used by sss serach as it is returned from pss search */
ue->rx_offset = sync_pos;
// 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);
set_default_frame_parms_single(config,&ue->frame_parms);
nr_init_frame_parms_ue(config,&ue->frame_parms);
//generate_dmrs_pbch(ue->dmrs_pbch_bitmap_nr, frame_parms->Nid_cell);
ret = pbch_detection(ue,mode);
// 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
}
/* 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
generate_pcfich_reg_mapping(frame_parms);
generate_phich_reg_mapping(frame_parms);
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;
}
/*
* 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/CODING/lte_interleaver_inline.h"
//#include "defs.h"
//#include "extern.h"
#include "PHY/phy_extern_nr_ue.h"
#include "PHY/sse_intrin.h"
#ifdef PHY_ABSTRACTION
#include "SIMULATION/TOOLS/defs.h"
#endif
//#define DEBUG_PBCH 1
//#define DEBUG_PBCH_ENCODING
//#define INTERFERENCE_MITIGATION 1
#ifdef OPENAIR2
//#include "PHY_INTERFACE/defs.h"
#endif
#define PBCH_A 24
uint16_t nr_pbch_extract(int **rxdataF,
int **dl_ch_estimates,
int **rxdataF_ext,
int **dl_ch_estimates_ext,
uint32_t symbol,
uint32_t high_speed_flag,
NR_DL_FRAME_PARMS *frame_parms)
{
uint16_t rb;
uint8_t i,j,aarx,aatx;
int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
int rx_offset = frame_parms->ofdm_symbol_size-3*12;
int ch_offset = frame_parms->N_RB_DL*6-3*12;
int nushiftmod4 = frame_parms->nushift%4;
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
/*
printf("extract_rbs (nushift %d): symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",frame_parms->nushift,symbol_mod,
(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2,
LTE_CE_OFFSET+ch_offset+(symbol_mod*(frame_parms->ofdm_symbol_size)));
*/
rxF = &rxdataF[aarx][(rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))];
rxF_ext = &rxdataF_ext[aarx][symbol*(20*12)];
for (rb=0; rb<20; rb++) {
// skip DC carrier
if (rb==10) {
rxF = &rxdataF[aarx][(1 + (symbol*(frame_parms->ofdm_symbol_size)))];
}
if ((symbol==1) || (symbol==3)) {
j=0;
for (i=0; i<12; i++) {
if ((i!=nushiftmod4) &&
(i!=(nushiftmod4+4)) &&
(i!=(nushiftmod4+8))) {
rxF_ext[j++]=rxF[i];
}
}
rxF+=12;
rxF_ext+=8;
} else { //symbol 2
if ((rb < 4) && (rb >15)){
for (i=0; i<12; i++) {
if ((i!=nushiftmod4) &&
(i!=(nushiftmod4+4)) &&
(i!=(nushiftmod4+8))) {
rxF_ext[j++]=rxF[i];
}
}
}
rxF+=12;
rxF_ext+=8;
}
}
for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
if (high_speed_flag == 1)
dl_ch0 = &dl_ch_estimates[(aatx<<1)+aarx][LTE_CE_OFFSET+ch_offset+(symbol*(frame_parms->ofdm_symbol_size))];
else
dl_ch0 = &dl_ch_estimates[(aatx<<1)+aarx][LTE_CE_OFFSET+ch_offset];
dl_ch0_ext = &dl_ch_estimates_ext[(aatx<<1)+aarx][symbol*(20*12)];
for (rb=0; rb<20; rb++) {
// skip DC carrier
// if (rb==3) dl_ch0++;
memcpy(dl_ch0_ext,dl_ch0,12*sizeof(int));
if ((symbol==1) || (symbol==3)) {
j=0;
for (i=0; i<12; i++) {
if ((i!=nushiftmod4) &&
(i!=(nushiftmod4+4)) &&
(i!=(nushiftmod4+8))) {
rxF_ext[j++]=rxF[i];
}
}
dl_ch0+=12;
dl_ch0_ext+=8;
}
else { //symbol 2
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];
}
}
}
dl_ch0+=12;
dl_ch0_ext+=8;
}
}
} //tx antenna loop
}
return(0);
}
//__m128i avg128;
//compute average channel_level on each (TX,RX) antenna pair
int nr_pbch_channel_level(int **dl_ch_estimates_ext,
NR_DL_FRAME_PARMS *frame_parms,
uint32_t symbol)
{
int16_t rb, nb_rb=6;
uint8_t aatx,aarx;
#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;
uint32_t nsymb = (frame_parms->Ncp==0) ? 7:6;
uint32_t symbol_mod = symbol % nsymb;
for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
//clear average level
#if defined(__x86_64__) || defined(__i386__)
avg128 = _mm_setzero_si128();
dl_ch128=(__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12];
#elif defined(__arm__)
avg128 = vdupq_n_s32(0);
dl_ch128=(int16x8_t *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12];
#endif
for (rb=0; rb<nb_rb; rb++) {
#if defined(__x86_64__) || defined(__i386__)
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]));
#elif defined(__arm__)
// to be filled in
#endif
dl_ch128+=3;
/*
if (rb==0) {
print_shorts("dl_ch128",&dl_ch128[0]);
print_shorts("dl_ch128",&dl_ch128[1]);
print_shorts("dl_ch128",&dl_ch128[2]);
}
*/
}
avg1 = (((int*)&avg128)[0] +
((int*)&avg128)[1] +
((int*)&avg128)[2] +
((int*)&avg128)[3])/(nb_rb*12);
if (avg1>avg2)
avg2 = avg1;
//msg("Channel level : %d, %d\n",avg1, avg2);
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
return(avg2);
}
#if defined(__x86_64__) || defined(__i386__)
__m128i mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
#elif defined(__arm__)
int16x8_t mmtmpP0,mmtmpP1,mmtmpP2,mmtmpP3;
#endif
void nr_pbch_channel_compensation(int **rxdataF_ext,
int **dl_ch_estimates_ext,
int **rxdataF_comp,
NR_DL_FRAME_PARMS *frame_parms,
uint8_t symbol,
uint8_t output_shift)
{
uint16_t rb,nb_rb=6;
uint8_t aatx,aarx,symbol_mod;
#if defined(__x86_64__) || defined(__i386__)
__m128i *dl_ch128,*rxdataF128,*rxdataF_comp128;
#elif defined(__arm__)
#endif
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
for (aatx=0; aatx<4; aatx++) //frame_parms->nb_antenna_ports_eNB;aatx++)
for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
#if defined(__x86_64__) || defined(__i386__)
dl_ch128 = (__m128i *)&dl_ch_estimates_ext[(aatx<<1)+aarx][symbol_mod*6*12];
rxdataF128 = (__m128i *)&rxdataF_ext[aarx][symbol_mod*6*12];
rxdataF_comp128 = (__m128i *)&rxdataF_comp[(aatx<<1)+aarx][symbol_mod*6*12];
#elif defined(__arm__)
// to be filled in
#endif
for (rb=0; rb<nb_rb; rb++) {
//printf("rb %d\n",rb);
#if defined(__x86_64__) || defined(__i386__)
// multiply by conjugated channel
mmtmpP0 = _mm_madd_epi16(dl_ch128[0],rxdataF128[0]);
// print_ints("re",&mmtmpP0);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[0],_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
// print_ints("im",&mmtmpP1);
mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[0]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
// print_ints("re(shift)",&mmtmpP0);
mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
// print_ints("im(shift)",&mmtmpP1);
mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
// print_ints("c0",&mmtmpP2);
// print_ints("c1",&mmtmpP3);
rxdataF_comp128[0] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
// print_shorts("rx:",rxdataF128);
// print_shorts("ch:",dl_ch128);
// print_shorts("pack:",rxdataF_comp128);
// multiply by conjugated channel
mmtmpP0 = _mm_madd_epi16(dl_ch128[1],rxdataF128[1]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[1],_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[1]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
rxdataF_comp128[1] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
// print_shorts("rx:",rxdataF128+1);
// print_shorts("ch:",dl_ch128+1);
// print_shorts("pack:",rxdataF_comp128+1);
if (symbol_mod>1) {
// multiply by conjugated channel
mmtmpP0 = _mm_madd_epi16(dl_ch128[2],rxdataF128[2]);
// mmtmpP0 contains real part of 4 consecutive outputs (32-bit)
mmtmpP1 = _mm_shufflelo_epi16(dl_ch128[2],_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_shufflehi_epi16(mmtmpP1,_MM_SHUFFLE(2,3,0,1));
mmtmpP1 = _mm_sign_epi16(mmtmpP1,*(__m128i*)&conjugate[0]);
mmtmpP1 = _mm_madd_epi16(mmtmpP1,rxdataF128[2]);
// mmtmpP1 contains imag part of 4 consecutive outputs (32-bit)
mmtmpP0 = _mm_srai_epi32(mmtmpP0,output_shift);
mmtmpP1 = _mm_srai_epi32(mmtmpP1,output_shift);
mmtmpP2 = _mm_unpacklo_epi32(mmtmpP0,mmtmpP1);
mmtmpP3 = _mm_unpackhi_epi32(mmtmpP0,mmtmpP1);
rxdataF_comp128[2] = _mm_packs_epi32(mmtmpP2,mmtmpP3);
// print_shorts("rx:",rxdataF128+2);
// print_shorts("ch:",dl_ch128+2);
// print_shorts("pack:",rxdataF_comp128+2);
dl_ch128+=3;
rxdataF128+=3;
rxdataF_comp128+=3;
} else {
dl_ch128+=2;
rxdataF128+=2;
rxdataF_comp128+=2;
}
#elif defined(__arm__)
// to be filled in
#endif
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
}
void nr_pbch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
int **rxdataF_comp,
uint8_t symbol)
{
uint8_t aatx, symbol_mod;
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) {
for (aatx=0; aatx<4; aatx++) { //frame_parms->nb_antenna_ports_eNB;aatx++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0 = (__m128i *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
rxdataF_comp128_1 = (__m128i *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];
#elif defined(__arm__)
rxdataF_comp128_0 = (int16x8_t *)&rxdataF_comp[(aatx<<1)][symbol_mod*6*12];
rxdataF_comp128_1 = (int16x8_t *)&rxdataF_comp[(aatx<<1)+1][symbol_mod*6*12];
#endif
// 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++) {
#if defined(__x86_64__) || defined(__i386__)
rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
#elif defined(__arm__)
rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
#endif
}
}
}
#if defined(__x86_64__) || defined(__i386__)
_mm_empty();
_m_empty();
#endif
}
void nr_pbch_scrambling(NR_DL_FRAME_PARMS *frame_parms,
uint8_t *pbch_e,
uint32_t length)
{
int i;
uint8_t reset;
uint32_t x1, x2, s=0;
reset = 1;
// x1 is set in lte_gold_generic
x2 = frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.6.1
// msg("pbch_scrambling: Nid_cell = %d\n",x2);
for (i=0; i<length; i++) {
if ((i&0x1f)==0) {
s = lte_gold_generic(&x1, &x2, reset);
// printf("lte_gold[%d]=%x\n",i,s);
reset = 0;
}
pbch_e[i] = (pbch_e[i]&1) ^ ((s>>(i&0x1f))&1);
}
}
void nr_pbch_unscrambling(NR_DL_FRAME_PARMS *frame_parms,
int8_t* llr,
uint32_t length,
uint8_t frame_mod4)
{
int i;
uint8_t reset;
uint32_t x1, x2, s=0;
reset = 1;
// x1 is set in first call to lte_gold_generic
x2 = frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.6.1
// msg("pbch_unscrambling: Nid_cell = %d\n",x2);
for (i=0; i<length; i++) {
if (i%32==0) {
s = lte_gold_generic(&x1, &x2, reset);
// printf("lte_gold[%d]=%x\n",i,s);
reset = 0;
}
// take the quarter of the PBCH that corresponds to this frame
if ((i>=(frame_mod4*(length>>2))) && (i<((1+frame_mod4)*(length>>2)))) {
// if (((s>>(i%32))&1)==1)
if (((s>>(i%32))&1)==0)
llr[i] = -llr[i];
}
}
}
void nr_pbch_alamouti(NR_DL_FRAME_PARMS *frame_parms,
int **rxdataF_comp,
uint8_t symbol)
{
int16_t *rxF0,*rxF1;
// __m128i *ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b;
uint8_t rb,re,symbol_mod;
int jj;
// printf("Doing alamouti\n");
symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
jj = (symbol_mod*6*12);
rxF0 = (int16_t*)&rxdataF_comp[0][jj]; //tx antenna 0 h0*y
rxF1 = (int16_t*)&rxdataF_comp[2][jj]; //tx antenna 1 h1*y
for (rb=0; rb<6; rb++) {
for (re=0; re<12; re+=2) {
// Alamouti RX combining
rxF0[0] = rxF0[0] + rxF1[2];
rxF0[1] = rxF0[1] - rxF1[3];
rxF0[2] = rxF0[2] - rxF1[0];
rxF0[3] = rxF0[3] + rxF1[1];
rxF0+=4;
rxF1+=4;
}
}
}
void nr_pbch_quantize(int8_t *pbch_llr8,
int16_t *pbch_llr,
uint16_t len)
{
uint16_t i;
for (i=0; i<len; i++) {
if (pbch_llr[i]>7)
pbch_llr8[i]=7;
else if (pbch_llr[i]<-8)
pbch_llr8[i]=-8;
else
pbch_llr8[i] = (char)(pbch_llr[i]);
}
}
static unsigned char dummy_w_rx[3*3*(16+PBCH_A)];
static int8_t pbch_w_rx[3*3*(16+PBCH_A)],pbch_d_rx[96+(3*(16+PBCH_A))];
uint16_t nr_rx_pbch( PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc,
NR_UE_PBCH *nr_ue_pbch_vars,
NR_DL_FRAME_PARMS *frame_parms,
uint8_t eNB_id,
MIMO_mode_t mimo_mode,
uint32_t high_speed_flag,
uint8_t frame_mod4)
{
NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars;
uint8_t log2_maxh;//,aatx,aarx;
int max_h=0;
int symbol,i;
uint32_t nsymb = (frame_parms->Ncp==0) ? 14:12;
uint16_t pbch_E;
uint8_t pbch_a[8];
uint8_t RCC;
int8_t *pbch_e_rx;
uint8_t *decoded_output = nr_ue_pbch_vars->decoded_output;
uint16_t crc;
int subframe_rx = proc->subframe_rx;
// pbch_D = 16+PBCH_A;
pbch_E = (frame_parms->Ncp==0) ? 1920 : 1728; //RE/RB * #RB * bits/RB (QPSK)
pbch_e_rx = &nr_ue_pbch_vars->llr[frame_mod4*(pbch_E>>2)];
#ifdef DEBUG_PBCH
msg("[PBCH] starting symbol loop (Ncp %d, frame_mod4 %d,mimo_mode %d\n",frame_parms->Ncp,frame_mod4,mimo_mode);
#endif
// clear LLR buffer
memset(nr_ue_pbch_vars->llr,0,pbch_E);
for (symbol=1; symbol<4; symbol++) {
#ifdef DEBUG_PBCH
msg("[PBCH] starting extract\n");
#endif
nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].rxdataF,
nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[subframe_rx]].dl_ch_estimates[eNB_id],
nr_ue_pbch_vars->rxdataF_ext,
nr_ue_pbch_vars->dl_ch_estimates_ext,
symbol,
high_speed_flag,
frame_parms);
#ifdef DEBUG_PBCH
msg("[PHY] PBCH Symbol %d\n",symbol);
msg("[PHY] PBCH starting channel_level\n");
#endif
max_h = nr_pbch_channel_level(nr_ue_pbch_vars->dl_ch_estimates_ext,
frame_parms,
symbol);
log2_maxh = 3+(log2_approx(max_h)/2);
#ifdef DEBUG_PBCH
msg("[PHY] PBCH log2_maxh = %d (%d)\n",log2_maxh,max_h);
#endif
nr_pbch_channel_compensation(nr_ue_pbch_vars->rxdataF_ext,
nr_ue_pbch_vars->dl_ch_estimates_ext,
nr_ue_pbch_vars->rxdataF_comp,
frame_parms,
symbol,
log2_maxh); // log2_maxh+I0_shift
/*if (frame_parms->nb_antennas_rx > 1)
pbch_detection_mrc(frame_parms,
nr_ue_pbch_vars->rxdataF_comp,
symbol);*/
if (mimo_mode == ALAMOUTI) {
nr_pbch_alamouti(frame_parms,nr_ue_pbch_vars->rxdataF_comp,symbol);
// msg("[PBCH][RX] Alamouti receiver not yet implemented!\n");
// return(-1);
} else if (mimo_mode != SISO) {
msg("[PBCH][RX] Unsupported MIMO mode\n");
return(-1);
}
if (symbol>(nsymb>>1)+1) {
nr_pbch_quantize(pbch_e_rx,
(short*)&(nr_ue_pbch_vars->rxdataF_comp[0][(symbol%(nsymb>>1))*72]),
144);
pbch_e_rx+=144;
} else {
nr_pbch_quantize(pbch_e_rx,
(short*)&(nr_ue_pbch_vars->rxdataF_comp[0][(symbol%(nsymb>>1))*72]),
96);
pbch_e_rx+=96;
}
}
pbch_e_rx = nr_ue_pbch_vars->llr;
//un-scrambling
#ifdef DEBUG_PBCH
msg("[PBCH] doing unscrambling\n");
#endif
nr_pbch_unscrambling(frame_parms,
pbch_e_rx,
pbch_E,
frame_mod4);
//un-rate matching
#ifdef DEBUG_PBCH
msg("[PBCH] doing un-rate-matching\n");
#endif
memset(dummy_w_rx,0,3*3*(16+PBCH_A));
RCC = generate_dummy_w_cc(16+PBCH_A,
dummy_w_rx);
lte_rate_matching_cc_rx(RCC,pbch_E,pbch_w_rx,dummy_w_rx,pbch_e_rx);
sub_block_deinterleaving_cc((unsigned int)(PBCH_A+16),
&pbch_d_rx[96],
&pbch_w_rx[0]);
memset(pbch_a,0,((16+PBCH_A)>>3));
phy_viterbi_lte_sse2(pbch_d_rx+96,pbch_a,16+PBCH_A);
// Fix byte endian of PBCH (bit 23 goes in first)
for (i=0; i<(PBCH_A>>3); i++)
decoded_output[(PBCH_A>>3)-i-1] = pbch_a[i];
#ifdef DEBUG_PBCH
for (i=0; i<(PBCH_A>>3); i++)
msg("[PBCH] pbch_a[%d] = %x\n",i,decoded_output[i]);
#endif //DEBUG_PBCH
#ifdef DEBUG_PBCH
msg("PBCH CRC %x : %x\n",
crc16(pbch_a,PBCH_A),
((uint16_t)pbch_a[PBCH_A>>3]<<8)+pbch_a[(PBCH_A>>3)+1]);
#endif
crc = (crc16(pbch_a,PBCH_A)>>16) ^
(((uint16_t)pbch_a[PBCH_A>>3]<<8)+pbch_a[(PBCH_A>>3)+1]);
if (crc == 0x0000)
return(1);
else if (crc == 0xffff)
return(2);
else if (crc == 0x5555)
return(4);
else
return(-1);
}
#ifdef PHY_ABSTRACTION
uint16_t rx_pbch_emul(PHY_VARS_UE *phy_vars_ue,
uint8_t eNB_id,
uint8_t pbch_phase)
{
double bler=0.0;//, x=0.0;
double sinr=0.0;
uint16_t nb_rb = phy_vars_ue->frame_parms.N_RB_DL;
int16_t f;
uint8_t CC_id=phy_vars_ue->CC_id;
int frame_rx = phy_vars_ue->proc.proc_rxtx[0].frame_rx;
// compute effective sinr
// TODO: adapt this to varible bandwidth
for (f=(nb_rb*6-3*12); f<(nb_rb*6+3*12); f++) {
if (f!=0) //skip DC
sinr += pow(10, 0.1*(phy_vars_ue->sinr_dB[f]));
}
sinr = 10*log10(sinr/(6*12));
bler = pbch_bler(sinr);
LOG_D(PHY,"EMUL UE rx_pbch_emul: eNB_id %d, pbch_phase %d, sinr %f dB, bler %f \n",
eNB_id,
pbch_phase,
sinr,
bler);
if (pbch_phase == (frame_rx % 4)) {
if (uniformrandom() >= bler) {
memcpy(phy_vars_ue->pbch_vars[eNB_id]->decoded_output,PHY_vars_eNB_g[eNB_id][CC_id]->pbch_pdu,PBCH_PDU_SIZE);
return(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antenna_ports_eNB);
} else
return(-1);
} else
return(-1);
}
#endif
......@@ -846,14 +846,14 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value, dB_fixed(peak_value)/2);
#ifdef DEBUG_PSS_NR
//#ifdef DEBUG_PSS_NR
#define PSS_DETECTION_FLOOR_NR (31)
if ((dB_fixed(peak_value)/2) > PSS_DETECTION_FLOOR_NR) {
printf("[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value,dB_fixed(peak_value)/2);
}
#endif
//#endif
#ifdef DEBUG_PHY
......
......@@ -589,7 +589,7 @@ int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max)
}
}
#ifdef DEBUG_SSS_NR
//#ifdef DEBUG_SSS_NR
#define SSS_METRIC_FLOOR_NR (30000)
if (*tot_metric > SSS_METRIC_FLOOR_NR) {
......@@ -597,7 +597,7 @@ if (*tot_metric > SSS_METRIC_FLOOR_NR) {
Nid1 = GET_NID1(frame_parms->Nid_cell);
printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
}
#endif
//#endif
return(0);
}
......@@ -143,6 +143,8 @@ typedef struct NR_DL_FRAME_PARMS {
uint8_t nb_antenna_ports_eNB;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
lte_prefix_type_t Ncp;
/// shift of pilot position in one RB
uint8_t nushift;
/// SRS configuration from TS 38.331 RRC
SRS_NR srs_nr;
......
[AD9371]
ad9371-phy.in_voltage2_rf_port_select = OFF
ad9371-phy.in_voltage2_hardwaregain = -156.000000 dB
ad9371-phy.in_voltage2_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_voltage0_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage0_hardwaregain = 0.000000 dB
ad9371-phy.out_voltage0_quadrature_tracking_en = 1
ad9371-phy.out_voltage1_hardwaregain = 0.000000 dB
ad9371-phy.out_voltage1_lo_leakage_tracking_en = 0
ad9371-phy.out_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage1_TX_LO_frequency = 2560000000
ad9371-phy.out_altvoltage2_RX_SN_LO_frequency = 2680000000
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage0_gain_control_mode = manual
ad9371-phy.in_voltage0_quadrature_tracking_en = 1
ad9371-phy.in_voltage0_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage0_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.in_voltage1_quadrature_tracking_en = 1
ad9371-phy.in_voltage1_hardwaregain = 30.000000 dB
ad9371-phy.in_voltage1_temp_comp_gain = 0.00 dB
ad9371-phy.in_voltage1_gain_control_mode = manual
ad9371-phy.in_voltage_rf_port_select_available = OFF INTERNALCALS OBS_SNIFFER SN_A SN_B SN_C ORX1_TX_LO ORX2_TX_LO ORX1_SN_LO ORX2_SN_LO
ad9371-phy.out_altvoltage0_RX_LO_frequency = 2680000000
ad9371-phy.calibrate_rx_qec_en = 0
ad9371-phy.calibrate_tx_lol_en = 0
ad9371-phy.calibrate_vswr_en = 0
ad9371-phy.calibrate_tx_qec_en = 0
ad9371-phy.calibrate_clgc_en = 0
ad9371-phy.ensm_mode = radio_on
ad9371-phy.calibrate_tx_lol_ext_en = 0
ad9371-phy.calibrate_dpd_en = 0
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage0_TX1_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage5_TX2_I_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage4_TX2_I_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_frequency = 7999809
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage6_TX2_Q_F1_scale = 0.251160
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage3_TX1_Q_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_phase = 0
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_scale = 0.000000
axi-ad9371-tx-hpc.out_altvoltage7_TX2_Q_F2_frequency = 1000327
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_raw = 1
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_phase = 0
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_scale = 0.501160
axi-ad9371-tx-hpc.out_altvoltage2_TX1_Q_F1_frequency = 1999718
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_frequency = 19998117
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_raw = 1
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_phase = 90000
axi-ad9371-tx-hpc.out_altvoltage1_TX1_I_F2_scale = 0.000000
load_myk_profile_file = /targets/ARCH/ADRV9371_ZC706/USERSPACE/PROFILES/profileNR80MHz.txt
dds_mode_tx1 = 1
dds_mode_tx2 = 1
dac_buf_filename = /usr/local/lib/osc/waveforms/LTE20.mat
tx_channel_0 = 1
tx_channel_1 = 1
tx_channel_2 = 0
tx_channel_3 = 0
global_settings_show = 1
tx_show = 1
rx_show = 1
obs_show = 1
fpga_show = 1
[ADRV9371_ZC706]
# NO_DEBUG=0; DEBUG=1
debug_mode = 0
# 20MHz 40MHz 80MHz=1; 10MHz=2; 5MHz=4
interpolation_decimation_factor = 1
# is taken into account only if "ad9371-phy.in_voltage0_gain_control_mode = manual"
rx_gain_offset = 53
......@@ -354,7 +354,7 @@ static void *UE_thread_synch(void *arg) {
#else
LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
#endif
if (initial_sync( UE, UE->mode ) == 0) {
if (nr_initial_sync( UE, UE->mode ) == 0) {
hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
......@@ -413,7 +413,7 @@ static void *UE_thread_synch(void *arg) {
//UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
//UE->rfdevice.trx_stop_func(&UE->rfdevice);
// sleep(1);
//nr_init_frame_parms(&UE->frame_parms);
nr_init_frame_parms_ue(&UE->frame_parms);
/*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
LOG_E(HW,"Could not start the device\n");
oai_exit=1;
......@@ -733,8 +733,8 @@ void *UE_thread(void *arg) {
#ifdef NAS_UE
MessageDef *message_p;
message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
//message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
//itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
#endif
int tti_nr=-1;
......
......@@ -693,6 +693,73 @@ int T_dont_fork = 0; /* default is to fork, see 'T_init' to understand */
}
}
void set_default_frame_parms_single(nfapi_config_request_t *config, NR_DL_FRAME_PARMS *frame_parms) {
//int CC_id;
//for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
frame_parms = (NR_DL_FRAME_PARMS*) malloc(sizeof(NR_DL_FRAME_PARMS));
/* Set some default values that may be overwritten while reading options */
frame_parms = (NR_DL_FRAME_PARMS*) malloc(sizeof(NR_DL_FRAME_PARMS));
config = (nfapi_config_request_t*) malloc(sizeof(nfapi_config_request_t));
config->subframe_config.numerology_index_mu.value =1;
config->subframe_config.duplex_mode.value = 1; //FDD
config->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
config->rf_config.dl_channel_bandwidth.value = 106;
config->rf_config.ul_channel_bandwidth.value = 106;
config->rf_config.tx_antenna_ports.value = 1;
config->rf_config.rx_antenna_ports.value = 1;
config->sch_config.physical_cell_id.value = 0;
frame_parms->frame_type = FDD;
frame_parms->tdd_config = 3;
//frame_parms[CC_id]->tdd_config_S = 0;
frame_parms->N_RB_DL = 100;
frame_parms->N_RB_UL = 100;
frame_parms->Ncp = NORMAL;
//frame_parms[CC_id]->Ncp_UL = NORMAL;
frame_parms->Nid_cell = 0;
//frame_parms[CC_id]->num_MBSFN_config = 0;
frame_parms->nb_antenna_ports_eNB = 1;
frame_parms->nb_antennas_tx = 1;
frame_parms->nb_antennas_rx = 1;
//frame_parms[CC_id]->nushift = 0;
///frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
//frame_parms[CC_id]->phich_config_common.phich_duration = normal;
// UL RS Config
/*frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 1;//n_DMRS1 set to 0
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
frame_parms[CC_id]->pusch_config_common.n_SB = 1;
frame_parms[CC_id]->pusch_config_common.hoppingMode = 0;
frame_parms[CC_id]->pusch_config_common.pusch_HoppingOffset = 0;
frame_parms[CC_id]->pusch_config_common.enable64QAM = 0;
frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;*/
// NR: Init to legacy LTE 20Mhz params
frame_parms->numerology_index = 0;
frame_parms->ttis_per_subframe = 1;
frame_parms->slots_per_tti = 2;
downlink_frequency[0][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
//downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
//downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
//downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
//printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
//}
}
void init_openair0(void);
void init_openair0() {
......@@ -931,10 +998,10 @@ int main( int argc, char **argv ) {
set_default_frame_parms(config[CC_id],frame_parms[CC_id]);
//init_ul_hopping(frame_parms[CC_id]);
nr_init_frame_parms(config[CC_id],frame_parms[CC_id]);
nr_init_frame_parms_ue(config[CC_id],frame_parms[CC_id]);
printf("after init frame_parms %d\n",frame_parms[CC_id]->ofdm_symbol_size);
// phy_init_top(frame_parms[CC_id]);
//phy_init_lte_top(frame_parms[CC_id]);
phy_init_nr_top(frame_parms[CC_id]);
}
......@@ -1009,8 +1076,11 @@ int main( int argc, char **argv ) {
//UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
}
//UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
//UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
rx_gain[CC_id][0] = 81;
tx_max_power[CC_id] = -40;
UE[CC_id]->rx_total_gain_dB = (int)rx_gain[CC_id][0] + rx_gain_off;
UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
if (frame_parms[CC_id]->frame_type==FDD) {
UE[CC_id]->N_TA_offset = 0;
......@@ -1025,7 +1095,7 @@ int main( int argc, char **argv ) {
}
// printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power));
// printf("tx_max_power = %d -> amp %d\n",tx_max_power[0],get_tx_amp(tx_max_poHwer,tx_max_power));
fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment