mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-13 04:30:28 +00:00
Merge remote-tracking branch 'origin/nr_ue_multiple_rf' into integration_2026_w05 (!3593)
NR UE: add support for multiple RF frontends
This MR adds basic support for multiple RF-frontends at the UE.
There are multiple reasons why we might want this:
1. There might be different antennas needed for different bands (e.g. NTN or
TN antennas). These antennas might be connected to different RF-frontends.
In case of Handover, the UE needs to dynamically switch between these
RF-frontends.
2. Each rf-simulator connection carries baseband I/Q samples. To be able to
perform a handover between two cells at different frequencies, there must
be two rf-simulator connections, as the baseband channels should not
interfere and thus cannot simply be added.
3. When we want to support multiple UE simulation within one instance of
nr-uesoftmodem, and allow multiple cells and probably even handover between
these cells, we need either:
1. dedicated RF-frontends for each simulated UE, or
2. dedicated RF-frontends for each connected cell and dynamically assign
simulated UEs accordingly.
This MR implements what is needed for 1., 2. and 3.1.
This commit is contained in:
@@ -390,7 +390,7 @@ void fh_if5_north_asynch_in(RU_t *ru,
|
||||
LTE_DL_FRAME_PARMS *fp = ru->frame_parms;
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
int tti_tx,frame_tx;
|
||||
openair0_timestamp timestamp_tx=0;
|
||||
openair0_timestamp_t timestamp_tx = 0;
|
||||
//recv_IF5(ru, ×tamp_tx, *subframe, IF5_RRH_GW_DL);
|
||||
// LOG_I(PHY,"Received subframe %d (TS %llu) from RCC\n",tti_tx,timestamp_tx);
|
||||
tti_tx = (timestamp_tx/fp->samples_per_tti)%10;
|
||||
@@ -540,7 +540,7 @@ void rx_rf(RU_t *ru,
|
||||
unsigned int rxs;
|
||||
int i;
|
||||
int resynch=0;
|
||||
openair0_timestamp ts=0,old_ts=0;
|
||||
openair0_timestamp_t ts = 0, old_ts = 0;
|
||||
|
||||
for (i=0; i<ru->nb_rx; i++)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
|
||||
|
||||
@@ -1686,7 +1686,8 @@ static void *UE_phy_stub_thread_rxn_txnp4(void *arg)
|
||||
* \param arg unused
|
||||
* \returns a pointer to an int. The storage is not on the heap and must not be freed.
|
||||
*/
|
||||
void write_dummy(PHY_VARS_UE *UE, openair0_timestamp timestamp) {
|
||||
void write_dummy(PHY_VARS_UE *UE, openair0_timestamp_t timestamp)
|
||||
{
|
||||
// we have to write to tell explicitly to the eNB, else it will wait for us forever
|
||||
// we write the next subframe (always write in future of what we received)
|
||||
//
|
||||
@@ -1709,7 +1710,7 @@ void *UE_thread(void *arg) {
|
||||
PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
|
||||
// int tx_enabled = 0;
|
||||
int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
|
||||
openair0_timestamp timestamp,timestamp1;
|
||||
openair0_timestamp_t timestamp, timestamp1;
|
||||
void *rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
|
||||
int start_rx_stream = 0;
|
||||
int i;
|
||||
|
||||
@@ -570,10 +570,10 @@ static void rx_rf(RU_t *ru, int *frame, int *slot)
|
||||
rxp[i] = (void *)&ru->common.rxdata[i][get_samples_slot_timestamp(fp, *slot)];
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1);
|
||||
openair0_timestamp old_ts = proc->timestamp_rx;
|
||||
openair0_timestamp_t old_ts = proc->timestamp_rx;
|
||||
LOG_D(PHY,"Reading %d samples for slot %d (%p)\n", samples_per_slot, *slot, rxp[0]);
|
||||
|
||||
openair0_timestamp ts;
|
||||
openair0_timestamp_t ts;
|
||||
unsigned int rxs;
|
||||
rxs = ru->rfdevice.trx_read_func(&ru->rfdevice, &ts, rxp, samples_per_slot, nb);
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#define CONFIG_HLP_CALPRACH "UE run normal prach with maximum power, but don't continue random-access\n"
|
||||
#define CONFIG_HLP_NOL2CN "bypass L2 and upper layers\n"
|
||||
#define CONFIG_HLP_UERXG "set UE RX gain\n"
|
||||
#define CONFIG_HLP_UERXGOFF "external UE amplifier offset\n"
|
||||
#define CONFIG_HLP_UETXG "set UE TX gain\n"
|
||||
#define CONFIG_HLP_UENANTR "set UE number of rx antennas\n"
|
||||
#define CONFIG_HLP_UENANTT "set UE number of tx antennas\n"
|
||||
|
||||
@@ -114,9 +114,6 @@ double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
|
||||
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
|
||||
#endif
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
|
||||
static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/;
|
||||
int chain_offset = 0;
|
||||
int numerology = 0;
|
||||
double cpuf;
|
||||
@@ -527,7 +524,6 @@ int main( int argc, char **argv ) {
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
#endif
|
||||
mode = normal_txrx;
|
||||
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
|
||||
logInit();
|
||||
lock_memory_to_ram();
|
||||
get_options(uniqCfg);
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
{"t" , CONFIG_HLP_ULMCS_PHYTEST, 0, .uptr=&target_ul_mcs, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"M" , CONFIG_HLP_DLBW_PHYTEST, 0, .uptr=&target_dl_bw, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"T" , CONFIG_HLP_ULBW_PHYTEST, 0, .uptr=&target_ul_bw, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"D" , CONFIG_HLP_DLBM_PHYTEST, 0, .u64ptr=&dlsch_slot_bitmap, .defintval=0, TYPE_UINT64, 0}, \
|
||||
{"U" , CONFIG_HLP_ULBM_PHYTEST, 0, .u64ptr=&ulsch_slot_bitmap, .defintval=0, TYPE_UINT64, 0}, \
|
||||
{"D" , CONFIG_HLP_DLBM_PHYTEST, 0, .u64ptr=&dlsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \
|
||||
{"U" , CONFIG_HLP_ULBM_PHYTEST, 0, .u64ptr=&ulsch_slot_bitmap, .defint64val=0, TYPE_UINT64, 0}, \
|
||||
{"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0, .iptr=&usrp_tx_thread, .defstrval=0, TYPE_INT, 0}, \
|
||||
{"uecap_file", CONFIG_HLP_UECAP_FILE, 0, .strptr=&uecap_file, .defstrval="./uecap_ports1.xml", TYPE_STRING, 0}, \
|
||||
}
|
||||
|
||||
528
executables/nr-ue-ru.c
Normal file
528
executables/nr-ue-ru.c
Normal file
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
/* NR UE cell configuration section name */
|
||||
#define CONFIG_STRING_NRUE_CELL_LIST "cells"
|
||||
|
||||
#define NRUE_CELL_RU_ID "ru_id"
|
||||
#define NRUE_CELL_BAND "band"
|
||||
#define NRUE_CELL_RF_FREQUENCY "rf_freq"
|
||||
#define NRUE_CELL_RF_FREQ_OFFSET "rf_offset"
|
||||
#define NRUE_CELL_NUMEROLOGY "numerology"
|
||||
#define NRUE_CELL_N_RB_DL "N_RB_DL"
|
||||
#define NRUE_CELL_SSB_START "ssb_start"
|
||||
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* NR UE cell configuration parameters */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt chkPptr */
|
||||
/*------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
// clang-format off
|
||||
#define NRUE_CELL_PARAMS_DESC { \
|
||||
{NRUE_CELL_RU_ID, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0, NULL }, \
|
||||
{NRUE_CELL_BAND, CONFIG_HLP_BAND, 0, .iptr=NULL, .defintval=78, TYPE_INT, 0, NULL }, \
|
||||
{NRUE_CELL_RF_FREQUENCY, CONFIG_HLP_DLF, 0, .u64ptr=NULL, .defint64val=0, TYPE_UINT64, 0, NULL }, \
|
||||
{NRUE_CELL_RF_FREQ_OFFSET, CONFIG_HLP_ULF, 0, .i64ptr=NULL, .defint64val=0, TYPE_INT64, 0, NULL }, \
|
||||
{NRUE_CELL_NUMEROLOGY, CONFIG_HLP_NUMEROLOGY, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0, NULL }, \
|
||||
{NRUE_CELL_N_RB_DL, CONFIG_HLP_PRB_SA, 0, .iptr=NULL, .defintval=106, TYPE_INT, 0, NULL }, \
|
||||
{NRUE_CELL_SSB_START, CONFIG_HLP_SSC, 0, .iptr=NULL, .defintval=516, TYPE_INT, 0, NULL }, \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
static int nrue_cell_count;
|
||||
static nrUE_cell_params_t *nrue_cells;
|
||||
static NR_DL_FRAME_PARMS *nrue_cell_fp;
|
||||
|
||||
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_cell_count(void)
|
||||
{
|
||||
return nrue_cell_count;
|
||||
}
|
||||
|
||||
const nrUE_cell_params_t *nrue_get_cell(int cell_id)
|
||||
{
|
||||
AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count);
|
||||
return &nrue_cells[cell_id];
|
||||
}
|
||||
|
||||
NR_DL_FRAME_PARMS *nrue_get_cell_fp(int cell_id)
|
||||
{
|
||||
AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count);
|
||||
return &nrue_cell_fp[cell_id];
|
||||
}
|
||||
|
||||
void nrue_set_cell(int cell_id, const nrUE_cell_params_t *cell)
|
||||
{
|
||||
AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count);
|
||||
nrue_cells[cell_id] = *cell;
|
||||
}
|
||||
|
||||
void nrue_set_cell_params(configmodule_interface_t *cfg)
|
||||
{
|
||||
paramdef_t cellParams[] = NRUE_CELL_PARAMS_DESC;
|
||||
paramlist_def_t cellParamList = {CONFIG_STRING_NRUE_CELL_LIST, NULL, 0};
|
||||
config_getlist(cfg, &cellParamList, cellParams, sizeofArray(cellParams), NULL);
|
||||
|
||||
if (cellParamList.numelt <= 0) {
|
||||
nrue_cell_count = 1;
|
||||
nrue_cell_fp = calloc_or_fail(nrue_cell_count, sizeof(NR_DL_FRAME_PARMS));
|
||||
nrue_cells = calloc_or_fail(nrue_cell_count, sizeof(nrUE_cell_params_t));
|
||||
nrue_cells[0] = (nrUE_cell_params_t){.ru_id = 0,
|
||||
.band = get_softmodem_params()->band,
|
||||
.rf_frequency = downlink_frequency[0][0],
|
||||
.rf_freq_offset = uplink_frequency_offset[0][0],
|
||||
.numerology = get_softmodem_params()->numerology,
|
||||
.N_RB_DL = get_nrUE_params()->N_RB_DL,
|
||||
.ssb_start = get_nrUE_params()->ssb_start_subcarrier,
|
||||
.used_by_ue = -1};
|
||||
return;
|
||||
}
|
||||
|
||||
nrue_cell_count = cellParamList.numelt;
|
||||
nrue_cell_fp = calloc_or_fail(nrue_cell_count, sizeof(NR_DL_FRAME_PARMS));
|
||||
nrue_cells = calloc_or_fail(nrue_cell_count, sizeof(nrUE_cell_params_t));
|
||||
|
||||
LOG_W(NR_PHY, "Ignoring command line cell parameters, using the following instead:\n");
|
||||
|
||||
for (int cell_id = 0; cell_id < nrue_cell_count; cell_id++) {
|
||||
nrue_cells[cell_id].ru_id = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RU_ID)->iptr);
|
||||
nrue_cells[cell_id].band = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_BAND)->iptr);
|
||||
nrue_cells[cell_id].rf_frequency = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RF_FREQUENCY)->u64ptr);
|
||||
nrue_cells[cell_id].rf_freq_offset = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_RF_FREQ_OFFSET)->i64ptr);
|
||||
nrue_cells[cell_id].numerology = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_NUMEROLOGY)->iptr);
|
||||
nrue_cells[cell_id].N_RB_DL = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_N_RB_DL)->iptr);
|
||||
nrue_cells[cell_id].ssb_start = *(gpd(cellParamList.paramarray[cell_id], sizeofArray(cellParams), NRUE_CELL_SSB_START)->iptr);
|
||||
nrue_cells[cell_id].used_by_ue = -1;
|
||||
|
||||
LOG_I(NR_PHY,
|
||||
"cell %d: ru_id %d, band %d, DL freq %lu, UL freq_offset %ld, numerology %d, N_RB_DL %d, ssb_start %d\n",
|
||||
cell_id,
|
||||
nrue_cells[cell_id].ru_id,
|
||||
nrue_cells[cell_id].band,
|
||||
nrue_cells[cell_id].rf_frequency,
|
||||
nrue_cells[cell_id].rf_freq_offset,
|
||||
nrue_cells[cell_id].numerology,
|
||||
nrue_cells[cell_id].N_RB_DL,
|
||||
nrue_cells[cell_id].ssb_start);
|
||||
}
|
||||
}
|
||||
|
||||
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_cell_id(int ru_id, int cell_id)
|
||||
{
|
||||
AssertFatal(ru_id >= 0 && ru_id < nrue_ru_count, "Invalid RU ID %d! RU count = %d\n", ru_id, nrue_ru_count);
|
||||
AssertFatal(cell_id >= 0 && cell_id < nrue_cell_count, "Invalid cell ID %d! Cell count = %d\n", cell_id, nrue_cell_count);
|
||||
nrue_rus[ru_id].used_by_cell = cell_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,
|
||||
.used_by_cell = -1};
|
||||
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].used_by_cell = -1;
|
||||
|
||||
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(void)
|
||||
{
|
||||
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);
|
||||
|
||||
for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) {
|
||||
int cell_id = nrue_rus[ru_id].used_by_cell;
|
||||
if (cell_id < 0) {
|
||||
LOG_W(PHY, "Skipping initialization of RU %d because it is not used by any cell!\n", ru_id);
|
||||
continue;
|
||||
}
|
||||
NR_DL_FRAME_PARMS *frame_parms = &nrue_cell_fp[cell_id];
|
||||
if (is_sidelink) {
|
||||
int UE_id = nrue_cells[cell_id].used_by_ue;
|
||||
if (UE_id < 0) {
|
||||
LOG_W(PHY, "Skipping initialization of RU %d because it is not used by any UE!\n", ru_id);
|
||||
continue;
|
||||
}
|
||||
extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
|
||||
frame_parms = &PHY_vars_UE_g[UE_id][0]->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
}
|
||||
|
||||
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->ru_id = ru_id;
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
void nrue_ru_set_freq(PHY_VARS_NR_UE *UE, uint64_t ul_carrier, uint64_t dl_carrier, int freq_offset)
|
||||
{
|
||||
int current_cell_id = nrue_rus[UE->rf_map.card].used_by_cell;
|
||||
NR_DL_FRAME_PARMS *fp0 = &nrue_cell_fp[current_cell_id];
|
||||
uint64_t dl_carrier_distance =
|
||||
fp0->dl_CarrierFreq > dl_carrier ? fp0->dl_CarrierFreq - dl_carrier : dl_carrier - fp0->dl_CarrierFreq;
|
||||
uint64_t ul_carrier_distance =
|
||||
fp0->ul_CarrierFreq > ul_carrier ? fp0->ul_CarrierFreq - ul_carrier : ul_carrier - fp0->ul_CarrierFreq;
|
||||
uint64_t carrier_distance = dl_carrier_distance + ul_carrier_distance;
|
||||
|
||||
for (int ru_id = 0; carrier_distance != 0 && ru_id < nrue_ru_count; ru_id++) {
|
||||
int cell_id = nrue_rus[ru_id].used_by_cell;
|
||||
if (cell_id < 0) // skip RUs that have no cell definition
|
||||
continue;
|
||||
if (nrue_cells[cell_id].used_by_ue >= 0) // skip cells that are already used by an UE
|
||||
continue;
|
||||
|
||||
fp0 = &nrue_cell_fp[cell_id];
|
||||
uint64_t this_dl_carrier_distance =
|
||||
fp0->dl_CarrierFreq > dl_carrier ? fp0->dl_CarrierFreq - dl_carrier : dl_carrier - fp0->dl_CarrierFreq;
|
||||
uint64_t this_ul_carrier_distance =
|
||||
fp0->ul_CarrierFreq > ul_carrier ? fp0->ul_CarrierFreq - ul_carrier : ul_carrier - fp0->ul_CarrierFreq;
|
||||
uint64_t this_carrier_distance = this_dl_carrier_distance + this_ul_carrier_distance;
|
||||
if (this_carrier_distance < carrier_distance) {
|
||||
UE->rf_map.card = ru_id;
|
||||
carrier_distance = this_carrier_distance;
|
||||
}
|
||||
}
|
||||
|
||||
nrue_cells[current_cell_id].used_by_ue = -1;
|
||||
current_cell_id = nrue_rus[UE->rf_map.card].used_by_cell;
|
||||
nrue_cells[current_cell_id].used_by_ue = UE->Mod_id;
|
||||
|
||||
openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card];
|
||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
dev0->trx_set_freq_func(dev0, cfg0);
|
||||
}
|
||||
|
||||
int nrue_ru_adjust_rx_gain(PHY_VARS_NR_UE *UE, int gain_change)
|
||||
{
|
||||
openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card];
|
||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
||||
|
||||
// Increase the RX gain by the value determined by adjust_rxgain
|
||||
cfg0->rx_gain[0] += gain_change;
|
||||
|
||||
// Set new RX gain.
|
||||
int ret_gain = dev0->trx_set_gains_func(dev0, cfg0);
|
||||
// APPLY RX gain again if crossed the MAX RX gain threshold
|
||||
if (ret_gain < 0) {
|
||||
gain_change += ret_gain;
|
||||
cfg0->rx_gain[0] += ret_gain;
|
||||
ret_gain = dev0->trx_set_gains_func(dev0, cfg0);
|
||||
}
|
||||
|
||||
int applied_rxgain = cfg0->rx_gain[0] - cfg0->rx_gain_offset[0];
|
||||
LOG_I(HW, "Rxgain adjusted by %d dB, RX gain: %d dB \n", gain_change, applied_rxgain);
|
||||
|
||||
return gain_change;
|
||||
}
|
||||
|
||||
int nrue_ru_read(PHY_VARS_NR_UE *UE, openair0_timestamp_t *ptimestamp, void **buff, int nsamps, int num_antennas)
|
||||
{
|
||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
||||
openair0_timestamp_t tmp_timestamp;
|
||||
int ret = dev0->trx_read_func(dev0, &tmp_timestamp, buff, nsamps, num_antennas);
|
||||
if (!dev0->firstTS_initialized) {
|
||||
dev0->firstTS = tmp_timestamp;
|
||||
dev0->firstTS_initialized = true;
|
||||
}
|
||||
*ptimestamp = tmp_timestamp - dev0->firstTS;
|
||||
|
||||
if (UE->Mod_id != 0)
|
||||
return ret;
|
||||
|
||||
// UE 0 needs to read from all RUs that are not used by any other UE
|
||||
|
||||
void *tmp_buf[num_antennas];
|
||||
uint32_t tmp_samples[nsamps];
|
||||
for (int ant = 0; ant < num_antennas; ant++)
|
||||
tmp_buf[ant] = tmp_samples;
|
||||
|
||||
for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) {
|
||||
int cell_id = nrue_rus[ru_id].used_by_cell;
|
||||
if (cell_id < 0) // skip RUs that have no cell definition
|
||||
continue;
|
||||
int ue_id = nrue_cells[cell_id].used_by_ue;
|
||||
if (ue_id >= 0) // skip cells that are already used by an UE
|
||||
continue;
|
||||
|
||||
dev0 = &openair0_dev[ru_id];
|
||||
dev0->trx_read_func(dev0, &tmp_timestamp, tmp_buf, nsamps, num_antennas);
|
||||
if (!dev0->firstTS_initialized) {
|
||||
dev0->firstTS = tmp_timestamp;
|
||||
dev0->firstTS_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int nrue_ru_write(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **buff, int nsamps, int num_antennas, int flags)
|
||||
{
|
||||
openair0_device_t *dev0 = &openair0_dev[UE->rf_map.card];
|
||||
int ret = dev0->trx_write_func(dev0, timestamp + dev0->firstTS, buff, nsamps, num_antennas, flags);
|
||||
|
||||
if (UE->Mod_id != 0)
|
||||
return ret;
|
||||
|
||||
// UE 0 needs to write to all RUs that are not used by any other UE
|
||||
|
||||
void *tmp_buf[num_antennas];
|
||||
uint32_t tmp_samples[nsamps];
|
||||
memset(tmp_samples, 0, sizeof(tmp_samples));
|
||||
for (int ant = 0; ant < num_antennas; ant++)
|
||||
tmp_buf[ant] = tmp_samples;
|
||||
|
||||
for (int ru_id = 0; ru_id < nrue_ru_count; ru_id++) {
|
||||
int cell_id = nrue_rus[ru_id].used_by_cell;
|
||||
if (cell_id < 0) // skip RUs that have no cell definition
|
||||
continue;
|
||||
int ue_id = nrue_cells[cell_id].used_by_ue;
|
||||
if (ue_id >= 0) // skip cells that are already used by an UE
|
||||
continue;
|
||||
|
||||
dev0 = &openair0_dev[ru_id];
|
||||
dev0->trx_write_func(dev0, timestamp + dev0->firstTS, tmp_buf, nsamps, num_antennas, flags);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
typedef int (*nrue_ru_write_t)(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags);
|
||||
int openair0_write_reorder_common(nrue_ru_write_t nrue_ru_write,
|
||||
PHY_VARS_NR_UE *UE,
|
||||
openair0_device_t *device,
|
||||
openair0_timestamp_t timestamp,
|
||||
void **txp,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int flags);
|
||||
|
||||
int nrue_ru_write_reorder(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags)
|
||||
{
|
||||
openair0_device_t *device = &openair0_dev[UE->rf_map.card];
|
||||
return openair0_write_reorder_common(nrue_ru_write, UE, device, timestamp, txp, nsamps, nbAnt, flags);
|
||||
}
|
||||
|
||||
void nrue_ru_write_reorder_clear_context(PHY_VARS_NR_UE *UE)
|
||||
{
|
||||
openair0_device_t *device = &openair0_dev[UE->rf_map.card];
|
||||
openair0_write_reorder_clear_context(device);
|
||||
}
|
||||
50
executables/nr-ue-ru.h
Normal file
50
executables/nr-ue-ru.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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_cell_count(void);
|
||||
const nrUE_cell_params_t *nrue_get_cell(int cell_id);
|
||||
NR_DL_FRAME_PARMS *nrue_get_cell_fp(int cell_id);
|
||||
void nrue_set_cell(int cell_id, const nrUE_cell_params_t *cell);
|
||||
void nrue_set_cell_params(configmodule_interface_t *cfg);
|
||||
|
||||
int nrue_get_ru_count(void);
|
||||
const nrUE_RU_params_t *nrue_get_ru(int ru_id);
|
||||
void nrue_set_ru_cell_id(int ru_id, int cell_id);
|
||||
void nrue_set_ru_params(configmodule_interface_t *cfg);
|
||||
|
||||
void nrue_init_openair0(void);
|
||||
|
||||
void nrue_ru_start(void);
|
||||
void nrue_ru_end(void);
|
||||
void nrue_ru_set_freq(PHY_VARS_NR_UE *UE, uint64_t ul_carrier, uint64_t dl_carrier, int freq_offset);
|
||||
int nrue_ru_adjust_rx_gain(PHY_VARS_NR_UE *UE, int gain_change);
|
||||
int nrue_ru_read(PHY_VARS_NR_UE *UE, openair0_timestamp_t *ptimestamp, void **buff, int nsamps, int num_antennas);
|
||||
int nrue_ru_write(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **buff, int nsamps, int num_antennas, int flags);
|
||||
int nrue_ru_write_reorder(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, void **txp, int nsamps, int nbAnt, int flags);
|
||||
void nrue_ru_write_reorder_clear_context(PHY_VARS_NR_UE *UE);
|
||||
|
||||
#endif
|
||||
@@ -23,6 +23,7 @@
|
||||
#define _GNU_SOURCE // For pthread_setname_np
|
||||
#include <pthread.h>
|
||||
#include <openair1/PHY/impl_defs_top.h>
|
||||
#include "executables/nr-ue-ru.h"
|
||||
#include "executables/nr-uesoftmodem.h"
|
||||
#include "PHY/INIT/nr_phy_init.h"
|
||||
#include "NR_MAC_UE/mac_proto.h"
|
||||
@@ -201,31 +202,10 @@ typedef struct {
|
||||
int rx_offset;
|
||||
} syncData_t;
|
||||
|
||||
static int nr_ue_adjust_rx_gain(PHY_VARS_NR_UE *UE, openair0_config_t *cfg0, int gain_change)
|
||||
{
|
||||
// Increase the RX gain by the value determined by adjust_rxgain
|
||||
cfg0->rx_gain[0] += gain_change;
|
||||
|
||||
// Set new RX gain.
|
||||
int ret_gain = UE->rfdevice.trx_set_gains_func(&UE->rfdevice, cfg0);
|
||||
// APPLY RX gain again if crossed the MAX RX gain threshold
|
||||
if (ret_gain < 0) {
|
||||
gain_change += ret_gain;
|
||||
cfg0->rx_gain[0] += ret_gain;
|
||||
ret_gain = UE->rfdevice.trx_set_gains_func(&UE->rfdevice, cfg0);
|
||||
}
|
||||
|
||||
int applied_rxgain = cfg0->rx_gain[0] - cfg0->rx_gain_offset[0];
|
||||
LOG_I(PHY, "Rxgain adjusted by %d dB, RX gain: %d dB \n", gain_change, applied_rxgain);
|
||||
|
||||
return gain_change;
|
||||
}
|
||||
|
||||
static void UE_synch(void *arg) {
|
||||
syncData_t *syncD = (syncData_t *)arg;
|
||||
PHY_VARS_NR_UE *UE = syncD->UE;
|
||||
UE->is_synchronized = 0;
|
||||
openair0_config_t *cfg0 = &UE->openair0_cfg[UE->rf_map.card];
|
||||
|
||||
if (UE->target_Nid_cell != -1) {
|
||||
LOG_W(NR_PHY, "Starting re-sync detection for target Nid_cell %i\n", UE->target_Nid_cell);
|
||||
@@ -259,27 +239,20 @@ static void UE_synch(void *arg) {
|
||||
UE->freq_offset = freq_offset - UE->dl_Doppler_shift;
|
||||
} else {
|
||||
// rerun with new cell parameters and frequency-offset
|
||||
nr_rf_card_config_freq(cfg0, ul_carrier, dl_carrier, freq_offset);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, cfg0);
|
||||
nrue_ru_set_freq(UE, ul_carrier, dl_carrier, freq_offset);
|
||||
}
|
||||
|
||||
if (get_nrUE_params()->agc) {
|
||||
nr_ue_adjust_rx_gain(UE, cfg0, UE->adjust_rxgain);
|
||||
nrue_ru_adjust_rx_gain(UE, UE->adjust_rxgain);
|
||||
}
|
||||
|
||||
LOG_I(PHY,
|
||||
"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %f (DL %f Hz, UL %f Hz)\n",
|
||||
hw_slot_offset,
|
||||
freq_offset,
|
||||
cfg0->rx_gain[0] - cfg0->rx_gain_offset[0],
|
||||
cfg0->rx_freq[0],
|
||||
cfg0->tx_freq[0]);
|
||||
LOG_I(PHY, "Got synch: hw_slot_offset %d, carrier off %d Hz\n", hw_slot_offset, freq_offset);
|
||||
|
||||
UE->is_synchronized = 1;
|
||||
} else {
|
||||
int gain_change = 0;
|
||||
if (get_nrUE_params()->agc)
|
||||
gain_change = nr_ue_adjust_rx_gain(UE, cfg0, INCREASE_IN_RXGAIN);
|
||||
gain_change = nrue_ru_adjust_rx_gain(UE, INCREASE_IN_RXGAIN);
|
||||
if (gain_change)
|
||||
LOG_I(PHY, "synch retry: Rx gain increased \n");
|
||||
else
|
||||
@@ -334,7 +307,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
radio_tx_burst_flag_t flags = TX_BURST_INVALID;
|
||||
|
||||
if (UE->received_config_request) {
|
||||
if (UE->openair0_cfg[0].duplex_mode == duplex_mode_FDD || get_softmodem_params()->continuous_tx) {
|
||||
if (fp->frame_type == FDD || get_softmodem_params()->continuous_tx) {
|
||||
flags = TX_BURST_MIDDLE;
|
||||
// In case of Sidelink, USRP write needed only in case transmission
|
||||
// needs to be done in this slot and not based on tdd ULDL configuration.
|
||||
@@ -379,13 +352,13 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
}
|
||||
}
|
||||
|
||||
openair0_timestamp writeTimestamp = proc->timestamp_tx;
|
||||
openair0_timestamp_t writeTimestamp = proc->timestamp_tx;
|
||||
int writeBlockSize = rxtxD->writeBlockSize;
|
||||
// if writeBlockSize gets longer that slot size, fill with dummy
|
||||
const int maxWriteBlockSize = get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
while (writeBlockSize > maxWriteBlockSize) {
|
||||
const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, maxWriteBlockSize);
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags);
|
||||
int tmp = nrue_ru_write_reorder(UE, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags);
|
||||
AssertFatal(tmp == dummyBlockSize, "");
|
||||
|
||||
writeTimestamp += dummyBlockSize;
|
||||
@@ -408,7 +381,7 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
writeBlockSize);
|
||||
}
|
||||
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
int tmp = nrue_ru_write_reorder(UE, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
AssertFatal(tmp == writeBlockSize, "");
|
||||
}
|
||||
|
||||
@@ -523,10 +496,9 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
|
||||
ul_CarrierFreq,
|
||||
cfg->dl_frequency,
|
||||
UE->target_Nid_cell);
|
||||
nrue_ru_set_freq(UE, ul_CarrierFreq, dl_CarrierFreq, 0);
|
||||
fp->dl_CarrierFreq = dl_CarrierFreq;
|
||||
fp->ul_CarrierFreq = ul_CarrierFreq;
|
||||
nr_rf_card_config_freq(&UE->openair0_cfg[UE->rf_map.card], ul_CarrierFreq, dl_CarrierFreq, 0);
|
||||
UE->rfdevice.trx_set_freq_func(&UE->rfdevice, &UE->openair0_cfg[UE->rf_map.card]);
|
||||
init_symbol_rotation(fp);
|
||||
}
|
||||
|
||||
@@ -647,23 +619,24 @@ void UE_dl_processing(void *arg) {
|
||||
TracyCZoneEnd(ctx);
|
||||
}
|
||||
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockSize) {
|
||||
void dummyWrite(PHY_VARS_NR_UE *UE, openair0_timestamp_t timestamp, int writeBlockSize)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
fp = &UE->SL_UE_PHY_PARAMS.sl_frame_params;
|
||||
|
||||
void *dummy_tx[fp->nb_antennas_tx];
|
||||
// 2 because the function we call use pairs of int16_t implicitly as complex numbers
|
||||
int16_t dummy_tx_data[fp->nb_antennas_tx][2 * writeBlockSize];
|
||||
int16_t dummy_tx_data[2 * writeBlockSize];
|
||||
memset(dummy_tx_data, 0, sizeof(dummy_tx_data));
|
||||
for (int i = 0; i < fp->nb_antennas_tx; i++)
|
||||
dummy_tx[i]=dummy_tx_data[i];
|
||||
dummy_tx[i] = dummy_tx_data;
|
||||
|
||||
int tmp = UE->rfdevice.trx_write_func(&UE->rfdevice, timestamp, dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4);
|
||||
int tmp = nrue_ru_write(UE, timestamp, dummy_tx, writeBlockSize, fp->nb_antennas_tx, 4);
|
||||
AssertFatal(writeBlockSize == tmp, "");
|
||||
}
|
||||
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, bool toTrash)
|
||||
void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, bool toTrash)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
// two frames for initial sync
|
||||
@@ -675,9 +648,11 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
|
||||
}
|
||||
|
||||
void *rxp[NB_ANTENNAS_RX];
|
||||
if (toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = malloc16(get_samples_per_slot(0, fp) * 4);
|
||||
if (toTrash) {
|
||||
rxp[0] = malloc16(get_samples_per_slot(0, fp) * 4);
|
||||
for (int i = 1; i < fp->nb_antennas_rx; i++)
|
||||
rxp[i] = rxp[0];
|
||||
}
|
||||
|
||||
for (int x = 0; x < num_frames * NR_NUMBER_OF_SUBFRAMES_PER_FRAME; x++) { // two frames for initial sync
|
||||
for (int slot = 0; slot < fp->slots_per_subframe; slot++) {
|
||||
@@ -687,13 +662,13 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
|
||||
((void *)&UE->common_vars.rxdata[i][0]) + 4 * ((x * fp->samples_per_subframe) + get_samples_slot_timestamp(fp, slot));
|
||||
|
||||
int read_block_size = get_samples_per_slot(slot, fp);
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, rxp, read_block_size, fp->nb_antennas_rx);
|
||||
int tmp = nrue_ru_read(UE, timestamp, rxp, read_block_size, fp->nb_antennas_rx);
|
||||
UEscopeCopy(UE, ueTimeDomainSamplesBeforeSync, rxp[0], sizeof(c16_t), 1, read_block_size, 0);
|
||||
AssertFatal(read_block_size == tmp, "");
|
||||
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
const openair0_timestamp_t writeTimestamp =
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, get_samples_per_slot(slot, fp));
|
||||
}
|
||||
@@ -701,11 +676,10 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_r
|
||||
}
|
||||
|
||||
if (toTrash)
|
||||
for (int i = 0; i < fp->nb_antennas_rx; i++)
|
||||
free(rxp[i]);
|
||||
free(rxp[0]);
|
||||
}
|
||||
|
||||
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, openair0_timestamp rx_offset)
|
||||
static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp_t *timestamp, int duration_rx_to_tx, openair0_timestamp_t rx_offset)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
if (UE->sl_mode == 2)
|
||||
@@ -717,11 +691,11 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int d
|
||||
int size = rx_offset;
|
||||
while (size > 0) {
|
||||
const int unitTransfer = min(get_samples_per_slot(slot, fp), size);
|
||||
const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
const int res = nrue_ru_read(UE, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx);
|
||||
DevAssert(unitTransfer == res);
|
||||
if (IS_SOFTMODEM_RFSIM) {
|
||||
int ta = UE->timing_advance + UE->timing_advance_ntn;
|
||||
const openair0_timestamp writeTimestamp =
|
||||
const openair0_timestamp_t writeTimestamp =
|
||||
*timestamp + get_samples_slot_duration(fp, slot, duration_rx_to_tx) - UE->N_TA_offset - ta;
|
||||
dummyWrite(UE, writeTimestamp, unitTransfer);
|
||||
}
|
||||
@@ -745,13 +719,11 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
|
||||
void *UE_thread(void *arg)
|
||||
{
|
||||
//this thread should be over the processing thread to keep in real time
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
|
||||
PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *)arg;
|
||||
// int tx_enabled = 0;
|
||||
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(&(UE->rfdevice), &UE->openair0_cfg[0]);
|
||||
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) {
|
||||
@@ -759,13 +731,7 @@ void *UE_thread(void *arg)
|
||||
sl_cfg = &UE->SL_UE_PHY_PARAMS.sl_config;
|
||||
}
|
||||
|
||||
UE->rfdevice.host_type = RAU_HOST;
|
||||
UE->is_synchronized = 0;
|
||||
int tmp2 = UE->rfdevice.trx_start_func(&UE->rfdevice);
|
||||
AssertFatal(tmp2 == 0, "Could not start the device\n");
|
||||
if (usrp_tx_thread == 1)
|
||||
UE->rfdevice.trx_write_init(&UE->rfdevice);
|
||||
|
||||
InitSinLUT();
|
||||
|
||||
notifiedFIFO_t nf;
|
||||
@@ -798,14 +764,14 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
int shiftForNextFrame = 0;
|
||||
int intialSyncOffset = 0;
|
||||
openair0_timestamp sync_timestamp;
|
||||
openair0_timestamp_t sync_timestamp;
|
||||
bool stats_printed = false;
|
||||
|
||||
if (get_softmodem_params()->sync_ref && UE->sl_mode == 2) {
|
||||
UE->is_synchronized = 1;
|
||||
} else {
|
||||
//warm up the RF board
|
||||
int64_t tmp;
|
||||
openair0_timestamp_t tmp;
|
||||
for (int i = 0; i < 50; i++)
|
||||
readFrame(UE, &tmp, duration_rx_to_tx, true);
|
||||
}
|
||||
@@ -845,7 +811,9 @@ void *UE_thread(void *arg)
|
||||
/* For IQ recorder-player we force synchronization to happen in a fixed duration so that
|
||||
the replay runs in sync with recorded samples.
|
||||
*/
|
||||
const unsigned int sync_in_frames = UE->rfdevice.openair0_cfg->recplay_conf->u_f_sync;
|
||||
extern openair0_config_t openair0_cfg[MAX_CARDS];
|
||||
openair0_config_t *cfg0 = &openair0_cfg[UE->rf_map.card];
|
||||
const unsigned int sync_in_frames = cfg0->recplay_conf->u_f_sync;
|
||||
while (trashed_frames != sync_in_frames) {
|
||||
readFrame(UE, &sync_timestamp, duration_rx_to_tx, true);
|
||||
trashed_frames += 2;
|
||||
@@ -886,16 +854,16 @@ void *UE_thread(void *arg)
|
||||
if (stream_status == STREAM_STATUS_UNSYNC) {
|
||||
stream_status = STREAM_STATUS_SYNCING;
|
||||
syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset);
|
||||
openair0_write_reorder_clear_context(&UE->rfdevice);
|
||||
nrue_ru_write_reorder_clear_context(UE);
|
||||
shiftForNextFrame = -(UE->init_sync_frame + trashed_frames + 2) * UE->max_pos_acc * get_nrUE_params()->time_sync_I; // compensate for the time drift that happened during initial sync
|
||||
LOG_I(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame);
|
||||
// read in first symbol
|
||||
AssertFatal(fp->ofdm_symbol_size + fp->nb_prefix_samples0
|
||||
== UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
&sync_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
fp->ofdm_symbol_size + fp->nb_prefix_samples0,
|
||||
fp->nb_antennas_rx),
|
||||
== nrue_ru_read(UE,
|
||||
&sync_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
fp->ofdm_symbol_size + fp->nb_prefix_samples0,
|
||||
fp->nb_antennas_rx),
|
||||
"");
|
||||
// we have the decoded frame index in the return of the synch process
|
||||
// and we shifted above to the first slot of next frame
|
||||
@@ -995,8 +963,8 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
|
||||
openair0_timestamp rx_timestamp;
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
openair0_timestamp_t rx_timestamp;
|
||||
int tmp = nrue_ru_read(UE, &rx_timestamp, rxp, readBlockSize, fp->nb_antennas_rx);
|
||||
metadata meta = {.slot = curMsg.proc.nr_slot_rx, .frame = curMsg.proc.frame_rx};
|
||||
UEscopeCopyWithMetadata(UE, ueTimeDomainSamples, rxp[0] - firstSymSamp * sizeof(c16_t), sizeof(c16_t), 1, readBlockSize, 0, &meta);
|
||||
AssertFatal(readBlockSize == tmp, "");
|
||||
@@ -1010,12 +978,8 @@ void *UE_thread(void *arg)
|
||||
int first_symbols = fp->ofdm_symbol_size + fp->nb_prefix_samples0; // first symbol of every frames
|
||||
|
||||
if (first_symbols > 0) {
|
||||
openair0_timestamp ignore_timestamp;
|
||||
int tmp = UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
&ignore_timestamp,
|
||||
(void **)UE->common_vars.rxdata,
|
||||
first_symbols,
|
||||
fp->nb_antennas_rx);
|
||||
openair0_timestamp_t ignore_timestamp;
|
||||
int tmp = nrue_ru_read(UE, &ignore_timestamp, (void **)UE->common_vars.rxdata, first_symbols, fp->nb_antennas_rx);
|
||||
AssertFatal(first_symbols == tmp, "");
|
||||
|
||||
} else
|
||||
@@ -1023,13 +987,13 @@ void *UE_thread(void *arg)
|
||||
}
|
||||
|
||||
// use previous timing_advance value to compute writeTimestamp
|
||||
const openair0_timestamp writeTimestamp =
|
||||
const openair0_timestamp_t writeTimestamp =
|
||||
rx_timestamp + get_samples_slot_duration(fp, slot_nr, duration_rx_to_tx) - firstSymSamp - UE->N_TA_offset - timing_advance;
|
||||
|
||||
// Calculate TX deadline, approximately 1 symbol before the first sample should be written
|
||||
const uint64_t samples_diff = writeTimestamp - rx_timestamp - fp->ofdm_symbol_size;
|
||||
const float deadline_us = samples_diff / UE->rfdevice.openair0_cfg->sample_rate * 1e6;
|
||||
const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec / 1e3 + deadline_us;
|
||||
const float deadline_us = samples_diff * 1e3 / fp->samples_per_subframe;
|
||||
const uint64_t absolute_deadline_us = current_time.tv_sec * 1e6 + current_time.tv_nsec * 1e-3 + deadline_us;
|
||||
|
||||
// but use current UE->timing_advance value to compute writeBlockSize
|
||||
int writeBlockSize = get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply;
|
||||
@@ -1106,11 +1070,11 @@ void *UE_thread(void *arg)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file)
|
||||
void init_NR_UE(int nb_inst, char *uecap_file, char *reconfig_file, char *rbconfig_file, int numerology)
|
||||
{
|
||||
for (int instance_id = 0; instance_id < nb_inst; instance_id++) {
|
||||
NR_UE_RRC_INST_t* rrc = nr_rrc_init_ue(uecap_file, instance_id, get_nrUE_params()->nb_antennas_tx);
|
||||
NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id);
|
||||
NR_UE_MAC_INST_t *mac = nr_l2_init_ue(instance_id, numerology);
|
||||
|
||||
nr_rrc_set_mac_queue(instance_id, &mac->input_nf);
|
||||
mac->if_module = nr_ue_if_module_init(instance_id);
|
||||
|
||||
@@ -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 <executables/nr-uesoftmodem.h>
|
||||
#include "executables/softmodem-common.h"
|
||||
#include "executables/thread-common.h"
|
||||
@@ -102,10 +103,6 @@ int get_node_type() {return -1;}
|
||||
RAN_CONTEXT_t RC;
|
||||
int oai_exit = 0;
|
||||
|
||||
static int tx_max_power[MAX_NUM_CCs] = {0};
|
||||
|
||||
double rx_gain_off = 0.0;
|
||||
|
||||
uint64_t downlink_frequency[MAX_NUM_CCs][4];
|
||||
int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
uint64_t sidelink_frequency[MAX_NUM_CCs][4];
|
||||
@@ -138,21 +135,11 @@ int create_tasks_nrue(uint32_t ue_nb) {
|
||||
|
||||
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert)
|
||||
{
|
||||
int CC_id;
|
||||
LOG_W(NR_PHY, "called by: %s:%d %s() Exiting OAI softmodem: %s\n", file, line, function, s ? s : "no msg");
|
||||
|
||||
oai_exit = 1;
|
||||
|
||||
if (PHY_vars_UE_g && PHY_vars_UE_g[0]) {
|
||||
for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
|
||||
if (PHY_vars_UE_g[0][CC_id] && PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func) {
|
||||
if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func) {
|
||||
PHY_vars_UE_g[0][CC_id]->rfdevice.trx_get_stats_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
|
||||
}
|
||||
PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
nrue_ru_end();
|
||||
|
||||
if (assert) {
|
||||
abort();
|
||||
@@ -188,20 +175,22 @@ 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){
|
||||
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
|
||||
static void set_UE_options(int CC_id, PHY_VARS_NR_UE *UE, int ru_id)
|
||||
{
|
||||
const nrUE_RU_params_t *RU = nrue_get_ru(ru_id);
|
||||
|
||||
// Set UE variables
|
||||
UE->rx_total_gain_dB = (int)nrUE_params.rx_gain + rx_gain_off;
|
||||
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;
|
||||
@@ -210,76 +199,21 @@ void set_options(int CC_id, PHY_VARS_NR_UE *UE){
|
||||
|
||||
LOG_I(PHY,"Set UE_fo_compensation %d, UE_scan_carrier %d, UE_no_timing_correction %d \n, chest-freq %d, chest-time %d\n",
|
||||
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 = nrUE_params.nb_antennas_rx;
|
||||
fp->nb_antennas_tx = nrUE_params.nb_antennas_tx;
|
||||
fp->threequarter_fs = get_softmodem_params()->threequarter_fs;
|
||||
fp->N_RB_DL = nrUE_params.N_RB_DL;
|
||||
fp->ssb_start_subcarrier = nrUE_params.ssb_start_subcarrier;
|
||||
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, ssb_start_subcarrier %d\n", fp->nb_antennas_rx, fp->nb_antennas_tx, fp->threequarter_fs, fp->ssb_start_subcarrier);
|
||||
|
||||
}
|
||||
|
||||
void init_openair0(PHY_VARS_NR_UE *ue)
|
||||
static void set_fp_options(int cell_id, int ru_id)
|
||||
{
|
||||
int card;
|
||||
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;
|
||||
NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id);
|
||||
const nrUE_RU_params_t *RU = nrue_get_ru(ru_id);
|
||||
|
||||
for (card=0; card<MAX_CARDS; card++) {
|
||||
openair0_config_t *cfg = &ue->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;
|
||||
// Set FP variables
|
||||
fp->nb_antennas_rx = RU->nb_rx;
|
||||
fp->nb_antennas_tx = RU->nb_tx;
|
||||
|
||||
if (frame_parms->frame_type==TDD)
|
||||
cfg->duplex_mode = duplex_mode_TDD;
|
||||
else
|
||||
cfg->duplex_mode = duplex_mode_FDD;
|
||||
fp->threequarter_fs = get_softmodem_params()->threequarter_fs;
|
||||
fp->ofdm_offset_divisor = nrUE_params.ofdm_offset_divisor;
|
||||
|
||||
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, rx_gain_off);
|
||||
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
// Stupid function addition because UE itti messages queues definition is common with eNB
|
||||
@@ -324,7 +258,6 @@ int main(int argc, char **argv)
|
||||
}
|
||||
//set_softmodem_sighandler();
|
||||
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||
memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
|
||||
// initialize logging
|
||||
logInit();
|
||||
// get options and fill parameters from configuration file
|
||||
@@ -379,7 +312,14 @@ int main(int argc, char **argv)
|
||||
nr_pdcp_layer_init();
|
||||
nas_init_nrue(NB_UE_INST);
|
||||
|
||||
init_NR_UE(NB_UE_INST, get_nrUE_params()->uecap_file, get_nrUE_params()->reconfig_file, get_nrUE_params()->rbconfig_file);
|
||||
nrue_set_ru_params(uniqCfg);
|
||||
nrue_set_cell_params(uniqCfg);
|
||||
|
||||
init_NR_UE(NB_UE_INST,
|
||||
get_nrUE_params()->uecap_file,
|
||||
get_nrUE_params()->reconfig_file,
|
||||
get_nrUE_params()->rbconfig_file,
|
||||
nrue_get_cell(0)->numerology);
|
||||
|
||||
// start time manager with some reasonable default for the running mode
|
||||
// (may be overwritten in configuration file or command line)
|
||||
@@ -396,24 +336,52 @@ int main(int argc, char **argv)
|
||||
IS_SOFTMODEM_RFSIM ? TIME_SOURCE_IQ_SAMPLES
|
||||
: TIME_SOURCE_REALTIME);
|
||||
|
||||
// initialize per-cell frame parameters
|
||||
for (int cell_id = 0; cell_id < nrue_get_cell_count(); cell_id++) {
|
||||
int ru_id = nrue_get_cell(cell_id)->ru_id;
|
||||
AssertFatal(ru_id >= 0 && ru_id < nrue_get_ru_count(),
|
||||
"Invalid ru_id (%d) for cell %d. Should be >= 0 and < %d\n",
|
||||
ru_id,
|
||||
cell_id,
|
||||
nrue_get_ru_count());
|
||||
AssertFatal(nrue_get_ru(ru_id)->used_by_cell == -1,
|
||||
"RU %d is already used by cell %d and therefore cannot also be used by cell %d\n",
|
||||
ru_id,
|
||||
nrue_get_ru(ru_id)->used_by_cell,
|
||||
cell_id);
|
||||
nrue_set_ru_cell_id(ru_id, cell_id);
|
||||
|
||||
set_fp_options(cell_id, ru_id);
|
||||
if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode)
|
||||
nr_init_frame_parms_ue_sa(nrue_get_cell_fp(cell_id), nrue_get_cell(cell_id));
|
||||
}
|
||||
|
||||
int cell_id = 0;
|
||||
for (int inst = 0; inst < NB_UE_INST; inst++) {
|
||||
PHY_VARS_NR_UE *UE[MAX_NUM_CCs];
|
||||
NR_UE_MAC_INST_t *mac = get_mac_inst(inst);
|
||||
|
||||
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]);
|
||||
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
|
||||
if (IS_SA_MODE(get_softmodem_params()) || get_softmodem_params()->sl_mode) {
|
||||
uint16_t nr_band = get_softmodem_params()->band;
|
||||
mac->nr_band = nr_band;
|
||||
mac->ssb_start_subcarrier = UE[CC_id]->frame_parms.ssb_start_subcarrier;
|
||||
nr_init_frame_parms_ue_sa(&UE[CC_id]->frame_parms,
|
||||
downlink_frequency[CC_id][0],
|
||||
uplink_frequency_offset[CC_id][0],
|
||||
get_softmodem_params()->numerology,
|
||||
nr_band);
|
||||
} else {
|
||||
PHY_VARS_NR_UE *UE_CC = PHY_vars_UE_g[inst][CC_id];
|
||||
|
||||
AssertFatal(cell_id >= 0 && cell_id < nrue_get_cell_count(),
|
||||
"There are not enough cell definitions for all UEs! NB_UE_INST = %d, MAX_NUM_CCs = %d, nrue_cell_count = %d\n",
|
||||
NB_UE_INST,
|
||||
MAX_NUM_CCs,
|
||||
nrue_get_cell_count());
|
||||
nrUE_cell_params_t cell = *nrue_get_cell(cell_id);
|
||||
|
||||
AssertFatal(cell.used_by_ue == -1,
|
||||
"Cell %d is already used by UE %d and cannot also be used by UE %d as cells map 1:1 to RUs and RU sharing is not implemented\n",
|
||||
cell_id,
|
||||
cell.used_by_ue,
|
||||
inst);
|
||||
cell.used_by_ue = inst;
|
||||
|
||||
set_UE_options(CC_id, UE_CC, cell.ru_id);
|
||||
init_nr_ue_phy_cpu_stats(&UE_CC->phy_cpu_stats);
|
||||
|
||||
NR_DL_FRAME_PARMS *fp = nrue_get_cell_fp(cell_id);
|
||||
if (!IS_SA_MODE(get_softmodem_params()) && !get_softmodem_params()->sl_mode) {
|
||||
do {
|
||||
notifiedFIFO_elt_t *elt = pollNotifiedFIFO(&mac->input_nf);
|
||||
if (!elt) {
|
||||
@@ -422,44 +390,60 @@ int main(int argc, char **argv)
|
||||
process_msg_rcc_to_mac(NotifiedFifoData(elt), inst);
|
||||
delNotifiedFIFO_elt(elt);
|
||||
} while (true);
|
||||
fapi_nr_config_request_t *nrUE_config = &UE[CC_id]->nrUE_config;
|
||||
nr_init_frame_parms_ue(&UE[CC_id]->frame_parms, nrUE_config, mac->nr_band);
|
||||
}
|
||||
fapi_nr_config_request_t *nrUE_config = &UE_CC->nrUE_config;
|
||||
nr_init_frame_parms_ue(fp, nrUE_config, mac->nr_band);
|
||||
|
||||
UE[CC_id]->sl_mode = get_softmodem_params()->sl_mode;
|
||||
init_actor(&UE[CC_id]->sync_actor, "SYNC_", -1);
|
||||
cell.band = fp->nr_band;
|
||||
cell.rf_frequency = fp->dl_CarrierFreq;
|
||||
cell.rf_freq_offset = fp->ul_CarrierFreq - fp->dl_CarrierFreq;
|
||||
cell.numerology = fp->numerology_index;
|
||||
cell.N_RB_DL = fp->N_RB_DL;
|
||||
cell.ssb_start = fp->ssb_start_subcarrier;
|
||||
}
|
||||
nrue_set_cell(cell_id, &cell);
|
||||
|
||||
UE_CC->frame_parms = *fp;
|
||||
mac->nr_band = cell.band;
|
||||
mac->ssb_start_subcarrier = cell.ssb_start;
|
||||
mac->dl_frequency = cell.rf_frequency;
|
||||
|
||||
UE_CC->sl_mode = get_softmodem_params()->sl_mode;
|
||||
init_actor(&UE_CC->sync_actor, "SYNC_", -1);
|
||||
if (get_nrUE_params()->num_dl_actors > 0) {
|
||||
UE[CC_id]->dl_actors = calloc_or_fail(get_nrUE_params()->num_dl_actors, sizeof(*UE[CC_id]->dl_actors));
|
||||
UE_CC->dl_actors = calloc_or_fail(get_nrUE_params()->num_dl_actors, sizeof(*UE_CC->dl_actors));
|
||||
for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) {
|
||||
init_actor(&UE[CC_id]->dl_actors[i], "DL_", -1);
|
||||
init_actor(&UE_CC->dl_actors[i], "DL_", -1);
|
||||
}
|
||||
}
|
||||
if (get_nrUE_params()->num_ul_actors > 0) {
|
||||
UE[CC_id]->ul_actors = calloc_or_fail(get_nrUE_params()->num_ul_actors, sizeof(*UE[CC_id]->ul_actors));
|
||||
UE_CC->ul_actors = calloc_or_fail(get_nrUE_params()->num_ul_actors, sizeof(*UE_CC->ul_actors));
|
||||
for (int i = 0; i < get_nrUE_params()->num_ul_actors; i++) {
|
||||
init_actor(&UE[CC_id]->ul_actors[i], "UL_", -1);
|
||||
init_actor(&UE_CC->ul_actors[i], "UL_", -1);
|
||||
}
|
||||
}
|
||||
init_nr_ue_vars(UE[CC_id], inst);
|
||||
init_nr_ue_vars(UE_CC, inst);
|
||||
|
||||
if (UE[CC_id]->sl_mode) {
|
||||
AssertFatal(UE[CC_id]->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
||||
if (UE_CC->sl_mode) {
|
||||
AssertFatal(UE_CC->sl_mode == 2, "Only Sidelink mode 2 supported. Mode 1 not yet supported\n");
|
||||
DevAssert(mac->if_module != NULL && mac->if_module->sl_phy_config_request != NULL);
|
||||
nr_sl_phy_config_t *phycfg = &mac->SL_MAC_PARAMS->sl_phy_config;
|
||||
phycfg->sl_config_req.sl_carrier_config.sl_num_rx_ant = get_nrUE_params()->nb_antennas_rx;
|
||||
phycfg->sl_config_req.sl_carrier_config.sl_num_tx_ant = get_nrUE_params()->nb_antennas_tx;
|
||||
mac->if_module->sl_phy_config_request(phycfg);
|
||||
sl_nr_ue_phy_params_t *sl_phy = &UE[CC_id]->SL_UE_PHY_PARAMS;
|
||||
sl_nr_ue_phy_params_t *sl_phy = &UE_CC->SL_UE_PHY_PARAMS;
|
||||
nr_init_frame_parms_ue_sl(&sl_phy->sl_frame_params,
|
||||
&sl_phy->sl_config,
|
||||
get_softmodem_params()->threequarter_fs,
|
||||
get_nrUE_params()->ofdm_offset_divisor);
|
||||
sl_ue_phy_init(UE[CC_id]);
|
||||
sl_ue_phy_init(UE_CC);
|
||||
}
|
||||
init_openair0(UE[CC_id]);
|
||||
|
||||
cell_id++; // initially connect each UE and carrier to its own cell
|
||||
}
|
||||
}
|
||||
|
||||
nrue_init_openair0();
|
||||
|
||||
lock_memory_to_ram();
|
||||
|
||||
if (IS_SOFTMODEM_DOSCOPE) {
|
||||
@@ -474,6 +458,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]);
|
||||
@@ -514,14 +500,12 @@ int main(int argc, char **argv)
|
||||
ret = pthread_join(phy_vars->stat_thread, NULL);
|
||||
AssertFatal(ret == 0, "pthread_join error %d, errno %d (%s)\n", ret, errno, strerror(errno));
|
||||
}
|
||||
if (phy_vars->rfdevice.trx_get_stats_func)
|
||||
phy_vars->rfdevice.trx_get_stats_func(&phy_vars->rfdevice);
|
||||
if (phy_vars->rfdevice.trx_end_func)
|
||||
phy_vars->rfdevice.trx_end_func(&phy_vars->rfdevice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nrue_ru_end();
|
||||
|
||||
free_nrLDPC_coding_interface(&nrLDPC_coding_interface);
|
||||
|
||||
time_manager_finish();
|
||||
|
||||
@@ -56,7 +56,6 @@ extern uint16_t ue_id_g;
|
||||
{"reconfig-file", CONFIG_HLP_RE_CFG_FILE, 0, .strptr=&nrUE_params.reconfig_file, .defstrval="./reconfig.raw", TYPE_STRING, 0}, \
|
||||
{"rbconfig-file", CONFIG_HLP_RB_CFG_FILE, 0, .strptr=&nrUE_params.rbconfig_file, .defstrval="./rbconfig.raw", TYPE_STRING, 0}, \
|
||||
{"ue-rxgain", CONFIG_HLP_UERXG, 0, .dblptr=&nrUE_params.rx_gain, .defdblval=110, TYPE_DOUBLE, 0}, \
|
||||
{"ue-rxgain-off", CONFIG_HLP_UERXGOFF, 0, .dblptr=&nrUE_params.rx_gain_off, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-txgain", CONFIG_HLP_UETXG, 0, .dblptr=&nrUE_params.tx_gain, .defdblval=0, TYPE_DOUBLE, 0}, \
|
||||
{"ue-nb-ant-rx", CONFIG_HLP_UENANTR, 0, .iptr=&(nrUE_params.nb_antennas_rx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
{"ue-nb-ant-tx", CONFIG_HLP_UENANTT, 0, .iptr=&(nrUE_params.nb_antennas_tx), .defuintval=1, TYPE_UINT8, 0}, \
|
||||
@@ -65,12 +64,12 @@ extern uint16_t ue_id_g;
|
||||
{"ue-max-power", NULL, 0, .iptr=&(nrUE_params.tx_max_power), .defintval=90, TYPE_INT, 0}, \
|
||||
{"r" , CONFIG_HLP_PRB_SA, 0, .iptr=&(nrUE_params.N_RB_DL), .defintval=106, TYPE_UINT, 0}, \
|
||||
{"ssb", CONFIG_HLP_SSC, 0, .iptr=&(nrUE_params.ssb_start_subcarrier), .defintval=516, TYPE_UINT16, 0}, \
|
||||
{"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(nrUE_params.if_freq), .defuintval=0, TYPE_UINT64, 0}, \
|
||||
{"if_freq" , CONFIG_HLP_IF_FREQ, 0, .u64ptr=&(nrUE_params.if_freq), .defint64val=0, TYPE_UINT64, 0}, \
|
||||
{"if_freq_off" , CONFIG_HLP_IF_FREQ_OFF, 0, .iptr=&(nrUE_params.if_freq_off), .defuintval=0, TYPE_INT, 0}, \
|
||||
{"chest-freq", CONFIG_HLP_CHESTFREQ, 0, .iptr=&(nrUE_params.chest_freq), .defintval=0, TYPE_INT, 0}, \
|
||||
{"chest-time", CONFIG_HLP_CHESTTIME, 0, .iptr=&(nrUE_params.chest_time), .defintval=0, TYPE_INT, 0}, \
|
||||
{"ue-timing-correction-disable", CONFIG_HLP_DISABLETIMECORR, PARAMFLAG_BOOL, .iptr=&(nrUE_params.no_timing_correction), .defintval=0, TYPE_INT, 0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \
|
||||
{"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defint64val=2600000000,TYPE_UINT64,0}, \
|
||||
{"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \
|
||||
{"time-sync-P", CONFIG_HLP_TIME_SYNC_P, 0, .dblptr=&(nrUE_params.time_sync_P), .defdblval=0.5, TYPE_DOUBLE, 0}, \
|
||||
{"time-sync-I", CONFIG_HLP_TIME_SYNC_I, 0, .dblptr=&(nrUE_params.time_sync_I), .defdblval=0.0, TYPE_DOUBLE, 0}, \
|
||||
@@ -120,7 +119,6 @@ typedef struct {
|
||||
char *uecap_file;
|
||||
double tx_gain;
|
||||
double rx_gain;
|
||||
double rx_gain_off;
|
||||
int vcdflag;
|
||||
int tx_max_power;
|
||||
int num_ul_actors;
|
||||
@@ -131,11 +129,9 @@ extern uint64_t get_nrUE_optmask(void);
|
||||
extern uint64_t set_nrUE_optmask(uint64_t bitmask);
|
||||
extern nrUE_params_t *get_nrUE_params(void);
|
||||
|
||||
|
||||
// In nr-ue.c
|
||||
extern int setup_nr_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
|
||||
extern void fill_ue_band_info(void);
|
||||
extern void init_NR_UE(int, char *, char *, char *);
|
||||
extern void init_NR_UE(int, char *, char *, char *, int);
|
||||
extern void init_NR_UE_threads(PHY_VARS_NR_UE *ue);
|
||||
void *UE_thread(void *arg);
|
||||
void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id);
|
||||
|
||||
@@ -153,7 +153,7 @@ extern int usrp_tx_thread;
|
||||
{"clock-source", CONFIG_HLP_CLK, 0, .uptr=&CLOCK_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"time-source", CONFIG_HLP_TME, 0, .uptr=&TIMING_SOURCE, .defintval=0, TYPE_UINT, 0}, \
|
||||
{"tune-offset", CONFIG_HLP_TUNE_OFFSET, 0, .dblptr=&TUNE_OFFSET, .defintval=0, TYPE_DOUBLE, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defuintval=0, TYPE_UINT64, 0}, \
|
||||
{"C" , CONFIG_HLP_DLF, 0, .u64ptr=&(downlink_frequency[0][0]), .defint64val=0, TYPE_UINT64, 0}, \
|
||||
{"CO" , CONFIG_HLP_ULF, 0, .iptr=&(uplink_frequency_offset[0][0]), .defintval=0, TYPE_INT, 0}, \
|
||||
{"a" , CONFIG_HLP_CHOFF, 0, .iptr=&CHAIN_OFFSET, .defintval=0, TYPE_INT, 0}, \
|
||||
{"d" , CONFIG_HLP_SOFTS, PARAMFLAG_BOOL, .uptr=&do_forms, .defintval=0, TYPE_UINT, 0}, \
|
||||
|
||||
Reference in New Issue
Block a user