diff --git a/lib/include/srsran/common/band_helper.h b/lib/include/srsran/common/band_helper.h index 4712ff13d..e59eeaff1 100644 --- a/lib/include/srsran/common/band_helper.h +++ b/lib/include/srsran/common/band_helper.h @@ -126,14 +126,29 @@ public: /** * @brief Compute the absolute frequency of the SSB for a DL ARFCN and a band. This selects an SSB center frequency + * following the band SS/PBCH frequency raster provided by TS38.104 table 5.4.3.1-1, which is the upper bound + * of the provided center frequency + * + * @param scs ssb subcarrier spacing. + * @param min_center_freq_hz center frequency above which the SSB absolute frequency must be. + * @return absolute frequency of the SSB in arfcn notation. + */ + uint32_t find_lower_bound_abs_freq_ssb(uint16_t band, srsran_subcarrier_spacing_t scs, uint32_t min_center_freq_hz); + + /** + * @brief Compute the absolute frequency of the SSB for a DL ARFCN and a band. This finds an SSB center frequency * following the band SS/PBCH frequency raster provided by TS38.104 table 5.4.3.1-1 as close as possible to PointA - * without letting any SS/PBCH subcarrier below PointA + * without letting any SS/PBCH subcarrier and CORESET#0 subcarrier (if RB offset is defined) below PointA * * @param scs ssb subcarrier spacing. * @param freq_point_a_arfcn frequency point a in arfcn notation. + * @param coreset0_offset_rb CORESET#0 RB offset. See TS 38.213, Table 13-1,2,3 * @return absolute frequency of the SSB in arfcn notation. */ - uint32_t get_abs_freq_ssb_arfcn(uint16_t band, srsran_subcarrier_spacing_t scs, uint32_t freq_point_a_arfcn); + uint32_t get_abs_freq_ssb_arfcn(uint16_t band, + srsran_subcarrier_spacing_t scs, + uint32_t freq_point_a_arfcn, + uint32_t coreset0_offset_rb = 0); /** * @brief Compute SSB center frequency for NR carrier diff --git a/lib/src/common/band_helper.cc b/lib/src/common/band_helper.cc index e4dd86756..5513837a0 100644 --- a/lib/src/common/band_helper.cc +++ b/lib/src/common/band_helper.cc @@ -133,23 +133,20 @@ double srsran_band_helper::get_abs_freq_point_a_from_center_freq(uint32_t nof_pr SRSRAN_NRE); } -uint32_t -srsran_band_helper::get_abs_freq_ssb_arfcn(uint16_t band, srsran_subcarrier_spacing_t scs, uint32_t freq_point_a_arfcn) +uint32_t srsran_band_helper::find_lower_bound_abs_freq_ssb(uint16_t band, + srsran_subcarrier_spacing_t scs, + uint32_t min_center_freq_hz) { sync_raster_t sync_raster = get_sync_raster(band, scs); if (!sync_raster.valid()) { return 0; } - // double abs_freq_ssb_hz = sync_raster.get_frequency(); - double freq_point_a_hz = nr_arfcn_to_freq(freq_point_a_arfcn); - double ssb_bw_hz = SRSRAN_SSB_BW_SUBC * SRSRAN_SUBC_SPACING_NR(scs); - while (!sync_raster.end()) { double abs_freq_ssb_hz = sync_raster.get_frequency(); - if ((abs_freq_ssb_hz > (freq_point_a_hz + ssb_bw_hz / 2)) and - ((uint32_t)std::round(abs_freq_ssb_hz - freq_point_a_hz) % SRSRAN_SUBC_SPACING_NR(scs) == 0)) { + if ((abs_freq_ssb_hz > min_center_freq_hz) and + ((uint32_t)std::round(abs_freq_ssb_hz - min_center_freq_hz) % SRSRAN_SUBC_SPACING_NR(scs) == 0)) { return freq_to_nr_arfcn(abs_freq_ssb_hz); } @@ -158,6 +155,17 @@ srsran_band_helper::get_abs_freq_ssb_arfcn(uint16_t band, srsran_subcarrier_spac return 0; } +uint32_t srsran_band_helper::get_abs_freq_ssb_arfcn(uint16_t band, + srsran_subcarrier_spacing_t scs, + uint32_t freq_point_a_arfcn, + uint32_t coreset0_offset_rb) +{ + double freq_point_a_hz = nr_arfcn_to_freq(freq_point_a_arfcn); + double ssb_bw_hz = SRSRAN_SSB_BW_SUBC * SRSRAN_SUBC_SPACING_NR(scs); + double coreset0_offset_hz = coreset0_offset_rb * SRSRAN_NRE * SRSRAN_SUBC_SPACING_NR(scs); + return find_lower_bound_abs_freq_ssb(band, scs, freq_point_a_hz + coreset0_offset_hz / 2 + ssb_bw_hz / 2); +} + srsran_ssb_patern_t srsran_band_helper::get_ssb_pattern(uint16_t band, srsran_subcarrier_spacing_t scs) const { // Look for the given band and SCS diff --git a/lib/src/common/test/band_helper_test.cc b/lib/src/common/test/band_helper_test.cc index 2ef31ced7..1ade62532 100644 --- a/lib/src/common/test/band_helper_test.cc +++ b/lib/src/common/test/band_helper_test.cc @@ -47,9 +47,11 @@ int bands_test_nr() TESTASSERT(bands.nr_arfcn_to_freq(342000) == 1710.0e6); TESTASSERT(bands.nr_arfcn_to_freq(348000) == 1740.0e6); TESTASSERT(bands.nr_arfcn_to_freq(361000) == 1805.0e6); + TESTASSERT_EQ(1842.5e6, bands.nr_arfcn_to_freq(368500)); TESTASSERT(bands.nr_arfcn_to_freq(376000) == 1880.0e6); TESTASSERT(bands.get_abs_freq_point_a_arfcn(52, 368500) == 367564); TESTASSERT(bands.get_abs_freq_ssb_arfcn(3, srsran_subcarrier_spacing_15kHz, 367564) > 367924); + TESTASSERT_EQ(368410, bands.get_abs_freq_ssb_arfcn(3, srsran_subcarrier_spacing_15kHz, 367564, 16)); // n5 TESTASSERT(bands.get_duplex_mode(5) == SRSRAN_DUPLEX_MODE_FDD); TESTASSERT(bands.nr_arfcn_to_freq(176300) == 881.5e6); diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 68f847d79..9be7d392f 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1161,6 +1161,21 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr return SRSRAN_ERROR; } + // update number of NR cells + rrc_cfg_->num_nr_cells = rrc_nr_cfg_->cell_list.size(); + args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_nr_cfg_->cell_list.size(); + ASSERT_VALID_CFG(args_->rf.nof_carriers > 0, "There must be at least one NR or LTE cell"); + if (rrc_nr_cfg_->cell_list.size() > 0) { + // NR cells available. + if (rrc_cfg_->cell_list.size() == 0) { + // SA mode. + rrc_nr_cfg_->is_standalone = true; + } else { + // NSA mode. + rrc_nr_cfg_->is_standalone = false; + } + } + // Set fields derived from others, and check for correctness of the parsed configuration if (enb_conf_sections::set_derived_args(args_, rrc_cfg_, phy_cfg_, cell_common_cfg) != SRSRAN_SUCCESS) { fprintf(stderr, "Error deriving EUTRA cell parameters\n"); @@ -1174,20 +1189,15 @@ int parse_cfg_files(all_args_t* args_, rrc_cfg_t* rrc_cfg_, rrc_nr_cfg_t* rrc_nr } // update number of NR cells - rrc_cfg_->num_nr_cells = rrc_nr_cfg_->cell_list.size(); - args_->rf.nof_carriers = rrc_cfg_->cell_list.size() + rrc_nr_cfg_->cell_list.size(); - ASSERT_VALID_CFG(args_->rf.nof_carriers > 0, "There must be at least one NR or LTE cell"); if (rrc_nr_cfg_->cell_list.size() > 0) { // NR cells available. - if (rrc_cfg_->cell_list.size() == 0) { + if (rrc_nr_cfg_->is_standalone) { // SA mode. Update NGAP args - rrc_nr_cfg_->is_standalone = true; args_->nr_stack.ngap.gnb_id = args_->enb.enb_id; args_->nr_stack.ngap.cell_id = rrc_nr_cfg_->cell_list[0].phy_cell.cell_id; args_->nr_stack.ngap.tac = rrc_nr_cfg_->cell_list[0].tac; } else { // NSA mode. - rrc_nr_cfg_->is_standalone = false; // update EUTRA RRC params for ENDC rrc_cfg_->endc_cfg.abs_frequency_ssb = rrc_nr_cfg_->cell_list.at(0).ssb_absolute_freq_point; rrc_cfg_->endc_cfg.nr_band = rrc_nr_cfg_->cell_list.at(0).band; @@ -1633,8 +1643,19 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_nr_cfg_, phy_cfg_t* } // fill remaining SSB fields + uint32_t coreset0_rb_offset = 0; + if (rrc_nr_cfg_->is_standalone) { + // Taken from TS 38.213, Table 13-1 + if (cfg.phy_cell.carrier.nof_prb > 96) { + coreset0_rb_offset = 96; + } else if (cfg.phy_cell.carrier.nof_prb > 48) { + coreset0_rb_offset = 16; + } else { + coreset0_rb_offset = 4; + } + } cfg.ssb_absolute_freq_point = - band_helper.get_abs_freq_ssb_arfcn(cfg.band, cfg.ssb_cfg.scs, cfg.dl_absolute_freq_point_a); + band_helper.get_abs_freq_ssb_arfcn(cfg.band, cfg.ssb_cfg.scs, cfg.dl_absolute_freq_point_a, coreset0_rb_offset); if (cfg.ssb_absolute_freq_point == 0) { ERROR("Can't derive SSB freq point for dl_arfcn %d and band %d", cfg.dl_arfcn, cfg.band); return SRSRAN_ERROR; diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index b7430d63c..7c11d055e 100644 --- a/srsgnb/src/stack/rrc/rrc_nr.cc +++ b/srsgnb/src/stack/rrc/rrc_nr.cc @@ -51,7 +51,7 @@ int rrc_nr::init(const rrc_nr_cfg_t& cfg_, cfg = cfg_; if (cfg.is_standalone) { // Generate parameters of Coreset#0 and SS#0 - const uint32_t coreset0_idx = 7; + const uint32_t coreset0_idx = 6; cfg.cell_list[0].phy_cell.pdcch.coreset_present[0] = true; // Get pointA and SSB absolute frequencies double pointA_abs_freq_Hz = cfg.cell_list[0].phy_cell.carrier.dl_center_frequency_hz -