diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 72da87cbdf..82c55a1465 100644 --- a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c +++ b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c @@ -202,7 +202,7 @@ int nr_pdcch_dmrs_rx(PHY_VARS_NR_UE *ue, return(0); } -int nr_pbch_dmrs_rx(int symbol, unsigned int *nr_gold_pbch, c16_t *output) +void nr_pbch_dmrs_rx(const int symbol, const unsigned int *nr_gold_pbch, c16_t *output) { int m,m0,m1; uint8_t idx=0; @@ -232,8 +232,6 @@ int nr_pbch_dmrs_rx(int symbol, unsigned int *nr_gold_pbch, c16_t *output) } #endif } - - return(0); } /*! diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index 763949150e..81c72f59ef 100644 --- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h +++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h @@ -30,7 +30,7 @@ /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PBCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables */ -int nr_pbch_dmrs_rx(int dmrss, unsigned int *nr_gold_pbch, c16_t *output); +void nr_pbch_dmrs_rx(const int dmrss, const unsigned int *nr_gold_pbch, c16_t *output); /*!\brief This function generates the NR Gold sequence (38-211, Sec 5.2.1) for the PDCCH DMRS. @param PHY_VARS_NR_UE* ue structure provides configuration, frame parameters and the pointers to the 32 bits sequence storage tables diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 090518575e..c2dc115e5b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -631,28 +631,19 @@ int nr_prs_channel_estimation(uint8_t gNB_id, return(0); } -int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - int dmrss, - NR_UE_SSB *current_ssb, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const int symbol, + const int dmrss, + const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD], + const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { - c16_t pilot[200] __attribute__((aligned(16))); - unsigned int pilot_cnt; - int symbol_offset; - - uint8_t ssb_index=current_ssb->i_ssb; - uint8_t n_hf=current_ssb->n_hf; + AssertFatal(dmrss >= 0 && dmrss < 3, "symbol %d is illegal for PBCH DM-RS \n", dmrss); unsigned int ssb_offset = ue->frame_parms.first_carrier_offset + ue->frame_parms.ssb_start_subcarrier; if (ssb_offset>= ue->frame_parms.ofdm_symbol_size) ssb_offset-=ue->frame_parms.ofdm_symbol_size; - AssertFatal(dmrss >= 0 && dmrss < 3, - "symbol %d is illegal for PBCH DM-RS \n", - dmrss); - - symbol_offset = ue->frame_parms.ofdm_symbol_size*symbol; + int symbol_offset = ue->frame_parms.ofdm_symbol_size * symbol; unsigned int k = ue->frame_parms.Nid_cell % 4; @@ -665,64 +656,64 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, // generate pilot // Note: pilot returned by the following function is already the complex conjugate of the transmitted DMRS - nr_pbch_dmrs_rx(dmrss, ue->nr_gold_pbch[n_hf][ssb_index], pilot); - + c16_t pilot[200] __attribute__((aligned(16))); + nr_pbch_dmrs_rx(dmrss, nr_gold_pbch, pilot); + c32_t computed_val = {0}; for (int aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { int re_offset = ssb_offset; c16_t *pil = pilot; - c16_t *rxF = &rxdataF[aarx][symbol_offset + k]; + const c16_t *rxF = &rxdataF[aarx][symbol_offset + k]; DEBUG_PBCH("pbch ch est pilot RB_DL %d\n", ue->frame_parms.N_RB_DL); DEBUG_PBCH("k %d, first_carrier %d\n", k, ue->frame_parms.first_carrier_offset); - //if ((ue->frame_parms.N_RB_DL&1)==0) { // Treat first 2 pilots specially (left edge) - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("ch 0 %d\n", pil->r * rxF[re_offset].r - pil->i * rxF[re_offset].i); DEBUG_PBCH("pilot 0 : rxF - > (%d,%d) pil -> (%d,%d) \n", rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("pilot 1 : rxF - > (%d,%d) pil -> (%d,%d) \n", rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("pilot 2 : rxF - > (%d,%d), pil -> (%d,%d) \n", rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size; - for (pilot_cnt = 3; pilot_cnt < (3 * 20); pilot_cnt += 3) { + for (int pilot_cnt = 3; pilot_cnt < (3 * 20); pilot_cnt += 3) { // in 2nd symbol, skip middle REs (48 with DMRS, 144 for SSS, and another 48 with DMRS) if (dmrss == 1 && pilot_cnt == 12) { pilot_cnt=48; re_offset = (re_offset + 144) % ue->frame_parms.ofdm_symbol_size; } - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("pilot %u : rxF= (%d,%d) pil= (%d,%d) \n", pilot_cnt, rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("pilot %u : rxF= (%d,%d) pil= (%d,%d) \n", pilot_cnt + 1, rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset+4) % ue->frame_parms.ofdm_symbol_size; - current_ssb->c = c32x16maddShift(*pil, rxF[re_offset], current_ssb->c, 15); + computed_val = c32x16maddShift(*pil, rxF[re_offset], computed_val, 15); DEBUG_PBCH("pilot %u : rxF= (%d,%d) pil= (%d,%d) \n", pilot_cnt + 2, rxF[re_offset].r, rxF[re_offset].i, pil->r, pil->i); pil++; re_offset = (re_offset + 4) % ue->frame_parms.ofdm_symbol_size; } } - return(0); + return computed_val; } int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index f47d49f877..64875331e5 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -57,12 +57,12 @@ void nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, c16_t pdcch_dl_ch_estimates[][pdcch_est_size], c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); -int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, - unsigned char symbol, - int dmrss, - NR_UE_SSB *current_ssb, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); +c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, + const UE_nr_rxtx_proc_t *proc, + const int symbol, + const int dmrss, + const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD], + const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, int estimateSz, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 8d1253274a..2fa9b00b93 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -44,6 +44,7 @@ #include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_REFSIG/sss_nr.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/TOOLS/tools_defs.h" //static nfapi_nr_config_request_t config_t; //static nfapi_nr_config_request_t* config =&config_t; @@ -52,11 +53,22 @@ int cnt=0; // #define DEBUG_INITIAL_SYNCH #define DUMP_PBCH_CH_ESTIMATES 0 +// structure used for multiple SSB detection +typedef struct NR_UE_SSB { + uint i_ssb; // i_ssb between 0 and 7 (it corresponds to ssb_index only for Lmax=4,8) + uint n_hf; // n_hf = 0,1 for Lmax =4 or n_hf = 0 for Lmax =8,64 + uint32_t metric; // metric to order SSB hypothesis +} NR_UE_SSB; -int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *ue, - int pbch_initial_symbol, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) +static int ssb_sort(const void *a, const void *b) +{ + return ((NR_UE_SSB *)b)->metric - ((NR_UE_SSB *)a)->metric; +} + +static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, + PHY_VARS_NR_UE *ue, + int pbch_initial_symbol, + c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; @@ -64,54 +76,62 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, const int N_hf = (frame_parms->Lmax == 4) ? 2 : 1; NR_UE_SSB best_ssb[N_L * N_hf]; NR_UE_SSB *current_ssb = best_ssb; - // loops over possible pbch dmrs cases to retrive best estimated i_ssb (and n_hf for Lmax=4) for multiple ssb detection + // loops over possible pbch dmrs cases to retrieve best estimated i_ssb (and n_hf for Lmax=4) for multiple ssb detection + start_meas(&ue->dlsch_channel_estimation_stats); for (int hf = 0; hf < N_hf; hf++) { - for (int l = 0; l < N_L ; l++) { - // initialization of structure - *current_ssb = (NR_UE_SSB){.i_ssb = l, .n_hf = hf}; - start_meas(&ue->dlsch_channel_estimation_stats); + for (int l = 0; l < N_L; l++) { // computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf - for(int i=pbch_initial_symbol; idlsch_channel_estimation_stats); + c32_t cumul = {0}; + for (int i = pbch_initial_symbol; i < pbch_initial_symbol + 3; i++) { + c32_t meas = nr_pbch_dmrs_correlation(ue, proc, i, i - pbch_initial_symbol, ue->nr_gold_pbch[hf][l], rxdataF); + csum(cumul, cumul, meas); + } + // initialization of structure + *current_ssb = (NR_UE_SSB){.i_ssb = l, .n_hf = hf, .metric = squaredMod(cumul)}; current_ssb++; } } + qsort(best_ssb, N_L * N_hf, sizeof(NR_UE_SSB), ssb_sort); + stop_meas(&ue->dlsch_channel_estimation_stats); - for (NR_UE_SSB *temp_ptr = best_ssb; ret != 0 && temp_ptr < best_ssb + N_L * N_hf; temp_ptr++) { + const int nb_ant = frame_parms->nb_antennas_rx; + for (NR_UE_SSB *ssb = best_ssb; ssb < best_ssb + N_L * N_hf; ssb++) { start_meas(&ue->dlsch_channel_estimation_stats); // computing channel estimation for selected best ssb const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; - __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz]; - __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; + __attribute__((aligned(32))) c16_t dl_ch_estimates[nb_ant][estimateSz]; + __attribute__((aligned(32))) c16_t dl_ch_estimates_time[nb_ant][frame_parms->ofdm_symbol_size]; for(int i=pbch_initial_symbol; ii_ssb,temp_ptr->n_hf,rxdataF); + nr_pbch_channel_estimation(ue, + estimateSz, + dl_ch_estimates, + dl_ch_estimates_time, + proc, + i, + i - pbch_initial_symbol, + ssb->i_ssb, + ssb->n_hf, + rxdataF); stop_meas(&ue->dlsch_channel_estimation_stats); fapiPbch_t result = {0}; - - int pbch_res = nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, temp_ptr->i_ssb, &result, rxdataF); - ret = pbch_res == 0; - - if (DUMP_PBCH_CH_ESTIMATES && ret) { - write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, frame_parms->nb_antennas_rx*estimateSz, 1, 1); - write_output("pbch_ch_estimates_time.m", - "pbch_ch_estimates_time", - dl_ch_estimates_time, - frame_parms->nb_antennas_rx * frame_parms->ofdm_symbol_size, - 1, - 1); + if (0 == nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, ssb->i_ssb, &result, rxdataF)) { + if (DUMP_PBCH_CH_ESTIMATES) { + write_output("pbch_ch_estimates.m", "pbch_ch_estimates", dl_ch_estimates, nb_ant * estimateSz, 1, 1); + write_output("pbch_ch_estimates_time.m", + "pbch_ch_estimates_time", + dl_ch_estimates_time, + nb_ant * frame_parms->ofdm_symbol_size, + 1, + 1); + } + return false; } } - if (ret == 0) { - LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); - } else { - LOG_W(PHY, "[UE%d] Initial sync: pbch not decoded, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); - } - return ret; + LOG_W(PHY, "[UE%d] Initial sync: pbch not decoded, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); + return true; } nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 5059ccd107..8bbb1f9d84 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -307,13 +307,6 @@ typedef struct { fapi_nr_ul_config_srs_pdu srs_config_pdu; } NR_UE_SRS; -// structure used for multiple SSB detection -typedef struct NR_UE_SSB { - uint8_t i_ssb; // i_ssb between 0 and 7 (it corresponds to ssb_index only for Lmax=4,8) - uint8_t n_hf; // n_hf = 0,1 for Lmax =4 or n_hf = 0 for Lmax =8,64 - c32_t c; -} NR_UE_SSB; - typedef struct UE_NR_SCAN_INFO_s { /// 10 best amplitudes (linear) for each pss signals int32_t amp[3][10];