diff --git a/common/utils/nr/nr_common.c b/common/utils/nr/nr_common.c index 6bc9eff5ff..fb9d9103e6 100644 --- a/common/utils/nr/nr_common.c +++ b/common/utils/nr/nr_common.c @@ -182,6 +182,123 @@ const nr_bandentry_t nr_bandtable[] = { {261,27500040,28350000,27500040,28350000, 2,2070833, 120} }; +// synchronization raster per band tables (Rel.15) +// (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) +// band nb, sub-carrier spacing index, Range of gscn (First, Step size, Last) +// clang-format off +const sync_raster_t sync_raster[] = { + {1, 0, 5279, 1, 5419}, + {2, 0, 4829, 1, 4969}, + {3, 0, 4517, 1, 4693}, + {5, 0, 2177, 1, 2230}, + {5, 1, 2183, 1, 2224}, + {7, 0, 6554, 1, 6718}, + {8, 0, 2318, 1, 2395}, + {12, 0, 1828, 1, 1858}, + {13, 0, 1871, 1, 1885}, + {14, 0, 1901, 1, 1915}, + {18, 0, 2156, 1, 2182}, + {20, 0, 1982, 1, 2047}, + {24, 0, 3818, 1, 3892}, + {24, 1, 3824, 1, 3886}, + {25, 0, 4829, 1, 4981}, + {26, 0, 2153, 1, 2230}, + {28, 0, 1901, 1, 2002}, + {29, 0, 1798, 1, 1813}, + {30, 0, 5879, 1, 5893}, + {34, 0, 5030, 1, 5056}, + {34, 1, 5036, 1, 5050}, + {38, 0, 6431, 1, 6544}, + {38, 1, 6437, 1, 6538}, + {39, 0, 4706, 1, 4795}, + {39, 1, 4712, 1, 4789}, + {40, 1, 5762, 1, 5989}, + {41, 0, 6246, 3, 6717}, + {41, 1, 6252, 3, 6714}, + {48, 1, 7884, 1, 7982}, + {50, 0, 3584, 1, 3787}, + {51, 0, 3572, 1, 3574}, + {53, 0, 6215, 1, 6232}, + {53, 1, 6221, 1, 6226}, + {65, 0, 5279, 1, 5494}, + {66, 0, 5279, 1, 5494}, + {66, 1, 5285, 1, 5488}, + {67, 0, 1850, 1, 1888}, + {70, 0, 4993, 1, 5044}, + {71, 0, 1547, 1, 1624}, + {74, 0, 3692, 1, 3790}, + {75, 0, 3584, 1, 3787}, + {76, 0, 3572, 1, 3574}, + {77, 1, 7711, 1, 8329}, + {78, 1, 7711, 1, 8051}, + {79, 1, 8480, 16, 8880}, + {85, 0, 1826, 1, 1858}, + {90, 1, 6252, 1, 6714}, + {91, 0, 3572, 1, 3574}, + {92, 0, 3584, 1, 3787}, + {93, 0, 3572, 1, 3574}, + {94, 0, 3584, 1, 3587}, + {257, 3, 22388, 1, 22558}, + {257, 4, 22390, 2, 22556}, + {258, 3, 22257, 1, 22443}, + {258, 4, 22258, 2, 22442}, + {260, 3, 22995, 1, 23166}, + {260, 4, 22996, 2, 23164}, + {261, 3, 22446, 1, 22492}, + {261, 4, 22446, 2, 22490}, +}; +// clang-format on + +// Section 5.4.3 of 38.101-1 and -2 +void check_ssb_raster(uint64_t freq, int band, int scs) +{ + int start_gscn = 0, step_gscn = 0, end_gscn = 0; + for (int i = 0; i < sizeof(sync_raster) / sizeof(sync_raster_t); i++) { + if (sync_raster[i].band == band && sync_raster[i].scs_index == scs) { + start_gscn = sync_raster[i].first_gscn; + step_gscn = sync_raster[i].step_gscn; + end_gscn = sync_raster[i].last_gscn; + break; + } + } + AssertFatal(start_gscn != 0, "Couldn't find band %d with SCS %d\n", band, scs); + int gscn; + if (freq < 3000000000) { + int N = 0; + int M = 0; + for (int k = 0; k < 3; k++) { + M = (k << 1) + 1; + if ((freq - M * 50000) % 1200000 == 0) { + N = (freq - M * 50000) / 1200000; + break; + } + } + AssertFatal(N != 0, "SSB frequency %lu Hz not on the synchronization raster (N * 1200kHz + M * 50 kHz)\n", freq); + gscn = (3 * N) + (M - 3) / 2; + } else if (freq < 24250000000) { + AssertFatal((freq - 3000000000) % 1440000 == 0, + "SSB frequency %lu Hz not on the synchronization raster (3000 MHz + N * 1.44 MHz)\n", + freq); + gscn = ((freq - 3000000000) / 1440000) + 7499; + } else { + AssertFatal((freq - 24250080000) % 17280000 == 0, + "SSB frequency %lu Hz not on the synchronization raster (24250.08 MHz + N * 17.28 MHz)\n", + freq); + gscn = ((freq - 24250080000) / 17280000) + 22256; + } + AssertFatal(gscn >= start_gscn && gscn <= end_gscn, + "GSCN %d corresponding to SSB frequency %lu does not belong to GSCN range for band %d\n", + gscn, + freq, + band); + int rel_gscn = gscn - start_gscn; + AssertFatal(rel_gscn % step_gscn == 0, + "GSCN %d corresponding to SSB frequency %lu not in accordance with GSCN step for band %d\n", + gscn, + freq, + band); +} + int get_supported_bw_mhz(frequency_range_t frequency_range, int scs, int nb_rb) { int bw_index = get_supported_band_index(scs, frequency_range, nb_rb); @@ -910,6 +1027,129 @@ uint32_t get_ssb_offset_to_pointA(uint32_t absoluteFrequencySSB, return ssb_offset_point_a; } +static double get_start_freq(const double fc, const int nbRB, const int mu) +{ + const int scs = MU_SCS(mu) * 1000; + return fc - (nbRB / 2 * NR_NB_SC_PER_RB * scs); +} + +static double get_stop_freq(const double fc, const int nbRB, const int mu) +{ + int scs = MU_SCS(mu) * 1000; + return fc + (nbRB / 2 * NR_NB_SC_PER_RB * scs); +} + +static void compute_M_and_N(const int gscn, int *rM, int *rN) +{ + if (gscn > 1 && gscn < 7499) { + for (int M = 1; M < 6; M += 2) { + /* GSCN = 3N + (M-3) / 2 + N(int) = 2 * GSCN + 3 - M + */ + if (((2 * gscn + 3 - M) % 6) == 0) { + *rM = M; + *rN = (2 * gscn + 3 - M) / 6; + break; + } + } + } else if (gscn > 7498 && gscn < 22256) { + *rN = gscn - 7499; + } else if (gscn > 22255 && gscn < 26638) { + *rN = gscn - 22256; + } else { + LOG_E(NR_PHY, "Invalid GSCN\n"); + abort(); + } +} + +// Section 5.4.3 of 38.101-1 and -2 +static double get_ssref_from_gscn(const int gscn) +{ + int M, N = -1; + compute_M_and_N(gscn, &M, &N); + if (gscn > 1 && gscn < 7499) { // Sub 3GHz + AssertFatal(N > 0 && N < 2500, "Invalid N\n"); + AssertFatal(M > 0 && M < 6 && (M & 0x1), "Invalid M\n"); + return (N * 1200e3 + M * 50e3); + } else if (gscn > 7498 && gscn < 22256) { + AssertFatal(N > -1 && N < 14757, "Invalid N\n"); + return (3000e6 + N * 1.44e6); + } else if (gscn > 22255 && gscn < 26638) { + AssertFatal(N > -1 && N < 4382, "Invalid N\n"); + return (24250.08e6 + N * 17.28e6); + } else { + LOG_E(NR_PHY, "Invalid GSCN\n"); + abort(); + } +} + +static void find_gscn_to_scan(const double startFreq, + const double stopFreq, + const sync_raster_t gscn, + int *scanGscnStart, + int *scanGscnStop) +{ + const double scs = MU_SCS(gscn.scs_index) * 1e3; + const double ssbBW = 20 * NR_NB_SC_PER_RB * scs; + + for (int g = gscn.first_gscn; g < gscn.last_gscn; g += gscn.step_gscn) { + const double centerSSBFreq = get_ssref_from_gscn(g); + const double startSSBFreq = centerSSBFreq - ssbBW / 2; + if (startSSBFreq < startFreq) + continue; + + *scanGscnStart = g; + break; + } + + for (int g = gscn.last_gscn; g > gscn.first_gscn; g -= gscn.step_gscn) { + const double centerSSBFreq = get_ssref_from_gscn(g); + const double stopSSBFreq = centerSSBFreq + ssbBW / 2 - 1; + if (stopSSBFreq > stopFreq) + continue; + + *scanGscnStop = g; + break; + } +} + +static int get_ssb_first_sc(const double pointA, const double ssbCenter, const int mu) +{ + const double scs = MU_SCS(mu) * 1e3; + const int ssbRBs = 20; + return (int)((ssbCenter - pointA) / scs - (ssbRBs / 2 * NR_NB_SC_PER_RB)); +} + +/* Returns array of first SCS offset in the scanning window */ +int get_scan_ssb_first_sc(const double fc, const int nbRB, const int nrBand, const int mu, nr_gscn_info_t ssbInfo[MAX_GSCN_BAND]) +{ + const double startFreq = get_start_freq(fc, nbRB, mu); + const double stopFreq = get_stop_freq(fc, nbRB, mu); + + int scanGscnStart = -1; + int scanGscnStop = -1; + sync_raster_t tmpRaster = {0}; + for (const sync_raster_t *r = sync_raster; r < r + (sizeof(sync_raster) / sizeof(sync_raster_t)); r++) { + if (r->band == nrBand && r->scs_index == mu) { + tmpRaster = *r; + break; + } + } + find_gscn_to_scan(startFreq, stopFreq, tmpRaster, &scanGscnStart, &scanGscnStop); + + const double scs = MU_SCS(mu) * 1e3; + const double pointA = fc - (nbRB / 2 * scs * NR_NB_SC_PER_RB); + int numGscn = 0; + for (int g = scanGscnStart; (g <= scanGscnStop) && (numGscn < MAX_GSCN_BAND); g += tmpRaster.step_gscn) { + ssbInfo[numGscn].ssRef = get_ssref_from_gscn(g); + ssbInfo[numGscn].ssbFirstSC = get_ssb_first_sc(pointA, ssbInfo[numGscn].ssRef, mu); + ssbInfo[numGscn].gscn = g; + numGscn++; + } + + return numGscn; +} + int get_delay_idx(int delay, int max_delay_comp) { int delay_idx = max_delay_comp + delay; diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h index 9efd8bd84f..c515e172ee 100644 --- a/common/utils/nr/nr_common.h +++ b/common/utils/nr/nr_common.h @@ -77,6 +77,9 @@ static inline const char *rnti_types(nr_rnti_type_t rr) } #undef R +#define MU_SCS(m) (15 << m) +#define MAX_GSCN_BAND 620 // n78 has the highest GSCN range of 619 + #define NR_MAX_NB_LAYERS 4 // 8 typedef struct nr_bandentry_s { @@ -98,6 +101,12 @@ typedef struct { int last_gscn; } sync_raster_t; +typedef struct { + int gscn; + double ssRef; + int ssbFirstSC; +} nr_gscn_info_t; + typedef enum frequency_range_e { FR1 = 0, FR2 @@ -232,6 +241,14 @@ void freq2time(uint16_t ofdm_symbol_size, void nr_est_delay(int ofdm_symbol_size, const c16_t *ls_est, c16_t *ch_estimates_time, delay_t *delay); +int get_scan_ssb_first_sc(const double fc, + const int nbRB, + const int nrBand, + const int mu, + nr_gscn_info_t ssbStartSC[MAX_GSCN_BAND]); + +void check_ssb_raster(uint64_t freq, int band, int scs); + #define CEILIDIV(a,b) ((a+b-1)/b) #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1)) diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 83b2bd75ac..dc26df6a08 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -706,7 +706,6 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue) { void phy_term_nr_top(void) { free_ul_reference_signal_sequences(); - free_context_synchro_nr(); } static void sl_generate_psbch_dmrs_qpsk_sequences(PHY_VARS_NR_UE *UE, struct complex16 *modulated_dmrs_sym, uint16_t slss_id) diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index 2e292e4705..d44e2a7537 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -109,9 +109,8 @@ void set_Lmax(NR_DL_FRAME_PARMS *fp) { } } - -int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb) { - +int nr_get_ssb_start_symbol(const NR_DL_FRAME_PARMS *fp, uint8_t i_ssb) +{ int mu = fp->numerology_index; int symbol = 0; uint8_t n, n_temp; diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index a39f931de1..bfbe21ce04 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -25,7 +25,7 @@ #include "PHY/defs_gNB.h" #include "PHY/defs_nr_UE.h" -int nr_get_ssb_start_symbol(NR_DL_FRAME_PARMS *fp,uint8_t i_ssb); +int nr_get_ssb_start_symbol(const NR_DL_FRAME_PARMS *fp, uint8_t i_ssb); void nr_init_frame_parms(nfapi_nr_config_request_scf_t *config, NR_DL_FRAME_PARMS *frame_parms); int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *frame_parms, fapi_nr_config_request_t *config, uint16_t nr_band); void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint8_t mu, uint16_t nr_band); diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h index 03c13db8ae..68d4c2c5a2 100644 --- a/openair1/PHY/MODULATION/modulation_UE.h +++ b/openair1/PHY/MODULATION/modulation_UE.h @@ -61,12 +61,11 @@ int sl_nr_slot_fep(PHY_VARS_NR_UE *ue, uint32_t sample_offset, c16_t rxdataF[][ue->SL_UE_PHY_PARAMS.sl_frame_params.samples_per_slot_wCP]); -int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, +int nr_slot_fep_init_sync(const NR_DL_FRAME_PARMS *frame_parms, unsigned char symbol, int sample_offset, - bool pbch_decoded, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], + const c16_t **rxdata, + c16_t rxdataF[][frame_parms->samples_per_slot_wCP], int link_type); int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index 4024796bb0..57d37a2fe6 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -203,31 +203,19 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, return 0; } -int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, +int nr_slot_fep_init_sync(const NR_DL_FRAME_PARMS *frame_parms, unsigned char symbol, int sample_offset, - bool pbch_decoded, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP], + const c16_t **rxdata, + c16_t rxdataF[][frame_parms->samples_per_slot_wCP], int link_type) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - NR_UE_COMMON *common_vars = &ue->common_vars; - int Ns = proc->nr_slot_rx; + int Ns = 0; AssertFatal(symbol < frame_parms->symbols_per_slot, "slot_fep: symbol must be between 0 and %d\n", frame_parms->symbols_per_slot-1); AssertFatal(Ns < frame_parms->slots_per_frame, "slot_fep: Ns must be between 0 and %d\n", frame_parms->slots_per_frame-1); - unsigned int nb_prefix_samples; - unsigned int nb_prefix_samples0; - if (pbch_decoded) { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples0; - } - else { - nb_prefix_samples = frame_parms->nb_prefix_samples; - nb_prefix_samples0 = frame_parms->nb_prefix_samples; - } + unsigned int nb_prefix_samples = frame_parms->nb_prefix_samples; unsigned int frame_length_samples = frame_parms->samples_per_frame; dft_size_idx_t dftsize = get_dft(frame_parms->ofdm_symbol_size); @@ -236,10 +224,7 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, unsigned int slot_offset = frame_parms->get_samples_slot_timestamp(Ns,frame_parms,0); unsigned int rx_offset = sample_offset + slot_offset; - unsigned int abs_symbol = Ns * frame_parms->symbols_per_slot + symbol; - for (int idx_symb = Ns*frame_parms->symbols_per_slot; idx_symb <= abs_symbol; idx_symb++) - rx_offset += (idx_symb%(0x7<numerology_index)) ? nb_prefix_samples : nb_prefix_samples0; - rx_offset += frame_parms->ofdm_symbol_size * symbol; + rx_offset += (frame_parms->ofdm_symbol_size + nb_prefix_samples) * symbol + nb_prefix_samples; #ifdef DEBUG_FEP // if (ue->frame <100) @@ -256,38 +241,29 @@ int nr_slot_fep_init_sync(PHY_VARS_NR_UE *ue, // rxdata is 2 frames len // we have to wrap on the end - memcpy((void *)&tmp_dft_in[0], - (void *)&common_vars->rxdata[aa][rx_offset], - (frame_length_samples*2 - rx_offset) * sizeof(int32_t)); - memcpy((void *)&tmp_dft_in[frame_length_samples*2 - rx_offset], - (void *)&common_vars->rxdata[aa][0], - (frame_parms->ofdm_symbol_size - (frame_length_samples*2 - rx_offset)) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], (frame_length_samples * 2 - rx_offset) * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[frame_length_samples * 2 - rx_offset], + (void *)&rxdata[aa][0], + (frame_parms->ofdm_symbol_size - (frame_length_samples * 2 - rx_offset)) * sizeof(int32_t)); rxdata_ptr = (int16_t *)tmp_dft_in; } else if ((rx_offset & 7) != 0) { // if input to dft is not 256-bit aligned - memcpy((void *)&tmp_dft_in[0], - (void *)&common_vars->rxdata[aa][rx_offset], - frame_parms->ofdm_symbol_size * sizeof(int32_t)); + memcpy((void *)&tmp_dft_in[0], (void *)&rxdata[aa][rx_offset], frame_parms->ofdm_symbol_size * sizeof(int32_t)); rxdata_ptr = (int16_t *)tmp_dft_in; } else { // use dft input from RX buffer directly - rxdata_ptr = (int16_t *)&common_vars->rxdata[aa][rx_offset]; - + rxdata_ptr = (int16_t *)&rxdata[aa][rx_offset]; } - start_meas(&ue->rx_dft_stats); - dft(dftsize, rxdata_ptr, (int16_t *)&rxdataF[aa][frame_parms->ofdm_symbol_size*symbol], 1); - stop_meas(&ue->rx_dft_stats); - int symb_offset = (Ns%frame_parms->slots_per_subframe)*frame_parms->symbols_per_slot; c16_t rot2 = frame_parms->symbol_rotation[link_type][symbol + symb_offset]; rot2.i=-rot2.i; diff --git a/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c b/openair1/PHY/NR_REFSIG/nr_dmrs_rx.c index 70381d0bd8..4f8d86762f 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); } -void nr_pbch_dmrs_rx(int symbol, unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) +void nr_pbch_dmrs_rx(int symbol, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink) { int m,m0,m1; uint8_t idx=0; diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c index 56dd09c0f0..3259aa3173 100644 --- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c +++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c @@ -21,15 +21,13 @@ #include "refsig_defs_ue.h" -void nr_gold_pbch(PHY_VARS_NR_UE* ue) +void nr_gold_pbch(uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD], int Nid, int Lmax) { unsigned int n = 0, x1 = 0, x2 = 0; - unsigned int Nid, i_ssb, i_ssb2; - unsigned char Lmax, l, n_hf, N_hf; + unsigned int i_ssb, i_ssb2; + unsigned char l, n_hf, N_hf; uint8_t reset; - Nid = ue->frame_parms.Nid_cell; - Lmax = ue->frame_parms.Lmax; N_hf = (Lmax == 4)? 2:1; for (n_hf = 0; n_hf < N_hf; n_hf++) { @@ -42,7 +40,7 @@ void nr_gold_pbch(PHY_VARS_NR_UE* ue) x2 = (1<<11) * (i_ssb2 + 1) * ((Nid>>2) + 1) + (1<<6) * (i_ssb2 + 1) + (Nid&3); for (n=0; nnr_gold_pbch[n_hf][l][n] = lte_gold_generic(&x1, &x2, reset); + nr_gold_pbch[n_hf][l][n] = lte_gold_generic(&x1, &x2, reset); reset = 0; } diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index ea098d088b..b5bc62d63e 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -76,8 +76,15 @@ #define SYNCF_TMP_SIZE (SYNCHRO_FFT_SIZE_MAX*IQ_SIZE) void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue); -void free_context_synchro_nr(void); -int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change); +int pss_synchro_nr(const c16_t **rxdata, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size], + int is, + bool fo_flag, + int target_Nid_cell, + int *nid2, + int *f_off); +void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size]); int16_t *get_primary_synchro_nr2(const int nid2); #endif /* PSS_NR_H */ diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h index c7919130b5..21d5a116d1 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 */ -void nr_pbch_dmrs_rx(int dmrss, unsigned int *nr_gold_pbch, c16_t *output, bool sidelink); +void nr_pbch_dmrs_rx(int dmrss, const unsigned int *nr_gold_pbch, c16_t *output, bool sidelink); /*!\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 @@ -51,7 +51,7 @@ int nr_pdsch_dmrs_rx(PHY_VARS_NR_UE *ue, unsigned short nb_pdsch_rb, uint8_t config_type); -void nr_gold_pbch(PHY_VARS_NR_UE* ue); +void nr_gold_pbch(uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD], int Nid, int Lmax); void nr_gold_pdcch(PHY_VARS_NR_UE* ue, unsigned short n_idDMRS); diff --git a/openair1/PHY/NR_REFSIG/sss_nr.h b/openair1/PHY/NR_REFSIG/sss_nr.h index 1dff912889..8175869205 100644 --- a/openair1/PHY/NR_REFSIG/sss_nr.h +++ b/openair1/PHY/NR_REFSIG/sss_nr.h @@ -95,11 +95,15 @@ void free_context_sss_nr(void); void insert_sss_nr(int16_t *sss_time, NR_DL_FRAME_PARMS *frame_parms); -bool rx_sss_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, +bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, + int nid2, + int target_Nid_cell, + int freq_offset_pss, + int ssb_start_subcarrier, + int *Nid_cell, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); + c16_t rxdataF[][frame_parms->samples_per_slot_wCP]); #endif /* SSS_NR_H */ 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 012d5c2121..a3cec5a76d 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -555,21 +555,24 @@ int nr_prs_channel_estimation(uint8_t gNB_id, return(0); } -c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, +c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp, const UE_nr_rxtx_proc_t *proc, const int symbol, const int dmrss, + const int Nid_cell, + const int ssb_start_subcarrier, const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD], - const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) + const c16_t rxdataF[][fp->samples_per_slot_wCP]) { 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; + unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier; + if (ssb_offset >= fp->ofdm_symbol_size) + ssb_offset -= fp->ofdm_symbol_size; - int symbol_offset = ue->frame_parms.ofdm_symbol_size * symbol; + int symbol_offset = fp->ofdm_symbol_size * symbol; - unsigned int k = ue->frame_parms.Nid_cell % 4; + unsigned int k = Nid_cell % 4; DEBUG_PBCH("PBCH DMRS Correlation : gNB_id %d , OFDM size %d, Ncp=%d, k=%u symbol %d\n", proc->gNB_id, @@ -583,8 +586,7 @@ c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, c16_t pilot[200] __attribute__((aligned(16))); nr_pbch_dmrs_rx(dmrss, (uint32_t *)nr_gold_pbch, pilot, false); c32_t computed_val = {0}; - for (int aarx=0; aarxframe_parms.nb_antennas_rx; aarx++) { - + for (int aarx = 0; aarx < fp->nb_antennas_rx; aarx++) { int re_offset = ssb_offset; c16_t *pil = pilot; const c16_t *rxF = &rxdataF[aarx][symbol_offset + k]; @@ -599,49 +601,50 @@ c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; 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; + re_offset = (re_offset + 144) % fp->ofdm_symbol_size; } 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; 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; + re_offset = (re_offset + 4) % fp->ofdm_symbol_size; } } return computed_val; } -int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - NR_DL_FRAME_PARMS *fp, +int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, + const sl_nr_ue_phy_params_t *sl_phy_params, + const uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD], int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size], @@ -650,7 +653,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, int dmrss, uint8_t ssb_index, uint8_t n_hf, - c16_t rxdataF[][fp->samples_per_slot_wCP], + int ssb_start_subcarrier, + const c16_t rxdataF[][fp->samples_per_slot_wCP], bool sidelink, uint16_t Nid) { @@ -659,13 +663,11 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, //int slot_pbch; uint8_t nushift = 0, lastsymbol = 0, num_rbs = 0; - uint32_t *gold_seq = NULL; + const uint32_t *gold_seq = NULL; if (sidelink) { AssertFatal(dmrss == 0 || (dmrss >= 5 && dmrss <= 12), "symbol %d is illegal for PSBCH DM-RS \n", dmrss); - sl_nr_ue_phy_params_t *sl_phy_params = &ue->SL_UE_PHY_PARAMS; - LOG_D(PHY, "PSBCH Channel Estimation SLSSID:%d\n", Nid); gold_seq = sl_phy_params->init_params.psbch_dmrs_gold_sequences[Nid]; @@ -673,16 +675,16 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, num_rbs = SL_NR_NUM_PSBCH_RBS_IN_ONE_SYMBOL; } else { - nushift = fp->Nid_cell % 4; + nushift = Nid % 4; AssertFatal(dmrss >= 0 && dmrss < 3, "symbol %d is illegal for PBCH DM-RS \n", dmrss); - gold_seq = ue->nr_gold_pbch[n_hf][ssb_index]; + gold_seq = nr_gold_pbch[n_hf][ssb_index]; lastsymbol = 2; num_rbs = 20; } - unsigned int ssb_offset = fp->first_carrier_offset + fp->ssb_start_subcarrier; + unsigned int ssb_offset = fp->first_carrier_offset + ssb_start_subcarrier; if (ssb_offset >= fp->ofdm_symbol_size) ssb_offset -= fp->ofdm_symbol_size; @@ -739,7 +741,7 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, for (int aarx = 0; aarx < fp->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]; c16_t *dl_ch = &dl_ch_estimates[aarx][ch_offset]; memset(dl_ch, 0, sizeof(c16_t) * fp->ofdm_symbol_size); @@ -824,15 +826,10 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, { // do ifft of channel estimate LOG_D(PHY,"Channel Impulse Computation Slot %d Symbol %d ch_offset %d\n", Ns, symbol, ch_offset); - freq2time(ue->frame_parms.ofdm_symbol_size, - (int16_t *)&dl_ch_estimates[aarx][ch_offset], - (int16_t *)&dl_ch_estimates_time[aarx]); + freq2time(fp->ofdm_symbol_size, (int16_t *)&dl_ch_estimates[aarx][ch_offset], (int16_t *)&dl_ch_estimates_time[aarx]); } } - if (!sidelink && dmrss == lastsymbol) - UEscopeCopy(ue, pbchDlChEstimateTime, (void *)dl_ch_estimates_time, sizeof(c16_t), fp->nb_antennas_rx, fp->ofdm_symbol_size, 0); - return(0); } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 701967a235..65bcd5c7d7 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -57,15 +57,18 @@ 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]); -c32_t nr_pbch_dmrs_correlation(const PHY_VARS_NR_UE *ue, +c32_t nr_pbch_dmrs_correlation(const NR_DL_FRAME_PARMS *fp, const UE_nr_rxtx_proc_t *proc, const int symbol, const int dmrss, + const int Nid_cell, + const int ssb_start_subcarrier, const uint32_t nr_gold_pbch[NR_PBCH_DMRS_LENGTH_DWORD], - const c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); + const c16_t rxdataF[][fp->samples_per_slot_wCP]); -int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, - NR_DL_FRAME_PARMS *fp, +int nr_pbch_channel_estimation(const NR_DL_FRAME_PARMS *fp, + const sl_nr_ue_phy_params_t *sl_phy_params, + const uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD], int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], struct complex16 dl_ch_estimates_time[][fp->ofdm_symbol_size], @@ -74,7 +77,8 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, int dmrss, uint8_t ssb_index, uint8_t n_hf, - c16_t rxdataF[][fp->samples_per_slot_wCP], + int ssb_start_subcarrier, + const c16_t rxdataF[][fp->samples_per_slot_wCP], bool sidelink, uint16_t Nid); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index c8c7f6e73d..40cc29d52a 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -45,6 +45,7 @@ #include "PHY/NR_REFSIG/sss_nr.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" #include "PHY/TOOLS/tools_defs.h" +#include "nr-uesoftmodem.h" //static nfapi_nr_config_request_t config_t; //static nfapi_nr_config_request_t* config =&config_t; @@ -64,24 +65,35 @@ static int ssb_sort(const void *a, const void *b) } static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *ue, + const NR_DL_FRAME_PARMS *frame_parms, + int Nid_cell, int pbch_initial_symbol, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) + int ssb_start_subcarrier, + int *half_frame_bit, + int *ssb_index, + int *symbol_offset, + fapiPbch_t *result, + const uint32_t nr_gold_pbch_ref[2][64][NR_PBCH_DMRS_LENGTH_DWORD], + const c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - const int N_L = (frame_parms->Lmax == 4) ? 4 : 8; 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 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++) { // computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf cd_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); + c32_t meas = nr_pbch_dmrs_correlation(frame_parms, + proc, + i, + i - pbch_initial_symbol, + Nid_cell, + ssb_start_subcarrier, + nr_gold_pbch_ref[hf][l], + rxdataF); csum(cumul, cumul, meas); } *current_ssb = (NR_UE_SSB){.i_ssb = l, .n_hf = hf, .metric = squaredMod(cumul)}; @@ -89,19 +101,18 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, } } qsort(best_ssb, N_L * N_hf, sizeof(NR_UE_SSB), ssb_sort); - stop_meas(&ue->dlsch_channel_estimation_stats); 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))) 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; iframe_parms, + nr_pbch_channel_estimation(frame_parms, + NULL, + nr_gold_pbch_ref, estimateSz, dl_ch_estimates, dl_ch_estimates_time, @@ -110,13 +121,26 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, i - pbch_initial_symbol, ssb->i_ssb, ssb->n_hf, + ssb_start_subcarrier, rxdataF, false, - frame_parms->Nid_cell); + Nid_cell); - stop_meas(&ue->dlsch_channel_estimation_stats); - fapiPbch_t result = {0}; - if (0 == nr_rx_pbch(ue, proc, estimateSz, dl_ch_estimates, frame_parms, ssb->i_ssb, &result, rxdataF)) { + if (0 + == nr_rx_pbch(NULL, + proc, + false, + estimateSz, + dl_ch_estimates, + frame_parms, + ssb->i_ssb, + ssb_start_subcarrier, + Nid_cell, + result, + half_frame_bit, + ssb_index, + symbol_offset, + 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", @@ -126,26 +150,32 @@ static bool nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, 1, 1); } - LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); + LOG_I(PHY, "Initial sync: pbch decoded sucessfully, ssb index %d\n", *ssb_index); return true; } } - LOG_W(PHY, "[UE%d] Initial sync: pbch not decoded, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); + LOG_W(PHY, "Initial sync: pbch not decoded, ssb index %d\n", frame_parms->ssb_index); return false; } -nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) +static void compensate_freq_offset(c16_t **x, const NR_DL_FRAME_PARMS *fp, const int offset, const int sn) { - int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, + double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time + double off_angle = -2 * M_PI * s_time * (offset); // offset rotation angle compensation per sample - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - nr_initial_sync_t ret = {.cell_detected = false}; - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN); - - LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); + for (int n = sn * fp->samples_per_frame; n < (sn + 1) * fp->samples_per_frame; n++) { + for (int ar = 0; ar < fp->nb_antennas_rx; ar++) { + const double re = x[ar][n].r; + const double im = x[ar][n].i; + x[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); + x[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); + } + } +} +void nr_scan_ssb(void *arg) +{ /* Initial synchronisation * * 1 radio frame = 10 ms @@ -159,45 +189,49 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i * sync_pos SS/PBCH block */ - const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; - __attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)arg; + c16_t **rxdata = ssbInfo->rxdata; + const NR_DL_FRAME_PARMS *fp = ssbInfo->fp; + + // Generate PSS time signal for this GSCN. + __attribute__((aligned(32))) c16_t pssTime[NUMBER_PSS_SEQUENCE][fp->ofdm_symbol_size]; + const int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; + for (int nid2 = 0; nid2 < pss_sequence; nid2++) + generate_pss_nr_time(fp, nid2, ssbInfo->gscnInfo.ssbFirstSC, pssTime[nid2]); // initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame - // only one frame is used for symulation tools - for (int frame_id = 0; frame_id < n_frames && !ret.cell_detected; frame_id++) { + // only one frame is used for simulation tools + for (int frame_id = 0; frame_id < ssbInfo->nFrames && !ssbInfo->syncRes.cell_detected; frame_id++) { /* process pss search on received buffer */ - sync_pos = pss_synchro_nr(ue, frame_id, NO_RATE_CHANGE); + ssbInfo->syncRes.frame_id = frame_id; + int nid2; + int freq_offset_pss; + const int sync_pos = pss_synchro_nr((const c16_t **)rxdata, + fp, + pssTime, + frame_id, + ssbInfo->foFlag, + ssbInfo->targetNidCell, + &nid2, + &freq_offset_pss); if (sync_pos < fp->nb_prefix_samples) continue; - ue->ssb_offset = sync_pos - fp->nb_prefix_samples; + ssbInfo->ssbOffset = sync_pos - fp->nb_prefix_samples; #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.nid2); LOG_I(PHY, "sync_pos %d ssb_offset %d \n", sync_pos, ue->ssb_offset); #endif /* check that SSS/PBCH block is continuous inside the received buffer */ - if (ue->ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) >= fp->samples_per_frame) { + if (ssbInfo->ssbOffset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) >= fp->samples_per_frame) { LOG_I(PHY, "Can't try to decode SSS from PSS position, will retry (PSS circular buffer wrapping): sync_pos %d\n", sync_pos); continue; } // 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 - - // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 - // and we do not know yet in which slot it goes. - - for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { - for (int ar = 0; ar < fp->nb_antennas_rx; ar++) { - const double re = ue->common_vars.rxdata[ar][n].r; - const double im = ue->common_vars.rxdata[ar][n].i; - ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); - ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); - } - } + if (ssbInfo->foFlag) { + compensate_freq_offset(rxdata, fp, freq_offset_pss, frame_id); } /* slot_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */ @@ -209,8 +243,15 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */ /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */ + const uint32_t rxdataF_sz = fp->samples_per_slot_wCP; + __attribute__((aligned(32))) c16_t rxdataF[fp->nb_antennas_rx][rxdataF_sz]; for (int i = 0; i < NR_N_SYMBOLS_SSB; i++) - nr_slot_fep_init_sync(ue, proc, i, frame_id * fp->samples_per_frame + ue->ssb_offset, false, rxdataF, link_type_dl); + nr_slot_fep_init_sync(fp, + i, + frame_id * fp->samples_per_frame + ssbInfo->ssbOffset, + (const c16_t **)rxdata, + rxdataF, + link_type_dl); #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY, "Calling sss detection (normal CP)\n"); @@ -219,69 +260,175 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i int freq_offset_sss = 0; int32_t metric_tdd_ncp = 0; uint8_t phase_tdd_ncp; - ret.cell_detected = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF); - - // digital compensation of FFO for SSB symbols - if (freq_offset_sss && ue->UE_fo_compensation) { - double s_time = 1 / (1.0e3 * fp->samples_per_subframe); // sampling time - double off_angle = -2 * M_PI * s_time * freq_offset_sss; // offset rotation angle compensation per sample + ssbInfo->syncRes.cell_detected = rx_sss_nr(fp, + nid2, + ssbInfo->targetNidCell, + freq_offset_pss, + ssbInfo->gscnInfo.ssbFirstSC, + &ssbInfo->nidCell, + &metric_tdd_ncp, + &phase_tdd_ncp, + &freq_offset_sss, + rxdataF); + ssbInfo->freqOffset = freq_offset_pss + freq_offset_sss; + + uint32_t nr_gold_pbch_ref[2][64][NR_PBCH_DMRS_LENGTH_DWORD]; + if (ssbInfo->syncRes.cell_detected) { // we got sss channel + nr_gold_pbch(nr_gold_pbch_ref, ssbInfo->nidCell, fp->Lmax); + ssbInfo->syncRes.cell_detected = nr_pbch_detection(ssbInfo->proc, + ssbInfo->fp, + ssbInfo->nidCell, + 1, + ssbInfo->gscnInfo.ssbFirstSC, + &ssbInfo->halfFrameBit, + &ssbInfo->ssbIndex, + &ssbInfo->symbolOffset, + &ssbInfo->pbchResult, + nr_gold_pbch_ref, + rxdataF); // start pbch detection at first symbol after pss + } + } +} + +nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) +{ + NR_DL_FRAME_PARMS *fp = &ue->frame_parms; + + // Get list of GSCN in this band, current UE's bandwidth and center frequency. + nr_gscn_info_t gscnInfo[MAX_GSCN_BAND]; + int numScans = get_scan_ssb_first_sc(fp->dl_CarrierFreq, fp->N_RB_DL, fp->nr_band, fp->numerology_index, gscnInfo); + notifiedFIFO_t nf; + initNotifiedFIFO(&nf); + + // Perform SSB scanning in parallel. One GSCN per thread. + LOG_I(NR_PHY, + "Starting cell search with center freq: %ld, bandwidth: %d. Scanning for %d number of GSCN.\n", + fp->dl_CarrierFreq, + fp->N_RB_DL, + numScans); + for (int s = 0; s < numScans; s++) { + notifiedFIFO_elt_t *req = newNotifiedFIFO_elt(sizeof(nr_ue_ssb_scan_t), gscnInfo[s].gscn, &nf, &nr_scan_ssb); + nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req); + ssbInfo->gscnInfo = gscnInfo[s]; + ssbInfo->rxdata = malloc16_clear(fp->nb_antennas_rx * sizeof(c16_t *)); + for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { + ssbInfo->rxdata[ant] = malloc16_clear((fp->samples_per_frame * 2 + fp->ofdm_symbol_size) * sizeof(c16_t)); + memcpy(ssbInfo->rxdata[ant], ue->common_vars.rxdata[ant], sizeof(c16_t) * fp->samples_per_frame * 2); + } + LOG_I(NR_PHY, + "Scanning GSCN: %d, with SSB offset: %d, SSB Freq: %lf\n", + ssbInfo->gscnInfo.gscn, + ssbInfo->gscnInfo.ssbFirstSC, + ssbInfo->gscnInfo.ssRef); + ssbInfo->fp = &ue->frame_parms; + ssbInfo->proc = proc; + ssbInfo->syncRes.cell_detected = false; + ssbInfo->nFrames = n_frames; + ssbInfo->foFlag = ue->UE_fo_compensation; + ssbInfo->targetNidCell = ue->target_Nid_cell; + pushTpool(&get_nrUE_params()->Tpool, req); + } + + // Collect the scan results + nr_ue_ssb_scan_t res = {0}; + while (numScans) { + notifiedFIFO_elt_t *req = pullTpool(&nf, &get_nrUE_params()->Tpool); + nr_ue_ssb_scan_t *ssbInfo = (nr_ue_ssb_scan_t *)NotifiedFifoData(req); + if (ssbInfo->syncRes.cell_detected) { + LOG_A(NR_PHY, + "Cell Detected with GSCN: %d, SSB SC offset: %d, SSB Ref: %lf\n", + ssbInfo->gscnInfo.gscn, + ssbInfo->gscnInfo.ssbFirstSC, + ssbInfo->gscnInfo.ssRef); + if (!res.syncRes.cell_detected) { // take the first cell detected + res = *ssbInfo; + } + } + for (int ant = 0; ant < fp->nb_antennas_rx; ant++) { + free(ssbInfo->rxdata[ant]); + } + free(ssbInfo->rxdata); + delNotifiedFIFO_elt(req); + numScans--; + } + + // Set globals based on detected cell + if (res.syncRes.cell_detected) { + fp->Nid_cell = res.nidCell; + fp->ssb_start_subcarrier = res.gscnInfo.ssbFirstSC; + fp->half_frame_bit = res.halfFrameBit; + fp->ssb_index = res.ssbIndex; + ue->symbol_offset = res.symbolOffset; + ue->common_vars.freq_offset = res.freqOffset; + } + + // In initial sync, we indicate PBCH to MAC after the scan is complete. + nr_downlink_indication_t dl_indication; + fapi_nr_rx_indication_t rx_ind = {0}; + uint16_t number_pdus = 1; + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, + FAPI_NR_RX_PDU_TYPE_SSB, + ue, + NULL, + NULL, + number_pdus, + proc, + res.syncRes.cell_detected ? (void *)&res.pbchResult : NULL, + NULL); + + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&dl_indication); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN); + + LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); + + if (res.syncRes.cell_detected) { + // digital compensation of FFO for SSB symbols + if (res.freqOffset && ue->UE_fo_compensation) { // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 // and we do not know yet in which slot it goes. - for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { - for (int ar = 0; ar < fp->nb_antennas_rx; ar++) { - const double re = ue->common_vars.rxdata[ar][n].r; - const double im = ue->common_vars.rxdata[ar][n].i; - ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); - ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); - } - } - ue->common_vars.freq_offset += freq_offset_sss; + compensate_freq_offset(ue->common_vars.rxdata, fp, res.freqOffset, res.syncRes.frame_id); + } + nr_gold_pbch(ue->nr_gold_pbch, fp->Nid_cell, fp->Lmax); + // sync at symbol ue->symbol_offset + // computing the offset wrt the beginning of the frame + int mu = fp->numerology_index; + // number of symbols with different prefix length + // every 7*(1<ofdm_symbol_size + fp->nb_prefix_samples0) + + (res.symbolOffset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of + // the n_frames we got sync + ue->init_sync_frame = n_frames - 1 - res.syncRes.frame_id; + + // compute the scramblingID_pdcch and the gold pdcch + ue->scramblingID_pdcch = fp->Nid_cell; + nr_gold_pdcch(ue, fp->Nid_cell); + + // compute the scrambling IDs for PDSCH DMRS + for (int i = 0; i < NR_NB_NSCID; i++) { + ue->scramblingID_dlsch[i] = fp->Nid_cell; + nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]); } - if (ret.cell_detected) { // we got sss channel - nr_gold_pbch(ue); - ret.cell_detected = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss + nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell); + + // initialize the pusch dmrs + for (int i = 0; i < NR_NB_NSCID; i++) { + ue->scramblingID_ulsch[i] = fp->Nid_cell; + nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i); } - if (ret.cell_detected) { - // sync at symbol ue->symbol_offset - // computing the offset wrt the beginning of the frame - int mu = fp->numerology_index; - // number of symbols with different prefix length - // every 7*(1<symbol_offset / (7 * (1 << mu))) + 1; - sync_pos_frame = n_symb_prefix0 * (fp->ofdm_symbol_size + fp->nb_prefix_samples0) - + (ue->symbol_offset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); - // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of - // the n_frames we got sync - ue->init_sync_frame = n_frames - 1 - frame_id; - - // compute the scramblingID_pdcch and the gold pdcch - ue->scramblingID_pdcch = fp->Nid_cell; - nr_gold_pdcch(ue, fp->Nid_cell); - - // compute the scrambling IDs for PDSCH DMRS - for (int i = 0; i < NR_NB_NSCID; i++) { - ue->scramblingID_dlsch[i] = fp->Nid_cell; - nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]); - } - - nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell); - - // initialize the pusch dmrs - for (int i = 0; i < NR_NB_NSCID; i++) { - ue->scramblingID_ulsch[i] = fp->Nid_cell; - nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i); - } - - // we also need to take into account the shift by samples_per_frame in case the if is true - if (ue->ssb_offset < sync_pos_frame) { - ret.rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset; - ue->init_sync_frame += 1; - } else - ret.rx_offset = ue->ssb_offset - sync_pos_frame; - } + // we also need to take into account the shift by samples_per_frame in case the if is true + if (res.ssbOffset < sync_pos_frame) { + res.syncRes.rx_offset = fp->samples_per_frame - sync_pos_frame + res.ssbOffset; + ue->init_sync_frame += 1; + } else + res.syncRes.rx_offset = res.ssbOffset - sync_pos_frame; + } #ifdef DEBUG_INITIAL_SYNCH LOG_I(PHY, @@ -292,25 +439,10 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i ret.cell_detected, ret.rx_offset); #endif - } - /* Consider this is a false detection if the offset is > 1000 Hz - Not to be used now that offest estimation is in place - if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) - { - ret=-1; - LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); - }*/ - - if (ret.cell_detected) { // PBCH found so indicate sync to higher layers and configure frame parameters - - //#ifdef DEBUG_INITIAL_SYNCH - - LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, ret.rx_offset); - - //#endif - - if (ue->UE_scan_carrier == 0) { + if (res.syncRes.cell_detected) { + LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, res.syncRes.rx_offset); + if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE LOG_I(PHY, "[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n", @@ -318,48 +450,45 @@ nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, i ue->rx_offset, ue->common_vars.freq_offset); #endif - - // send sync status to higher layers later when timing offset converge to target timing - } - - LOG_I(PHY, "[UE %d] Measured Carrier Frequency offset %d Hz\n", ue->Mod_id, ue->common_vars.freq_offset); - } else { + } + LOG_I(PHY, "[UE %d] Measured Carrier Frequency offset %d Hz\n", ue->Mod_id, res.freqOffset); + } 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.nid2); 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 - } + } // gain control - if (!ret.cell_detected) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates) - int rx_power = 0; + if (!res.syncRes.cell_detected) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates) + int rx_power = 0; - // do a measurement on the best guess of the PSS - // for (aarx=0; aarxnb_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 best guess of the PSS + // for (aarx=0; aarxnb_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; aarxnb_antennas_rx; aarx++) - rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], - frame_parms->samples_per_subframe*10); - */ + /* + // do a measurement on the full frame + for (aarx=0; aarxnb_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/fp->nb_antennas_rx; + // we might add a low-pass filter here later + ue->measurements.rx_power_avg[0] = rx_power / fp->nb_antennas_rx; - ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]); + 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 - } else { - LOG_A(PHY, "Initial sync successful\n"); - } + } else { + LOG_A(PHY, "Initial sync successful\n"); + } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); - return ret; + return res.syncRes; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c index e18a6a1633..96c2638c9e 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync_sl.c @@ -462,8 +462,9 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, uint8_t decoded_output[4]; for (int symbol = 0; symbol < SL_NR_NUMSYM_SLSS_NORMAL_CP - 1;) { - nr_pbch_channel_estimation(UE, - frame_parms, + nr_pbch_channel_estimation(frame_parms, + &UE->SL_UE_PHY_PARAMS, + UE->nr_gold_pbch, rxdataF_sz, dl_ch_estimates, dl_ch_estimates_time, @@ -472,6 +473,7 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, symbol, 0, 0, + frame_parms->ssb_start_subcarrier, rxdataF, 1, rx_slss_id); diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index f60d9c89ea..fd848c7522 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -47,14 +47,15 @@ #define print_shorts(s,x) printf("%s : %d,%d,%d,%d,%d,%d,%d,%d\n",s,((int16_t*)x)[0],((int16_t*)x)[1],((int16_t*)x)[2],((int16_t*)x)[3],((int16_t*)x)[4],((int16_t*)x)[5],((int16_t*)x)[6],((int16_t*)x)[7]) static uint16_t nr_pbch_extract(uint32_t rxdataF_sz, - c16_t rxdataF[][rxdataF_sz], + const c16_t rxdataF[][rxdataF_sz], const int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], uint32_t symbol, uint32_t s_offset, - NR_DL_FRAME_PARMS *frame_parms) + int ssb_start_subcarrier, + const NR_DL_FRAME_PARMS *frame_parms) { uint16_t rb; uint8_t i, j, aarx; @@ -64,9 +65,9 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz, symbol); for (aarx=0; aarxnb_antennas_rx; aarx++) { - unsigned int rx_offset = frame_parms->first_carrier_offset + frame_parms->ssb_start_subcarrier; + unsigned int rx_offset = frame_parms->first_carrier_offset + ssb_start_subcarrier; rx_offset = (rx_offset)%(frame_parms->ofdm_symbol_size); - struct complex16 *rxF = &rxdataF[aarx][(symbol+s_offset)*frame_parms->ofdm_symbol_size]; + const struct complex16 *rxF = &rxdataF[aarx][(symbol + s_offset) * frame_parms->ofdm_symbol_size]; struct complex16 *rxF_ext = rxdataF_ext[aarx]; #ifdef DEBUG_PBCH printf("extract_rbs (nushift %d): rx_offset=%d, symbol %u\n", @@ -203,8 +204,9 @@ static uint16_t nr_pbch_extract(uint32_t rxdataF_sz, //compute average channel_level on each (TX,RX) antenna pair int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - NR_DL_FRAME_PARMS *frame_parms, - int nb_re) { + const NR_DL_FRAME_PARMS *frame_parms, + int nb_re) +{ int16_t nb_rb=nb_re/12; simde__m128i avg128; simde__m128i *dl_ch128; @@ -244,7 +246,7 @@ void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL], - NR_DL_FRAME_PARMS *frame_parms, + const NR_DL_FRAME_PARMS *frame_parms, uint8_t output_shift) { for (int aarx=0; aarxnb_antennas_rx; aarx++) { @@ -365,35 +367,30 @@ const uint8_t pbch_deinterleaving_pattern[32] = {28, 0, 31, 30, 7, 29, 25, 27, int nr_rx_pbch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, + bool is_synchronized, int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], - NR_DL_FRAME_PARMS *frame_parms, + const NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, + int ssb_start_subcarrier, + int Nid_cell, fapiPbch_t *result, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) + int *half_frame_bit, + int *ssb_index, + int *ret_symbol_offset, + const struct complex16 rxdataF[][frame_parms->samples_per_slot_wCP]) { int max_h=0; int symbol; - // uint8_t pbch_a[64]; - // FT ?? cppcheck doesn't like pbch_a allocation because of line 525..and i don't get what this variable is for.. - // uint8_t *pbch_a = malloc(sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS); uint8_t Lmax=frame_parms->Lmax; int M = NR_POLAR_PBCH_E; int nushift = (Lmax == 4) ? i_ssb & 3 : i_ssb & 7; - //uint16_t crc; - //unsigned short idx_demod =0; - uint32_t decoderState=0; - //uint8_t decoderListSize = 8, pathMetricAppr = 0; - //time_stats_t polar_decoder_init,polar_rate_matching,decoding,bit_extraction,deinterleaving; - //time_stats_t path_metric,sorting,update_LLR; - // FT ?? cppcheck fix memset(&pbch_a[0], 0, sizeof(uint8_t) * NR_POLAR_PBCH_PAYLOAD_BITS); - //printf("nr_pbch_ue nid_cell %d\n",frame_parms->Nid_cell); int16_t pbch_e_rx[960]= {0}; //Fixme: previous version erase only NR_POLAR_PBCH_E bytes int16_t pbch_unClipped[960]= {0}; int pbch_e_rx_idx=0; int symbol_offset=1; - if (ue->is_synchronized > 0) + if (is_synchronized) symbol_offset=nr_get_ssb_start_symbol(frame_parms, i_ssb)%(frame_parms->symbols_per_slot); else symbol_offset=0; @@ -411,7 +408,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, __attribute__ ((aligned(32))) struct complex16 rxdataF_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL]; __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_ext[frame_parms->nb_antennas_rx][PBCH_MAX_RE_PER_SYMBOL]; memset(dl_ch_estimates_ext,0, sizeof dl_ch_estimates_ext); - nr_pbch_extract(ue->frame_parms.samples_per_slot_wCP, + nr_pbch_extract(frame_parms->samples_per_slot_wCP, rxdataF, estimateSz, dl_ch_estimates, @@ -419,6 +416,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, dl_ch_estimates_ext, symbol, symbol_offset, + ssb_start_subcarrier, frame_parms); #ifdef DEBUG_PBCH LOG_I(PHY,"[PHY] PBCH Symbol %d ofdm size %d\n",symbol, frame_parms->ofdm_symbol_size); @@ -457,8 +455,10 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, } // legacy code use int16, but it is complex16 - UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0); - UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0); + if (ue) { + UEscopeCopy(ue, pbchRxdataF_comp, pbch_unClipped, sizeof(struct complex16), frame_parms->nb_antennas_rx, pbch_e_rx_idx / 2, 0); + UEscopeCopy(ue, pbchLlr, pbch_e_rx, sizeof(int16_t), frame_parms->nb_antennas_rx, pbch_e_rx_idx, 0); + } #ifdef DEBUG_PBCH for (int cnt = 0; cnt < 864 ; cnt++) printf("pbch rx llr %d\n", *(pbch_e_rx + cnt)); @@ -467,23 +467,29 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, uint32_t unscrambling_mask = (Lmax==64)?0x100006D:0x1000041; uint32_t pbch_a_interleaved=0; uint32_t pbch_a_prime=0; - nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_E, + nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_E, 0, 0, pbch_a_prime, &pbch_a_interleaved); //polar decoding de-rate matching uint64_t tmp=0; - decoderState = polar_decoder_int16(pbch_e_rx,(uint64_t *)&tmp,0, - NR_POLAR_PBCH_MESSAGE_TYPE, NR_POLAR_PBCH_PAYLOAD_BITS, NR_POLAR_PBCH_AGGREGATION_LEVEL); + const uint32_t decoderState = polar_decoder_int16(pbch_e_rx, + (uint64_t *)&tmp, + 0, + NR_POLAR_PBCH_MESSAGE_TYPE, + NR_POLAR_PBCH_PAYLOAD_BITS, + NR_POLAR_PBCH_AGGREGATION_LEVEL); pbch_a_prime = tmp; nr_downlink_indication_t dl_indication; fapi_nr_rx_indication_t rx_ind = {0}; uint16_t number_pdus = 1; - if(decoderState) { - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&dl_indication); + if (decoderState) { + if (ue) { // decoding failed in synced state + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL); + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&dl_indication); + } return(decoderState); } // printf("polar decoder output 0x%08x\n",pbch_a_prime); @@ -494,7 +500,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, M = (Lmax == 64)? (NR_POLAR_PBCH_PAYLOAD_BITS - 6) : (NR_POLAR_PBCH_PAYLOAD_BITS - 3); nushift = ((pbch_a_prime>>24)&1) ^ (((pbch_a_prime>>6)&1)<<1); pbch_a_interleaved=0; - nr_pbch_unscrambling(pbch_e_rx, frame_parms->Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, + nr_pbch_unscrambling(pbch_e_rx, Nid_cell, nushift, M, NR_POLAR_PBCH_PAYLOAD_BITS, 1, unscrambling_mask, pbch_a_prime, &pbch_a_interleaved); //printf("nushift %d sfn 3rd %d 2nd %d", nushift,((pbch_a_prime>>6)&1), ((pbch_a_prime>>24)&1) ); //payload deinterleaving @@ -516,19 +522,19 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, for (int i=0; i<3; i++) result->decoded_output[i] = (uint8_t)((payload>>((3-i)<<3))&0xff); - - frame_parms->half_frame_bit = (result->xtra_byte>>4)&0x01; // computing the half frame index from the extra byte - frame_parms->ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8 - + + *half_frame_bit = (result->xtra_byte >> 4) & 0x01; // computing the half frame index from the extra byte + *ssb_index = i_ssb; // ssb index corresponds to i_ssb for Lmax = 4,8 + if (Lmax == 64) { // for Lmax = 64 ssb index 4th,5th and 6th bits are in extra byte for (int i=0; i<3; i++) - frame_parms->ssb_index += (((result->xtra_byte>>(7-i))&0x01)<<(3+i)); + *ssb_index += (((result->xtra_byte >> (7 - i)) & 0x01) << (3 + i)); } - ue->symbol_offset = nr_get_ssb_start_symbol(frame_parms,frame_parms->ssb_index); + *ret_symbol_offset = nr_get_ssb_start_symbol(frame_parms, *ssb_index); - if (frame_parms->half_frame_bit) - ue->symbol_offset += (frame_parms->slots_per_frame>>1)*frame_parms->symbols_per_slot; + if (*half_frame_bit) + *ret_symbol_offset += (frame_parms->slots_per_frame >> 1) * frame_parms->symbols_per_slot; #ifdef DEBUG_PBCH printf("xtra_byte %x payload %x\n", result->xtra_byte, payload); @@ -540,11 +546,13 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, #endif - nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); - nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); + if (ue) { + nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL); + nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL); - if (ue->if_inst && ue->if_inst->dl_indication) - ue->if_inst->dl_indication(&dl_indication); + if (ue->if_inst && ue->if_inst->dl_indication) + ue->if_inst->dl_indication(&dl_indication); + } return 0; } diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index 111e457c05..b4315d292b 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -291,12 +291,18 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin int nr_rx_pbch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, - const int estimateSz, + bool is_synchronized, + int estimateSz, struct complex16 dl_ch_estimates[][estimateSz], - NR_DL_FRAME_PARMS *frame_parms, + const NR_DL_FRAME_PARMS *frame_parms, uint8_t i_ssb, + int ssb_start_subcarrier, + int Nid_cell, fapiPbch_t *result, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); + int *half_frame_bit, + int *ssb_index, + int *ret_symbol_offset, + const struct complex16 rxdataF[][frame_parms->samples_per_slot_wCP]); #ifndef modOrder #define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS @@ -319,10 +325,6 @@ int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, @param n_frames @param sa current running mode */ -typedef struct { - bool cell_detected; - int rx_offset; -} nr_initial_sync_t; nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa); /*! @@ -435,13 +437,13 @@ nr_initial_sync_t sl_nr_slss_search(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc, // Reuse already existing PBCH functions int nr_pbch_channel_level(struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], - NR_DL_FRAME_PARMS *frame_parms, + const NR_DL_FRAME_PARMS *frame_parms, int nb_re); void nr_pbch_channel_compensation(struct complex16 rxdataF_ext[][PBCH_MAX_RE_PER_SYMBOL], struct complex16 dl_ch_estimates_ext[][PBCH_MAX_RE_PER_SYMBOL], int nb_re, struct complex16 rxdataF_comp[][PBCH_MAX_RE_PER_SYMBOL], - NR_DL_FRAME_PARMS *frame_parms, + const NR_DL_FRAME_PARMS *frame_parms, uint8_t output_shift); void nr_pbch_unscrambling(int16_t *demod_pbch_e, uint16_t Nid, diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 721697e248..ae64c53f88 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -50,10 +50,17 @@ //#define DBG_PSS_NR static time_stats_t generic_time[TIME_LAST]; -static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is); +static int pss_search_time_nr(const c16_t **rxdata, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size], + bool fo_flag, + int is, + int target_Nid_cell, + int *nid2, + int *f_off); -static int16_t *primary_synchro_nr2[NUMBER_PSS_SEQUENCE] = {0}; -static c16_t *primary_synchro_time_nr[NUMBER_PSS_SEQUENCE] = {0}; +static int16_t primary_synchro_nr2[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; +static c16_t primary_synchro[NUMBER_PSS_SEQUENCE][LENGTH_PSS_NR] = {0}; int16_t *get_primary_synchro_nr2(const int nid2) { return primary_synchro_nr2[nid2]; @@ -80,7 +87,6 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) int16_t d_pss[LENGTH_PSS_NR]; int16_t x[LENGTH_PSS_NR]; - c16_t primary_synchro[LENGTH_PSS_NR] = {0}; int16_t *primary_synchro2 = primary_synchro_nr2[N_ID_2]; /* pss in complex with alternatively i then q */ #define INITIAL_PSS_NR (7) @@ -98,7 +104,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) /* PSS is directly mapped to subcarrier without modulation 38.211 */ for (int i=0; i < LENGTH_PSS_NR; i++) { - primary_synchro[i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */ + primary_synchro[N_ID_2][i].r = (d_pss[i] * SHRT_MAX) >> SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */ primary_synchro2[i] = d_pss[i]; } @@ -115,6 +121,7 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) } #endif +} /* call of IDFT should be done with ordered input as below * @@ -137,21 +144,22 @@ void generate_pss_nr(NR_DL_FRAME_PARMS *fp, int N_ID_2) * * sample 0 is for continuous frequency which is used here */ - +void generate_pss_nr_time(const NR_DL_FRAME_PARMS *fp, const int N_ID_2, int ssbFirstSCS, c16_t pssTime[fp->ofdm_symbol_size]) +{ unsigned int subcarrier_start = get_softmodem_params()->sl_mode == 0 ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL; - unsigned int k = fp->first_carrier_offset + fp->ssb_start_subcarrier + subcarrier_start; + unsigned int k = fp->first_carrier_offset + ssbFirstSCS + subcarrier_start; if (k>= fp->ofdm_symbol_size) k-=fp->ofdm_symbol_size; c16_t synchroF_tmp[fp->ofdm_symbol_size] __attribute__((aligned(32))); memset(synchroF_tmp, 0, sizeof(synchroF_tmp)); for (int i=0; i < LENGTH_PSS_NR; i++) { - synchroF_tmp[k % fp->ofdm_symbol_size] = primary_synchro[i]; + synchroF_tmp[k % fp->ofdm_symbol_size] = primary_synchro[N_ID_2][i]; k++; } /* IFFT will give temporal signal of Pss */ idft((int16_t)get_idft(fp->ofdm_symbol_size), (int16_t *)synchroF_tmp, /* complex input but legacy type is wrong*/ - (int16_t *)primary_synchro_time_nr[N_ID_2], /* complex output */ + (int16_t *)pssTime, /* complex output */ 1); /* scaling factor */ #ifdef DBG_PSS_NR @@ -239,34 +247,10 @@ static void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue) AssertFatal(frame_parms_ue->ofdm_symbol_size > 127, "illegal ofdm_symbol_size %d\n", frame_parms_ue->ofdm_symbol_size); int pss_sequence = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; for (int i = 0; i < pss_sequence; i++) { - primary_synchro_nr2[i] = malloc16_clear(LENGTH_PSS_NR * sizeof(int16_t)); - AssertFatal(primary_synchro_nr2[i], "Fatal memory allocation problem \n"); - primary_synchro_time_nr[i] = malloc16_clear(frame_parms_ue->ofdm_symbol_size * sizeof(c16_t)); - AssertFatal(primary_synchro_time_nr[i], "Fatal memory allocation problem \n"); generate_pss_nr(frame_parms_ue,i); } } -/******************************************************************* -* -* NAME : free_context_pss_nr -* -* PARAMETERS : none -* -* RETURN : none -* -* DESCRIPTION : free context related to pss -* -*********************************************************************/ - -static void free_context_pss_nr(void) -{ - for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) { - free_and_zero(primary_synchro_nr2[i]); - free_and_zero(primary_synchro_time_nr[i]); - } -} - /******************************************************************* * * NAME : init_context_synchro_nr @@ -286,23 +270,6 @@ void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue) init_context_sss_nr(AMP); } -/******************************************************************* -* -* NAME : free_context_synchro_nr -* -* PARAMETERS : none -* -* RETURN : free context for pss and sss -* -* DESCRIPTION : deallocate memory of synchronisation -* -*********************************************************************/ - -void free_context_synchro_nr(void) -{ - free_context_pss_nr(); -} - /******************************************************************* * * NAME : set_frame_context_pss_nr @@ -321,8 +288,6 @@ void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change); frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / rate_change); - free_context_pss_nr(); - /* pss reference have to be rebuild with new parameters ie ofdm symbol size */ init_context_synchro_nr(frame_parms_ue); @@ -348,8 +313,6 @@ void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_ch frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change; frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * rate_change; - free_context_pss_nr(); - /* pss reference have to be rebuild with new parameters ie ofdm symbol size */ init_context_synchro_nr(frame_parms_ue); #ifdef SYNCHRO_DECIMAT @@ -420,13 +383,15 @@ void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **r * *********************************************************************/ -int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) +int pss_synchro_nr(const c16_t **rxdata, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size], + int is, + bool fo_flag, + int target_Nid_cell, + int *nid2, + int *f_off) { - NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); - int synchro_position; - c16_t **rxdata = NULL; - int fo_flag = PHY_vars_UE->UE_fo_compensation; // flag to enable freq offset estimation and compensation - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SYNCHRO_NR, VCD_FUNCTION_IN); #ifdef DBG_PSS_NR @@ -434,24 +399,6 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) #endif - if (rate_change != 1) { - - rxdata = (c16_t**)malloc16(frame_parms->nb_antennas_rx * sizeof(c16_t*)); - - for (int aa = 0; aa < frame_parms->nb_antennas_rx; aa++) { - rxdata[aa] = (c16_t*)malloc16_clear((frame_parms->samples_per_frame + 8192) * sizeof(c16_t)); - } -#ifdef SYNCHRO_DECIMAT - - decimation_synchro_nr(PHY_vars_UE, rate_change, rxdata); - -#endif - } - else { - - rxdata = PHY_vars_UE->common_vars.rxdata; - } - #ifdef DBG_PSS_NR LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame,1,1); @@ -468,7 +415,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_IN); - synchro_position = pss_search_time_nr(rxdata, PHY_vars_UE, fo_flag, is); + int synchro_position = pss_search_time_nr(rxdata, frame_parms, pssTime, fo_flag, is, target_Nid_cell, nid2, f_off); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PSS_SEARCH_TIME_NR, VCD_FUNCTION_OUT); @@ -507,8 +454,6 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) return synchro_position; } - - /******************************************************************* * * NAME : pss_search_time_nr @@ -559,11 +504,15 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) * *********************************************************************/ -static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, int is) +static int pss_search_time_nr(const c16_t **rxdata, + const NR_DL_FRAME_PARMS *frame_parms, + const c16_t pssTime[NUMBER_PSS_SEQUENCE][frame_parms->ofdm_symbol_size], + bool fo_flag, + int is, + int target_Nid_cell, + int *nid2, + int *f_off) { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - int *nid2 = (int *)&ue->common_vars.nid2; - int *f_off = (int *)&ue->common_vars.freq_offset; unsigned int n, ar, peak_position, pss_source; int64_t peak_value; int64_t avg[NUMBER_PSS_SEQUENCE] = {0}; @@ -587,8 +536,8 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i int max_size = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; for (int j = 0; j < max_size; j++) for (int i = 0; i < frame_parms->ofdm_symbol_size; i++) { - maxval = max(maxval, abs(primary_synchro_time_nr[j][i].r)); - maxval = max(maxval, abs(primary_synchro_time_nr[j][i].i)); + maxval = max(maxval, abs(pssTime[j][i].r)); + maxval = max(maxval, abs(pssTime[j][i].i)); } int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2); @@ -598,8 +547,8 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i uint16_t pss_index_start = 0; uint16_t pss_index_end = get_softmodem_params()->sl_mode == 0 ? NUMBER_PSS_SEQUENCE : NUMBER_PSS_SEQUENCE_SL; - if (ue->target_Nid_cell != -1) { - pss_index_start = GET_NID2(ue->target_Nid_cell); + if (target_Nid_cell != -1) { + pss_index_start = GET_NID2(target_Nid_cell); pss_index_end = pss_index_start + 1; } @@ -612,7 +561,7 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i for (ar=0; arnb_antennas_rx; ar++) { /* perform correlation of rx data and pss sequence ie it is a dot product */ - const c32_t result = dot_product(primary_synchro_time_nr[pss_index], + const c32_t result = dot_product(pssTime[pss_index], &(rxdata[ar][n + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size, shift); @@ -645,13 +594,13 @@ static int pss_search_time_nr(c16_t **rxdata, PHY_VARS_NR_UE *ue, int fo_flag, i // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. // Computing cross-correlation at peak on half the symbol size for first half of data - c32_t r1 = dot_product(primary_synchro_time_nr[pss_source], + c32_t r1 = dot_product(pssTime[pss_source], &(rxdata[0][peak_position + is * frame_parms->samples_per_frame]), frame_parms->ofdm_symbol_size >> 1, shift); // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift - c32_t r2 = dot_product(primary_synchro_time_nr[pss_source] + (frame_parms->ofdm_symbol_size >> 1), + c32_t r2 = dot_product(pssTime[pss_source] + (frame_parms->ofdm_symbol_size >> 1), &(rxdata[0][peak_position + is * frame_parms->samples_per_frame]) + (frame_parms->ofdm_symbol_size >> 1), frame_parms->ofdm_symbol_size >> 1, shift); diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c index 09d8ce4f4a..05fdb33903 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c @@ -187,13 +187,14 @@ void insert_sss_nr(int16_t *sss_time, * *********************************************************************/ -static int pss_ch_est_nr(PHY_VARS_NR_UE *ue, +static int pss_ch_est_nr(const NR_DL_FRAME_PARMS *frame_parms, + int nid2, c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR]) { - int16_t *pss = get_primary_synchro_nr2(ue->common_vars.nid2); + int16_t *pss = get_primary_synchro_nr2(nid2); - for (int aarx = 0; aarx < ue->frame_parms.nb_antennas_rx; aarx++) { + for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { c16_t *sss_ext2 = sss_ext[aarx]; c16_t *pss_ext2 = pss_ext[aarx]; for (int i = 0; i < LENGTH_PSS_NR; i++) { @@ -250,16 +251,15 @@ static int pss_ch_est_nr(PHY_VARS_NR_UE *ue, *********************************************************************/ static int do_pss_sss_extract_nr( - PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, + const NR_DL_FRAME_PARMS *frame_parms, c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], uint8_t doPss, uint8_t doSss, uint8_t subframe, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both + int ssb_start_subcarrier, + c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) // add flag to indicate extracting only PSS, only SSS, or both { - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; AssertFatal(frame_parms->nb_antennas_rx > 0, "UB as sss_ext is not set to any value\n"); for (int aarx = 0; aarx < frame_parms->nb_antennas_rx; aarx++) { @@ -275,11 +275,8 @@ static int do_pss_sss_extract_nr( c16_t *pss_rxF_ext = pss_ext[aarx]; c16_t *sss_rxF_ext = sss_ext[aarx]; - unsigned int k = frame_parms->first_carrier_offset + - frame_parms->ssb_start_subcarrier + - ((get_softmodem_params()->sl_mode == 0) ? - PSS_SSS_SUB_CARRIER_START : - PSS_SSS_SUB_CARRIER_START_SL); + unsigned int k = frame_parms->first_carrier_offset + ssb_start_subcarrier + + ((get_softmodem_params()->sl_mode == 0) ? PSS_SSS_SUB_CARRIER_START : PSS_SSS_SUB_CARRIER_START_SL); if (k>= frame_parms->ofdm_symbol_size) k-=frame_parms->ofdm_symbol_size; @@ -333,14 +330,21 @@ static int do_pss_sss_extract_nr( * *********************************************************************/ -static int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, - const UE_nr_rxtx_proc_t *proc, +static int pss_sss_extract_nr(const NR_DL_FRAME_PARMS *frame_parms, c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR], c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR], uint8_t subframe, - c16_t rxdataF[][phy_vars_ue->frame_parms.samples_per_slot_wCP]) + int ssb_start_subcarrier, + c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) { - return do_pss_sss_extract_nr(phy_vars_ue, proc, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe, rxdataF); + return do_pss_sss_extract_nr(frame_parms, + pss_ext, + sss_ext, + 1 /* doPss */, + 1 /* doSss */, + subframe, + ssb_start_subcarrier, + rxdataF); } /******************************************************************* @@ -355,31 +359,29 @@ static int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue, * so Nid_cell in ue context is set according to Nid1 & Nid2 * *********************************************************************/ -bool rx_sss_nr(PHY_VARS_NR_UE *ue, - const UE_nr_rxtx_proc_t *proc, +bool rx_sss_nr(const NR_DL_FRAME_PARMS *frame_parms, + int nid2, + int target_Nid_cell, + int freq_offset_pss, + int ssb_start_subcarrier, + int *Nid_cell, int32_t *tot_metric, uint8_t *phase_max, int *freq_offset_sss, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]) + c16_t rxdataF[][frame_parms->samples_per_slot_wCP]) { uint8_t i; c16_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR] = {0}; c16_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR] = {0}; - uint8_t Nid2 = GET_NID2(ue->common_vars.nid2); + uint8_t Nid2 = GET_NID2(nid2); uint16_t Nid1; uint8_t phase; - NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms; int32_t metric, metric_re; int16_t *d; // pss sss extraction - pss_sss_extract_nr(ue, - proc, - pss_ext, - sss_ext, - 0, - rxdataF); /* subframe */ + pss_sss_extract_nr(frame_parms, pss_ext, sss_ext, 0, ssb_start_subcarrier, rxdataF); /* subframe */ #ifdef DEBUG_PLOT_SSS @@ -406,9 +408,7 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, // get conjugated channel estimate from PSS, H* = R* \cdot PSS // and do channel estimation and compensation based on PSS - pss_ch_est_nr(ue, - pss_ext, - sss_ext); + pss_ch_est_nr(frame_parms, nid2, pss_ext, sss_ext); // now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h *tot_metric = INT_MIN; @@ -453,8 +453,8 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, uint16_t Nid1_start = 0; uint16_t Nid1_end = N_ID_1_NUMBER; - if (ue->target_Nid_cell != -1) { - Nid1_start = GET_NID1(ue->target_Nid_cell); + if (target_Nid_cell != -1) { + Nid1_start = GET_NID1(target_Nid_cell); Nid1_end = Nid1_start + 1; } @@ -476,7 +476,7 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, // if the current metric is better than the last save it if (metric > *tot_metric) { *tot_metric = metric; - ue->frame_parms.Nid_cell = Nid2+(3*Nid1); + *Nid_cell = Nid2 + (3 * Nid1); *phase_max = phase; #ifdef DEBUG_SSS_NR @@ -490,9 +490,9 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, //#ifdef DEBUG_SSS_NR #define SSS_METRIC_FLOOR_NR (30000) - if (*tot_metric > SSS_METRIC_FLOOR_NR) { - Nid2 = GET_NID2(frame_parms->Nid_cell); - Nid1 = GET_NID1(frame_parms->Nid_cell); + if (*tot_metric > SSS_METRIC_FLOOR_NR) { + Nid2 = GET_NID2(*Nid_cell); + Nid1 = GET_NID1(*Nid_cell); LOG_D(PHY,"Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max); } // #endif @@ -504,7 +504,7 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, "Failed to detect SSS after PSS, metric of SSS %d, threshold to consider SSS valid %d, detected PCI: %d\n", *tot_metric, SSS_METRIC_FLOOR_NR, - frame_parms->Nid_cell); + *Nid_cell); return false; } d = (int16_t *)&d_sss[Nid2][Nid1]; @@ -515,10 +515,10 @@ bool rx_sss_nr(PHY_VARS_NR_UE *ue, double ffo_sss = atan2(im,re)/M_PI/4.3; *freq_offset_sss = (int)(ffo_sss*frame_parms->subcarrier_spacing); - double ffo_pss = ((double)ue->common_vars.freq_offset)/frame_parms->subcarrier_spacing; + double ffo_pss = ((double)freq_offset_pss) / frame_parms->subcarrier_spacing; LOG_W(NR_PHY, "SSS detected, PCI: %d, ffo_pss %f (%i Hz), ffo_sss %f (%i Hz), ffo_pss+ffo_sss %f (%i Hz), nid1: %d, nid2: %d\n", - frame_parms->Nid_cell, + *Nid_cell, ffo_pss, (int)(ffo_pss * frame_parms->subcarrier_spacing), ffo_sss, diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index c746bd69b8..fa4dc3bfa1 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -49,6 +49,7 @@ #include "common_lib.h" #include "fapi_nr_ue_interface.h" #include "assertions.h" +//#include "openair1/SCHED_NR_UE/defs.h" #ifdef MEX #define msg mexPrintf @@ -60,9 +61,9 @@ #endif #define msg(aRGS...) LOG_D(PHY, ##aRGS) #endif -//use msg in the real-time thread context +// use msg in the real-time thread context #define msg_nrt printf -//use msg_nrt in the non real-time context (for initialization, ...) +// use msg_nrt in the non real-time context (for initialization, ...) #ifndef malloc16 #define malloc16(x) memalign(32,x) #endif @@ -123,6 +124,11 @@ typedef enum { #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg +typedef struct { + uint8_t decoded_output[3]; // PBCH paylod not larger than 3B + uint8_t xtra_byte; +} fapiPbch_t; + typedef struct { // RRC measurements @@ -614,6 +620,30 @@ typedef struct { int frame_rx; } UE_nr_rxtx_proc_t; +typedef struct { + bool cell_detected; + int rx_offset; + int frame_id; +} nr_initial_sync_t; + +typedef struct { + nr_gscn_info_t gscnInfo; + int foFlag; + int targetNidCell; + c16_t **rxdata; + NR_DL_FRAME_PARMS *fp; + UE_nr_rxtx_proc_t *proc; + int nFrames; + int halfFrameBit; + int symbolOffset; + int ssbIndex; + int ssbOffset; + int nidCell; + int freqOffset; + nr_initial_sync_t syncRes; + fapiPbch_t pbchResult; +} nr_ue_ssb_scan_t; + typedef struct nr_phy_data_tx_s { NR_UE_ULSCH_t ulsch; NR_UE_PUCCH pucch_vars; diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index b34d021390..bdb3341387 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -81,12 +81,6 @@ #define DAQ_AGC_ON 1 #define DAQ_AGC_OFF 0 - -typedef struct { - uint8_t decoded_output[3]; // PBCH paylod not larger than 3B - uint8_t xtra_byte; -} fapiPbch_t; - /** @addtogroup _PHY_PROCEDURES_ * @{ */ diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 935563c35f..49de880804 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -387,13 +387,20 @@ static int nr_ue_pbch_procedures(PHY_VARS_NR_UE *ue, LOG_D(PHY,"[UE %d] Frame %d Slot %d, Trying PBCH (NidCell %d, gNB_id %d)\n",ue->Mod_id,frame_rx,nr_slot_rx,ue->frame_parms.Nid_cell,gNB_id); fapiPbch_t result; + int hf_frame_bit, ssb_index, symb_offset; ret = nr_rx_pbch(ue, proc, + ue->is_synchronized, estimateSz, dl_ch_estimates, &ue->frame_parms, - (ue->frame_parms.ssb_index)&7, + (ue->frame_parms.ssb_index) & 7, + ue->frame_parms.ssb_start_subcarrier, + ue->frame_parms.Nid_cell, &result, + &hf_frame_bit, + &ssb_index, + &symb_offset, rxdataF); if (ret==0) { @@ -884,8 +891,9 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ nr_slot_fep(ue, fp, proc, (ssb_start_symbol + i) % (fp->symbols_per_slot), rxdataF, link_type_dl); start_meas(&ue->dlsch_channel_estimation_stats); - nr_pbch_channel_estimation(ue, - &ue->frame_parms, + nr_pbch_channel_estimation(&ue->frame_parms, + NULL, + ue->nr_gold_pbch, estimateSz, dl_ch_estimates, dl_ch_estimates_time, @@ -894,10 +902,20 @@ int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_ i - 1, ssb_index & 7, ssb_slot_2 == nr_slot_rx, + fp->ssb_start_subcarrier, rxdataF, false, fp->Nid_cell); stop_meas(&ue->dlsch_channel_estimation_stats); + + if (i - 1 == 2) + UEscopeCopy(ue, + pbchDlChEstimateTime, + (void *)dl_ch_estimates_time, + sizeof(c16_t), + fp->nb_antennas_rx, + fp->ofdm_symbol_size, + 0); } nr_ue_ssb_rsrp_measurements(ue, ssb_index, proc, rxdataF); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c index 2bf8ee6cb9..d9a3d51267 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue_sl.c @@ -193,8 +193,9 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_d nr_slot_fep(ue, fp, proc, sym, rxdataF, link_type_ul); start_meas(&sl_phy_params->channel_estimation_stats); - nr_pbch_channel_estimation(ue, - fp, + nr_pbch_channel_estimation(fp, + &ue->SL_UE_PHY_PARAMS, + ue->nr_gold_pbch, estimateSz, dl_ch_estimates, dl_ch_estimates_time, @@ -203,10 +204,19 @@ int psbch_pscch_processing(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, nr_phy_d sym, 0, 0, + fp->ssb_start_subcarrier, rxdataF, true, sl_phy_params->sl_config.sl_sync_source.rx_slss_id); stop_meas(&sl_phy_params->channel_estimation_stats); + if (sym == 12) + UEscopeCopy(ue, + pbchDlChEstimateTime, + (void *)dl_ch_estimates_time, + sizeof(c16_t), + fp->nb_antennas_rx, + fp->ofdm_symbol_size, + 0); // PSBCH present in symbols 0, 5-12 for normal cp sym = (sym == 0) ? 5 : sym + 1; diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index 74d4568b70..b642d25adc 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -823,7 +823,7 @@ int main(int argc, char **argv) init_nr_ue_transport(UE); - nr_gold_pbch(UE); + nr_gold_pbch(UE->nr_gold_pbch, frame_parms->Nid_cell, frame_parms->Lmax); // compute the scramblingID_pdcch and the gold pdcch UE->scramblingID_pdcch = frame_parms->Nid_cell; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 408fe64d28..3967779d98 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -199,6 +199,7 @@ int main(int argc, char **argv) uint16_t Nid_cell=0; uint64_t SSB_positions=0x01; int ssb_subcarrier_offset = 0; + int ssb_scan_threads = 0; channel_desc_t *gNB2UE; get_softmodem_params()->sa = 1; @@ -493,8 +494,9 @@ int main(int argc, char **argv) set_tdd_config_nr(&gNB->gNB_config, mu, 7, 6, 2, 4); phy_init_nr_gNB(gNB); frame_parms->ssb_start_subcarrier = 12 * gNB->gNB_config.ssb_table.ssb_offset_point_a.value + ssb_subcarrier_offset; + initFloatingCoresTpool(ssb_scan_threads, &nrUE_params.Tpool, false, "UE-tpool"); - uint8_t n_hf = 0; + int n_hf = 0; int cyclic_prefix_type = NFAPI_CP_NORMAL; double fs=0, eps; @@ -608,7 +610,7 @@ int main(int argc, char **argv) exit(-1); } - nr_gold_pbch(UE); + nr_gold_pbch(UE->nr_gold_pbch, Nid_cell, frame_parms->Lmax); processingData_L1tx_t msgDataTx; // generate signal @@ -759,13 +761,16 @@ int main(int argc, char **argv) } if (n_trials==1) { - LOG_M("rxsig0.m","rxs0", UE->common_vars.rxdata[0],frame_parms->samples_per_frame,1,1); - if (gNB->frame_parms.nb_antennas_tx>1) - LOG_M("rxsig1.m","rxs1", UE->common_vars.rxdata[1],frame_parms->samples_per_frame,1,1); + LOG_M("rxsig0.m", "rxs0", UE->common_vars.rxdata[0], frame_parms->samples_per_frame, 1, 1); + if (gNB->frame_parms.nb_antennas_tx > 1) + LOG_M("rxsig1.m", "rxs1", UE->common_vars.rxdata[1], frame_parms->samples_per_frame, 1, 1); } if (UE->is_synchronized == 0) { - UE_nr_rxtx_proc_t proc={0}; - nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0); + UE_nr_rxtx_proc_t proc = {0}; + nr_gscn_info_t gscnInfo[MAX_GSCN_BAND] = {0}; + const int numGscn = 1; + gscnInfo[0].ssbFirstSC = frame_parms->ssb_start_subcarrier; + nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0, gscnInfo, numGscn); printf("nr_initial_sync1 returns %s\n", ret.cell_detected ? "cell detected" : "cell not detected"); if (!ret.cell_detected) n_errors++; @@ -788,8 +793,9 @@ int main(int argc, char **argv) for (int i = UE->symbol_offset + 1; i < UE->symbol_offset + 4; i++) { nr_slot_fep(UE, frame_parms, &proc, i % frame_parms->symbols_per_slot, rxdataF, link_type_dl); - nr_pbch_channel_estimation(UE, - &UE->frame_parms, + nr_pbch_channel_estimation(&UE->frame_parms, + &UE->SL_UE_PHY_PARAMS, + UE->nr_gold_pbch, estimateSz, dl_ch_estimates, dl_ch_estimates_time, @@ -798,12 +804,15 @@ int main(int argc, char **argv) i - (UE->symbol_offset + 1), ssb_index % 8, n_hf, + frame_parms->ssb_start_subcarrier, rxdataF, false, frame_parms->Nid_cell); } fapiPbch_t result; - ret = nr_rx_pbch(UE, &proc, estimateSz, dl_ch_estimates, frame_parms, ssb_index % 8, &result, rxdataF); + int ret_ssb_idx; + int ret_symbol_offset; + ret = nr_rx_pbch(UE, &proc, true, estimateSz, dl_ch_estimates, frame_parms, ssb_index % 8, frame_parms->ssb_start_subcarrier, Nid_cell, &result, &n_hf, &ret_ssb_idx, &ret_symbol_offset, rxdataF); if (ret == 0) { // UE->rx_ind.rx_indication_body->mib_pdu.ssb_index; //not yet detected automatically diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c index 560d78ca85..e880ef9c79 100644 --- a/openair2/GNB_APP/gnb_config.c +++ b/openair2/GNB_APP/gnb_config.c @@ -97,71 +97,6 @@ extern uint16_t sf_ahead; -// synchronization raster per band tables (Rel.15) -// (38.101-1 Table 5.4.3.3-1 and 38.101-2 Table 5.4.3.3-1) -// band nb, sub-carrier spacing index, Range of gscn (First, Step size, Last) -const sync_raster_t sync_raster[] = { - {1, 0, 5279, 1, 5419}, - {2, 0, 4829, 1, 4969}, - {3, 0, 4517, 1, 4693}, - {5, 0, 2177, 1, 2230}, - {5, 1, 2183, 1, 2224}, - {7, 0, 6554, 1, 6718}, - {8, 0, 2318, 1, 2395}, - {12, 0, 1828, 1, 1858}, - {13, 0, 1871, 1, 1885}, - {14, 0, 1901, 1, 1915}, - {18, 0, 2156, 1, 2182}, - {20, 0, 1982, 1, 2047}, - {24, 0, 3818, 1, 3892}, - {24, 1, 3824, 1, 3886}, - {25, 0, 4829, 1, 4981}, - {26, 0, 2153, 1, 2230}, - {28, 0, 1901, 1, 2002}, - {29, 0, 1798, 1, 1813}, - {30, 0, 5879, 1, 5893}, - {34, 0, 5030, 1, 5056}, - {34, 1, 5036, 1, 5050}, - {38, 0, 6431, 1, 6544}, - {38, 1, 6437, 1, 6538}, - {39, 0, 4706, 1, 4795}, - {39, 1, 4712, 1, 4789}, - {40, 1, 5762, 1, 5989}, - {41, 0, 6246, 3, 6717}, - {41, 1, 6252, 3, 6714}, - {48, 1, 7884, 1, 7982}, - {50, 0, 3584, 1, 3787}, - {51, 0, 3572, 1, 3574}, - {53, 0, 6215, 1, 6232}, - {53, 1, 6221, 1, 6226}, - {65, 0, 5279, 1, 5494}, - {66, 0, 5279, 1, 5494}, - {66, 1, 5285, 1, 5488}, - {67, 0, 1850, 1, 1888}, - {70, 0, 4993, 1, 5044}, - {71, 0, 1547, 1, 1624}, - {74, 0, 3692, 1, 3790}, - {75, 0, 3584, 1, 3787}, - {76, 0, 3572, 1, 3574}, - {77, 1, 7711, 1, 8329}, - {78, 1, 7711, 1, 8051}, - {79, 1, 8480, 16, 8880}, - {85, 0, 1826, 1, 1858}, - {90, 1, 6252, 1, 6714}, - {91, 0, 3572, 1, 3574}, - {92, 0, 3584, 1, 3787}, - {93, 0, 3572, 1, 3574}, - {94, 0, 3584, 1, 3587}, - {257, 3, 22388, 1, 22558}, - {257, 4, 22390, 2, 22556}, - {258, 3, 22257, 1, 22443}, - {258, 4, 22258, 2, 22442}, - {260, 3, 22995, 1, 23166}, - {260, 4, 22996, 2, 23164}, - {261, 3, 22446, 1, 22492}, - {261, 4, 22446, 2, 22490}, -}; - extern int config_check_band_frequencies(int ind, int16_t band, uint64_t downlink_frequency, int32_t uplink_frequency_offset, uint32_t frame_type); @@ -960,8 +895,6 @@ void RCconfig_NR_L1(void) } } -static void check_ssb_raster(uint64_t freq, int band, int scs); - static NR_ServingCellConfigCommon_t *get_scc_config(configmodule_interface_t *cfg, int minRXTXTIME) { NR_ServingCellConfigCommon_t *scc = calloc(1,sizeof(*scc)); @@ -1536,56 +1469,6 @@ void config_security(gNB_RRC_INST *rrc) } } -// Section 5.4.3 of 38.101-1 and -2 -static void check_ssb_raster(uint64_t freq, int band, int scs) -{ - int start_gscn = 0, step_gscn = 0, end_gscn = 0; - for (int i = 0; i < sizeof(sync_raster) / sizeof(sync_raster_t); i++) { - if (sync_raster[i].band == band && - sync_raster[i].scs_index == scs) { - start_gscn = sync_raster[i].first_gscn; - step_gscn = sync_raster[i].step_gscn; - end_gscn = sync_raster[i].last_gscn; - break; - } - } - AssertFatal(start_gscn != 0, "Couldn't find band %d with SCS %d\n", band, scs); - int gscn; - if (freq < 3000000000) { - int N = 0; - int M = 0; - for (int k = 0; k < 3; k++) { - M = (k << 1) + 1; - if ((freq - M * 50000) % 1200000 == 0) { - N = (freq - M * 50000) / 1200000; - break; - } - } - AssertFatal(N != 0, "SSB frequency %lu Hz not on the synchronization raster (N * 1200kHz + M * 50 kHz)\n", - freq); - gscn = (3 * N) + (M - 3) / 2; - } - else if (freq < 24250000000) { - AssertFatal((freq - 3000000000) % 1440000 == 0, - "SSB frequency %lu Hz not on the synchronization raster (3000 MHz + N * 1.44 MHz)\n", - freq); - gscn = ((freq - 3000000000) / 1440000) + 7499; - } - else { - AssertFatal((freq - 24250080000) % 17280000 == 0, - "SSB frequency %lu Hz not on the synchronization raster (24250.08 MHz + N * 17.28 MHz)\n", - freq); - gscn = ((freq - 24250080000) / 17280000) + 22256; - } - AssertFatal(gscn >= start_gscn && gscn <= end_gscn, - "GSCN %d corresponding to SSB frequency %lu does not belong to GSCN range for band %d\n", - gscn, freq, band); - int rel_gscn = gscn - start_gscn; - AssertFatal(rel_gscn % step_gscn == 0, - "GSCN %d corresponding to SSB frequency %lu not in accordance with GSCN step for band %d\n", - gscn, freq, band); -} - void RCconfig_NRRRC(gNB_RRC_INST *rrc) { diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c index 16f35f6c92..e599ec5608 100644 --- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c +++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c @@ -1038,6 +1038,7 @@ static int handle_bcch_bch(NR_UE_MAC_INST_t *mac, mac->mib_ssb = ssb_index; mac->physCellId = cell_id; mac->mib_additional_bits = additional_bits; + mac->ssb_start_subcarrier = ssb_start_subcarrier; if(ssb_length == 64) mac->frequency_range = FR2; else