/** * * \section COPYRIGHT * * Copyright 2013-2021 Software Radio Systems Limited * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the distribution. * */ #include "srsran/common/band_helper.h" #include #include namespace srsran { // definition of static members constexpr std::array srsran_band_helper::nr_band_table_fr1; constexpr std::array srsran_band_helper::nr_fr_params; constexpr std::array srsran_band_helper::nr_operating_bands_fr1; constexpr std::array srsran_band_helper::nr_band_ss_raster_table; // Formula in 5.4.2.1 double srsran_band_helper::nr_arfcn_to_freq(uint32_t nr_arfcn) { nr_raster_params params = get_raster_params(nr_arfcn); return (params.F_REF_Offs_MHz * 1e6 + params.delta_F_global_kHz * (nr_arfcn - params.N_REF_Offs) * 1e3); } // Implements 5.4.2.1 in TS 38.401 std::vector srsran_band_helper::get_bands_nr(uint32_t nr_arfcn, srsran_band_helper::delta_f_raster_t delta_f_raster) { std::vector bands; for (const auto& nr_band : nr_band_table_fr1) { if (nr_arfcn >= nr_band.dl_nref_first && nr_arfcn <= nr_band.dl_nref_last && nr_arfcn % nr_band.dl_nref_step == 0) { // band must not already be present if (std::find(bands.begin(), bands.end(), nr_band.band) == bands.end()) { if (delta_f_raster == DEFAULT) { // add band if delta_f_raster has default value bands.push_back(nr_band.band); } else { // if delta_f_raster is set explicitly, only add if band matches if (nr_band.delta_f_raster == delta_f_raster) { bands.push_back(nr_band.band); } } } } } return bands; } uint16_t srsran_band_helper::get_band_from_dl_freq_Hz(double freq) const { uint32_t freq_MHz = (uint32_t)round(freq / 1e6); for (const nr_operating_band& band : nr_operating_bands_fr1) { if (freq_MHz >= band.F_DL_low and freq_MHz <= band.F_DL_high) { return band.band; } } return UINT16_MAX; } uint16_t srsran_band_helper::get_band_from_dl_arfcn(uint32_t arfcn) const { for (const nr_band& band : nr_band_table_fr1) { // Check given ARFCN is between the first and last possible ARFCN and matches step if (arfcn >= band.dl_nref_first and arfcn <= band.dl_nref_last and (arfcn - band.dl_nref_first) % band.dl_nref_step == 0) { return band.band; } } return UINT16_MAX; } 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 for (const nr_band_ss_raster& ss_raster : nr_band_ss_raster_table) { // Check if band and SCS match! if (ss_raster.band == band && ss_raster.scs == scs) { return ss_raster.pattern; } // As bands are in ascending order, do not waste more time if the current band is bigger if (ss_raster.band > band) { return SRSRAN_SSB_PATTERN_INVALID; } } // Band is out of range, so consider invalid return SRSRAN_SSB_PATTERN_INVALID; } srsran_duplex_mode_t srsran_band_helper::get_duplex_mode(uint16_t band) const { // Look for the given band for (const nr_operating_band& b : nr_operating_bands_fr1) { // Check if band and SCS match! if (b.band == band) { return b.duplex_mode; } // As bands are in ascending order, do not waste more time if the current band is bigger if (b.band > band) { return SRSRAN_DUPLEX_MODE_INVALID; } } // Band is out of range, so consider invalid return SRSRAN_DUPLEX_MODE_INVALID; } struct sync_raster_impl : public srsran_band_helper::sync_raster_t { public: sync_raster_impl(uint32_t f, uint32_t s, uint32_t l) : sync_raster_t(f, s, l) { // Do nothing } }; double srsran_band_helper::sync_raster_t::get_frequency() const { // Row 1 if (gscn >= 2 and gscn <= 7498) { double N = std::ceil((gscn - 1) / 3.0); double M = (gscn - 3 * N) / 2.0 + 3.0; return N * 1200e3 + M * 50e3; } // Row 2 if (gscn >= 7499 and gscn <= 22255) { double N = gscn - 7499; return 3000e6 + N * 1.44e6; } // Row 3 if (gscn >= 22256 and gscn <= 26639) { double N = gscn - 22256; return 2425.08e6 + N * 17.28e6; } // Unhandled case return NAN; } srsran_band_helper::sync_raster_t srsran_band_helper::get_sync_raster(uint16_t band, srsran_subcarrier_spacing_t scs) const { // Look for the given band and SCS for (const nr_band_ss_raster& ss_raster : nr_band_ss_raster_table) { // Check if band and SCS match! if (ss_raster.band == band && ss_raster.scs == scs) { return sync_raster_impl(ss_raster.gscn_first, ss_raster.gscn_step, ss_raster.gscn_last); } // As bands are in ascending order, do not waste more time if the current band is bigger if (ss_raster.band > band) { return sync_raster_impl(0, 0, 0); } } // Band is out of range, so consider invalid return sync_raster_impl(0, 0, 0); } srsran_band_helper::nr_raster_params srsran_band_helper::get_raster_params(uint32_t nr_arfcn) { for (auto& fr : nr_fr_params) { if (nr_arfcn >= fr.N_REF_min && nr_arfcn <= fr.N_REF_max) { return fr; } } return {}; // return empty params } } // namespace srsran