nr,gnb: account for CORESET#0 RB offset (See 38.213, table 13-1) in computation of SSB center frequency

master
Francisco 3 years ago committed by Andre Puschmann
parent e68bdf3718
commit 92c4e6e2d0

@ -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

@ -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

@ -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);

@ -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;

@ -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 -

Loading…
Cancel
Save