diff --git a/lib/include/srsran/common/band_helper.h b/lib/include/srsran/common/band_helper.h index e24ee0f3a..41425b5f8 100644 --- a/lib/include/srsran/common/band_helper.h +++ b/lib/include/srsran/common/band_helper.h @@ -268,22 +268,22 @@ private: {1, KHZ_100, 384000, 20, 396000, 422000, 20, 434000}, {2, KHZ_100, 370000, 20, 382000, 386000, 20, 398000}, {3, KHZ_100, 342000, 20, 357000, 361000, 20, 376000}, - + {5, KHZ_100, 164800, 20, 169800, 173800, 20, 178800}, {7, KHZ_100, 500000, 20, 514000, 524000, 20, 538000}, {8, KHZ_100, 176000, 20, 183000, 185000, 20, 192000}, - + {12, KHZ_100, 139800, 20, 143200, 145800, 20, 149200}, - + {20, KHZ_100, 166400, 20, 172400, 158200, 20, 164200}, {25, KHZ_100, 370000, 20, 383000, 386000, 20, 399000}, {28, KHZ_100, 140600, 20, 149600, 151600, 20, 160600}, - + {34, KHZ_100, 402000, 20, 405000, 402000, 20, 405000}, {38, KHZ_100, 514000, 20, 524000, 514000, 20, 524000}, {39, KHZ_100, 376000, 20, 384000, 376000, 20, 384000}, - + {40, KHZ_100, 460000, 20, 480000, 460000, 20, 480000}, {41, KHZ_15, 499200, 3, 537999, 499200, 3, 537999}, @@ -291,13 +291,13 @@ private: {50, KHZ_100, 286400, 20, 303400, 286400, 20, 303400}, {51, KHZ_100, 285400, 20, 286400, 285400, 20, 286400}, - + {66, KHZ_100, 342000, 20, 356000, 422000, 20, 440000}, - + {70, KHZ_100, 339000, 20, 342000, 399000, 20, 404000}, {71, KHZ_100, 132600, 20, 139600, 123400, 20, 130400}, {74, KHZ_100, 285400, 20, 294000, 295000, 20, 303600}, - + {75, KHZ_100, 0, 0, 0, 286400, 20, 303400}, {76, KHZ_100, 0, 0, 0, 285400, 20, 286400}, @@ -316,23 +316,22 @@ private: {83, KHZ_100, 140600, 20, 149600, 0, 0, 0}, {84, KHZ_100, 384000, 20, 396000, 0, 0, 0}, {86, KHZ_100, 342000, 20, 356000, 0, 0, 0} - // clang-format on + // clang-format on }}; static const uint32_t nof_nr_bands_fr2 = 8; - static constexpr std::array nr_band_table_fr2 = {{ - {257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165}, - {257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165}, - - {258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832}, - {258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832}, - - {260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165}, - {260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165}, - - {261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999}, - {261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999} - }}; + static constexpr std::array nr_band_table_fr2 = { + {{257, KHZ_60, 2054166, 1, 2104165, 2054166, 1, 2104165}, + {257, KHZ_120, 2054167, 2, 2104165, 2054167, 20, 2104165}, + + {258, KHZ_60, 2016667, 1, 2070832, 2016667, 1, 2070832}, + {258, KHZ_120, 2016667, 2, 2070831, 2016667, 2, 2070832}, + + {260, KHZ_60, 2229166, 1, 2279165, 2229166, 1, 2279165}, + {260, KHZ_120, 2229167, 2, 2279165, 2229167, 2, 2279165}, + + {261, KHZ_60, 2070833, 1, 2084999, 2070833, 1, 2084999}, + {261, KHZ_120, 2070833, 2, 2084999, 2070833, 2, 2084999}}}; // Elements of TS 38.101-1 Table 5.4.3.3-1 : Applicable SS raster entries per operating band struct nr_band_ss_raster { @@ -345,35 +344,35 @@ private: }; static const uint32_t nof_nr_band_ss_raster = 29; static constexpr std::array nr_band_ss_raster_table = {{ - {1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419}, - {2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969}, - {3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693}, - {5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230}, - {5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224}, - {7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718}, - {8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395}, - {12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858}, - {20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047}, - {25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981}, - {28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002}, - {34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056}, - {38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544}, - {39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795}, - {40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995}, - {41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717}, - {41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714}, - {50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, - {51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, - {66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494}, - {66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488}, - {70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044}, - {71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624}, - {74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790}, - {75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, - {76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, - {77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329}, - {78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051}, - {79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880}, + {1, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5419}, + {2, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4969}, + {3, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4517, 1, 4693}, + {5, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2177, 1, 2230}, + {5, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 2183, 1, 2224}, + {7, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6554, 1, 6718}, + {8, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 2318, 1, 2395}, + {12, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1828, 1, 1858}, + {20, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1982, 1, 2047}, + {25, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4829, 1, 4981}, + {28, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1901, 1, 2002}, + {34, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5030, 1, 5056}, + {38, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6431, 1, 6544}, + {39, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4706, 1, 4795}, + {40, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5756, 1, 5995}, + {41, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 6246, 3, 6717}, + {41, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 6252, 3, 6714}, + {50, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, + {51, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, + {66, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 5279, 1, 5494}, + {66, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_B, 5285, 1, 5488}, + {70, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 4993, 1, 5044}, + {71, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 1547, 1, 1624}, + {74, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3692, 1, 3790}, + {75, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3584, 1, 3787}, + {76, srsran_subcarrier_spacing_15kHz, SRSRAN_SSB_PATTERN_A, 3572, 1, 3574}, + {77, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8329}, + {78, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 7711, 1, 8051}, + {79, srsran_subcarrier_spacing_30kHz, SRSRAN_SSB_PATTERN_C, 8480, 16, 8880}, }}; }; diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index ec4d23f52..91efba3dd 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -161,6 +161,7 @@ public: srsran_carrier_nr_t carrier; srsran_pdcch_cfg_nr_t pdcch; srsran_prach_cfg_t prach; + srsran_ssb_cfg_t ssb; srsran_duplex_mode_t duplex_mode; }; diff --git a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h index 5b726baea..fba566f6c 100644 --- a/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_rrc_nr_interfaces.h @@ -43,6 +43,7 @@ struct rrc_cell_cfg_nr_t { uint32_t ssb_absolute_freq_point; // derived from DL ARFCN uint32_t band; srsran_duplex_mode_t duplex_mode; + srsran_ssb_cfg_t ssb_cfg; }; typedef std::vector rrc_cell_list_nr_t; diff --git a/lib/include/srsran/phy/gnb/gnb_dl.h b/lib/include/srsran/phy/gnb/gnb_dl.h index 909a42a03..f2707f7f2 100644 --- a/lib/include/srsran/phy/gnb/gnb_dl.h +++ b/lib/include/srsran/phy/gnb/gnb_dl.h @@ -19,15 +19,20 @@ #include "srsran/phy/phch/pdcch_cfg_nr.h" #include "srsran/phy/phch/pdcch_nr.h" #include "srsran/phy/phch/pdsch_nr.h" +#include "srsran/phy/sync/ssb.h" typedef struct SRSRAN_API { - srsran_pdsch_nr_args_t pdsch; - srsran_pdcch_nr_args_t pdcch; - uint32_t nof_tx_antennas; - uint32_t nof_max_prb; + srsran_pdsch_nr_args_t pdsch; + srsran_pdcch_nr_args_t pdcch; + uint32_t nof_tx_antennas; + uint32_t nof_max_prb; ///< Maximum number of allocated RB + double srate_hz; ///< Fix sampling rate, set to 0 for minimum to fit nof_max_prb + srsran_subcarrier_spacing_t scs; } srsran_gnb_dl_args_t; typedef struct SRSRAN_API { + float srate_hz; + uint32_t symbol_sz; uint32_t max_prb; uint32_t nof_tx_antennas; srsran_carrier_nr_t carrier; @@ -41,12 +46,15 @@ typedef struct SRSRAN_API { srsran_dci_nr_t dci; ///< Stores DCI configuration srsran_pdcch_nr_t pdcch; + srsran_ssb_t ssb; } srsran_gnb_dl_t; SRSRAN_API int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const srsran_gnb_dl_args_t* args); SRSRAN_API int srsran_gnb_dl_set_carrier(srsran_gnb_dl_t* q, const srsran_carrier_nr_t* carrier); +SRSRAN_API int srsran_gnb_dl_set_ssb_config(srsran_gnb_dl_t* q, const srsran_ssb_cfg_t* ssb); + SRSRAN_API int srsran_gnb_dl_set_pdcch_config(srsran_gnb_dl_t* q, const srsran_pdcch_cfg_nr_t* cfg, const srsran_dci_cfg_nr_t* dci_cfg); @@ -57,6 +65,8 @@ SRSRAN_API int srsran_gnb_dl_base_zero(srsran_gnb_dl_t* q); SRSRAN_API void srsran_gnb_dl_gen_signal(srsran_gnb_dl_t* q); +SRSRAN_API int srsran_gnb_dl_add_ssb(srsran_gnb_dl_t* q, const srsran_pbch_msg_nr_t* pbch_msg, uint32_t sf_idx); + SRSRAN_API int srsran_gnb_dl_pdcch_put_dl(srsran_gnb_dl_t* q, const srsran_slot_cfg_t* slot_cfg, const srsran_dci_dl_nr_t* dci_dl); diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 5cc362700..3155b69a2 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -426,7 +426,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) } carrier.ssb_center_freq_hz = carrier.dl_center_frequency_hz; ssb.position_in_burst[0] = true; - ssb.periodicity_ms = 5; + ssb.periodicity_ms = 10; switch (reference_cfg.pdcch) { case reference_cfg_t::R_PDCCH_CUSTOM_COMMON_SS: diff --git a/lib/src/phy/gnb/gnb_dl.c b/lib/src/phy/gnb/gnb_dl.c index 11b5a3ad3..0c025fc45 100644 --- a/lib/src/phy/gnb/gnb_dl.c +++ b/lib/src/phy/gnb/gnb_dl.c @@ -61,11 +61,23 @@ int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const return SRSRAN_ERROR; } + // Check symbol size is vlid + int symbol_sz = srsran_symbol_sz_from_srate(args->srate_hz, args->scs); + if (symbol_sz <= 0) { + ERROR("Error calculating symbol size from sampling rate of %.2f MHz and subcarrier spacing %s", + q->srate_hz / 1e6, + srsran_subcarrier_spacing_to_str(args->scs)); + return SRSRAN_ERROR; + } + q->symbol_sz = symbol_sz; + + // Create initial OFDM configuration srsran_ofdm_cfg_t fft_cfg = {}; fft_cfg.nof_prb = args->nof_max_prb; - fft_cfg.symbol_sz = srsran_min_symbol_sz_rb(args->nof_max_prb); + fft_cfg.symbol_sz = (uint32_t)symbol_sz; fft_cfg.keep_dc = true; + // Initialise a different OFDM modulator per channel for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { fft_cfg.in_buffer = q->sf_symbols[i]; fft_cfg.out_buffer = output[i]; @@ -82,6 +94,15 @@ int srsran_gnb_dl_init(srsran_gnb_dl_t* q, cf_t* output[SRSRAN_MAX_PORTS], const return SRSRAN_ERROR; } + srsran_ssb_args_t ssb_args = {}; + ssb_args.enable_encode = true; + ssb_args.max_srate_hz = args->srate_hz; + ssb_args.min_scs = args->scs; + if (srsran_ssb_init(&q->ssb, &ssb_args) < SRSRAN_SUCCESS) { + ERROR("Error SSB"); + return SRSRAN_ERROR; + } + return SRSRAN_SUCCESS; } @@ -103,6 +124,7 @@ void srsran_gnb_dl_free(srsran_gnb_dl_t* q) srsran_dmrs_sch_free(&q->dmrs); srsran_pdcch_nr_free(&q->pdcch); + srsran_ssb_free(&q->ssb); SRSRAN_MEM_ZERO(q, srsran_gnb_dl_t, 1); } @@ -141,6 +163,38 @@ int srsran_gnb_dl_set_carrier(srsran_gnb_dl_t* q, const srsran_carrier_nr_t* car return SRSRAN_SUCCESS; } +int srsran_gnb_dl_set_ssb_config(srsran_gnb_dl_t* q, const srsran_ssb_cfg_t* ssb) +{ + if (q == NULL || ssb == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + if (srsran_ssb_set_cfg(&q->ssb, ssb) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + +int srsran_gnb_dl_add_ssb(srsran_gnb_dl_t* q, const srsran_pbch_msg_nr_t* pbch_msg, uint32_t sf_idx) +{ + if (q == NULL || pbch_msg == NULL) { + return SRSRAN_ERROR_INVALID_INPUTS; + } + + // Skip SSB if it is not the time for it + if (!srsran_ssb_send(&q->ssb, sf_idx)) { + return SRSRAN_SUCCESS; + } + + if (srsran_ssb_add(&q->ssb, q->carrier.pci, pbch_msg, q->fft[0].cfg.out_buffer, q->fft[0].cfg.out_buffer) < + SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + return SRSRAN_SUCCESS; +} + int srsran_gnb_dl_set_pdcch_config(srsran_gnb_dl_t* q, const srsran_pdcch_cfg_nr_t* cfg, const srsran_dci_cfg_nr_t* dci_cfg) diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 20e3cb74a..40fff8944 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -252,6 +252,7 @@ int main(int argc, char** argv) gnb_dl_args.pdsch.sch.disable_simd = false; gnb_dl_args.pdcch.disable_simd = false; gnb_dl_args.nof_max_prb = carrier.nof_prb; + gnb_dl_args.srate_hz = SRSRAN_SUBC_SPACING_NR(carrier.scs) * srsran_min_symbol_sz_rb(carrier.nof_prb); srsran_pdcch_cfg_nr_t pdcch_cfg = {}; diff --git a/srsenb/hdr/phy/nr/slot_worker.h b/srsenb/hdr/phy/nr/slot_worker.h index ab90890e5..7222e553a 100644 --- a/srsenb/hdr/phy/nr/slot_worker.h +++ b/srsenb/hdr/phy/nr/slot_worker.h @@ -32,12 +32,14 @@ class slot_worker final : public srsran::thread_pool::worker { public: struct args_t { - uint32_t cell_index = 0; - uint32_t nof_max_prb = SRSRAN_MAX_PRB_NR; - uint32_t nof_tx_ports = 1; - uint32_t nof_rx_ports = 1; - uint32_t rf_port = 0; - uint32_t pusch_max_nof_iter = 10; + uint32_t cell_index = 0; + uint32_t nof_max_prb = SRSRAN_MAX_PRB_NR; + uint32_t nof_tx_ports = 1; + uint32_t nof_rx_ports = 1; + uint32_t rf_port = 0; + srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_15kHz; + uint32_t pusch_max_nof_iter = 10; + double srate_hz = 0.0; }; slot_worker(srsran::phy_common_interface& common_, stack_interface_phy_nr& stack_, srslog::basic_logger& logger); @@ -45,7 +47,9 @@ public: bool init(const args_t& args); - bool set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_); + bool set_common_cfg(const srsran_carrier_nr_t& carrier, + const srsran_pdcch_cfg_nr_t& pdcch_cfg_, + const srsran_ssb_cfg_t& ssb_cfg_); /* Functions used by main PHY thread */ cf_t* get_buffer_rx(uint32_t antenna_idx); diff --git a/srsenb/hdr/phy/nr/worker_pool.h b/srsenb/hdr/phy/nr/worker_pool.h index 4c816e577..2bcbe704e 100644 --- a/srsenb/hdr/phy/nr/worker_pool.h +++ b/srsenb/hdr/phy/nr/worker_pool.h @@ -83,14 +83,17 @@ private: srslog::basic_logger& logger; prach_stack_adaptor_t prach_stack_adaptor; uint32_t nof_prach_workers = 0; + double srate_hz = 0.0; ///< Current sampling rate in Hz // Current configuration std::mutex common_cfg_mutex; srsran_carrier_nr_t carrier = {}; srsran_pdcch_cfg_nr_t pdcch_cfg = {}; + srsran_ssb_cfg_t ssb_cfg = {}; public: struct args_t { + double srate_hz = 0.0; uint32_t nof_phy_threads = 3; uint32_t nof_prach_workers = 0; uint32_t prio = 52; diff --git a/srsenb/src/enb_cfg_parser.cc b/srsenb/src/enb_cfg_parser.cc index 9eec0f3ac..8e2e30d1f 100644 --- a/srsenb/src/enb_cfg_parser.cc +++ b/srsenb/src/enb_cfg_parser.cc @@ -1543,6 +1543,9 @@ int set_derived_args_nr(all_args_t* args_, rrc_nr_cfg_t* rrc_cfg_, phy_cfg_t* ph // Convert to frequency for PHY cfg.phy_cell.carrier.ssb_center_freq_hz = band_helper.nr_arfcn_to_freq(cfg.ssb_absolute_freq_point); + // TODO: set SSB config + cfg.ssb_cfg = {}; + phy_cfg_->phy_cell_cfg_nr.push_back(cfg.phy_cell); } diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index cf49708f2..a75e010aa 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -29,7 +29,7 @@ bool slot_worker::init(const args_t& args) std::lock_guard lock(mutex); // Calculate subframe length - sf_len = SRSRAN_SF_LEN_PRB_NR(args.nof_max_prb); + sf_len = (uint32_t)(args.srate_hz / 1000.0); // Copy common configurations cell_index = args.cell_index; @@ -62,6 +62,7 @@ bool slot_worker::init(const args_t& args) dl_args.pdsch.max_prb = args.nof_max_prb; dl_args.nof_tx_antennas = args.nof_tx_ports; dl_args.nof_max_prb = args.nof_max_prb; + dl_args.srate_hz = args.srate_hz; // Initialise DL if (srsran_gnb_dl_init(&gnb_dl, tx_buffer.data(), &dl_args) < SRSRAN_SUCCESS) { @@ -342,7 +343,10 @@ bool slot_worker::work_dl() // Add SSB to the baseband signal for (const stack_interface_phy_nr::ssb_t& ssb : dl_sched.ssb) { - // ... + if (srsran_gnb_dl_add_ssb(&gnb_dl, &ssb.pbch_msg, dl_slot_cfg.idx) < SRSRAN_SUCCESS) { + logger.error("SSB: Error putting signal"); + return false; + } } return true; @@ -375,7 +379,9 @@ void slot_worker::work_imp() common.worker_end(context, true, tx_rf_buffer); } -bool slot_worker::set_common_cfg(const srsran_carrier_nr_t& carrier, const srsran_pdcch_cfg_nr_t& pdcch_cfg_) +bool slot_worker::set_common_cfg(const srsran_carrier_nr_t& carrier, + const srsran_pdcch_cfg_nr_t& pdcch_cfg_, + const srsran_ssb_cfg_t& ssb_cfg_) { // Set gNb DL carrier if (srsran_gnb_dl_set_carrier(&gnb_dl, &carrier) < SRSRAN_SUCCESS) { @@ -383,6 +389,12 @@ bool slot_worker::set_common_cfg(const srsran_carrier_nr_t& carrier, const srsra return false; } + // Configure SSB + if (srsran_gnb_dl_set_ssb_config(&gnb_dl, &ssb_cfg_) < SRSRAN_SUCCESS) { + logger.error("Error setting SSB"); + return false; + } + // Set gNb UL carrier if (srsran_gnb_ul_set_carrier(&gnb_ul, &carrier) < SRSRAN_SUCCESS) { logger.error("Error setting UL carrier (pci=%d, nof_prb=%d, max_mimo_layers=%d)", diff --git a/srsenb/src/phy/nr/worker_pool.cc b/srsenb/src/phy/nr/worker_pool.cc index ebe9237ad..fde8aa6a6 100644 --- a/srsenb/src/phy/nr/worker_pool.cc +++ b/srsenb/src/phy/nr/worker_pool.cc @@ -10,6 +10,7 @@ * */ #include "srsenb/hdr/phy/nr/worker_pool.h" +#include "srsran/common/band_helper.h" namespace srsenb { namespace nr { @@ -32,6 +33,13 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li { nof_prach_workers = args.nof_prach_workers; + // Calculate sampling rate in Hz + if (not std::isnormal(args.srate_hz)) { + srate_hz = SRSRAN_SUBC_SPACING_NR(cell_list[0].carrier.scs) * srsran_min_symbol_sz_rb(cell_list[0].carrier.nof_prb); + } else { + srate_hz = args.srate_hz; + } + // Configure logger srslog::basic_levels log_level = srslog::str_to_basic_level(args.log.phy_level); logger.set_level(log_level); @@ -53,6 +61,7 @@ bool worker_pool::init(const args_t& args, const phy_cell_cfg_list_nr_t& cell_li w_args.nof_tx_ports = cell_list[cell_index].carrier.max_mimo_layers; w_args.nof_rx_ports = cell_list[cell_index].carrier.max_mimo_layers; w_args.rf_port = cell_list[cell_index].rf_port; + w_args.srate_hz = srate_hz; w_args.pusch_max_nof_iter = args.pusch_max_nof_iter; if (not w->init(w_args)) { @@ -80,16 +89,18 @@ slot_worker* worker_pool::wait_worker(uint32_t tti) if (w != nullptr) { srsran_carrier_nr_t carrier_; srsran_pdcch_cfg_nr_t pdcch_cfg_; + srsran_ssb_cfg_t ssb_cfg_; // Copy configuration { std::unique_lock lock(common_cfg_mutex); carrier_ = carrier; pdcch_cfg_ = pdcch_cfg; + ssb_cfg_ = ssb_cfg; } // Set worker configuration - if (not w->set_common_cfg(carrier_, pdcch_cfg_)) { + if (not w->set_common_cfg(carrier_, pdcch_cfg_, ssb_cfg_)) { logger.error("Error setting common config"); return nullptr; } @@ -141,8 +152,12 @@ int worker_pool::set_common_cfg(const phy_interface_rrc_nr::common_cfg_t& common // Save current configuration { std::unique_lock lock(common_cfg_mutex); - carrier = common_cfg.carrier; - pdcch_cfg = common_cfg.pdcch; + carrier = common_cfg.carrier; + pdcch_cfg = common_cfg.pdcch; + ssb_cfg = common_cfg.ssb; + ssb_cfg.srate_hz = srate_hz; + ssb_cfg.scaling = + srsran_convert_dB_to_amplitude(srsran_gnb_dl_get_maximum_signal_power_dBfs(common_cfg.carrier.nof_prb)); } return SRSRAN_SUCCESS; diff --git a/srsenb/src/stack/rrc/rrc_nr.cc b/srsenb/src/stack/rrc/rrc_nr.cc index e79fffff5..7fc9903b5 100644 --- a/srsenb/src/stack/rrc/rrc_nr.cc +++ b/srsenb/src/stack/rrc/rrc_nr.cc @@ -228,7 +228,7 @@ void rrc_nr::config_phy() common_cfg.pdcch = cfg.cell_list[0].phy_cell.pdcch; common_cfg.prach = cfg.cell_list[0].phy_cell.prach; common_cfg.duplex_mode = cfg.cell_list[0].duplex_mode; - + common_cfg.ssb = cfg.cell_list[0].ssb_cfg; if (phy->set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { logger.error("Couldn't set common PHY config"); return; diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index d2141bada..0c79a85b9 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -7,8 +7,19 @@ # if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) + # gNb options set(NR_PHY_TEST_GNB_NOF_THREADS 1) + set(NR_PHY_TEST_GNB_PHY_LOG_LEVEL "error") + + # UE options set(NR_PHY_TEST_UE_NOF_THREADS 1) + set(NR_PHY_TEST_UE_PHY_LOG_LEVEL "error") + + # Build common arguments + set(NR_PHY_TEST_COMMON_ARGS + --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} + --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + --ue.phy.log.level=${NR_PHY_TEST_UE_PHY_LOG_LEVEL}) add_executable(nr_phy_test nr_phy_test.cc) target_link_libraries(nr_phy_test @@ -41,8 +52,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=27 # Maximum MCS --gnb.stack.pusch.slots=none - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) endforeach () @@ -55,8 +65,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) # DL and UL flooding @@ -71,8 +80,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) endforeach () @@ -89,8 +97,7 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS --gnb.stack.use_dummy_sched=false # Use real NR scheduler - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) # Test PRACH transmission and detection @@ -110,10 +117,9 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --duration=1000 # 1000 slots --gnb.stack.pdsch.slots=none # No PDSCH --gnb.stack.pusch.slots=none # No PUSCH - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.stack.prach.period=30 # Transmit PRACH every 30 radio frames --ue.stack.prach.preamble=10 # Use preamble 10 - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) # Test scheduling request @@ -122,9 +128,8 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --duration=1000 # 1000 slots --gnb.stack.pdsch.slots=none # No PDSCH --gnb.stack.pusch.slots=none # No PUSCH - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.stack.sr.period=4 # Transmit SR every 4 opportunities - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) # Test scheduling request multiplexed with HARQ ACK feedback @@ -133,9 +138,8 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --duration=1000 # 1000 slots --gnb.stack.pdsch.slots=all # All PDSCH --gnb.stack.pusch.slots=none # No PUSCH - --gnb.phy.nof_threads=${NR_PHY_TEST_GNB_NOF_THREADS} --ue.stack.sr.period=4 # Transmit SR every 4 opportunities - --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} + ${NR_PHY_TEST_COMMON_ARGS} ) endforeach () endif () diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index a71b5589a..546d0dbdb 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -365,7 +365,7 @@ public: if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { if (args.pdsch.slots == "all") { - for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + for (uint32_t n = 1; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { dl.slots.insert(n); } } else { @@ -498,6 +498,15 @@ public: } } + // Schedule SSB + for (uint32_t ssb_idx = 0; ssb_idx < SRSRAN_SSB_NOF_CANDIDATES; ssb_idx++) { + if (phy_cfg.ssb.position_in_burst[ssb_idx]) { + mac_interface_phy_nr::ssb_t ssb = {}; + ssb.pbch_msg.ssb_idx = (uint32_t)ssb_idx; + dl_sched.ssb.push_back(ssb); + } + } + return SRSRAN_SUCCESS; } diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index b35e0b264..8269652c3 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -83,6 +83,7 @@ public: common_cfg.pdcch = args.phy_cfg.pdcch; common_cfg.prach = args.phy_cfg.prach; common_cfg.duplex_mode = args.phy_cfg.duplex.mode; + common_cfg.ssb = args.phy_cfg.get_ssb_cfg(); if (gnb_phy.set_common_cfg(common_cfg) < SRSRAN_SUCCESS) { return;