diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index c8612c317..8e6c6cea8 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -704,6 +704,16 @@ SRSRAN_API int srsran_coreset_zero(uint32_t n_cell_id, uint32_t idx, srsran_coreset_t* coreset); +/** + * @brief Obtain offset in RBs between CoresetZero and SSB. See TS 38.213, Tables 13-{1,...,10} + * @param idx Index of 13-{1,...10} table + * @param ssb_scs SS/PBCH block subcarrier spacing + * @param pdcch_scs PDCCH subcarrier spacing + * @return offset in RBs, or -1 in case of invalid inputs + */ +SRSRAN_API int +srsran_coreset0_ssb_offset(uint32_t idx, srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs); + /** * @brief Convert SSB pattern to string * @param pattern diff --git a/lib/src/common/band_helper.cc b/lib/src/common/band_helper.cc index 5513837a0..5eee021a8 100644 --- a/lib/src/common/band_helper.cc +++ b/lib/src/common/band_helper.cc @@ -163,7 +163,7 @@ uint32_t srsran_band_helper::get_abs_freq_ssb_arfcn(uint16_t 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); + return find_lower_bound_abs_freq_ssb(band, scs, freq_point_a_hz + coreset0_offset_hz + ssb_bw_hz / 2); } srsran_ssb_patern_t srsran_band_helper::get_ssb_pattern(uint16_t band, srsran_subcarrier_spacing_t scs) const diff --git a/lib/src/common/test/band_helper_test.cc b/lib/src/common/test/band_helper_test.cc index 1ade62532..4e5b86c00 100644 --- a/lib/src/common/test/band_helper_test.cc +++ b/lib/src/common/test/band_helper_test.cc @@ -51,7 +51,7 @@ int bands_test_nr() 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)); + TESTASSERT_EQ(368410, bands.get_abs_freq_ssb_arfcn(3, srsran_subcarrier_spacing_15kHz, 367564, 12)); // n5 TESTASSERT(bands.get_duplex_mode(5) == SRSRAN_DUPLEX_MODE_FDD); TESTASSERT(bands.nr_arfcn_to_freq(176300) == 881.5e6); diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index b3b2e3360..acb3f7fdf 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -682,6 +682,48 @@ int srsran_coreset_zero(uint32_t n_cell_id, return SRSRAN_SUCCESS; } +int srsran_coreset0_ssb_offset(uint32_t idx, srsran_subcarrier_spacing_t ssb_scs, srsran_subcarrier_spacing_t pdcch_scs) +{ + // Verify inputs + if (idx >= 16) { + ERROR("Invalid CORESET Zero input. idx=%d", idx); + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Default entry to NULL + const coreset_zero_entry_t* entry = NULL; + + // Table 13-1: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {15, 15} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_15kHz && pdcch_scs == srsran_subcarrier_spacing_15kHz) { + entry = &coreset_zero_15_15[idx]; + } + // Table 13-2: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {15, 30} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_15kHz && pdcch_scs == srsran_subcarrier_spacing_30kHz) { + entry = &coreset_zero_15_30[idx]; + } + + // Table 13-3: Set of resource blocks and slot symbols of CORESET for Type0-PDCCH search space set + // when {SS/PBCH block, PDCCH} SCS is {30, 15} kHz for frequency bands with minimum channel + // bandwidth 5 MHz or 10 MHz + if (ssb_scs == srsran_subcarrier_spacing_30kHz && pdcch_scs == srsran_subcarrier_spacing_15kHz) { + entry = &coreset_zero_30_15[idx]; + } + + // Check a valid entry has been selected + if (entry == NULL) { + ERROR("Unhandled case ssb_scs=%s, pdcch_scs=%s", + srsran_subcarrier_spacing_to_str(ssb_scs), + srsran_subcarrier_spacing_to_str(pdcch_scs)); + return SRSRAN_ERROR; + } + + return entry->offset_rb; +} + const char* srsran_ssb_pattern_to_str(srsran_ssb_patern_t pattern) { switch (pattern) { diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 9be7d392f..d30357f2b 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1643,23 +1643,20 @@ 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; + int 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; - } + const uint32_t coreset0_idx = 6; // See TS 38.331 - controlResourceSetZero / Table 13-1 index + cfg.phy_cell.pdcch.coreset_present[0] = true; + // Get offset in RBs between CORESET#0 and SSB + coreset0_rb_offset = srsran_coreset0_ssb_offset(coreset0_idx, cfg.ssb_cfg.scs, cfg.phy_cell.carrier.scs); + srsran_assert(coreset0_rb_offset >= 0, "Failed to compute RB offset between CORESET#0 and SSB"); } cfg.ssb_absolute_freq_point = 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; - } + srsran_assert(cfg.ssb_absolute_freq_point > 0, + "Can't derive SSB freq point for dl_arfcn %d and band %d", + cfg.dl_arfcn, + cfg.band); // Convert to frequency for PHY cfg.phy_cell.carrier.ssb_center_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ssb_absolute_freq_point); diff --git a/srsgnb/src/stack/rrc/rrc_nr.cc b/srsgnb/src/stack/rrc/rrc_nr.cc index 7c11d055e..f26fa7b2c 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 = 6; + const uint32_t coreset0_idx = 6; // See TS 38.331 - controlResourceSetZero 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 -