diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 2c3bcfb0e..ad0e79736 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -517,6 +517,10 @@ typedef struct { std::vector dl_earfcn_list = {3400}; // vectorized version of dl_earfcn that gets populated during init std::map ul_earfcn_map; // Map linking DL EARFCN and UL EARFCN + std::string dl_nr_arfcn = "632628"; // comma-separated list of DL NR ARFCNs + std::vector dl_nr_arfcn_list = { + 632628}; // vectorized version of dl_nr_arfcn that gets populated during init + float dl_freq = -1.0f; float ul_freq = -1.0f; diff --git a/srsue/hdr/stack/rrc/rrc_nr.h b/srsue/hdr/stack/rrc/rrc_nr.h index aaef98453..d476e1804 100644 --- a/srsue/hdr/stack/rrc/rrc_nr.h +++ b/srsue/hdr/stack/rrc/rrc_nr.h @@ -32,9 +32,10 @@ struct core_less_args_t { }; struct rrc_nr_args_t { - core_less_args_t coreless; - std::string log_level; - uint32_t log_hex_limit; + core_less_args_t coreless; + std::vector supported_bands; + std::string log_level; + uint32_t log_hex_limit; }; struct rrc_nr_metrics_t {}; diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 2be8bb912..1455ab015 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -67,26 +67,27 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("ue.phy", bpo::value(&args->phy.type)->default_value("lte"), "Type of the PHY [lte]") ("ue.stack", bpo::value(&args->stack.type)->default_value("lte"), "Type of the upper stack [lte, nr]") - ("rf.dl_earfcn", bpo::value(&args->phy.dl_earfcn)->default_value("3400"), "Downlink EARFCN list") - ("rf.ul_earfcn", bpo::value(&args->phy.ul_earfcn), "Uplink EARFCN list. Optional.") - ("rf.srate", bpo::value(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz") - ("rf.freq_offset", bpo::value(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") - ("rf.dl_freq", bpo::value(&args->phy.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)") - ("rf.ul_freq", bpo::value(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") - ("rf.rx_gain", bpo::value(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain") - ("rf.tx_gain", bpo::value(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain (all channels)") - ("rf.tx_gain[0]", bpo::value(&args->rf.tx_gain_ch[0])->default_value(-1), "Front-end transmitter gain CH0") - ("rf.tx_gain[1]", bpo::value(&args->rf.tx_gain_ch[1])->default_value(-1), "Front-end transmitter gain CH1") - ("rf.tx_gain[2]", bpo::value(&args->rf.tx_gain_ch[2])->default_value(-1), "Front-end transmitter gain CH2") - ("rf.tx_gain[3]", bpo::value(&args->rf.tx_gain_ch[3])->default_value(-1), "Front-end transmitter gain CH3") - ("rf.tx_gain[4]", bpo::value(&args->rf.tx_gain_ch[4])->default_value(-1), "Front-end transmitter gain CH4") - ("rf.rx_gain[0]", bpo::value(&args->rf.rx_gain_ch[0])->default_value(-1), "Front-end receiver gain CH0") - ("rf.rx_gain[1]", bpo::value(&args->rf.rx_gain_ch[1])->default_value(-1), "Front-end receiver gain CH1") - ("rf.rx_gain[2]", bpo::value(&args->rf.rx_gain_ch[2])->default_value(-1), "Front-end receiver gain CH2") - ("rf.rx_gain[3]", bpo::value(&args->rf.rx_gain_ch[3])->default_value(-1), "Front-end receiver gain CH3") - ("rf.rx_gain[4]", bpo::value(&args->rf.rx_gain_ch[4])->default_value(-1), "Front-end receiver gain CH4") - ("rf.nof_carriers", bpo::value(&args->rf.nof_carriers)->default_value(1), "Number of carriers") - ("rf.nof_antennas", bpo::value(&args->rf.nof_antennas)->default_value(1), "Number of antennas per carrier") + ("rf.dl_earfcn", bpo::value(&args->phy.dl_earfcn)->default_value("3400"), "Downlink EARFCN list") + ("rf.ul_earfcn", bpo::value(&args->phy.ul_earfcn), "Uplink EARFCN list. Optional.") + ("rf.dl_nr_arfcn", bpo::value(&args->phy.dl_nr_arfcn)->default_value("632628"), "Downlink NR-ARFCN list") + ("rf.srate", bpo::value(&args->rf.srate_hz)->default_value(0.0), "Force Tx and Rx sampling rate in Hz") + ("rf.freq_offset", bpo::value(&args->rf.freq_offset)->default_value(0), "(optional) Frequency offset") + ("rf.dl_freq", bpo::value(&args->phy.dl_freq)->default_value(-1), "Downlink Frequency (if positive overrides EARFCN)") + ("rf.ul_freq", bpo::value(&args->phy.ul_freq)->default_value(-1), "Uplink Frequency (if positive overrides EARFCN)") + ("rf.rx_gain", bpo::value(&args->rf.rx_gain)->default_value(-1), "Front-end receiver gain") + ("rf.tx_gain", bpo::value(&args->rf.tx_gain)->default_value(-1), "Front-end transmitter gain (all channels)") + ("rf.tx_gain[0]", bpo::value(&args->rf.tx_gain_ch[0])->default_value(-1), "Front-end transmitter gain CH0") + ("rf.tx_gain[1]", bpo::value(&args->rf.tx_gain_ch[1])->default_value(-1), "Front-end transmitter gain CH1") + ("rf.tx_gain[2]", bpo::value(&args->rf.tx_gain_ch[2])->default_value(-1), "Front-end transmitter gain CH2") + ("rf.tx_gain[3]", bpo::value(&args->rf.tx_gain_ch[3])->default_value(-1), "Front-end transmitter gain CH3") + ("rf.tx_gain[4]", bpo::value(&args->rf.tx_gain_ch[4])->default_value(-1), "Front-end transmitter gain CH4") + ("rf.rx_gain[0]", bpo::value(&args->rf.rx_gain_ch[0])->default_value(-1), "Front-end receiver gain CH0") + ("rf.rx_gain[1]", bpo::value(&args->rf.rx_gain_ch[1])->default_value(-1), "Front-end receiver gain CH1") + ("rf.rx_gain[2]", bpo::value(&args->rf.rx_gain_ch[2])->default_value(-1), "Front-end receiver gain CH2") + ("rf.rx_gain[3]", bpo::value(&args->rf.rx_gain_ch[3])->default_value(-1), "Front-end receiver gain CH3") + ("rf.rx_gain[4]", bpo::value(&args->rf.rx_gain_ch[4])->default_value(-1), "Front-end receiver gain CH4") + ("rf.nof_carriers", bpo::value(&args->rf.nof_carriers)->default_value(1), "Number of carriers") + ("rf.nof_antennas", bpo::value(&args->rf.nof_antennas)->default_value(1), "Number of antennas per carrier") ("rf.device_name", bpo::value(&args->rf.device_name)->default_value("auto"), "Front-end device name") ("rf.device_args", bpo::value(&args->rf.device_args)->default_value("auto"), "Front-end device arguments") diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index f5d2db15d..7285a4f82 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -199,19 +199,21 @@ void rrc_nr::get_eutra_nr_capabilities(srslte::byte_buffer_t* eutra_nr_caps_pdu) band_param_eutra.set_eutra(); band_param_eutra.eutra().ca_bw_class_dl_eutra_present = true; band_param_eutra.eutra().ca_bw_class_ul_eutra_present = true; - band_param_eutra.eutra().band_eutra = 1; + band_param_eutra.eutra().band_eutra = 1; // TODO: this also needs to be set here? band_param_eutra.eutra().ca_bw_class_dl_eutra = asn1::rrc_nr::ca_bw_class_eutra_opts::options::a; band_param_eutra.eutra().ca_bw_class_ul_eutra = asn1::rrc_nr::ca_bw_class_eutra_opts::options::a; band_combination.band_list.push_back(band_param_eutra); - struct band_params_c band_param_nr; - band_param_nr.set_nr(); - band_param_nr.nr().ca_bw_class_dl_nr_present = true; - band_param_nr.nr().ca_bw_class_ul_nr_present = true; - band_param_nr.nr().band_nr = 78; - band_param_nr.nr().ca_bw_class_dl_nr = asn1::rrc_nr::ca_bw_class_nr_opts::options::a; - band_param_nr.nr().ca_bw_class_ul_nr = asn1::rrc_nr::ca_bw_class_nr_opts::options::a; - band_combination.band_list.push_back(band_param_nr); + for (const auto& band : args.supported_bands) { + struct band_params_c band_param_nr; + band_param_nr.set_nr(); + band_param_nr.nr().ca_bw_class_dl_nr_present = true; + band_param_nr.nr().ca_bw_class_ul_nr_present = true; + band_param_nr.nr().band_nr = band; + band_param_nr.nr().ca_bw_class_dl_nr = asn1::rrc_nr::ca_bw_class_nr_opts::options::a; + band_param_nr.nr().ca_bw_class_ul_nr = asn1::rrc_nr::ca_bw_class_nr_opts::options::a; + band_combination.band_list.push_back(band_param_nr); + } mrdc_cap.rf_params_mrdc.supported_band_combination_list.push_back(band_combination); mrdc_cap.rf_params_mrdc.supported_band_combination_list_present = true; @@ -226,10 +228,12 @@ void rrc_nr::get_eutra_nr_capabilities(srslte::byte_buffer_t* eutra_nr_caps_pdu) band_info_eutra.band_info_eutra().band_eutra = 1; mrdc_cap.rf_params_mrdc.applied_freq_band_list_filt.push_back(band_info_eutra); - freq_band_info_c band_info_nr; - band_info_nr.set_band_info_nr(); - band_info_nr.band_info_nr().band_nr = 78; - mrdc_cap.rf_params_mrdc.applied_freq_band_list_filt.push_back(band_info_nr); + for (const auto& band : args.supported_bands) { + freq_band_info_c band_info_nr; + band_info_nr.set_band_info_nr(); + band_info_nr.band_info_nr().band_nr = band; + mrdc_cap.rf_params_mrdc.applied_freq_band_list_filt.push_back(band_info_nr); + } mrdc_cap.rf_params_mrdc.applied_freq_band_list_filt_present = true; @@ -387,18 +391,19 @@ bool rrc_nr::rrc_reconfiguration(bool endc_release_and_add_r15, void rrc_nr::get_nr_capabilities(srslte::byte_buffer_t* nr_caps_pdu) { - struct ue_nr_cap_s nr_cap; nr_cap.access_stratum_release = access_stratum_release_opts::rel15; // PDCP nr_cap.pdcp_params.max_num_rohc_context_sessions = pdcp_params_s::max_num_rohc_context_sessions_opts::cs2; - band_nr_s band_nr; - band_nr.band_nr = 78; - band_nr.ue_pwr_class_present = true; - band_nr.ue_pwr_class = band_nr_s::ue_pwr_class_opts::pc3; - nr_cap.rf_params.supported_band_list_nr.push_back(band_nr); + for (const auto& band : args.supported_bands) { + band_nr_s band_nr; + band_nr.band_nr = band; + band_nr.ue_pwr_class_present = true; + band_nr.ue_pwr_class = band_nr_s::ue_pwr_class_opts::pc3; + nr_cap.rf_params.supported_band_list_nr.push_back(band_nr); + } nr_cap.rlc_params_present = true; nr_cap.rlc_params.um_with_short_sn_present = true; diff --git a/srsue/src/ue.cc b/srsue/src/ue.cc index 2c463c6a7..55a95504e 100644 --- a/srsue/src/ue.cc +++ b/srsue/src/ue.cc @@ -12,6 +12,7 @@ #include "srsue/hdr/ue.h" #include "srslte/build_info.h" +#include "srslte/common/band_helper.h" #include "srslte/common/string_helpers.h" #include "srslte/radio/radio.h" #include "srslte/radio/radio_null.h" @@ -245,6 +246,32 @@ int ue::parse_args(const all_args_t& args_) } } + srslte_band_helper bands_helper; + + // populate NR DL ARFCNs + if (args.phy.nof_nr_carriers > 0) { + if (not args.phy.dl_nr_arfcn.empty()) { + // Parse list + srslte::string_parse_list(args.phy.dl_nr_arfcn, ',', args.phy.dl_nr_arfcn_list); + + // Populates supported bands + for (uint32_t& arfcn : args.phy.dl_nr_arfcn_list) { + std::vector bands = bands_helper.get_bands_nr(arfcn); + for (const auto& band : bands) { + // make sure we don't add duplicates + if (std::find(args.stack.rrc_nr.supported_bands.begin(), args.stack.rrc_nr.supported_bands.end(), band) == + args.stack.rrc_nr.supported_bands.end()) { + args.stack.rrc_nr.supported_bands.push_back(band); + } + } + } + } else { + log.error("Error: dl_nr_arfcn list is empty\n"); + srslte::console("Error: dl_nr_arfcn list is empty\n"); + return SRSLTE_ERROR; + } + } + // Set UE category args.stack.rrc.ue_category = (uint32_t)strtoul(args.stack.rrc.ue_category_str.c_str(), nullptr, 10); diff --git a/srsue/ue.conf.example b/srsue/ue.conf.example index b9890f966..47176060d 100644 --- a/srsue/ue.conf.example +++ b/srsue/ue.conf.example @@ -5,12 +5,13 @@ ##################################################################### # RF configuration # -# dl_earfcn: Downlink EARFCN code. +# dl_earfcn: Downlink EARFCN code. # freq_offset: Uplink and Downlink optional frequency offset (in Hz) # tx_gain: Transmit gain (dB). # rx_gain: Optional receive gain (dB). If disabled, AGC if enabled # # Optional parameters: +# dl_nr_arfcn: Downlink NR ARFCN for EN-DC # dl_freq: Override DL frequency corresponding to dl_earfcn # ul_freq: Override UL frequency corresponding to dl_earfcn # nof_carriers: Number of carriers @@ -29,6 +30,7 @@ ##################################################################### [rf] dl_earfcn = 3350 +#dl_nr_arfcn = 632628 freq_offset = 0 tx_gain = 80 #rx_gain = 40