From 90ad9fac1a5e1aaf639ef055eb708ba52d2eb001 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Mon, 14 Jul 2025 12:23:39 +0000 Subject: [PATCH] NR UE: introduce support to define multiple RUs --- CMakeLists.txt | 1 + ci-scripts/conf_files/nrue.uicc.ntn-leo.conf | 15 ++ executables/nr-ue-ru.c | 248 +++++++++++++++++++ executables/nr-ue-ru.h | 37 +++ executables/nr-ue.c | 8 - executables/nr-uesoftmodem.c | 111 ++------- openair1/PHY/defs_nr_UE.h | 16 ++ 7 files changed, 341 insertions(+), 95 deletions(-) create mode 100644 executables/nr-ue-ru.c create mode 100644 executables/nr-ue-ru.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 14d90a4c3b..762080e31b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1872,6 +1872,7 @@ add_executable(nr-uesoftmodem ${OPENAIR_DIR}/executables/nr-uesoftmodem.c ${OPENAIR_DIR}/executables/position_interface.c ${OPENAIR_DIR}/executables/nr-ue.c + ${OPENAIR_DIR}/executables/nr-ue-ru.c ${OPENAIR_DIR}/executables/softmodem-common.c ${OPENAIR_DIR}/radio/COMMON/common_lib.c ${OPENAIR_DIR}/radio/COMMON/record_player.c diff --git a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf index d8ad297180..9f2787f2d8 100644 --- a/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf +++ b/ci-scripts/conf_files/nrue.uicc.ntn-leo.conf @@ -14,6 +14,21 @@ position0 = { thread-pool = "-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1" +RUs = ( + { + nb_tx = 1; + nb_rx = 1; + att_tx = 0; + att_rx = 0; + max_rxgain = 114; + sdr_addrs = "type=x300"; + clock_src = "internal"; + time_src = "internal"; + # if_freq = 3700000000L; + # if_offset = 1000000; + } +); + #/* configuration for channel modelisation */ #/* To be included in main config file when */ #/* channel modelisation is used (rfsimulator with chanmod options enabled) */ diff --git a/executables/nr-ue-ru.c b/executables/nr-ue-ru.c new file mode 100644 index 0000000000..497bbc309b --- /dev/null +++ b/executables/nr-ue-ru.c @@ -0,0 +1,248 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#include "nr-ue-ru.h" +#include "nr-uesoftmodem.h" +#include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" + +/* NR UE RU configuration section name */ +#define CONFIG_STRING_NRUE_RU_LIST "RUs" + +#define NRUE_RU_NB_TX "nb_tx" +#define NRUE_RU_NB_RX "nb_rx" +#define NRUE_RU_ATT_TX "att_tx" +#define NRUE_RU_ATT_RX "att_rx" +#define NRUE_RU_MAX_RXGAIN "max_rxgain" +#define NRUE_RU_SDR_ADDRS "sdr_addrs" +#define NRUE_RU_TX_SUBDEV "tx_subdev" +#define NRUE_RU_RX_SUBDEV "rx_subdev" +#define NRUE_RU_CLOCK_SRC "clock_src" +#define NRUE_RU_TIME_SRC "time_src" +#define NRUE_RU_TUNE_OFFSET "tune_offset" +#define NRUE_RU_IF_FREQUENCY "if_freq" +#define NRUE_RU_IF_FREQ_OFFSET "if_offset" + +#define NRUE_RU_SRC_CHECK \ + &(checkedparam_t) \ + { \ + .s3a = { config_checkstr_assign_integer, {"internal", "external", "gpsdo"}, {internal, external, gpsdo}, 3 } \ + } + +/*------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* NR UE RU configuration parameters */ +/* optname helpstr paramflags XXXptr defXXXval type numelt chkPptr */ +/*------------------------------------------------------------------------------------------------------------------------------------------------*/ +// clang-format off +#define NRUE_RU_PARAMS_DESC { \ + {NRUE_RU_NB_TX, CONFIG_HLP_UENANTT, 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0, NULL }, \ + {NRUE_RU_NB_RX, CONFIG_HLP_UENANTR, 0, .uptr=NULL, .defuintval=1, TYPE_UINT, 0, NULL }, \ + {NRUE_RU_ATT_TX, NULL, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, NULL }, \ + {NRUE_RU_ATT_RX, NULL, 0, .uptr=NULL, .defuintval=0, TYPE_UINT, 0, NULL }, \ + {NRUE_RU_MAX_RXGAIN, NULL, 0, .iptr=NULL, .defintval=120, TYPE_INT, 0, NULL }, \ + {NRUE_RU_SDR_ADDRS, CONFIG_HLP_USRP_ARGS, 0, .strptr=NULL, .defstrval="type=b200", TYPE_STRING, 0, NULL }, \ + {NRUE_RU_TX_SUBDEV, CONFIG_HLP_TX_SUBDEV, 0, .strptr=NULL, .defstrval="", TYPE_STRING, 0, NULL }, \ + {NRUE_RU_RX_SUBDEV, CONFIG_HLP_RX_SUBDEV, 0, .strptr=NULL, .defstrval="", TYPE_STRING, 0, NULL }, \ + {NRUE_RU_CLOCK_SRC, NULL, 0, .strptr=NULL, .defstrval="internal", TYPE_STRING, 0, NRUE_RU_SRC_CHECK }, \ + {NRUE_RU_TIME_SRC, NULL, 0, .strptr=NULL, .defstrval="internal", TYPE_STRING, 0, NRUE_RU_SRC_CHECK }, \ + {NRUE_RU_TUNE_OFFSET, CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=NULL, .defdblval=0.0, TYPE_DOUBLE, 0, NULL }, \ + {NRUE_RU_IF_FREQUENCY, CONFIG_HLP_IF_FREQ, 0, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0, NULL }, \ + {NRUE_RU_IF_FREQ_OFFSET, CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, NULL }, \ +} +// clang-format on + +static int nrue_ru_count; +static nrUE_RU_params_t *nrue_rus; + +openair0_config_t openair0_cfg[MAX_CARDS]; +openair0_device_t openair0_dev[MAX_CARDS]; + +int nrue_get_ru_count(void) +{ + return nrue_ru_count; +} + +const nrUE_RU_params_t *nrue_get_ru(int ru_id) +{ + AssertFatal(ru_id >= 0 && ru_id < nrue_ru_count, "Invalid RU ID %d! RU count = %d\n", ru_id, nrue_ru_count); + return &nrue_rus[ru_id]; +} + +void nrue_set_ru_params(configmodule_interface_t *cfg) +{ + paramdef_t RUParams[] = NRUE_RU_PARAMS_DESC; + paramlist_def_t RUParamList = {CONFIG_STRING_NRUE_RU_LIST, NULL, 0}; + config_getlist(cfg, &RUParamList, RUParams, sizeofArray(RUParams), NULL); + + if (RUParamList.numelt <= 0) { + nrue_ru_count = 1; + nrue_rus = calloc_or_fail(nrue_ru_count, sizeof(nrUE_RU_params_t)); + nrue_rus[0] = (nrUE_RU_params_t){.nb_tx = get_nrUE_params()->nb_antennas_tx, + .nb_rx = get_nrUE_params()->nb_antennas_rx, + .att_tx = get_nrUE_params()->tx_gain, + .att_rx = 0, + .max_rxgain = get_nrUE_params()->rx_gain, + .sdr_addrs = get_nrUE_params()->usrp_args, + .tx_subdev = get_nrUE_params()->tx_subdev, + .rx_subdev = get_nrUE_params()->rx_subdev, + .clock_source = get_softmodem_params()->clock_source, + .time_source = get_softmodem_params()->timing_source, + .tune_offset = get_softmodem_params()->tune_offset, + .if_frequency = get_nrUE_params()->if_freq, + .if_freq_offset = get_nrUE_params()->if_freq_off}; + return; + } + + nrue_ru_count = RUParamList.numelt; + nrue_rus = calloc_or_fail(nrue_ru_count, sizeof(nrUE_RU_params_t)); + + LOG_W(NR_PHY, "Ignoring command line RU parameters, using the following instead:\n"); + + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + nrue_rus[ru_id].nb_tx = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_NB_TX)->uptr); + nrue_rus[ru_id].nb_rx = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_NB_RX)->uptr); + nrue_rus[ru_id].att_tx = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_ATT_TX)->uptr); + nrue_rus[ru_id].att_rx = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_ATT_RX)->uptr); + nrue_rus[ru_id].max_rxgain = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_MAX_RXGAIN)->iptr); + nrue_rus[ru_id].tune_offset = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_TUNE_OFFSET)->dblptr); + nrue_rus[ru_id].if_frequency = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_IF_FREQUENCY)->u64ptr); + nrue_rus[ru_id].if_freq_offset = *(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_IF_FREQ_OFFSET)->iptr); + + nrue_rus[ru_id].sdr_addrs = strdup(*(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_SDR_ADDRS)->strptr)); + nrue_rus[ru_id].tx_subdev = strdup(*(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_TX_SUBDEV)->strptr)); + nrue_rus[ru_id].rx_subdev = strdup(*(gpd(RUParamList.paramarray[ru_id], sizeofArray(RUParams), NRUE_RU_RX_SUBDEV)->strptr)); + + int clock_src_idx = config_paramidx_fromname(RUParams, sizeofArray(RUParams), NRUE_RU_CLOCK_SRC); + AssertFatal(clock_src_idx >= 0, "Index for clock_src config option not found!\n"); + nrue_rus[ru_id].clock_source = config_get_processedint(cfg, &RUParamList.paramarray[ru_id][clock_src_idx]); + + int time_src_idx = config_paramidx_fromname(RUParams, sizeofArray(RUParams), NRUE_RU_TIME_SRC); + AssertFatal(time_src_idx >= 0, "Index for time_src config option not found!\n"); + nrue_rus[ru_id].time_source = config_get_processedint(cfg, &RUParamList.paramarray[ru_id][time_src_idx]); + + LOG_I(NR_PHY, + "RU %d: nb_tx %d, nb_rx %d, att_tx %d, att_rx %d, max_rxgain %d, tune_offset %f, if_frequency %lu, if_freq_offset %d, " + "sdr_addrs \"%s\", tx_subdev \"%s\", rx_subdev \"%s\", clock_source %d, time_source %d\n", + ru_id, + nrue_rus[ru_id].nb_tx, + nrue_rus[ru_id].nb_rx, + nrue_rus[ru_id].att_tx, + nrue_rus[ru_id].att_rx, + nrue_rus[ru_id].max_rxgain, + nrue_rus[ru_id].tune_offset, + nrue_rus[ru_id].if_frequency, + nrue_rus[ru_id].if_freq_offset, + nrue_rus[ru_id].sdr_addrs, + nrue_rus[ru_id].tx_subdev, + nrue_rus[ru_id].rx_subdev, + nrue_rus[ru_id].clock_source, + nrue_rus[ru_id].time_source); + } +} + +void nrue_init_openair0(const PHY_VARS_NR_UE *ue) +{ + int freq_off = 0; + bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false; + + memset(openair0_cfg, 0, sizeof(openair0_config_t) * MAX_CARDS); + memset(openair0_dev, 0, sizeof(openair0_device_t) * MAX_CARDS); + + AssertFatal(MAX_CARDS >= nrue_ru_count, + "Too many RUs allocated (%d)! Maybe increase MAX_CARDS (%d).\n", + nrue_ru_count, + MAX_CARDS); + + const NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + if (is_sidelink) + frame_parms = &ue->SL_UE_PHY_PARAMS.sl_frame_params; + + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + openair0_config_t *cfg = &openair0_cfg[ru_id]; + cfg->configFilename = NULL; + cfg->sample_rate = frame_parms->samples_per_subframe * 1e3; + cfg->samples_per_frame = frame_parms->samples_per_frame; + + if (frame_parms->frame_type == TDD) + cfg->duplex_mode = duplex_mode_TDD; + else + cfg->duplex_mode = duplex_mode_FDD; + + cfg->Mod_id = 0; + cfg->num_rb_dl = frame_parms->N_RB_DL; + cfg->tx_num_channels = min(4, frame_parms->nb_antennas_tx); + cfg->rx_num_channels = min(4, frame_parms->nb_antennas_rx); + + LOG_I(PHY, + "HW: Configuring ru_id %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", + ru_id, + cfg->sample_rate, + cfg->tx_num_channels, + cfg->rx_num_channels, + duplex_mode_txt[cfg->duplex_mode]); + + uint64_t dl_carrier, ul_carrier; + if (is_sidelink || nrue_rus[ru_id].if_frequency == 0) { + dl_carrier = frame_parms->dl_CarrierFreq; + ul_carrier = frame_parms->ul_CarrierFreq; + } else { + dl_carrier = nrue_rus[ru_id].if_frequency; + ul_carrier = nrue_rus[ru_id].if_frequency + nrue_rus[ru_id].if_freq_offset; + } + + nr_rf_card_config_freq(cfg, ul_carrier, dl_carrier, freq_off); + nr_rf_card_config_gain(cfg); + + cfg->configFilename = get_softmodem_params()->rf_config_file; + + cfg->sdr_addrs = nrue_rus[ru_id].sdr_addrs; + cfg->tx_subdev = nrue_rus[ru_id].tx_subdev; + cfg->rx_subdev = nrue_rus[ru_id].rx_subdev; + cfg->clock_source = nrue_rus[ru_id].clock_source; + cfg->time_source = nrue_rus[ru_id].time_source; + cfg->tune_offset = nrue_rus[ru_id].tune_offset; + } +} + +void nrue_ru_start(void) +{ + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + openair0_config_t *cfg0 = &openair0_cfg[ru_id]; + openair0_device_t *dev0 = &openair0_dev[ru_id]; + + dev0->host_type = RAU_HOST; + int tmp = openair0_device_load(dev0, cfg0); + AssertFatal(tmp == 0, "Could not load the device %d\n", ru_id); + int tmp2 = dev0->trx_start_func(dev0); + AssertFatal(tmp2 == 0, "Could not start the device %d\n", ru_id); + if (usrp_tx_thread == 1) + dev0->trx_write_init(dev0); + } +} + +void nrue_ru_end(void) +{ + for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) { + if (openair0_dev[ru_id].trx_get_stats_func) + openair0_dev[ru_id].trx_get_stats_func(&openair0_dev[ru_id]); + if (openair0_dev[ru_id].trx_end_func) + openair0_dev[ru_id].trx_end_func(&openair0_dev[ru_id]); + } +} diff --git a/executables/nr-ue-ru.h b/executables/nr-ue-ru.h new file mode 100644 index 0000000000..4f5aee107a --- /dev/null +++ b/executables/nr-ue-ru.h @@ -0,0 +1,37 @@ +/* + * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The OpenAirInterface Software Alliance licenses this file to You under + * the OAI Public License, Version 1.0 (the "License"); you may not use this file + * except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.openairinterface.org/?page_id=698 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------------------- + * For more information about the OpenAirInterface (OAI) Software Alliance: + * contact@openairinterface.org + */ + +#ifndef NR_UE_RU_H +#define NR_UE_RU_H + +#include "PHY/defs_nr_UE.h" +#include "radio/COMMON/common_lib.h" + +int nrue_get_ru_count(void); +const nrUE_RU_params_t *nrue_get_ru(int ru_id); +void nrue_set_ru_params(configmodule_interface_t *cfg); + +void nrue_init_openair0(const PHY_VARS_NR_UE *ue); + +void nrue_ru_start(void); +void nrue_ru_end(void); + +#endif diff --git a/executables/nr-ue.c b/executables/nr-ue.c index ce406f6e0b..0cae01f266 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -767,8 +767,6 @@ void *UE_thread(void *arg) void *rxp[NB_ANTENNAS_RX]; enum stream_status_e stream_status = STREAM_STATUS_UNSYNC; fapi_nr_config_request_t *cfg = &UE->nrUE_config; - int tmp = openair0_device_load(dev0, cfg0); - AssertFatal(tmp == 0, "Could not load the device\n"); NR_DL_FRAME_PARMS *fp = &UE->frame_parms; sl_nr_phy_config_request_t *sl_cfg = NULL; if (UE->sl_mode == 2) { @@ -776,13 +774,7 @@ void *UE_thread(void *arg) sl_cfg = &UE->SL_UE_PHY_PARAMS.sl_config; } - dev0->host_type = RAU_HOST; UE->is_synchronized = 0; - int tmp2 = dev0->trx_start_func(dev0); - AssertFatal(tmp2 == 0, "Could not start the device\n"); - if (usrp_tx_thread == 1) - dev0->trx_write_init(dev0); - InitSinLUT(); notifiedFIFO_t nf; diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 6ab006e047..e05d676396 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -81,6 +81,7 @@ unsigned short config_frames[4] = {2,9,11,13}; // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0) #include "PHY/TOOLS/phy_scope_interface.h" #include "PHY/TOOLS/nr_phy_scope.h" +#include "executables/nr-ue-ru.h" #include #include "executables/softmodem-common.h" #include "executables/thread-common.h" @@ -107,8 +108,6 @@ int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; uint64_t sidelink_frequency[MAX_NUM_CCs][4]; // UE and OAI config variables -openair0_config_t openair0_cfg[MAX_CARDS]; -openair0_device_t openair0_dev[MAX_CARDS]; double cpuf; int create_tasks_nrue(uint32_t ue_nb) { @@ -140,14 +139,7 @@ void exit_function(const char *file, const char *function, const int line, const oai_exit = 1; - for (int card = 0; card < MAX_CARDS; card++) { - if (openair0_dev[card].trx_end_func) { - if (openair0_dev[card].trx_get_stats_func) { - openair0_dev[card].trx_get_stats_func(&openair0_dev[card]); - } - openair0_dev[card].trx_end_func(&openair0_dev[card]); - } - } + nrue_ru_end(); if (assert) { abort(); @@ -183,20 +175,23 @@ static void get_options(configmodule_interface_t *cfg) } // set PHY vars from command line -void set_options(int CC_id, PHY_VARS_NR_UE *UE){ +static void set_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id) +{ NR_DL_FRAME_PARMS *fp = &UE->frame_parms; + const nrUE_RU_params_t *RU = nrue_get_ru(ru_id); // Set UE variables - UE->rx_total_gain_dB = (int)nrUE_params.rx_gain; - UE->tx_total_gain_dB = (int)nrUE_params.tx_gain; + UE->rx_total_gain_dB = RU->max_rxgain - RU->att_rx; + UE->tx_total_gain_dB = RU->att_tx; + UE->if_freq = RU->if_frequency; + UE->if_freq_off = RU->if_freq_offset; + UE->rf_map.card = ru_id; + UE->rf_map.chain = CC_id; + UE->tx_power_max_dBm = nrUE_params.tx_max_power; - UE->rf_map.card = 0; - UE->rf_map.chain = CC_id + 0; UE->max_ldpc_iterations = nrUE_params.max_ldpc_iterations; UE->UE_scan_carrier = nrUE_params.UE_scan_carrier; UE->UE_fo_compensation = nrUE_params.UE_fo_compensation; - UE->if_freq = nrUE_params.if_freq; - UE->if_freq_off = nrUE_params.if_freq_off; UE->chest_freq = nrUE_params.chest_freq; UE->chest_time = nrUE_params.chest_time; UE->no_timing_correction = nrUE_params.no_timing_correction; @@ -207,71 +202,15 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){ UE->UE_fo_compensation, UE->UE_scan_carrier, UE->no_timing_correction, UE->chest_freq, UE->chest_time); // Set FP variables + fp->nb_antennas_rx = RU->nb_rx; + fp->nb_antennas_tx = RU->nb_tx; - fp->nb_antennas_rx = nrUE_params.nb_antennas_rx; - fp->nb_antennas_tx = nrUE_params.nb_antennas_tx; - fp->threequarter_fs = get_softmodem_params()->threequarter_fs; - fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; + fp->threequarter_fs = get_softmodem_params()->threequarter_fs; + fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor; LOG_I(PHY, "Set UE nb_rx_antenna %d, nb_tx_antenna %d, threequarter_fs %d, ofdm_offset_divisor %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ofdm_offset_divisor); } -void init_openair0(PHY_VARS_NR_UE *ue) -{ - int freq_off = 0; - NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; - bool is_sidelink = (get_softmodem_params()->sl_mode) ? true : false; - if (is_sidelink) - frame_parms = &ue->SL_UE_PHY_PARAMS.sl_frame_params; - - for (int card = 0; card < MAX_CARDS; card++) { - openair0_config_t *cfg = &openair0_cfg[card]; - uint64_t dl_carrier, ul_carrier; - cfg->configFilename = NULL; - cfg->sample_rate = frame_parms->samples_per_subframe * 1e3; - cfg->samples_per_frame = frame_parms->samples_per_frame; - - if (frame_parms->frame_type==TDD) - cfg->duplex_mode = duplex_mode_TDD; - else - cfg->duplex_mode = duplex_mode_FDD; - - cfg->Mod_id = 0; - cfg->num_rb_dl = frame_parms->N_RB_DL; - cfg->clock_source = get_softmodem_params()->clock_source; - cfg->time_source = get_softmodem_params()->timing_source; - cfg->tune_offset = get_softmodem_params()->tune_offset; - cfg->tx_num_channels = min(4, frame_parms->nb_antennas_tx); - cfg->rx_num_channels = min(4, frame_parms->nb_antennas_rx); - - LOG_I(PHY, - "HW: Configuring card %d, sample_rate %f, tx/rx num_channels %d/%d, duplex_mode %s\n", - card, - cfg->sample_rate, - cfg->tx_num_channels, - cfg->rx_num_channels, - duplex_mode_txt[cfg->duplex_mode]); - - if (is_sidelink) { - dl_carrier = frame_parms->dl_CarrierFreq; - ul_carrier = frame_parms->ul_CarrierFreq; - } else - nr_get_carrier_frequencies(PHY_vars_UE_g[0][0], &dl_carrier, &ul_carrier); - - nr_rf_card_config_freq(cfg, ul_carrier, dl_carrier, freq_off); - nr_rf_card_config_gain(cfg); - - cfg->configFilename = get_softmodem_params()->rf_config_file; - - if (get_nrUE_params()->usrp_args) - cfg->sdr_addrs = get_nrUE_params()->usrp_args; - if (get_nrUE_params()->tx_subdev) - cfg->tx_subdev = get_nrUE_params()->tx_subdev; - if (get_nrUE_params()->rx_subdev) - cfg->rx_subdev = get_nrUE_params()->rx_subdev; - } -} - // Stupid function addition because UE itti messages queues definition is common with eNB void *rrc_enb_process_msg(void *notUsed) { return NULL; @@ -314,8 +253,6 @@ int main(int argc, char **argv) } //set_softmodem_sighandler(); CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP); - memset(openair0_cfg, 0, sizeof(openair0_config_t) * MAX_CARDS); - memset(openair0_dev, 0, sizeof(openair0_device_t) * MAX_CARDS); // initialize logging logInit(); // get options and fill parameters from configuration file @@ -387,11 +324,14 @@ int main(int argc, char **argv) IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES : TIME_SOURCE_REALTIME); + nrue_set_ru_params(uniqCfg); + + int ru_id = 0; // initialize all UEs to RU 0 for now for (int inst = 0; inst < NB_UE_INST; inst++) { PHY_VARS_NR_UE *UE[MAX_NUM_CCs]; for (int CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) { UE[CC_id] = PHY_vars_UE_g[inst][CC_id]; - set_options(CC_id, UE[CC_id]); + set_options(CC_id, UE[CC_id], ru_id); NR_UE_MAC_INST_t *mac = get_mac_inst(inst); init_nr_ue_phy_cpu_stats(&UE[CC_id]->phy_cpu_stats); // set frame config to initial values from command line and assume that the SSB is centered on the grid @@ -449,7 +389,7 @@ int main(int argc, char **argv) get_nrUE_params()->ofdm_offset_divisor); sl_ue_phy_init(UE[CC_id]); } - init_openair0(UE[CC_id]); + nrue_init_openair0(UE[CC_id]); } } @@ -467,6 +407,8 @@ int main(int argc, char **argv) load_module_shlib("imscope_record", NULL, 0, PHY_vars_UE_g[0][0]); } + nrue_ru_start(); + for (int inst = 0; inst < NB_UE_INST; inst++) { LOG_I(PHY,"Intializing UE Threads for instance %d ...\n", inst); init_NR_UE_threads(PHY_vars_UE_g[inst][0]); @@ -511,12 +453,7 @@ int main(int argc, char **argv) } } - for (int card = 0; card < MAX_CARDS; card++) { - if (openair0_dev[card].trx_get_stats_func) - openair0_dev[card].trx_get_stats_func(&openair0_dev[card]); - if (openair0_dev[card].trx_end_func) - openair0_dev[card].trx_end_func(&openair0_dev[card]); - } + nrue_ru_end(); free_nrLDPC_coding_interface(&nrLDPC_coding_interface); diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index e46c411e8b..2eba24f6d1 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -342,6 +342,22 @@ typedef struct UE_NR_SCAN_INFO_s { int32_t freq_offset_Hz[3][10]; } UE_NR_SCAN_INFO_t; +typedef struct { + unsigned int nb_tx; + unsigned int nb_rx; + unsigned int att_tx; + unsigned int att_rx; + int max_rxgain; + char *sdr_addrs; + char *tx_subdev; + char *rx_subdev; + clock_source_t clock_source; + clock_source_t time_source; + double tune_offset; + uint64_t if_frequency; + int if_freq_offset; +} nrUE_RU_params_t; + /// Top-level PHY Data Structure for UE typedef struct PHY_VARS_NR_UE_s { /// \brief Module ID indicator for this instance