diff --git a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf
index 58ba62696a..e314a1f299 100644
--- a/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf
+++ b/ci-scripts/conf_files/gnb-du.sa.band78.106prb.usrpb200.conf
@@ -149,7 +149,7 @@ gNBs =
bwp_list = (
{ scs = 1; bwpStart = 0; bwpSize = 106;},
{ scs = 1; bwpStart = 0; bwpSize = 36;},
- { scs = 1; bwpStart = 36; bwpSize = 70;}
+ { scs = 1; bwpStart = 40; bwpSize = 50;}
);
# ------- SCTP definitions
diff --git a/ci-scripts/conf_files/gnb-vnf.sa.band66.u0.25prb.nfapi.conf b/ci-scripts/conf_files/gnb-vnf.sa.band66.u0.25prb.nfapi.conf
index c14759c6af..6f914cf17a 100644
--- a/ci-scripts/conf_files/gnb-vnf.sa.band66.u0.25prb.nfapi.conf
+++ b/ci-scripts/conf_files/gnb-vnf.sa.band66.u0.25prb.nfapi.conf
@@ -16,8 +16,6 @@ gNBs =
nr_cellid = 12345678L;
////////// Physical parameters:
-
- sib1_tda = 5;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf
index f2455bc2c6..c37acc89f5 100644
--- a/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf
+++ b/ci-scripts/conf_files/gnb.sa.band261.u3.32prb.rfsim.conf
@@ -18,8 +18,6 @@ gNBs =
tr_s_preference = "local_mac"
////////// Physical parameters:
-
- sib1_tda = 15;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf
index afe40c733c..7153c90421 100644
--- a/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf
+++ b/ci-scripts/conf_files/gnb.sa.band78.24prb.rfsim.conf
@@ -16,8 +16,6 @@ gNBs =
nr_cellid = 12345678L;
////////// Physical parameters:
-
- sib1_tda = 15;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
index 8d6a0e90cd..ee2930f8ad 100644
--- a/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
+++ b/ci-scripts/conf_files/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
# force_UL256qam_off = 1;
servingCellConfigCommon = (
diff --git a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml
index cde84b00e7..f00e6b26f1 100644
--- a/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml
+++ b/ci-scripts/xml_files/container_5g_rfsim_ntn_leo.xml
@@ -32,6 +32,11 @@
000003
020001
020002
+ 040001
+ 020022
+ 040002
+ 020001
+ 020002
100001
222222
@@ -94,6 +99,33 @@
5
+
+ Custom_Command
+ Trigger Reestablishment
+ localhost
+ echo ci force_reestab | ncat 192.168.71.140 9090 | grep -E 'Reset RLC counters of UE RNTI [0-9a-f]{4} to trigger reestablishment'
+ yes
+
+
+
+ Ping
+ Ping ext-dn from NR-UE
+ rfsim5g_ue
+ localhost
+ rfsim5g_ext_dn
+ localhost
+ -c 20 -i0.5 -w25
+ 80
+
+
+
+ Custom_Command
+ Verify Reestablishment
+ localhost
+ echo ci get_reestab_count | ncat 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'
+ yes
+
+
Undeploy_Object
true
diff --git a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml
index 836143431a..d0a65801a3 100644
--- a/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml
+++ b/ci-scripts/xml_files/container_sa_e1_b200_quectel.xml
@@ -183,7 +183,7 @@
-t 10 -R
idefix
sabox-nepes
- 85
+ 65
diff --git a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
index 3b5e7170ba..a3f8ec2a7e 100644
--- a/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
+++ b/ci-scripts/yaml_files/5g_rfsimulator_ntn_leo/docker-compose.yaml
@@ -93,7 +93,9 @@ services:
- ALL
environment:
USE_ADDITIONAL_OPTIONS: --rfsim --log_config.global_log_options level,nocolor,time
- ASAN_OPTIONS: detect_leaks=0
+ --telnetsrv --telnetsrv.listenaddr 192.168.71.140
+ --telnetsrv.shrmod ci
+ ASAN_OPTIONS: detect_leaks=0:detect_odr_violation=0
depends_on:
- oai-ext-dn
networks:
diff --git a/common/config/config_cmdline.c b/common/config/config_cmdline.c
index c3f3d5ae21..f8b10ad14b 100644
--- a/common/config/config_cmdline.c
+++ b/common/config/config_cmdline.c
@@ -213,7 +213,7 @@ int config_check_unknown_cmdlineopt(configmodule_interface_t *cfg, char *prefix)
return unknowndetected;
} /* config_check_unknown_cmdlineopt */
-int config_process_cmdline(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, char *prefix)
+int config_process_cmdline(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, const char *prefix)
{
int c = cfg->argc;
int i,j;
diff --git a/common/config/config_common.c b/common/config/config_common.c
index c617c426d7..0b4b8f76d6 100644
--- a/common/config/config_common.c
+++ b/common/config/config_common.c
@@ -118,7 +118,7 @@ void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree)
return ptr;
}
-int config_setdefault_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
config_check_valptr(cfg, cfgoptions, sizeof(*cfgoptions->iptr), 1);
@@ -132,7 +132,7 @@ int config_setdefault_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions,
return status;
}
-int config_setdefault_int64(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_int64(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
config_check_valptr(cfg, cfgoptions, sizeof(*cfgoptions->i64ptr), 1);
@@ -150,7 +150,7 @@ int config_setdefault_int64(configmodule_interface_t *cfg, paramdef_t *cfgoption
return status;
}
-int config_setdefault_intlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_intlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
@@ -167,7 +167,7 @@ int config_setdefault_intlist(configmodule_interface_t *cfg, paramdef_t *cfgopti
return status;
}
-int config_setdefault_string(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_string(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
@@ -190,7 +190,7 @@ int config_setdefault_string(configmodule_interface_t *cfg, paramdef_t *cfgoptio
return status;
}
-int config_setdefault_stringlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_stringlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
@@ -210,7 +210,7 @@ int config_setdefault_stringlist(configmodule_interface_t *cfg, paramdef_t *cfgo
return status;
}
-int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
config_check_valptr(cfg, cfgoptions, sizeof(*cfgoptions->dblptr), 1);
@@ -224,7 +224,7 @@ int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptio
return status;
}
-int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *ipv4addr)
+int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *ipv4addr)
{
config_check_valptr(cfg, cfgoptions, sizeof(*cfgoptions->uptr), 1);
int rst=inet_pton(AF_INET, ipv4addr,cfgoptions->uptr );
@@ -246,7 +246,7 @@ int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions
return 0;
}
-int config_setdefault_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix)
+int config_setdefault_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix)
{
int status = 0;
@@ -322,7 +322,7 @@ void config_assign_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, ch
* @param[in] prefix Optional prefix for the parameter name (can be NULL).
* @return 1 if the default value was set, 0 if ignored, or -1 on error/unsupported type.
*/
-int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, char *prefix)
+int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, const char *prefix)
{
if( (cfgoption->paramflags & PARAMFLAG_DONOTREAD) != 0) {
return 0;
diff --git a/common/config/config_common.h b/common/config/config_common.h
index 00211c9519..0400e703c7 100644
--- a/common/config/config_common.h
+++ b/common/config/config_common.h
@@ -41,16 +41,16 @@ extern "C"
#endif
void config_check_valptr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int elt_sz, int nb_elt);
/* functions to set a parameter to its default value */
-int config_setdefault_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_int64(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_intlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_string(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_stringlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
-int config_setdefault_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *prefix);
+int config_setdefault_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_int64(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_intlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_string(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_stringlist(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_double(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
+int config_setdefault_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *prefix);
void *config_allocate_new(configmodule_interface_t *cfg, int sz, bool autoFree);
void config_assign_int(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *fullname, int val);
-int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, char *prefix);
+int config_common_getdefault(configmodule_interface_t *cfg, paramdef_t *cfgoption, const char *prefix);
#ifdef __cplusplus
}
diff --git a/common/config/config_load_configmodule.c b/common/config/config_load_configmodule.c
index f5dfe6137f..5d8bb2cfcc 100644
--- a/common/config/config_load_configmodule.c
+++ b/common/config/config_load_configmodule.c
@@ -150,7 +150,7 @@ int config_cmdlineonly_getlist(configmodule_interface_t *cfg,
return 0;
}
-int config_cmdlineonly_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, char *prefix)
+int config_cmdlineonly_get(configmodule_interface_t *cfg, paramdef_t *cfgoptions, int numoptions, const char *prefix)
{
int defval;
int fatalerror=0;
diff --git a/common/config/config_load_configmodule.h b/common/config/config_load_configmodule.h
index d5f87d0f8b..2c45f788d4 100644
--- a/common/config/config_load_configmodule.h
+++ b/common/config/config_load_configmodule.h
@@ -59,10 +59,10 @@
#define CONFIG_ABORT (1<<21) // config failed,abort execution
#define CONFIG_NOOOPT (1<<22) // no -O option found when parsing command line
struct configmodule_interface;
-typedef int (*configmodule_getfunc_t)(struct configmodule_interface *, paramdef_t *, int numparams, char *prefix);
+typedef int (*configmodule_getfunc_t)(struct configmodule_interface *, paramdef_t *, int numparams, const char *prefix);
typedef int (
*configmodule_getlistfunc_t)(struct configmodule_interface *, paramlist_def_t *, paramdef_t *, int numparams, char *prefix);
-typedef int (*configmodule_setfunc_t)(paramdef_t *cfgoptions, int numoptions, char *prefix);
+typedef int (*configmodule_setfunc_t)(paramdef_t *cfgoptions, int numoptions, const char *prefix);
typedef void (*configmodule_endfunc_t)(struct configmodule_interface *cfg);
typedef int (*configmodule_initfunc_t)(struct configmodule_interface *cfg);
diff --git a/common/config/config_paramdesc.h b/common/config/config_paramdesc.h
index 8ddd507ee6..9333a778af 100644
--- a/common/config/config_paramdesc.h
+++ b/common/config/config_paramdesc.h
@@ -105,7 +105,7 @@ typedef union checkedparam {
#define DEFAULT_EXTRA_SZ 256
typedef struct paramdef {
char optname[MAX_OPTNAME_SIZE]; /* parameter name, can be used as long command line option */
- char *helpstr; /* help string */
+ const char *helpstr; /* help string */
unsigned int paramflags; /* value is a "ored" combination of above PARAMFLAG_XXXX values */
union { /* pointer to the parameter value, completed by the config module */
char **strptr;
@@ -122,7 +122,7 @@ typedef struct paramdef {
void *voidptr;
} ;
union { /* default parameter value, to be used when PARAMFLAG_MANDATORY is not specified */
- char *defstrval;
+ const char *defstrval;
char **defstrlistval;
uint32_t defuintval;
int defintval;
@@ -161,6 +161,50 @@ typedef struct paramdef {
#define TYPE_LIST 55
#define ANY_IPV4ADDR_STRING "0.0.0.0"
+
+// Macros to simplify defining parameters in paramdef_t arrays in C++ source code
+#define OPTNAME(x) .optname = x
+#define HELPSTR(x) .helpstr = x
+#define PARAMFLAG(x) .paramflags = x
+#define PARAMTYPE(x) .type = x
+#define STRINGPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .strptr = ptr, .defstrval = defval, PARAMTYPE(TYPE_STRING), .numelt = 0 \
+ }
+#define DOUBLEPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .dblptr = ptr, .defdblval = defval, PARAMTYPE(TYPE_DOUBLE), .numelt = 0 \
+ }
+#define INTPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .iptr = ptr, .defintval = defval, PARAMTYPE(TYPE_INT), .numelt = 0 \
+ }
+#define UINT16PARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .u16ptr = ptr, .defuintval = defval, PARAMTYPE(TYPE_UINT16), .numelt = 0 \
+ }
+#define STRLISTPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .strlistptr = ptr, .defstrlistval = defval, PARAMTYPE(TYPE_STRINGLIST), \
+ .numelt = 0 \
+ }
+#define INT64PARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .i64ptr = ptr, .defint64val = defval, PARAMTYPE(TYPE_INT64), .numelt = 0 \
+ }
+#define INTPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .iptr = ptr, .defintval = defval, PARAMTYPE(TYPE_INT), .numelt = 0 \
+ }
+#define BOOLPARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .iptr = ptr, .defintval = defval, PARAMTYPE(TYPE_INT), .numelt = 0 \
+ }
+#define UINT64PARAM(name, help, flags, ptr, defval) \
+ { \
+ OPTNAME(name), HELPSTR(help), PARAMFLAG(flags), .u64ptr = ptr, .defuintval = defval, PARAMTYPE(TYPE_UINT64), .numelt = 0 \
+ }
+
typedef struct paramlist_def {
char listname[MAX_OPTNAME_SIZE];
paramdef_t **paramarray;
diff --git a/common/config/config_userapi.c b/common/config/config_userapi.c
index 9f7477f5cd..1a831d28c5 100644
--- a/common/config/config_userapi.c
+++ b/common/config/config_userapi.c
@@ -71,7 +71,7 @@ int config_get_processedint(configmodule_interface_t *cfg, paramdef_t *cfgoption
return ret;
}
-void config_printhelp(paramdef_t *params,int numparams, char *prefix) {
+void config_printhelp(paramdef_t *params,int numparams, const char *prefix) {
printf("\n-----Help for section %-26s: %03i entries------\n",(prefix==NULL)?"(root section)":prefix,numparams);
for (int i=0 ; irtflags |= P; }
#define CONFIG_CLEARRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags &= (~P); }
#define CONFIG_ISPARAMFLAGSET(P,F) ( !!(P.paramflags & F))
-int config_paramidx_fromname(paramdef_t *params, int numparams, char *name);
+int config_paramidx_fromname(paramdef_t *params, int numparams, const char *name);
/* utility functions, to be used by configuration module and/or configuration libraries */
-void config_printhelp(paramdef_t *, int numparams, char *prefix);
-int config_process_cmdline(configmodule_interface_t *cfg, paramdef_t *params, int numparams, char *prefix);
-int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, char *ipv4addr);
+void config_printhelp(paramdef_t *, int numparams, const char *prefix);
+int config_process_cmdline(configmodule_interface_t *cfg, paramdef_t *params, int numparams, const char *prefix);
+int config_assign_ipv4addr(configmodule_interface_t *cfg, paramdef_t *cfgoptions, const char *ipv4addr);
/* apis to get/check parameters, to be used by oai modules, at configuration time */
#define CONFIG_CHECKALLSECTIONS "ALLSECTIONS"
int config_check_unknown_cmdlineopt(configmodule_interface_t *cfg, char *prefix);
-int config_get(configmodule_interface_t *cfg, paramdef_t *params, int numparams, char *prefix);
+int config_get(configmodule_interface_t *cfg, paramdef_t *params, int numparams, const char *prefix);
int config_getlist(configmodule_interface_t *cfg, paramlist_def_t *ParamList, paramdef_t *params, int numparams, char *prefix);
/* apis to set some of the paramdef_t fields before using the get/getlist api's */
diff --git a/common/config/yaml/tests/test_yaml_config.cpp b/common/config/yaml/tests/test_yaml_config.cpp
index 814e3a3635..b2bd53e349 100644
--- a/common/config/yaml/tests/test_yaml_config.cpp
+++ b/common/config/yaml/tests/test_yaml_config.cpp
@@ -411,7 +411,7 @@ TEST(yaml_config, test_read_ipv4) {
config_yaml_get(cfg, &p, 1, prefix);
printf("%x\n", addr);
- p.defstrval = strdup("10.0.0.1");
+ p.defstrval = "10.0.0.1";
strncpy(p.optname, "ipv4_3", sizeof(p.optname) - 1);
config_yaml_get(cfg, &p, 1, prefix);
printf("%x\n", addr);
@@ -419,7 +419,6 @@ TEST(yaml_config, test_read_ipv4) {
config_yaml_end(cfg);
free(cfg->cfgP[0]);
end_configmodule(cfg);
- free(p.defstrval);
}
TEST(yaml_config, yaml_read_str_as_int) {
diff --git a/common/utils/load_module_shlib.c b/common/utils/load_module_shlib.c
index 825012ce6a..13eec39776 100644
--- a/common/utils/load_module_shlib.c
+++ b/common/utils/load_module_shlib.c
@@ -252,7 +252,7 @@ load_module_shlib_exit:
return ret;
}
-void * get_shlibmodule_fptr(char *modname, char *fname)
+void * get_shlibmodule_fptr(const char *modname, const char *fname)
{
for (int i=0; iprach_fftSize = prach_config->prach_sequence_length.value == 0 ? 10 : 8; // need to handle 5kHz cases better than this
split7->fftSize = log2(fp->ofdm_symbol_size);
// M-plane related parameters
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index bb88768029..2772fc5aae 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -176,8 +176,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id)
ue->dci_thres = 0;
ue->target_Nid_cell = -1;
- ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
- ue->ntn_config_message->update = false;
+ ue->nrUE_config.ntn_config.params_changed = false;
// initialize all signal buffers
init_nr_ue_signal(ue, nb_connected_gNB);
@@ -257,7 +256,7 @@ static void UE_synch(void *arg) {
+ round((float)((ret.rx_offset << 1) % fp->samples_per_subframe) / fp->samples_per_slot0);
if (get_nrUE_params()->cont_fo_comp) {
- UE->freq_offset = freq_offset;
+ 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);
@@ -398,8 +397,15 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
double ul_freq_offset = -UE->freq_offset * ((double)fp->ul_CarrierFreq / (double)fp->dl_CarrierFreq);
if (get_nrUE_params()->cont_fo_comp == 2) // different from LO frequency error compensation, Doppler UL pre-compensation has to be negative
ul_freq_offset = -ul_freq_offset;
+ else if (get_nrUE_params()->cont_fo_comp == 3) // do not consider residual DL FO for UL pre-compensation at all
+ ul_freq_offset = 0;
for (int i = 0; i < fp->nb_antennas_tx; i++)
- nr_fo_compensation(ul_freq_offset, fp->samples_per_subframe, writeTimestamp, txp[i], txp[i], writeBlockSize);
+ nr_fo_compensation(UE->ul_Doppler_shift + ul_freq_offset,
+ fp->samples_per_subframe,
+ writeTimestamp,
+ txp[i],
+ txp[i],
+ writeBlockSize);
}
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
@@ -491,6 +497,8 @@ static uint64_t get_carrier_frequency(const int N_RB, const int mu, const uint32
return carrier_freq;
}
+static void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx);
+
static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
{
NR_DL_FRAME_PARMS *fp = &UE->frame_parms;
@@ -515,6 +523,12 @@ static int handle_sync_req_from_mac(PHY_VARS_NR_UE *UE)
init_symbol_rotation(fp);
}
+ // Apply Doppler based on NTN-Config for target cell
+ if (UE->nrUE_config.ntn_config.is_targetcell)
+ apply_ntn_timing_advance_and_doppler(UE, fp, -1);
+ // Apply NTN DL Doppler as initial FO
+ UE->initial_fo = UE->dl_Doppler_shift;
+
/* Clearing UE harq while DL actors are active causes race condition.
So we let the current execution to complete here.*/
for (int i = 0; i < get_nrUE_params()->num_dl_actors; i++) {
@@ -721,25 +735,80 @@ static inline int get_readBlockSize(uint16_t slot, NR_DL_FRAME_PARMS *fp) {
return rem_samples + next_slot_first_symbol;
}
-#define SPEED_OF_LIGHT 299792458
-static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
+static void fix_ntn_epoch_hfn(PHY_VARS_NR_UE *UE, int hfn, int frame)
{
- const fapi_nr_dl_ntn_config_command_pdu *ntn_config_params = &UE->ntn_config_message->ntn_config_params;
+ if (!UE->nrUE_config.ntn_config.is_targetcell)
+ return;
+ UE->nrUE_config.ntn_config.is_targetcell = false;
+
+ const int epoch_frame = UE->nrUE_config.ntn_config.epoch_sfn;
+ const int diff1 = (frame - epoch_frame + 1024) % 1024;
+ const int diff2 = (epoch_frame - frame + 1024) % 1024;
+
+ int *epoch_hfn = &UE->nrUE_config.ntn_config.epoch_hfn;
+ if (diff1 < diff2) { // epoch_frame in the past
+ LOG_I(PHY, "epoch is %d frames in the past\n", diff1);
+ if (epoch_frame <= frame)
+ *epoch_hfn = hfn;
+ else
+ *epoch_hfn = hfn - 1;
+ } else { // epoch_frame in the future
+ LOG_I(PHY, "epoch is %d frames in the future\n", diff2);
+ if (epoch_frame >= frame)
+ *epoch_hfn = hfn;
+ else
+ *epoch_hfn = hfn + 1;
+ }
+ LOG_I(PHY, "setting epoch_hfn = %d\n", *epoch_hfn);
+}
+
+#define SPEED_OF_LIGHT 299792458
+
+// calculate TA and Doppler based on the NTN-Config, if abs_subframe_tx < 0 then apply only Doppler
+static void apply_ntn_timing_advance_and_doppler(PHY_VARS_NR_UE *UE, const NR_DL_FRAME_PARMS *fp, int abs_subframe_tx)
+{
+ const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
+
+ // Handle terrestrial networks
+ if (ntn_config_params->cell_specific_k_offset == 0) {
+ if (abs_subframe_tx >= 0)
+ UE->timing_advance_ntn = 0;
+ UE->dl_Doppler_shift = 0;
+ UE->ul_Doppler_shift = 0;
+ return;
+ }
const int abs_subframe_epoch = ntn_config_params->epoch_subframe
+ ntn_config_params->epoch_sfn * 10
+ ntn_config_params->epoch_hfn * 10240;
- const int ms_since_epoch = abs_subframe_tx - abs_subframe_epoch;
-
- const double omega = ntn_config_params->omega;
- const double cos_wt = cos(omega * ms_since_epoch);
- const double sin_wt = sin(omega * ms_since_epoch);
+ const int ms_since_epoch = abs_subframe_tx < 0 ? 0 : abs_subframe_tx - abs_subframe_epoch;
const position_t pos_sat_0 = ntn_config_params->pos_sat_0;
- const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
- const position_t pos_sat = {pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
- pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
- pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
+ const position_t vel_sat_0 = ntn_config_params->vel_sat_0;
+
+ position_t pos_sat;
+ position_t vel_sat;
+
+ const double omega = ntn_config_params->omega;
+ if (omega) {
+ const double cos_wt = cos(omega * ms_since_epoch);
+ const double sin_wt = sin(omega * ms_since_epoch);
+
+ const position_t pos_sat_90 = ntn_config_params->pos_sat_90;
+ pos_sat = (position_t){pos_sat_0.X * cos_wt + pos_sat_90.X * sin_wt,
+ pos_sat_0.Y * cos_wt + pos_sat_90.Y * sin_wt,
+ pos_sat_0.Z * cos_wt + pos_sat_90.Z * sin_wt};
+
+ const position_t vel_sat_90 = ntn_config_params->vel_sat_90;
+ vel_sat = (position_t){vel_sat_0.X * cos_wt + vel_sat_90.X * sin_wt,
+ vel_sat_0.Y * cos_wt + vel_sat_90.Y * sin_wt,
+ vel_sat_0.Z * cos_wt + vel_sat_90.Z * sin_wt};
+ } else {
+ pos_sat = (position_t){pos_sat_0.X + vel_sat_0.X * ms_since_epoch / 1000,
+ pos_sat_0.Y + vel_sat_0.Y * ms_since_epoch / 1000,
+ pos_sat_0.Z + vel_sat_0.Z * ms_since_epoch / 1000};
+ vel_sat = vel_sat_0;
+ }
position_t pos_ue = {0};
get_position_coordinates(UE->Mod_id, &pos_ue);
@@ -750,6 +819,15 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM
// calculate distance between SAT and UE
const double distance = sqrt(dir_sat_ue.X * dir_sat_ue.X + dir_sat_ue.Y * dir_sat_ue.Y + dir_sat_ue.Z * dir_sat_ue.Z);
+ // calculate projected velocity from SAT towards UE
+ const double vel_sat_ue = (vel_sat.X * dir_sat_ue.X + vel_sat.Y * dir_sat_ue.Y + vel_sat.Z * dir_sat_ue.Z) / distance;
+
+ // calculate DL Doppler shift (moving source)
+ const double dl_Doppler_shift = (vel_sat_ue / (SPEED_OF_LIGHT - vel_sat_ue)) * fp->dl_CarrierFreq;
+
+ // calculate UL Doppler shift (moving target)
+ const double ul_Doppler_shift = (vel_sat_ue / SPEED_OF_LIGHT) * fp->ul_CarrierFreq;
+
// calculate round-trip-time (factor 2) between SAT and UE in ms (factor 1000)
const double N_UE_TA_adj = 2000 * distance / SPEED_OF_LIGHT;
@@ -757,47 +835,73 @@ static inline void apply_ntn_timing_advance(PHY_VARS_NR_UE *UE, const NR_DL_FRAM
const double N_common_ta_drift = ntn_config_params->N_common_ta_drift;
const double N_common_ta_drift_variant = ntn_config_params->N_common_ta_drift_variant;
- UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj
- + N_common_ta_drift * ms_since_epoch / 1e6
- + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
- * fp->samples_per_subframe;
+ if (abs_subframe_tx >= 0) {
+ UE->timing_advance_ntn = (N_UE_TA_adj + N_common_ta_adj + N_common_ta_drift * ms_since_epoch / 1e6
+ + N_common_ta_drift_variant * ((int64_t)ms_since_epoch * ms_since_epoch) / 1e9)
+ * fp->samples_per_subframe;
+ }
- LOG_D(PHY,
- "N_UE_TA_adj = %f ms, N_common_ta_adj = %f ms, N_common_ta_drift = %f µs/s, N_common_ta_drift_variant = %f µs/s², ms_since_epoch = %d ms, "
- "computed timing_advance_ntn = %d samples\n",
- N_UE_TA_adj,
- N_common_ta_adj,
- N_common_ta_drift,
- N_common_ta_drift_variant,
- ms_since_epoch,
- UE->timing_advance_ntn);
+ UE->freq_offset -= dl_Doppler_shift - UE->dl_Doppler_shift;
+ UE->dl_Doppler_shift = dl_Doppler_shift;
+ UE->ul_Doppler_shift = ul_Doppler_shift;
+
+ if (abs_subframe_tx < 0) {
+ LOG_I(PHY,
+ "satellite velocity towards UE = %f m/s, DL Doppler shift = %f kHz, UL Doppler shift = %f kHz\n",
+ vel_sat_ue,
+ dl_Doppler_shift / 1000,
+ ul_Doppler_shift / 1000);
+ }
}
-static inline void apply_ntn_config(PHY_VARS_NR_UE *UE,
- NR_DL_FRAME_PARMS *fp,
- int hfn_rx,
- int frame_rx,
- int slot_rx,
- int *duration_rx_to_tx,
- int *timing_advance,
- int *ntn_koffset)
+// apply values based on the NTN-Config
+static void apply_ntn_config(PHY_VARS_NR_UE *UE,
+ NR_DL_FRAME_PARMS *fp,
+ int hfn_rx,
+ int frame_rx,
+ int slot_rx,
+ int *duration_rx_to_tx,
+ int *timing_advance,
+ int *ntn_koffset,
+ bool *ntn_targetcell)
{
- if (UE->ntn_config_message->update) {
- UE->ntn_config_message->update = false;
+ // return if there is no pending update
+ if (!UE->nrUE_config.ntn_config.params_changed)
+ return;
- const int mu = fp->numerology_index;
- const int koffset = UE->ntn_config_message->ntn_config_params.cell_specific_k_offset;
+ *ntn_targetcell = UE->nrUE_config.ntn_config.is_targetcell;
- *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
- if (koffset > *ntn_koffset)
- *timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
- else if (koffset < *ntn_koffset)
- *timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
- *ntn_koffset = koffset;
+ // skip update if it is for the target cell
+ if (UE->nrUE_config.ntn_config.is_targetcell)
+ return;
- const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
- apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
- }
+ UE->nrUE_config.ntn_config.params_changed = false;
+
+ const fapi_nr_ntn_config_t *ntn_config_params = &UE->nrUE_config.ntn_config;
+
+ const int mu = fp->numerology_index;
+ const int koffset = ntn_config_params->cell_specific_k_offset;
+
+ *duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX + (koffset << mu);
+ if (koffset > *ntn_koffset)
+ *timing_advance += get_samples_slot_duration(fp, slot_rx, (koffset - *ntn_koffset) << mu);
+ else if (koffset < *ntn_koffset)
+ *timing_advance -= get_samples_slot_duration(fp, slot_rx, (*ntn_koffset - koffset) << mu);
+ *ntn_koffset = koffset;
+
+ const int abs_subframe_tx = 10240 * hfn_rx + 10 * frame_rx + ((slot_rx + *duration_rx_to_tx) >> mu);
+ apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
+
+ LOG_I(PHY,
+ "k_offset: %dms, N_Common_Ta: %fms, drift: %fµs/s, variant: %fµs/s², "
+ "timing_advance_ntn: %d samples, DL Doppler shift: %fkHz, UL Doppler shift: %fkHz\n",
+ koffset << mu,
+ ntn_config_params->N_common_ta_adj,
+ ntn_config_params->N_common_ta_drift,
+ ntn_config_params->N_common_ta_drift_variant,
+ UE->timing_advance_ntn,
+ UE->dl_Doppler_shift / 1000,
+ UE->ul_Doppler_shift / 1000);
}
void *UE_thread(void *arg)
@@ -832,9 +936,15 @@ void *UE_thread(void *arg)
notifiedFIFO_t freeBlocks;
initNotifiedFIFO_nothreadSafe(&freeBlocks);
- double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
- int ntn_koffset = 0;
+ const double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift;
+ if (get_nrUE_params()->time_sync_I)
+ // ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame
+ UE->max_pos_acc = ntn_init_time_drift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I;
+ else
+ UE->max_pos_acc = 0;
+ bool ntn_targetcell = false;
+ int ntn_koffset = 0;
int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX;
int timing_advance = UE->timing_advance + UE->timing_advance_ntn;
UE->N_TA_offset = determine_N_TA_offset(UE);
@@ -930,10 +1040,6 @@ void *UE_thread(void *arg)
syncMsg->UE = UE;
memset(&syncMsg->proc, 0, sizeof(syncMsg->proc));
pushNotifiedFIFO(&UE->sync_actor.fifo, Msg);
- if (ntn_koffset == 0) { // reset timing_advance for TN
- timing_advance = 0;
- UE->timing_advance = 0;
- }
trashed_frames = 0;
syncRunning = true;
continue;
@@ -943,13 +1049,8 @@ void *UE_thread(void *arg)
stream_status = STREAM_STATUS_SYNCING;
syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset);
openair0_write_reorder_clear_context(&UE->rfdevice);
- if (get_nrUE_params()->time_sync_I)
- // ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame
- UE->max_pos_acc = ntn_init_time_drift * 1e-6 * fp->samples_per_frame / get_nrUE_params()->time_sync_I;
- else
- UE->max_pos_acc = 0;
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_D(PHY, "max_pos_acc = %d, shiftForNextFrame = %d\n", UE->max_pos_acc, shiftForNextFrame);
+ 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,
@@ -961,12 +1062,35 @@ void *UE_thread(void *arg)
// we have the decoded frame index in the return of the synch process
// and we shifted above to the first slot of next frame
decoded_frame_rx = (decoded_frame_rx + 1) % MAX_FRAME_NUMBER;
+ const int prev_frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER;
+ const int prev_hfn_rx = (absolute_slot / nb_slot_frame) / MAX_FRAME_NUMBER;
+ int decoded_hfn_rx = prev_hfn_rx;
+ if (decoded_frame_rx <= prev_frame_rx)
+ decoded_hfn_rx++;
// we do ++ first in the regular processing, so it will be begin of frame;
- absolute_slot = decoded_frame_rx * nb_slot_frame - 1;
+ absolute_slot = (decoded_hfn_rx * MAX_FRAME_NUMBER + decoded_frame_rx) * nb_slot_frame - 1;
if (UE->sl_mode == 2) {
// Set to the slot where the SL-SSB was decoded
absolute_slot += UE->SL_UE_PHY_PARAMS.sync_params.slot_offset;
}
+ // With the correct frame and slot numbers, we can now fix the UL timing
+ fix_ntn_epoch_hfn(UE, decoded_hfn_rx, decoded_frame_rx);
+ if (UE->nrUE_config.ntn_config.params_changed) {
+ apply_ntn_config(UE,
+ fp,
+ decoded_hfn_rx,
+ decoded_frame_rx,
+ 0,
+ &duration_rx_to_tx,
+ &timing_advance,
+ &ntn_koffset,
+ &ntn_targetcell);
+ } else {
+ const int abs_subframe_tx = (absolute_slot + 1 + duration_rx_to_tx) / fp->slots_per_subframe;
+ apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
+ ntn_targetcell = false;
+ }
+ UE->timing_advance = 0;
// We have resynchronized, maybe after RF loss so we need to purge any existing context
memset(tx_wait_for_dlsch, 0, sizeof(tx_wait_for_dlsch));
for (int i = 0; i < NUM_PROCESS_SLOT_TX_BARRIERS; i++) {
@@ -1026,9 +1150,10 @@ void *UE_thread(void *arg)
}
// Calculate new TA based on SIB19 information for each subframe in NTN mode, if "autonomous_ta" is not enabled
- if (ntn_koffset && !get_nrUE_params()->autonomous_ta && (absolute_slot + duration_rx_to_tx) % fp->slots_per_subframe == 0) {
+ if (ntn_koffset && !ntn_targetcell && !get_nrUE_params()->autonomous_ta
+ && (absolute_slot + duration_rx_to_tx) % fp->slots_per_subframe == 0) {
const int abs_subframe_tx = (absolute_slot + duration_rx_to_tx) / fp->slots_per_subframe;
- apply_ntn_timing_advance(UE, fp, abs_subframe_tx);
+ apply_ntn_timing_advance_and_doppler(UE, fp, abs_subframe_tx);
}
const int readBlockSize = get_readBlockSize(slot_nr, fp) - iq_shift_to_apply;
@@ -1081,6 +1206,11 @@ void *UE_thread(void *arg)
writeBlockSize -= new_N_TA_offset - UE->N_TA_offset;
UE->N_TA_offset = new_N_TA_offset;
}
+ if (writeBlockSize < 0) {
+ timing_advance += writeBlockSize - 1;
+ LOG_I(PHY, "writeBlockSize is %d, setting it to 1 and changing timing_advance to %d\n", writeBlockSize, timing_advance);
+ writeBlockSize = 1;
+ }
if (curMsg.proc.nr_slot_rx == 0)
nr_ue_rrc_timer_trigger(UE->Mod_id, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.gNB_id);
@@ -1099,7 +1229,15 @@ void *UE_thread(void *arg)
}
// apply new NTN timing information
- apply_ntn_config(UE, fp, curMsg.proc.hfn_rx, curMsg.proc.frame_rx, curMsg.proc.nr_slot_rx, &duration_rx_to_tx, &timing_advance, &ntn_koffset);
+ apply_ntn_config(UE,
+ fp,
+ curMsg.proc.hfn_rx,
+ curMsg.proc.frame_rx,
+ curMsg.proc.nr_slot_rx,
+ &duration_rx_to_tx,
+ &timing_advance,
+ &ntn_koffset,
+ &ntn_targetcell);
// Start TX slot processing here. It runs in parallel with RX slot processing
// in current code, DURATION_RX_TO_TX constant is the limit to get UL data to encode from a RX slot
@@ -1113,7 +1251,7 @@ void *UE_thread(void *arg)
curMsgTx->absolute_deadline_us = absolute_deadline_us;
int slot = curMsgTx->proc.nr_slot_tx;
- int slot_and_frame = slot + curMsgTx->proc.frame_tx * UE->frame_parms.slots_per_frame;
+ int slot_and_frame = slot + curMsgTx->proc.frame_tx * nb_slot_frame;
int next_tx_slot_and_frame = absolute_slot + duration_rx_to_tx + 1;
int wait_for_prev_slot = stream_status == STREAM_STATUS_SYNCED ? 1 : 0;
diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h
index df13e2e02e..f14594b0dd 100644
--- a/executables/nr-uesoftmodem.h
+++ b/executables/nr-uesoftmodem.h
@@ -21,7 +21,7 @@ extern uint16_t ue_id_g;
#define CONFIG_HLP_INITIAL_FO "Initially compensated DL frequency offset (e.g. known Doppler shift in NTN LEO scenario)\n"
#define CONFIG_HLP_FREQ_SYNC_P "coefficient for Proportional part of continuous frequency offset compensation PI controller\n"
#define CONFIG_HLP_FREQ_SYNC_I "coefficient for Integrating part of continuous frequency offset compensation PI controller\n"
-#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift)\n"
+#define CONFIG_HLP_CONT_FO_COMP "Enable continuous frequency offset (FO) estimation and (pre-)compensation and specify main FO source (1 = local oscillator, 2 = Doppler shift, 3 = Don't consider residual DL FO in UL FO pre-compensation)\n"
#define CONFIG_HLP_AGC "Rx Gain control used for UE\n"
#define CONFIG_HLP_NUM_UL_ACTORS "Number of UL actors to use. Set to 0 to disable UL actor framework and do processing inline\n"
#define CONFIG_HLP_NUM_DL_ACTORS "Number of DL actors to use. Set to 0 to disable DL actor framework and do processing inline\n"
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
index 57292ecee5..04bb77f5de 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
@@ -51,9 +51,7 @@
#define FAPI_NR_DL_CONFIG_TYPE_CSI_RS 0x06
#define FAPI_NR_DL_CONFIG_TYPE_CSI_IM 0x07
#define FAPI_NR_CONFIG_TA_COMMAND 0x08
-#define FAPI_NR_DL_NTN_CONFIG_PARAMS 0x09
-#define FAPI_NR_DL_CONFIG_TYPES 0x09
-
+#define FAPI_NR_DL_CONFIG_TYPES 0x08
#define FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED 0x01
#define FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED 0x02
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index 37337e82d3..dd6b8135ab 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -73,6 +73,7 @@ typedef struct {
typedef struct {
/// frequency_domain_resource;
uint8_t frequency_domain_resource[6];
+ uint32_t rb_offset;
uint8_t StartSymbolIndex;
uint16_t StartSymbolBitmap;
uint8_t duration;
@@ -569,10 +570,14 @@ typedef struct {
// orbital angular velocity in rad/ms
double omega;
- // satellite position at epoch time
+ // satellite position vector at epoch time
position_t pos_sat_0;
- // satellite position at 90° orbit
+ // satellite position vector at 90° orbit
position_t pos_sat_90;
+ // satellite velocity vector at epoch time
+ position_t vel_sat_0;
+ // satellite velocity vector at 90° orbit
+ position_t vel_sat_90;
// N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
double N_common_ta_adj;
@@ -583,7 +588,10 @@ typedef struct {
// cell scheduling offset expressed in terms of 15kHz SCS
long cell_specific_k_offset;
-} fapi_nr_dl_ntn_config_command_pdu;
+
+ bool is_targetcell;
+ bool params_changed;
+} fapi_nr_ntn_config_t;
typedef struct {
uint8_t pdu_type;
@@ -593,7 +601,6 @@ typedef struct {
fapi_nr_dl_config_csirs_pdu csirs_config_pdu;
fapi_nr_dl_config_csiim_pdu csiim_config_pdu;
fapi_nr_ta_command_pdu ta_command_pdu;
- fapi_nr_dl_ntn_config_command_pdu ntn_config_command_pdu;
};
} fapi_nr_dl_config_request_pdu_t;
@@ -725,6 +732,7 @@ typedef struct {
fapi_nr_ssb_table_t ssb_table;
fapi_nr_tdd_table_t tdd_table;
fapi_nr_prach_config_t prach_config;
+ fapi_nr_ntn_config_t ntn_config;
} fapi_nr_config_request_t;
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index ded11bc4af..e5c8e975c9 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -337,8 +337,6 @@ void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
free_and_zero(ue->prs_vars[idx]);
}
- free_and_zero(ue->ntn_config_message);
-
sl_ue_free(ue);
}
diff --git a/openair1/PHY/INIT/tests/CMakeLists.txt b/openair1/PHY/INIT/tests/CMakeLists.txt
index 9f41e0fec0..6c532ebd99 100644
--- a/openair1/PHY/INIT/tests/CMakeLists.txt
+++ b/openair1/PHY/INIT/tests/CMakeLists.txt
@@ -1,2 +1,4 @@
add_executable(test_nr_frame_params test_nr_frame_params.cpp)
target_link_libraries(test_nr_frame_params PRIVATE LOG minimal_lib PHY_NR -lm GTest::gtest)
+add_dependencies(tests test_nr_frame_params)
+add_test(NAME test_nr_frame_params COMMAND ./test_nr_frame_params)
diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c
index 9045e50cb0..58e47fc13a 100644
--- a/openair1/PHY/MODULATION/slot_fep_nr.c
+++ b/openair1/PHY/MODULATION/slot_fep_nr.c
@@ -119,7 +119,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
if (ue && ue->cont_fo_comp) {
start_meas_nr_ue_phy(ue, RX_FO_COMPENSATION_STATS);
- nr_fo_compensation(ue->freq_offset,
+ nr_fo_compensation(ue->dl_Doppler_shift + ue->freq_offset,
frame_parms->samples_per_subframe,
rx_offset,
rxdata_symb_ptr[aa],
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dci.c b/openair1/PHY/NR_TRANSPORT/nr_dci.c
index 28d22b31bb..12bff45dee 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dci.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dci.c
@@ -61,9 +61,13 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
int reg_list[MAX_DCI_CORESET][NR_MAX_PDCCH_AGG_LEVEL * NR_NB_REG_PER_CCE];
nr_fill_reg_list(reg_list, pdcch_pdu_rel15);
// compute rb_offset and n_prb based on frequency allocation
- int rb_offset;
- int n_rb;
- get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource,&n_rb,&rb_offset);
+ int n_rb, cset_start;
+ get_coreset_rballoc(pdcch_pdu_rel15->FreqDomainResource, &n_rb, &cset_start);
+ int additional_offset = 0;
+ // first common RB of the first group of 6 PRBs has common RB index equal to 6 * ⌈BWP_start / 6⌉
+ if (pdcch_pdu_rel15->CoreSetType == 1)
+ additional_offset = (pdcch_pdu_rel15->BWPStart + 5) / 6 * 6 - pdcch_pdu_rel15->BWPStart;
+ int rb_offset = cset_start + additional_offset;
uint16_t cset_start_sc = frame_parms->first_carrier_offset + (pdcch_pdu_rel15->BWPStart + rb_offset) * NR_NB_SC_PER_RB;
int idx1 = pdcch_pdu_rel15->StartSymbolIndex+pdcch_pdu_rel15->DurationSymbols;
int idx2 = (((n_rb + rb_offset + pdcch_pdu_rel15->BWPStart) * 3) + 15) & ~15;
@@ -194,7 +198,7 @@ void nr_generate_dci(PHY_VARS_gNB *gNB,
// dmrs index depends on reference point for k according to 38.211 7.4.1.3.2
int dmrs_idx;
if (pdcch_pdu_rel15->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
- dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart) * 3;
+ dmrs_idx = (reg_list[d][reg_count] + pdcch_pdu_rel15->BWPStart + rb_offset) * 3;
else
dmrs_idx = (reg_list[d][reg_count] + rb_offset) * 3;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
index f4ab076921..822389ebdc 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
@@ -204,6 +204,7 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
c16_t dl_ch_estimates_ext[][arraySz],
NR_DL_FRAME_PARMS *frame_parms,
uint8_t *coreset_freq_dom,
+ uint32_t rb_offset,
uint32_t coreset_nbr_rb,
uint32_t n_BWP_start)
{
@@ -250,7 +251,7 @@ static void nr_pdcch_extract_rbs_single(uint32_t rxdataF_sz,
continue;
}
for (int rb = 0; rb < 6; rb++) {
- int c_rb = rb_group * 6 + rb;
+ int c_rb = rb_group * 6 + rb + rb_offset;
c16_t *rxF = NULL;
if ((frame_parms->N_RB_DL & 1) == 0) {
if ((c_rb + n_BWP_start) < frame_parms->N_RB_DL / 2)
@@ -338,10 +339,9 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
fapi_nr_coreset_t *coreset = &phy_pdcch_config->pdcch_config[ss_idx].coreset;
int32_t pdcch_est_size = ceil_mod(fp->ofdm_symbol_size + LTE_CE_FILTER_LENGTH, 16);
__attribute__((aligned(16))) c16_t pdcch_dl_ch_estimates[fp->nb_antennas_rx][pdcch_est_size];
- int n_rb;
- int rb_offset;
- get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &rb_offset);
-
+ int n_rb, cset_start;
+ get_coreset_rballoc(coreset->frequency_domain_resource, &n_rb, &cset_start);
+ int rb_offset = cset_start + coreset->rb_offset;
unsigned short scrambling_id = coreset->pdcch_dmrs_scrambling_id;
int dmrs_ref = 0;
if (coreset->CoreSetType == NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG)
@@ -376,6 +376,7 @@ static void nr_rx_pdcch_symbol(PHY_VARS_NR_UE *ue,
pdcch_dl_ch_estimates_ext,
fp,
coreset->frequency_domain_resource,
+ coreset->rb_offset,
n_rb,
phy_pdcch_config->pdcch_config[ss_idx].BWPStart);
@@ -509,10 +510,8 @@ void nr_pdcch_dci_indication(const UE_nr_rxtx_proc_t *proc,
uint8_t unused_start_symb[NR_SYMBOLS_PER_SLOT] = {0};
const int num_monitoring_occ = get_pdcch_mon_occasions_slot(rel15, unused_start_symb);
const int llr_stride = llr_size / rel15->coreset.duration;
-
- int n_rb;
- int rb_offset;
- get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
+ int n_rb, cset_start;
+ get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
for (int m = 0; m < num_monitoring_occ; m++) {
/// PDCCH/DCI e-sequence (input to rate matching).
@@ -643,9 +642,9 @@ static void nr_dci_decoding_procedure(PHY_VARS_NR_UE *ue,
.ss_type = rel15->ss_type_options[k],
.coreset_type = rel15->coreset.CoreSetType,
};
- int n_rb, rb_offset;
- get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &rb_offset);
- dci->cset_start = rel15->BWPStart + rb_offset;
+ int n_rb, cset_start;
+ get_coreset_rballoc(rel15->coreset.frequency_domain_resource, &n_rb, &cset_start);
+ dci->cset_start = rel15->BWPStart + cset_start + rel15->coreset.rb_offset;
dci->payloadSize = dci_length;
memcpy(dci->payloadBits, dci_estimation, (dci_length + 7) / 8);
dci_ind->number_of_dcis++;
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index f266d7aad5..a166dc13cd 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -329,11 +329,6 @@ typedef struct UE_NR_SCAN_INFO_s {
int32_t freq_offset_Hz[3][10];
} UE_NR_SCAN_INFO_t;
-typedef struct {
- bool update;
- fapi_nr_dl_ntn_config_command_pdu ntn_config_params;
-} ntn_config_message_t;
-
/// Top-level PHY Data Structure for UE
typedef struct PHY_VARS_NR_UE_s {
openair0_config_t openair0_cfg[MAX_CARDS];
@@ -462,8 +457,10 @@ typedef struct PHY_VARS_NR_UE_s {
double initial_fo; /// initial frequency offset provided by the user
int cont_fo_comp; /// flag enabling the continuous frequency offset estimation and compensation
- double freq_offset; /// currently compensated frequency offset
- double freq_off_acc; /// accumulated frequency error (for PI controller)
+ double freq_offset; /// currently compensated DL frequency offset (without dl_Doppler_shift)
+ double freq_off_acc; /// accumulated DL frequency error (for PI controller)
+ double dl_Doppler_shift; /// calculated DL Doppler shift
+ double ul_Doppler_shift; /// calculated UL Doppler shift
/// Timing Advance updates variables
/// Timing advance update computed from the TA command signalled from gNB
@@ -525,7 +522,6 @@ typedef struct PHY_VARS_NR_UE_s {
Actor_t sync_actor;
Actor_t *dl_actors;
Actor_t *ul_actors;
- ntn_config_message_t* ntn_config_message;
pthread_t main_thread;
pthread_t stat_thread;
} PHY_VARS_NR_UE;
diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c
index 6bc7cb933a..03631e3c7e 100644
--- a/openair1/SCHED_NR/nr_ru_procedures.c
+++ b/openair1/SCHED_NR/nr_ru_procedures.c
@@ -199,10 +199,11 @@ void nr_feptx_prec(RU_t *ru, int frame_tx, int slot_tx)
if (nr_slot_select(cfg,frame_tx,slot_tx) == NR_UPLINK_SLOT)
return;
+ int Ptx = cfg->carrier_config.num_tx_ant.value;
// If there is no digital beamforming we just need to copy the data to RU
if (ru->config.dbt_config.num_dig_beams == 0 || ru->gNB_list[0]->common_vars.analog_bf) {
for (int b = 0; b < ru->num_beams_period; b++) {
- for (int i = 0; i < ru->nb_tx; ++i) {
+ for (int i = 0; i < Ptx; ++i) {
int tx_idx = i + b * ru->nb_tx;
memcpy((void*)ru->common.txdataF_BF[tx_idx],
(void*)&gNB->common_vars.txdataF[b][i][txdataF_offset],
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index 6810f2c08d..4a07f7f5ca 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -90,29 +90,6 @@ static void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
}
}
-static void configure_ntn_params(PHY_VARS_NR_UE *ue, fapi_nr_dl_ntn_config_command_pdu* ntn_params_message)
-{
- if (!ue->ntn_config_message) {
- ue->ntn_config_message = CALLOC(1, sizeof(*ue->ntn_config_message));
- }
-
- ue->ntn_config_message->ntn_config_params.epoch_hfn = ntn_params_message->epoch_hfn;
- ue->ntn_config_message->ntn_config_params.epoch_sfn = ntn_params_message->epoch_sfn;
- ue->ntn_config_message->ntn_config_params.epoch_subframe = ntn_params_message->epoch_subframe;
-
- ue->ntn_config_message->ntn_config_params.omega = ntn_params_message->omega;
- ue->ntn_config_message->ntn_config_params.pos_sat_0 = ntn_params_message->pos_sat_0;
- ue->ntn_config_message->ntn_config_params.pos_sat_90 = ntn_params_message->pos_sat_90;
-
- ue->ntn_config_message->ntn_config_params.N_common_ta_adj = ntn_params_message->N_common_ta_adj;
- ue->ntn_config_message->ntn_config_params.N_common_ta_drift = ntn_params_message->N_common_ta_drift;
- ue->ntn_config_message->ntn_config_params.N_common_ta_drift_variant = ntn_params_message->N_common_ta_drift_variant;
-
- ue->ntn_config_message->ntn_config_params.cell_specific_k_offset = ntn_params_message->cell_specific_k_offset;
-
- ue->ntn_config_message->update = true;
-}
-
static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command_pdu)
{
/* Time Alignment procedure
@@ -229,9 +206,6 @@ static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac,
case FAPI_NR_CONFIG_TA_COMMAND:
configure_ta_command(phy, &pdu->ta_command_pdu);
break;
- case FAPI_NR_DL_NTN_CONFIG_PARAMS:
- configure_ntn_params(phy, &pdu->ntn_config_command_pdu);
- break;
default:
LOG_W(PHY, "unhandled dl pdu type %d \n", pdu->pdu_type);
}
diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c
index bed23968e4..92e191b2dc 100644
--- a/openair1/SIMULATION/TOOLS/random_channel.c
+++ b/openair1/SIMULATION/TOOLS/random_channel.c
@@ -48,8 +48,8 @@ static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static int channelmod_modify_cmd(char *buff, int debug, telnet_printfunc_t prnt);
static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt);
int get_modchannel_index(char *buf, int debug, void *vdata, telnet_printfunc_t prnt);
-int get_channel_params(char *buf, int debug, void *tdata, telnet_printfunc_t prnt);
-int get_currentchannels_type(char *buf, int debug, void *vdata, telnet_printfunc_t prnt);
+int get_channel_params(const char *buf, int debug, void *tdata, telnet_printfunc_t prnt);
+int get_currentchannels_type(const char *buf, int debug, void *vdata, telnet_printfunc_t prnt);
#define HELP_WEBIF_MODIFCHAN_STRING ""
static telnetshell_cmddef_t channelmod_cmdarray[] = {
@@ -1696,7 +1696,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
return(chan_desc);
} /* channel_desc_t *new_channel_desc_scm */
-channel_desc_t *find_channel_desc_fromname( char *modelname ) {
+channel_desc_t *find_channel_desc_fromname(const char *modelname) {
for(int i=0; imodel_name,modelname) == 0)
@@ -2029,7 +2029,7 @@ static int channelmod_print_help(char *buff, int debug, telnet_printfunc_t prnt
static char *pnames[] = {"riceanf", "aoa", "randaoa", "ploss", "noise_power_dB", "offset", "forgetf", NULL};
static char *pformat[] = {"%lf", "%lf", "%i", "%lf", "%lf", "%i", "%lf", NULL};
-int get_channel_params(char *buf, int debug, void *vdata, telnet_printfunc_t prnt)
+int get_channel_params(const char *buf, int debug, void *vdata, telnet_printfunc_t prnt)
{
if (buf == NULL) {
LOG_I(UTIL, "%s received NULL buffer\n", __FUNCTION__);
@@ -2111,7 +2111,7 @@ static void display_channelmodel(channel_desc_t *cd,int debug, telnet_printfunc_
}
}
-int get_currentchannels_type(char *buf, int debug, void *vdata, telnet_printfunc_t prnt)
+int get_currentchannels_type(const char *buf, int debug, void *vdata, telnet_printfunc_t prnt)
{
webdatadef_t *tdata;
if (buf == NULL) {
diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h
index 7104d524e2..6e60ce76de 100644
--- a/openair1/SIMULATION/TOOLS/sim.h
+++ b/openair1/SIMULATION/TOOLS/sim.h
@@ -347,7 +347,7 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
double path_loss_dB,
float noise_power_dB);
-channel_desc_t *find_channel_desc_fromname( char *modelname );
+channel_desc_t *find_channel_desc_fromname(const char *modelname);
/**
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index d70bf712b8..36ee2e4f0c 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -699,7 +699,6 @@ void RCconfig_verify(configmodule_interface_t *cfg, ngran_node_t node_type)
verify_gnb_param_notset(gnbp, GNB_PDSCH_ANTENNAPORTS_XP_IDX, GNB_CONFIG_STRING_PDSCHANTENNAPORTS_XP);
verify_gnb_param_notset(gnbp, GNB_PUSCH_ANTENNAPORTS_IDX, GNB_CONFIG_STRING_PUSCHANTENNAPORTS);
verify_gnb_param_notset(gnbp, GNB_MINRXTXTIME_IDX, GNB_CONFIG_STRING_MINRXTXTIME);
- verify_gnb_param_notset(gnbp, GNB_SIB1_TDA_IDX, GNB_CONFIG_STRING_SIB1TDA);
verify_gnb_param_notset(gnbp, GNB_DO_CSIRS_IDX, GNB_CONFIG_STRING_DOCSIRS);
verify_gnb_param_notset(gnbp, GNB_DO_SRS_IDX, GNB_CONFIG_STRING_DOSRS);
verify_gnb_param_notset(gnbp, GNB_FORCE256QAMOFF_IDX, GNB_CONFIG_STRING_FORCE256QAMOFF);
@@ -1436,8 +1435,6 @@ void RCconfig_nr_macrlc(configmodule_interface_t *cfg)
}
config.minRXTXTIME = *GNBParamList.paramarray[0][GNB_MINRXTXTIME_IDX].iptr;
LOG_I(GNB_APP, "minTXRXTIME %d\n", config.minRXTXTIME);
- config.sib1_tda = *GNBParamList.paramarray[0][GNB_SIB1_TDA_IDX].iptr;
- LOG_I(GNB_APP, "SIB1 TDA %d\n", config.sib1_tda);
config.do_CSIRS = *GNBParamList.paramarray[0][GNB_DO_CSIRS_IDX].iptr;
config.do_SRS = *GNBParamList.paramarray[0][GNB_DO_SRS_IDX].iptr;
config.max_num_rsrp = *GNBParamList.paramarray[0][GNB_LIMIT_RSRP_REPORT_IDX].iptr;
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 4ec09d06f0..14cd6ba3c8 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -114,7 +114,6 @@ typedef enum {
#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N2 "pdsch_AntennaPorts_N2"
#define GNB_CONFIG_STRING_PDSCHANTENNAPORTS_XP "pdsch_AntennaPorts_XP"
#define GNB_CONFIG_STRING_PUSCHANTENNAPORTS "pusch_AntennaPorts"
-#define GNB_CONFIG_STRING_SIB1TDA "sib1_tda"
#define GNB_CONFIG_STRING_DOCSIRS "do_CSIRS"
#define GNB_CONFIG_STRING_DOSRS "do_SRS"
#define GNB_CONFIG_STRING_NRCELLID "nr_cellid"
@@ -179,7 +178,6 @@ typedef enum {
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_N2, "vert. log. antenna ports", 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_PDSCHANTENNAPORTS_XP, "XP log. antenna ports", 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_PUSCHANTENNAPORTS, NULL, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
-{GNB_CONFIG_STRING_SIB1TDA, NULL, 0, .iptr=NULL, .defintval=1, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_DOCSIRS, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_DOSRS, NULL, 0, .iptr=NULL, .defintval=0, TYPE_INT, 0}, \
{GNB_CONFIG_STRING_NRCELLID, NULL, 0, .u64ptr=NULL,.defint64val=1, TYPE_UINT64, 0}, \
@@ -225,30 +223,29 @@ typedef enum {
#define GNB_PDSCH_ANTENNAPORTS_N2_IDX 14
#define GNB_PDSCH_ANTENNAPORTS_XP_IDX 15
#define GNB_PUSCH_ANTENNAPORTS_IDX 16
-#define GNB_SIB1_TDA_IDX 17
-#define GNB_DO_CSIRS_IDX 18
-#define GNB_DO_SRS_IDX 19
-#define GNB_NRCELLID_IDX 20
-#define GNB_MINRXTXTIME_IDX 21
-#define GNB_ULPRBBLACKLIST_IDX 22
-#define GNB_UMONDEFAULTDRB_IDX 23
-#define GNB_FORCE256QAMOFF_IDX 24
-#define GNB_ENABLE_SDAP_IDX 25
-#define GNB_DRBS 26
-#define GNB_GNB_DU_ID_IDX 27
-#define GNB_GNB_CU_UP_ID_IDX 28
-#define GNB_USE_DELTA_MCS_IDX 29
-#define GNB_FORCEUL256QAMOFF_IDX 30
-#define GNB_MAXMIMOLAYERS_IDX 31
-#define GNB_DISABLE_HARQ_IDX 32
-#define GNB_NUM_DL_HARQ_IDX 33
-#define GNB_NUM_UL_HARQ_IDX 34
-#define GNB_UESS_AGG_LEVEL_LIST_IDX 35
-#define GNB_CU_SIBS_IDX 36
-#define GNB_DU_SIBS_IDX 37
-#define GNB_CONFIG_REP_IDX 38
-#define GNB_1ST_ACTIVE_BWP_IDX 39
-#define GNB_LIMIT_RSRP_REPORT_IDX 40
+#define GNB_DO_CSIRS_IDX 17
+#define GNB_DO_SRS_IDX 18
+#define GNB_NRCELLID_IDX 19
+#define GNB_MINRXTXTIME_IDX 20
+#define GNB_ULPRBBLACKLIST_IDX 21
+#define GNB_UMONDEFAULTDRB_IDX 22
+#define GNB_FORCE256QAMOFF_IDX 23
+#define GNB_ENABLE_SDAP_IDX 24
+#define GNB_DRBS 25
+#define GNB_GNB_DU_ID_IDX 26
+#define GNB_GNB_CU_UP_ID_IDX 27
+#define GNB_USE_DELTA_MCS_IDX 28
+#define GNB_FORCEUL256QAMOFF_IDX 29
+#define GNB_MAXMIMOLAYERS_IDX 30
+#define GNB_DISABLE_HARQ_IDX 31
+#define GNB_NUM_DL_HARQ_IDX 32
+#define GNB_NUM_UL_HARQ_IDX 33
+#define GNB_UESS_AGG_LEVEL_LIST_IDX 34
+#define GNB_CU_SIBS_IDX 35
+#define GNB_DU_SIBS_IDX 36
+#define GNB_CONFIG_REP_IDX 37
+#define GNB_1ST_ACTIVE_BWP_IDX 38
+#define GNB_LIMIT_RSRP_REPORT_IDX 39
#define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
#define NUM_DL_HARQ_OKVALUES {2,4,6,8,10,12,16,32}
@@ -287,7 +284,6 @@ typedef enum {
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
{ .s5 = { NULL } }, \
- { .s5 = { NULL } }, \
{ .s1 = { config_check_intval, NUM_DL_HARQ_OKVALUES,8 } }, \
{ .s1 = { config_check_intval, NUM_UL_HARQ_OKVALUES,2 } }, \
{ .s5 = { NULL } }, \
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index c92c8225f6..4077e793ab 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -263,7 +263,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo
}
// prepare data for orbit propagation based on SIB19 ephemeris data to be able to compute the round-trip-time between ue and sat
-static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timing_advance_componets_t *ntn_ta)
+static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, fapi_nr_ntn_config_t *ntn_ta)
{
// get sat position coordinates
const position_t pos_sat = {sat_pos->positionX_r17 * 1.3, sat_pos->positionY_r17 * 1.3, sat_pos->positionZ_r17 * 1.3};
@@ -279,19 +279,28 @@ static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timi
const double vel_sat_2 = vel_sat.X * vel_sat.X + vel_sat.Y * vel_sat.Y + vel_sat.Z * vel_sat.Z;
const double vel_mag = sqrt(vel_sat_2);
- // calculate angular velocity in rad/ms
- const double omega = vel_mag / (radius * 1000);
+ double omega; // angular velocity in rad/ms
+ position_t pos_sat_90; // sat position vector in 90° orbit
+ position_t vel_sat_90; // sat velocity vector in 90° orbit
- // calculate sat position in 90° orbit
- position_t pos_sat_90 = pos_sat;
- if (vel_mag) {
- const double scaling = radius / vel_mag;
+ // assuming circular orbit when satellite moves faster than 1000 m/s
+ // 1000 m/s are chosen because according to Wikipedia, this seems to be a reasonable minimal
+ // orbital velocity: https://en.wikipedia.org/wiki/Orbital_speed#Tangential_velocities_at_altitude
+ if (vel_mag > 1000) {
+ omega = vel_mag / (radius * 1000);
+ double scaling = radius / vel_mag;
pos_sat_90 = (position_t){vel_sat.X * scaling, vel_sat.Y * scaling, vel_sat.Z * scaling};
+ scaling = -vel_mag / radius;
+ vel_sat_90 = (position_t){pos_sat.X * scaling, pos_sat.Y * scaling, pos_sat.Z * scaling};
+ } else {
+ omega = 0;
+ pos_sat_90 = pos_sat;
+ vel_sat_90 = vel_sat;
}
LOG_I(NR_MAC,
- "Satellite angular velocity = %e rad/ms, sat_pos = {%f, %f, %f}, sat_pos_90 = {%f, %f, %f}\n",
- omega,
+ "Satellite orbital radius %f m, pos_sat_0 = {%f, %f, %f}, pos_sat_90 = {%f, %f, %f}\n",
+ radius,
pos_sat.X,
pos_sat.Y,
pos_sat.Z,
@@ -299,13 +308,30 @@ static void prepare_ue_sat_ta(const NR_PositionVelocity_r17_t *sat_pos, ntn_timi
pos_sat_90.Y,
pos_sat_90.Z);
+ LOG_I(NR_MAC,
+ "Satellite velocity %f m/s, angular velocity = %e rad/ms, vel_sat_0 = {%f, %f, %f}, vel_sat_90 = {%f, %f, %f}\n",
+ vel_mag,
+ omega,
+ vel_sat.X,
+ vel_sat.Y,
+ vel_sat.Z,
+ vel_sat_90.X,
+ vel_sat_90.Y,
+ vel_sat_90.Z);
+
ntn_ta->omega = omega;
ntn_ta->pos_sat_0 = pos_sat;
ntn_ta->pos_sat_90 = pos_sat_90;
+ ntn_ta->vel_sat_0 = vel_sat;
+ ntn_ta->vel_sat_90 = vel_sat_90;
}
// populate ntn_ta structure from mac
-static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NTN_Config_r17_t *ntn_Config_r17, int hfn, int frame)
+static void configure_ntn_ta(fapi_nr_ntn_config_t *ntn_ta,
+ const NR_NTN_Config_r17_t *ntn_Config_r17,
+ int hfn,
+ int frame,
+ bool is_targetcell)
{
if (!ntn_Config_r17)
return;
@@ -320,25 +346,6 @@ static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NT
ntn_ta->epoch_sfn = epoch_time_r17->sfn_r17;
ntn_ta->epoch_subframe = epoch_time_r17->subFrameNR_r17;
- // handle ephemerisInfo_r17
- const NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17;
- if (ephemeris_info) {
- if (ephemeris_info->present == NR_EphemerisInfo_r17_PR_positionVelocity_r17) {
- const NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17;
- AssertFatal(position_velocity, "position_velocity should not be NULL here\n");
- prepare_ue_sat_ta(position_velocity, ntn_ta);
- } else {
- LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n");
- ntn_ta->omega = 0;
- ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
- ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
- }
- } else { // Need R - Release if not present
- ntn_ta->omega = 0;
- ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
- ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
- }
-
// handle cellSpecificKoffset_r17
if (ntn_Config_r17->cellSpecificKoffset_r17)
ntn_ta->cell_specific_k_offset = *ntn_Config_r17->cellSpecificKoffset_r17;
@@ -365,11 +372,9 @@ static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NT
ntn_ta->N_common_ta_drift_variant = 0;
}
- ntn_ta->ntn_params_changed = true;
-
LOG_I(NR_MAC,
- "SIB19 Rxd. Epoch HFN: %d, Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, "
- "N_Common_Ta: %fms, drift: %fµs/s, variant %fµs/s²\n",
+ "NTN Config Rxd. Epoch HFN: %d, Epoch SFN: %d, Epoch Subframe: %d, k_offset: %ldms, "
+ "N_Common_Ta: %fms, drift: %fµs/s, variant: %fµs/s²\n",
ntn_ta->epoch_hfn,
ntn_ta->epoch_sfn,
ntn_ta->epoch_subframe,
@@ -377,6 +382,32 @@ static void configure_ntn_ta(ntn_timing_advance_componets_t *ntn_ta, const NR_NT
ntn_ta->N_common_ta_adj,
ntn_ta->N_common_ta_drift,
ntn_ta->N_common_ta_drift_variant);
+
+ // handle ephemerisInfo_r17
+ const NR_EphemerisInfo_r17_t *ephemeris_info = ntn_Config_r17->ephemerisInfo_r17;
+ if (ephemeris_info) {
+ if (ephemeris_info->present == NR_EphemerisInfo_r17_PR_positionVelocity_r17) {
+ const NR_PositionVelocity_r17_t *position_velocity = ephemeris_info->choice.positionVelocity_r17;
+ AssertFatal(position_velocity, "position_velocity should not be NULL here\n");
+ prepare_ue_sat_ta(position_velocity, ntn_ta);
+ } else {
+ LOG_W(NR_MAC, "NR UE currently supports only ephemerisInfo_r17 of type positionVelocity_r17\n");
+ ntn_ta->omega = 0;
+ ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
+ ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
+ ntn_ta->vel_sat_0 = (position_t){0, 0, 0};
+ ntn_ta->vel_sat_90 = (position_t){0, 0, 0};
+ }
+ } else { // Need R - Release if not present
+ ntn_ta->omega = 0;
+ ntn_ta->pos_sat_0 = (position_t){0, 0, 0};
+ ntn_ta->pos_sat_90 = (position_t){0, 0, 0};
+ ntn_ta->vel_sat_0 = (position_t){0, 0, 0};
+ ntn_ta->vel_sat_90 = (position_t){0, 0, 0};
+ }
+
+ ntn_ta->is_targetcell = is_targetcell;
+ ntn_ta->params_changed = true;
}
static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t *scc, int cc_idP, int hfn, int frame)
@@ -553,7 +584,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t
// NTN Config
if (scc->ext2) {
UPDATE_IE(mac->sc_info.ntn_Config_r17, scc->ext2->ntn_Config_r17, NR_NTN_Config_r17_t);
- configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame);
+ configure_ntn_ta(&mac->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame, true);
} else {
asn1cFreeStruc(asn_DEF_NR_NTN_Config_r17, mac->sc_info.ntn_Config_r17);
}
@@ -1951,6 +1982,7 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si
mac->state = UE_PERFORMING_RA;
mac->if_module->phy_config_request(&mac->phy_config);
+ mac->phy_config.config_req.ntn_config.params_changed = false;
ret = pthread_mutex_unlock(&mac->if_mutex);
AssertFatal(!ret, "mutex failed %d\n", ret);
}
@@ -1964,7 +1996,9 @@ void nr_rrc_mac_config_other_sib(module_id_t module_id, NR_SIB19_r17_t *sib19, i
if (sib19) {
// update ntn_Config_r17 with received values
UPDATE_IE(mac->sc_info.ntn_Config_r17, sib19->ntn_Config_r17, NR_NTN_Config_r17_t);
- configure_ntn_ta(&mac->ntn_ta, mac->sc_info.ntn_Config_r17, hfn, frame);
+ configure_ntn_ta(&mac->phy_config.config_req.ntn_config, mac->sc_info.ntn_Config_r17, hfn, frame, false);
+ mac->if_module->phy_config_request(&mac->phy_config);
+ mac->phy_config.config_req.ntn_config.params_changed = false;
}
if (mac->state == UE_RECEIVING_SIB && can_start_ra)
mac->state = UE_PERFORMING_RA;
@@ -2027,6 +2061,7 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac,
mac->synch_request.synch_req.target_Nid_cell = mac->physCellId;
mac->if_module->synch_request(&mac->synch_request);
mac->if_module->phy_config_request(&mac->phy_config);
+ mac->phy_config.config_req.ntn_config.params_changed = false;
}
static void configure_physicalcellgroup(NR_UE_MAC_INST_t *mac,
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 7fda4a4b6c..65bf66505b 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -545,31 +545,6 @@ typedef struct {
A_SEQUENCE_OF(si_schedinfo_config_t) si_SchedInfo_list;
} si_schedInfo_t;
-typedef struct ntn_timing_advance_components {
- int epoch_hfn;
- int epoch_sfn;
- int epoch_subframe;
-
- // orbital angular velocity in rad/ms
- double omega;
- // satellite position at epoch time
- position_t pos_sat_0;
- // satellite position at 90° orbit
- position_t pos_sat_90;
-
- // N_common_ta_adj represents common round-trip-time between gNB and SAT received in SIB19 (ms)
- double N_common_ta_adj;
- // drift rate of common ta in µs/s
- double N_common_ta_drift;
- // change rate of common ta drift in µs/s²
- double N_common_ta_drift_variant;
-
- // cell scheduling offset expressed in terms of 15kHz SCS
- long cell_specific_k_offset;
-
- bool ntn_params_changed;
-} ntn_timing_advance_componets_t;
-
/*!\brief Top level UE MAC structure */
typedef struct NR_UE_MAC_INST_s {
module_id_t ue_id;
@@ -633,8 +608,6 @@ typedef struct NR_UE_MAC_INST_s {
int p_Max;
int p_Max_alt;
- ntn_timing_advance_componets_t ntn_ta;
-
long pdsch_HARQ_ACK_Codebook;
NR_Type0_PDCCH_CSS_config_t type0_PDCCH_CSS_config;
@@ -675,12 +648,12 @@ typedef struct NR_UE_MAC_INST_s {
notifiedFIFO_t input_nf;
} NR_UE_MAC_INST_t;
-static inline int GET_NTN_UE_K_OFFSET(const ntn_timing_advance_componets_t *ntn_ta, int scs)
+static inline int GET_NTN_UE_K_OFFSET(const fapi_nr_ntn_config_t *ntn_ta, int scs)
{
return (int)ntn_ta->cell_specific_k_offset << scs;
}
-static inline long GET_DURATION_RX_TO_TX(const ntn_timing_advance_componets_t *ntn_ta, int scs)
+static inline long GET_DURATION_RX_TO_TX(const fapi_nr_ntn_config_t *ntn_ta, int scs)
{
return NR_UE_CAPABILITY_SLOT_RX_TO_TX + (ntn_ta->cell_specific_k_offset << scs);
}
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index 4cf96b46bc..461d21f3aa 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -69,7 +69,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac)
mac->p_Max = INT_MIN;
mac->p_Max_alt = INT_MIN;
mac->msg3_C_RNTI = false;
- mac->ntn_ta.ntn_params_changed = false;
+ mac->phy_config.config_req.ntn_config.params_changed = false;
initNotifiedFIFO(&mac->input_nf);
reset_mac_inst(mac);
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
index ecf8edb022..dfe16de822 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
@@ -813,7 +813,7 @@ static void setup_ra_response_window(NR_UE_MAC_INST_t *mac,
LOG_E(NR_MAC, "RA-ResponseWindow need to be configured to a value lower than or equal to 10 ms\n");
}
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
ra->response_window_setup_time = respwind_value + ntn_ue_koffset;
}
@@ -1027,7 +1027,7 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s
{
RA_config_t *ra = &mac->ra;
NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
const int slots_per_ms = mac->frame_structure.numb_slots_frame / 10;
// start contention resolution timer
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
index 1f84b11a48..af6bf37aff 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
@@ -122,9 +122,18 @@ static void config_dci_pdu(NR_UE_MAC_INST_t *mac,
if(coreset_id > 0) {
coreset = ue_get_coreset(pdcch_config, coreset_id);
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_PDCCH_CONFIG;
+ if (coreset->ext1 && coreset->ext1->rb_Offset_r16)
+ rel15->coreset.rb_offset = *coreset->ext1->rb_Offset_r16;
+ else {
+ // first common RB of the first group of 6 PRBs has common RB index equal to
+ // 6 * ⌈BWP_start / 6⌉ if rb-Offset is not provided
+ int start_common = (current_DL_BWP->BWPStart + 5) / 6 * 6;
+ rel15->coreset.rb_offset = start_common - current_DL_BWP->BWPStart;
+ }
} else {
coreset = mac->coreset0;
rel15->coreset.CoreSetType = NFAPI_NR_CSET_CONFIG_MIB_SIB1;
+ rel15->coreset.rb_offset = 0;
}
rel15->coreset.duration = coreset->duration;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 86d7b9254f..241a56b180 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -563,7 +563,7 @@ static int nr_ue_process_dci_ul_00(NR_UE_MAC_INST_t *mac,
frame_t frame_tx;
int slot_tx;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) {
LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1;
@@ -661,7 +661,7 @@ static int nr_ue_process_dci_ul_01(NR_UE_MAC_INST_t *mac,
tda_info.k2 = csi_K2;
}
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
if (-1 == nr_ue_pusch_scheduler(mac, 0, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset)) {
LOG_E(MAC, "Cannot schedule PUSCH\n");
return -1;
@@ -998,7 +998,7 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 9.2.3
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
uint16_t feedback_ti = 0;
if (rnti_type == TYPE_RA_RNTI_) {
@@ -1006,17 +1006,17 @@ static int nr_ue_process_dci_dl_10(NR_UE_MAC_INST_t *mac,
// that can process the MSG3. Also assume that RAR is sent in the same slot as DCI (k0 == 0)
// This is not perfect as the MSG3 might end up being scheduled later, so we could be
// halting the UL scheduler for a longer time than necessary.
- feedback_ti = max(1 + GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
+ feedback_ti = max(1 + GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
get_delta_for_k2(mac->current_UL_BWP->scs) + get_j_for_k2(mac->current_UL_BWP->scs));
}
if (rnti_type != TYPE_RA_RNTI_ && rnti_type != TYPE_SI_RNTI_) {
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = 1 + dci->pdsch_to_harq_feedback_timing_indicator.val + ntn_ue_koffset;
- AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
+ AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld).\n",
feedback_ti,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing));
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
set_harq_status(mac,
@@ -1312,16 +1312,16 @@ static int nr_ue_process_dci_dl_11(NR_UE_MAC_INST_t *mac,
/* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
// according to TS 38.213 Table 9.2.3-1
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing);
uint16_t feedback_ti = 0;
if (!get_FeedbackDisabled(mac->sc_info.downlinkHARQ_FeedbackDisabled_r17, dci->harq_pid.val)) {
feedback_ti = pucch_Config->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0] + ntn_ue_koffset;
- AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing),
+ AssertFatal(feedback_ti >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing),
"PDSCH to HARQ feedback time (%d) needs to be higher than DURATION_RX_TO_TX (%ld). Min feedback time set in config "
"file (min_rxtxtime).\n",
feedback_ti,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, dlsch_pdu->SubcarrierSpacing));
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, dlsch_pdu->SubcarrierSpacing));
// set the harq status at MAC for feedback
const int tpc[] = {-1, 0, 1, 3};
@@ -3620,7 +3620,7 @@ static void set_time_alignment(NR_UE_MAC_INST_t *mac, int ta, ta_type_t type, in
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
ul_time_alignment->ta_command = ta;
ul_time_alignment->ta_apply = type;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
const int n_slots_frame = mac->frame_structure.numb_slots_frame;
ul_time_alignment->frame = (frame + (slot + ntn_ue_koffset) / n_slots_frame) % MAX_FRAME_NUMBER;
ul_time_alignment->slot = (slot + ntn_ue_koffset) % n_slots_frame;
@@ -4095,7 +4095,7 @@ static void handle_rar_reception(NR_UE_MAC_INST_t *mac, NR_MAC_RAR *rar, frame_t
}
frame_t frame_tx = 0;
int slot_tx = 0;
- const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->ntn_ta, mac->current_UL_BWP->scs);
+ const int ntn_ue_koffset = GET_NTN_UE_K_OFFSET(&mac->phy_config.config_req.ntn_config, mac->current_UL_BWP->scs);
int ret = nr_ue_pusch_scheduler(mac, 1, frame, slot, &frame_tx, &slot_tx, tda_info.k2 + ntn_ue_koffset);
// TA command
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index c8d40e7f11..c21a0ce3bd 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -59,7 +59,6 @@
static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t slotP);
static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac);
-static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac);
static void nr_ue_fill_phr(NR_UE_MAC_INST_t *mac,
NR_SINGLE_ENTRY_PHR_MAC_CE *phr,
@@ -1056,10 +1055,10 @@ void nr_ue_aperiodic_srs_scheduling(NR_UE_MAC_INST_t *mac, long resource_trigger
}
int scs = mac->current_UL_BWP->scs;
- AssertFatal(slot_offset > GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs),
+ AssertFatal(slot_offset > GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, scs),
"Slot offset between DCI and aperiodic SRS (%d) needs to be higher than DURATION_RX_TO_TX (%ld)\n",
slot_offset,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, scs));
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, scs));
int n_slots_frame = mac->frame_structure.numb_slots_frame;
int sched_slot = (slot + slot_offset) % n_slots_frame;
if (!is_ul_slot(sched_slot, &mac->frame_structure)) {
@@ -1157,11 +1156,6 @@ void nr_ue_dl_scheduler(NR_UE_MAC_INST_t *mac, nr_downlink_indication_t *dl_info
if (mac->ul_time_alignment.ta_apply != no_ta)
schedule_ta_command(dl_config, mac);
-
- if (mac->ntn_ta.ntn_params_changed) {
- mac->ntn_ta.ntn_params_changed = false;
- schedule_ntn_config_command(dl_config, mac);
- }
nr_scheduled_response_t scheduled_response = {.dl_config = dl_config,
.module_id = mac->ue_id,
@@ -1570,24 +1564,24 @@ int nr_ue_pusch_scheduler(const NR_UE_MAC_INST_t *mac,
delta = get_delta_for_k2(mu);
- AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ AssertFatal((k2 + delta) > GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
"Slot offset (%ld) for Msg3 needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to "
"%ld in gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu));
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
*slot_tx = (current_slot + k2 + delta) % slots_per_frame;
*frame_tx = (current_frame + (current_slot + k2 + delta) / slots_per_frame) % MAX_FRAME_NUMBER;
} else {
- AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
+ AssertFatal(k2 >= GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
"Slot offset K2 (%ld) needs to be higher than DURATION_RX_TO_TX (%ld). Please set min_rxtxtime at least to %ld in "
"gNB config file or gNBs.[0].min_rxtxtime=%ld via command line.\n",
k2,
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu),
- GET_DURATION_RX_TO_TX(&mac->ntn_ta, mu));
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu),
+ GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mu));
if (k2 < 0) { // This can happen when a false DCI is received
LOG_W(PHY, "%d.%d. Received k2 %ld\n", current_frame, current_slot, k2);
@@ -2210,9 +2204,8 @@ static void nr_ue_prach_scheduler(NR_UE_MAC_INST_t *mac, frame_t frameP, slot_t
next_slot = temp_slot;
add_slots++;
}
- nr_timer_setup(&ra->response_window_timer,
- ra->response_window_setup_time + add_slots + GET_DURATION_RX_TO_TX(&mac->ntn_ta, mac->current_DL_BWP->scs),
- 1);
+ add_slots += GET_DURATION_RX_TO_TX(&mac->phy_config.config_req.ntn_config, mac->current_DL_BWP->scs);
+ nr_timer_setup(&ra->response_window_timer, ra->response_window_setup_time + add_slots, 1);
nr_timer_start(&ra->response_window_timer);
} else if (ra->ra_type == RA_2_STEP) {
NR_MsgA_PUSCH_Resource_r16_t *msgA_PUSCH_Resource =
@@ -2844,28 +2837,6 @@ static uint8_t nr_ue_get_sdu(NR_UE_MAC_INST_t *mac,
return mac_ce_info.num_sdus > 0; // success if we got at least one sdu
}
-static void schedule_ntn_config_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
-{
- fapi_nr_dl_ntn_config_command_pdu *ntn_config_command_pdu = &dl_config->dl_config_list[dl_config->number_pdus].ntn_config_command_pdu;
-
- ntn_config_command_pdu->epoch_hfn = mac->ntn_ta.epoch_hfn;
- ntn_config_command_pdu->epoch_sfn = mac->ntn_ta.epoch_sfn;
- ntn_config_command_pdu->epoch_subframe = mac->ntn_ta.epoch_subframe;
-
- ntn_config_command_pdu->omega = mac->ntn_ta.omega;
- ntn_config_command_pdu->pos_sat_0 = mac->ntn_ta.pos_sat_0;
- ntn_config_command_pdu->pos_sat_90 = mac->ntn_ta.pos_sat_90;
-
- ntn_config_command_pdu->N_common_ta_adj = mac->ntn_ta.N_common_ta_adj;
- ntn_config_command_pdu->N_common_ta_drift = mac->ntn_ta.N_common_ta_drift;
- ntn_config_command_pdu->N_common_ta_drift_variant = mac->ntn_ta.N_common_ta_drift_variant;
-
- ntn_config_command_pdu->cell_specific_k_offset = mac->ntn_ta.cell_specific_k_offset;
-
- dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_DL_NTN_CONFIG_PARAMS;
- dl_config->number_pdus += 1;
-}
-
static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MAC_INST_t *mac)
{
NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index d8c4ee04ba..dd5558d546 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -255,7 +255,7 @@ void schedule_nr_mib(module_id_t module_idP, frame_t frameP, slot_t slotP, nfapi
}
}
-static void update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16_t *vrb_map)
+static bool update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes, uint16_t *vrb_map)
{
const NR_tda_info_t *tda_info = &pdsch->tda_info;
@@ -296,12 +296,15 @@ static void update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes,
break;
}
}
- AssertFatal(pdsch->tb_size >= num_total_bytes,
- "Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n",
- num_total_bytes,
- pdsch->rbStart,
- pdsch->rbSize,
- bwpSize);
+ if (pdsch->tb_size < num_total_bytes) {
+ LOG_D(NR_MAC,
+ "Couldn't allocate enough resources for %d bytes in SIB PDSCH (rbStart %d, rbSize %d, bwpSize %d)\n",
+ num_total_bytes,
+ pdsch->rbStart,
+ pdsch->rbSize,
+ bwpSize);
+ return false;
+ }
LOG_D(NR_MAC,
"mcs=%i, startSymbolIndex = %i, nrOfSymbols = %i, rbSize = %i, TBS = %i, dmrs_length %d, N_PRB_DMRS = %d, mappingtype = %d\n",
@@ -313,6 +316,7 @@ static void update_rb_mcs_tbs(NR_sched_pdsch_t *pdsch, uint32_t num_total_bytes,
pdsch->dmrs_parms.N_DMRS_SLOT,
N_PRB_DMRS,
tda_info->mapping_type);
+ return true;
}
static NR_sched_pdsch_t schedule_control_sib1(gNB_MAC_INST *gNB_mac,
@@ -342,11 +346,12 @@ static NR_sched_pdsch_t schedule_control_sib1(gNB_MAC_INST *gNB_mac,
uint8_t nr_of_candidates = 0;
- for (int i=0; i<3; i++) {
+ for (int i = 0; i < 3; i++) {
find_aggregation_candidates(&gNB_mac->sched_ctrlCommon->aggregation_level, &nr_of_candidates, gNB_mac->sched_ctrlCommon->search_space,4<0) break; // choosing the lower value of aggregation level available
+ if (nr_of_candidates > 0)
+ break; // choosing the lower value of aggregation level available
}
- AssertFatal(nr_of_candidates>0,"nr_of_candidates is 0\n");
+ AssertFatal(nr_of_candidates > 0, "nr_of_candidates is 0\n");
gNB_mac->sched_ctrlCommon->cce_index = find_pdcch_candidate(gNB_mac,
CC_id,
gNB_mac->sched_ctrlCommon->aggregation_level,
@@ -358,18 +363,23 @@ static NR_sched_pdsch_t schedule_control_sib1(gNB_MAC_INST *gNB_mac,
AssertFatal(gNB_mac->sched_ctrlCommon->cce_index >= 0, "Could not find CCE for coreset0\n");
- update_rb_mcs_tbs(&pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map);
-
- // Mark the corresponding RBs as used
- fill_pdcch_vrb_map(gNB_mac,
- CC_id,
- pdcch,
- gNB_mac->sched_ctrlCommon->cce_index,
- gNB_mac->sched_ctrlCommon->aggregation_level,
- beam);
- for (int rb = 0; rb < pdsch.rbSize; rb++) {
- vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
+ bool success = update_rb_mcs_tbs(&pdsch, gNB_mac->sched_ctrlCommon->num_total_bytes, vrb_map);
+ if (success) {
+ // Mark the corresponding RBs as used
+ fill_pdcch_vrb_map(gNB_mac,
+ CC_id,
+ pdcch,
+ gNB_mac->sched_ctrlCommon->cce_index,
+ gNB_mac->sched_ctrlCommon->aggregation_level,
+ beam);
+ for (int rb = 0; rb < pdsch.rbSize; rb++) {
+ vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info->startSymbolIndex, tda_info->nrOfSymbols);
+ }
+ } else {
+ pdsch.tb_size = 0; // to signal we couldn't allocate TBS
+ pdsch.time_domain_allocation = -1;
}
+
return pdsch;
}
@@ -464,6 +474,53 @@ static void nr_fill_nfapi_dl_SIB_pdu(gNB_MAC_INST *gNB_mac,
pdcch_pdu_rel15->numDlDci);
}
+static bool check_sib1_tda(gNB_MAC_INST *gNB_mac,
+ NR_sched_pdcch_t *sched_pdcch,
+ NR_beam_alloc_t *beam,
+ int tda,
+ int ssb_index,
+ int CC_id,
+ int candidate_idx)
+{
+ NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
+ NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
+ NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config = &gNB_mac->type0_PDCCH_CSS_config[ssb_index];
+ default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern);
+ // If the PDSCH was scheduled with SI-RNTI in PDCCH Type0 common search space,
+ // the UE may assume that this PDSCH resource allocation is not applied (Table 5.1.2.1.1-4 and 5 in 38.214)
+ int row = tda + 1;
+ if (table_type == defaultB && (row == 12 || row == 13 || row == 14))
+ false;
+ if (table_type == defaultC && (row == 1 || row == 6 || row == 7 ||row > 12))
+ false;
+ // assuming normal CP
+ NR_tda_info_t tda_info = get_info_from_tda_tables(table_type, tda, scc->dmrs_TypeA_Position, true);
+ // SIB1 TDA going to the last symbol would cause overlap with CSI-RS
+ if (!tda_info.valid_tda || tda_info.startSymbolIndex + tda_info.nrOfSymbols == 14)
+ false;
+ if (tda_info.startSymbolIndex < type0_PDCCH_CSS_config->first_symbol_index + type0_PDCCH_CSS_config->num_symbols)
+ false;
+
+ NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
+ // Configure sched_ctrlCommon for SIB1
+ gNB_mac->sib1_pdsch[ssb_index] = schedule_control_sib1(gNB_mac,
+ CC_id,
+ sched_pdcch,
+ type0_PDCCH_CSS_config,
+ tda,
+ &dmrs_parms,
+ &tda_info,
+ candidate_idx,
+ beam->idx,
+ cc->sib1_bcch_length);
+ if (gNB_mac->sib1_pdsch[ssb_index].tb_size > 0) {
+ LOG_D(NR_MAC, "Found TDA for SIB1: %d\n", tda);
+ return true;
+ } else {
+ return false;
+ }
+}
+
void schedule_nr_sib1(module_id_t module_idP,
frame_t frameP,
slot_t slotP,
@@ -474,12 +531,9 @@ void schedule_nr_sib1(module_id_t module_idP,
// TODO: Get these values from RRC
const int CC_id = 0;
uint8_t candidate_idx = 0;
-
gNB_MAC_INST *gNB_mac = RC.nrmac[module_idP];
- NR_ServingCellConfigCommon_t *scc = gNB_mac->common_channels[CC_id].ServingCellConfigCommon;
-
- int time_domain_allocation = gNB_mac->radio_config.sib1_tda;
-
+ NR_COMMON_channels_t *cc = &gNB_mac->common_channels[CC_id];
+ NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
int L_max;
switch (scc->ssb_PositionsInBurst->present) {
case 1:
@@ -492,8 +546,7 @@ void schedule_nr_sib1(module_id_t module_idP,
L_max = 64;
break;
default:
- AssertFatal(0,"SSB bitmap size value %d undefined (allowed values 1,2,3)\n",
- scc->ssb_PositionsInBurst->present);
+ AssertFatal(false, "SSB bitmap size value %d undefined (allowed values 1,2,3)\n", scc->ssb_PositionsInBurst->present);
}
for (int i = 0; i < L_max; i++) {
@@ -513,17 +566,6 @@ void schedule_nr_sib1(module_id_t module_idP,
NR_beam_alloc_t beam = beam_allocation_procedure(&gNB_mac->beam_info, frameP, slotP, beam_index, n_slots_frame);
AssertFatal(beam.idx >= 0, "Cannot allocate SIB1 corresponding to SSB %d in any available beam\n", i);
LOG_D(NR_MAC,"(%d.%d) SIB1 transmission: ssb_index %d\n", frameP, slotP, type0_PDCCH_CSS_config->ssb_index);
-
- default_table_type_t table_type = get_default_table_type(type0_PDCCH_CSS_config->type0_pdcch_ss_mux_pattern);
- // assuming normal CP
- NR_tda_info_t tda_info = get_info_from_tda_tables(table_type, time_domain_allocation, scc->dmrs_TypeA_Position, true);
-
- AssertFatal((tda_info.startSymbolIndex + tda_info.nrOfSymbols) < 14,
- "SIB1 TDA %d would cause overlap with CSI-RS. Please select a different SIB1 TDA.\n",
- time_domain_allocation);
-
- NR_pdsch_dmrs_t dmrs_parms = get_dl_dmrs_params(scc, NULL, &tda_info, 1);
-
NR_sched_pdcch_t sched_pdcch = set_pdcch_structure(NULL,
gNB_mac->sched_ctrlCommon->search_space,
gNB_mac->sched_ctrlCommon->coreset,
@@ -531,23 +573,24 @@ void schedule_nr_sib1(module_id_t module_idP,
NULL,
type0_PDCCH_CSS_config);
- NR_COMMON_channels_t *cc = &gNB_mac->common_channels[0];
- // Configure sched_ctrlCommon for SIB1
- NR_sched_pdsch_t sched_pdsch = schedule_control_sib1(gNB_mac,
- CC_id,
- &sched_pdcch,
- type0_PDCCH_CSS_config,
- time_domain_allocation,
- &dmrs_parms,
- &tda_info,
- candidate_idx,
- beam.idx,
- cc->sib1_bcch_length);
-
+ bool res = false;
+ if (gNB_mac->sib1_pdsch[i].time_domain_allocation < 0) {
+ for (int t = 0; t < 16; t++) {
+ if (check_sib1_tda(gNB_mac, &sched_pdcch, &beam, t, i, CC_id, candidate_idx)) {
+ res = true;
+ break;
+ }
+ }
+ }
+ AssertFatal(gNB_mac->sib1_pdsch[i].time_domain_allocation >= 0, "Couldn't select any TDA for SIB1\n");
+ if (!res)
+ res = check_sib1_tda(gNB_mac, &sched_pdcch, &beam, gNB_mac->sib1_pdsch[i].time_domain_allocation, i, CC_id, candidate_idx);
+ int tb_size = gNB_mac->sib1_pdsch[i].tb_size;
+ AssertFatal(res && tb_size > 0, "Couldn't allocate TB for SIB1 for an already allocated TDA\n");
nfapi_nr_dl_tti_request_body_t *dl_req = &DL_req->dl_tti_request_body;
int pdu_index = gNB_mac->pdu_index[0]++;
nr_fill_nfapi_dl_SIB_pdu(gNB_mac,
- &sched_pdsch,
+ &gNB_mac->sib1_pdsch[i],
&sched_pdcch,
gNB_mac->sched_ctrlCommon->search_space,
gNB_mac->sched_ctrlCommon->coreset,
@@ -563,11 +606,11 @@ void schedule_nr_sib1(module_id_t module_idP,
nfapi_nr_pdu_t *tx_req = &TX_req->pdu_list[ntx_req];
// Data to be transmitted
- memcpy(tx_req->TLVs[0].value.direct, cc->sib1_bcch_pdu, sched_pdsch.tb_size);
+ memcpy(tx_req->TLVs[0].value.direct, cc->sib1_bcch_pdu, tb_size);
tx_req->PDU_index = pdu_index;
tx_req->num_TLV = 1;
- tx_req->TLVs[0].length = sched_pdsch.tb_size;
+ tx_req->TLVs[0].length = tb_size;
tx_req->PDU_length = compute_PDU_length(tx_req->num_TLV, tx_req->TLVs[0].length);
TX_req->Number_of_PDUs++;
TX_req->SFN = frameP;
@@ -673,7 +716,8 @@ static void other_sib_sched_control(module_id_t module_idP,
uint16_t *vrb_map = cc->vrb_map[beam.idx];
uint8_t *sib_bcch_pdu = cc->other_sib_bcch_pdu[payload_idx];
int num_total_bytes = cc->other_sib_bcch_length[payload_idx];
- update_rb_mcs_tbs(&sched_pdsch_otherSI, num_total_bytes, vrb_map);
+ bool success = update_rb_mcs_tbs(&sched_pdsch_otherSI, num_total_bytes, vrb_map);
+ AssertFatal(success, "Couldn't allocate TBS for other SIB\n");
for (int rb = 0; rb < sched_pdsch_otherSI.rbSize; rb++) {
vrb_map[rb + type0_PDCCH_CSS_config->cset_start_rb] |= SL_to_bitmap(tda_info.startSymbolIndex, tda_info.nrOfSymbols);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 00c41953a1..782721c4e2 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -404,7 +404,8 @@ bwp_info_t get_pdsch_bwp_start_size(gNB_MAC_INST *nr_mac, NR_UE_info_t *UE)
if (sched_ctrl->coreset->controlResourceSetId == 0) {
bwp_info.bwpStart = nr_mac->cset0_bwp_start;
} else {
- bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start;
+ int additional_offset = (dl_bwp->BWPStart + 5) / 6 * 6 - dl_bwp->BWPStart;
+ bwp_info.bwpStart = dl_bwp->BWPStart + sched_ctrl->sched_pdcch.rb_start + additional_offset;
}
if (nr_mac->cset0_bwp_size > 0) {
bwp_info.bwpSize = min(dl_bwp->BWPSize, nr_mac->cset0_bwp_size);
@@ -595,17 +596,17 @@ static bool allocate_dl_retransmission(gNB_MAC_INST *nr_mac,
static void ack_reconfig(gNB_MAC_INST *mac, NR_UE_info_t *UE)
{
- if (UE->reconfigSpCellConfig) {
- // in case of reestablishment, the spCellConfig had to be released
- // temporarily. Reapply now before doing the reconfiguration.
- UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
- // UE->reconfigSpCellConfig to be NULLed after receiving reconfiguration complete
+ if (!UE->reconfigCellGroup) {
+ LOG_W(NR_MAC, "Received ACK for RRCReconfiguration, but nothing to apply!\n");
+ return;
}
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
+ UE->CellGroup = UE->reconfigCellGroup;
+ UE->reconfigCellGroup = NULL;
NR_ServingCellConfigCommon_t *scc = mac->common_channels[0].ServingCellConfigCommon;
/* clean BWP structures */
clean_bwp_structures(UE->CellGroup->spCellConfig);
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
- UE->await_reconfig = false;
}
typedef struct UEsched_s {
@@ -885,7 +886,7 @@ static void pf_dl(gNB_MAC_INST *mac,
sched_pdsch.action = NULL;
int srb1 = 1;
/* everything that's only 3 bytes is an ack. To be safe, use a bit more. */
- if (iterator->UE->await_reconfig && sched_ctrl->rlc_status[srb1].bytes_in_buffer > 10)
+ if (iterator->UE->reconfigCellGroup && sched_ctrl->rlc_status[srb1].bytes_in_buffer > 10)
sched_pdsch.action = ack_reconfig;
// Fix me: currently, the RLC does not give us the total number of PDUs
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index f9a099d79b..4a7213ab34 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -454,6 +454,7 @@ static NR_SearchSpace_t *get_searchspace(NR_ServingCellConfigCommon_t *scc,
/// @param rb_start Output parameter for the starting resource block index of the CORESET
static void get_coreset_rb_params(const NR_ControlResourceSet_t *coreset, uint16_t *n_rb, uint16_t *rb_start)
{
+ AssertFatal(!coreset->ext1 || !coreset->ext1->rb_Offset_r16, "rb-Offset in coreset configuration not handled\n");
*n_rb = 0;
*rb_start = 0;
@@ -2490,7 +2491,7 @@ NR_UE_info_t *find_ra_UE(NR_UEs_t *UEs, rnti_t rntiP)
void delete_nr_ue_data(NR_UE_info_t *UE, NR_COMMON_channels_t *ccPtr, uid_allocator_t *uia)
{
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
- ASN_STRUCT_FREE(asn_DEF_NR_SpCellConfig, UE->reconfigSpCellConfig);
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
seq_arr_free(&sched_ctrl->lc_config, NULL);
@@ -2854,6 +2855,20 @@ void configure_UE_BWP(gNB_MAC_INST *nr_mac,
sc_info->nrofHARQ_ProcessesForPUSCH_r17 = pusch_servingcellconfig->ext3->nrofHARQ_ProcessesForPUSCH_r17;
}
}
+ } else {
+ sc_info->csi_MeasConfig = NULL;
+ sc_info->nrofHARQ_ProcessesForPDSCH = NULL;
+ sc_info->maxMIMO_Layers_PDSCH = NULL;
+ sc_info->downlinkHARQ_FeedbackDisabled_r17 = NULL;
+ sc_info->pdsch_CGB_Transmission = NULL;
+ sc_info->nrofHARQ_ProcessesForPDSCH_v1700 = NULL;
+ sc_info->crossCarrierSchedulingConfig = NULL;
+ sc_info->supplementaryUplink = NULL;
+ sc_info->carrierSwitching = NULL;
+ sc_info->maxMIMO_Layers_PUSCH = NULL;
+ sc_info->rateMatching_PUSCH = NULL;
+ sc_info->pusch_CGB_Transmission = NULL;
+ sc_info->nrofHARQ_ProcessesForPUSCH_r17 = NULL;
}
if (CellGroup && CellGroup->physicalCellGroupConfig)
@@ -3941,7 +3956,8 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE,
buf,
sizeof(buf));
AssertFatal(enc_rval.encoded > 0, "ASN1 encoding of CellGroupConfig failed, failed type %s\n", enc_rval.failed_type->name);
- UE->await_reconfig = true;
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
+ UE->reconfigCellGroup = cellGroup_for_UE;
du_to_cu_rrc_information_t du2cu = {
.cellGroupConfig = buf,
.cellGroupConfig_length = (enc_rval.encoded + 7) >> 3,
@@ -3955,8 +3971,6 @@ void nr_mac_trigger_reconfiguration(const gNB_MAC_INST *nrmac, NR_UE_info_t *UE,
.cause_value = F1AP_CauseRadioNetwork_action_desirable_for_radio_reasons,
};
nrmac->mac_rrc.ue_context_modification_required(&required);
- if (cellGroup_for_UE)
- free_cellGroupConfig(cellGroup_for_UE);
}
long get_lcid_from_drbid(int drb_id)
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 6fbac36caa..bc29981928 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -981,11 +981,6 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
return;
}
- NR_CSI_MeasConfig_t *csi_MeasConfig = UE->sc_info.csi_MeasConfig;
- if (csi_MeasConfig == NULL) {
- NR_SCHED_UNLOCK(&nrmac->sched_lock);
- return;
- }
NR_UE_sched_ctrl_t *sched_ctrl = &UE->UE_sched_ctrl;
// tpc (power control)
@@ -1021,8 +1016,11 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id, frame_t frame, slot_t slot, c
if ((uci_234->pduBitmap >> 2) & 0x01) {
LOG_D(NR_MAC, "CSI CRC %d\n", uci_234->csi_part1.csi_part1_crc);
if (uci_234->csi_part1.csi_part1_crc != 1) {
- // API to parse the csi report and store it into sched_ctrl
- extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac);
+ NR_CSI_MeasConfig_t *csi_MeasConfig = UE->sc_info.csi_MeasConfig;
+ if (csi_MeasConfig != NULL) {
+ // API to parse the csi report and store it into sched_ctrl
+ extract_pucch_csi_report(csi_MeasConfig, uci_234, frame, slot, UE, nrmac);
+ }
}
free(uci_234->csi_part1.csi_part1_payload);
}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index f815caf9fd..92b9221054 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -882,7 +882,7 @@ static void nr_rx_ra_sdu(const module_id_t mod_id,
// Only trigger RRCReconfiguration if UE is not performing RRCReestablishment
// The RRCReconfiguration will be triggered by the RRCReestablishmentComplete
- if (!old_UE->reconfigSpCellConfig) {
+ if (!old_UE->reconfigCellGroup) {
LOG_I(NR_MAC, "Received UL_SCH_LCID_C_RNTI with C-RNTI 0x%04x, triggering RRC Reconfiguration\n", crnti);
// Trigger RRCReconfiguration
nr_mac_trigger_reconfiguration(mac, old_UE, -1);
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
index 6d105078b7..20b30cb074 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_rrc_dl_handler.c
@@ -695,8 +695,8 @@ void ue_context_setup_request(const f1ap_ue_context_setup_req_t *req)
cgc.len = (enc_rval.encoded + 7) >> 3;
resp.du_to_cu_rrc_info.cell_group_config = cgc;
- ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
- UE->CellGroup = new_CellGroup;
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
+ UE->reconfigCellGroup = new_CellGroup;
int ss_type = cg_configinfo ? NR_SearchSpace__searchSpaceType_PR_ue_Specific: NR_SearchSpace__searchSpaceType_PR_common;
configure_UE_BWP(mac, scc, UE, false, ss_type, -1, -1);
@@ -770,19 +770,19 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
"RRC reconfiguration outcome unsuccessful, but no rollback mechanism implemented to come back to old configuration\n");
} else if (req->reconfig_compl) {
LOG_I(NR_MAC, "DU received confirmation of successful RRC Reconfiguration\n");
- if (UE->reconfigSpCellConfig) {
- if (UE->await_reconfig) {
- // in case of reestablishment, the spCellConfig had to be released
- // temporarily. Reapply now before doing the reconfiguration.
- UE->CellGroup->spCellConfig = UE->reconfigSpCellConfig;
- UE->await_reconfig = false;
- }
- UE->reconfigSpCellConfig = NULL;
+ if (UE->reconfigCellGroup) {
+ LOG_W(NR_MAC, "reconfigCellGroup still present, did we miss ACK for RRCReconfiguration?\n");
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
+ UE->CellGroup = UE->reconfigCellGroup;
+ UE->reconfigCellGroup = NULL;
+ }
+ if (UE->reestablish_rlc) {
for (int i = 1; i < seq_arr_size(&UE->UE_sched_ctrl.lc_config); ++i) {
nr_lc_config_t *c = seq_arr_at(&UE->UE_sched_ctrl.lc_config, i);
c->suspended = false;
nr_rlc_reestablish_entity(req->gNB_DU_ue_id, c->lcid);
}
+ UE->reestablish_rlc = false;
}
// we re-configure the BWP to apply the CellGroup and to use UE specific Search Space with DCIX1
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_ue_Specific, -1, -1);
@@ -809,8 +809,8 @@ void ue_context_modification_request(const f1ap_ue_context_mod_req_t *req)
cgc.len = (enc_rval.encoded + 7) >> 3;
resp.du_to_cu_rrc_info->cell_group_config = cgc;
- ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
- UE->CellGroup = new_CellGroup;
+ ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->reconfigCellGroup);
+ UE->reconfigCellGroup = new_CellGroup;
configure_UE_BWP(mac, scc, UE, false, NR_SearchSpace__searchSpaceType_PR_common, -1, -1);
} else {
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, new_CellGroup); // we actually don't need it
@@ -966,16 +966,19 @@ void dl_rrc_message_transfer(const f1ap_dl_rrc_message_t *dl_rrc)
ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, UE->CellGroup);
UE->CellGroup = oldUE->CellGroup;
oldUE->CellGroup = NULL;
+ ASN_STRUCT_FREE(asn_DEF_NR_UE_NR_Capability, UE->capability);
UE->capability = oldUE->capability;
oldUE->capability = NULL;
UE->mac_stats = oldUE->mac_stats;
UE->measgap_config = oldUE->measgap_config;
+ UE->local_bwp_id = oldUE->local_bwp_id;
/* 38.331 5.3.7.2 says that the UE releases the spCellConfig, so we drop it
* from the current configuration. It will be reapplied when the
* reconfiguration has succeeded (indicated by the CU) */
- UE->reconfigSpCellConfig = UE->CellGroup->spCellConfig;
+ asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&UE->reconfigCellGroup, UE->CellGroup);
+ ASN_STRUCT_FREE(asn_DEF_NR_SpCellConfig, UE->CellGroup->spCellConfig);
UE->CellGroup->spCellConfig = NULL;
- UE->await_reconfig = true;
+ UE->reestablish_rlc = true;
mac_remove_nr_ue(mac, *dl_rrc->old_gNB_DU_ue_id);
pthread_mutex_unlock(&mac->sched_lock);
nr_rlc_remove_ue(dl_rrc->gNB_DU_ue_id);
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index f3f070b0e7..7b32665717 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -302,7 +302,8 @@ void mac_top_init_gNB(ngran_node_t node_type,
RC.nrmac[i]->tag = (NR_TAG_t*)malloc(sizeof(NR_TAG_t));
memset((void*)RC.nrmac[i]->tag,0,sizeof(NR_TAG_t));
-
+ for(int n = 0; n < MAX_NUM_OF_SSB; n++)
+ RC.nrmac[i]->sib1_pdsch[n].time_domain_allocation = -1;
RC.nrmac[i]->common_channels[0].ServingCellConfigCommon = scc;
RC.nrmac[i]->radio_config = *config;
RC.nrmac[i]->rlc_config = *default_rlc_config;
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index ca1e217099..5914c74a45 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -186,7 +186,6 @@ typedef enum {
} nr_config_report_type_t;
typedef struct nr_mac_config_t {
- int sib1_tda;
nr_pdsch_AntennaPorts_t pdsch_AntennaPorts;
int pusch_AntennaPorts;
int minRXTXTIME;
@@ -788,9 +787,8 @@ typedef struct NR_UE_info {
NR_mac_stats_t mac_stats;
/// currently active CellGroupConfig
NR_CellGroupConfig_t *CellGroup;
- /// in case of reestablishment, old spCellConfig to apply after
- /// reconfiguration
- NR_SpCellConfig_t *reconfigSpCellConfig;
+ /// in case of reconfiguration, new CellConfig to apply
+ NR_CellGroupConfig_t *reconfigCellGroup;
NR_UE_NR_Capability_t *capability;
measgap_config_t measgap_config;
// UE selected beam index
@@ -799,7 +797,7 @@ typedef struct NR_UE_info {
float dl_thr_ue;
long pdsch_HARQ_ACK_Codebook;
bool is_redcap;
- bool await_reconfig;
+ bool reestablish_rlc;
NR_RA_t *ra;
// 3GPP mandates that BWPs are enumerated consecutively, but we only send one (dedicated)
// BWP to the UE (and modify that BWP on reconfiguration); consequently, the BWP ID for a
@@ -994,6 +992,7 @@ typedef struct gNB_MAC_INST_s {
bool identity_pm;
int precoding_matrix_size[NR_MAX_NB_LAYERS];
int beam_index_list[MAX_NUM_OF_SSB];
+ NR_sched_pdsch_t sib1_pdsch[MAX_NUM_OF_SSB];
/// dedicate UL TDA, common for all UEs
seq_arr_t ul_tda;
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c
index 72bc611e2c..35d4c95ece 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.c
@@ -273,21 +273,23 @@ NR_SearchSpace_t *rrc_searchspace_config(bool is_common,
return ss;
}
-static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int curr_bwp, uint64_t ssb_bitmap)
+static NR_ControlResourceSet_t *get_coreset_config(int bwp_id, int bwp_start, int bwp_size, uint64_t ssb_bitmap)
{
NR_ControlResourceSet_t *coreset = calloc(1, sizeof(*coreset));
AssertFatal(coreset != NULL, "out of memory\n");
// frequency domain resources depending on BWP size
+ int additional_offset = (bwp_start + 5) / 6 * 6 - bwp_start;
+ int eff_bwp_size = bwp_size - additional_offset;
coreset->frequencyDomainResources.buf = calloc(1,6);
- coreset->frequencyDomainResources.buf[0] = (curr_bwp < 48) ? 0xf0 : 0xff;
- coreset->frequencyDomainResources.buf[1] = (curr_bwp < 96) ? 0x00 : 0xff;
- coreset->frequencyDomainResources.buf[2] = (curr_bwp < 144) ? 0x00 : 0xff;
- coreset->frequencyDomainResources.buf[3] = (curr_bwp < 192) ? 0x00 : 0xff;
- coreset->frequencyDomainResources.buf[4] = (curr_bwp < 240) ? 0x00 : 0xff;
+ coreset->frequencyDomainResources.buf[0] = (eff_bwp_size < 48) ? 0xf0 : 0xff;
+ coreset->frequencyDomainResources.buf[1] = (eff_bwp_size < 96) ? 0x00 : 0xff;
+ coreset->frequencyDomainResources.buf[2] = (eff_bwp_size < 144) ? 0x00 : 0xff;
+ coreset->frequencyDomainResources.buf[3] = (eff_bwp_size < 192) ? 0x00 : 0xff;
+ coreset->frequencyDomainResources.buf[4] = (eff_bwp_size < 240) ? 0x00 : 0xff;
coreset->frequencyDomainResources.buf[5] = 0x00;
coreset->frequencyDomainResources.size = 6;
coreset->frequencyDomainResources.bits_unused = 3;
- coreset->duration = (curr_bwp < 48) ? 2 : 1;
+ coreset->duration = (eff_bwp_size < 48) ? 2 : 1;
coreset->cce_REG_MappingType.present = NR_ControlResourceSet__cce_REG_MappingType_PR_nonInterleaved;
coreset->precoderGranularity = NR_ControlResourceSet__precoderGranularity_sameAsREG_bundle;
@@ -1746,10 +1748,10 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
bwp->bwp_Common->pdcch_ConfigCommon->choice.setup = calloc(1,sizeof(*bwp->bwp_Common->pdcch_ConfigCommon->choice.setup));
bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->controlResourceSetZero = NULL;
- int curr_bwp = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
-
+ int bwp_size = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+ int bwp_start = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
uint64_t ssb_bitmap = get_ssb_bitmap(scc);
- NR_ControlResourceSet_t *coreset = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap);
+ NR_ControlResourceSet_t *coreset = get_coreset_config(bwp->bwp_Id, bwp_start, bwp_size, ssb_bitmap);
bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonControlResourceSet = coreset;
bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->searchSpaceZero=NULL;
@@ -1790,7 +1792,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
nr_rrc_config_dl_tda(bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList,
get_frame_type((int)*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0], *scc->ssbSubcarrierSpacing),
scc->tdd_UL_DL_ConfigurationCommon,
- curr_bwp);
+ bwp_size);
if (!bwp->bwp_Dedicated) {
bwp->bwp_Dedicated=calloc(1,sizeof(*bwp->bwp_Dedicated));
@@ -1803,7 +1805,7 @@ static NR_BWP_Downlink_t *config_downlinkBWP(const NR_ServingCellConfigCommon_t
// coreset2 is identical to coreset above, but reallocated to prevent double
// frees
- NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, curr_bwp, ssb_bitmap);
+ NR_ControlResourceSet_t *coreset2 = get_coreset_config(bwp->bwp_Id, bwp_start, bwp_size, ssb_bitmap);
asn1cSeqAdd(&bwp->bwp_Dedicated->pdcch_Config->choice.setup->controlResourceSetToAddModList->list, coreset2);
int rrc_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
int num_cces = get_coreset_num_cces(coreset2->frequencyDomainResources.buf, coreset2->duration);
@@ -3332,8 +3334,9 @@ static NR_BWP_DownlinkDedicated_t *configure_initial_dl_bwp(const NR_ServingCell
pdcch_Config->searchSpacesToAddModList = calloc(1, sizeof(*pdcch_Config->searchSpacesToAddModList));
pdcch_Config->controlResourceSetToAddModList = calloc(1, sizeof(*pdcch_Config->controlResourceSetToAddModList));
NR_BWP_t *genericParameters = &scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters;
- int curr_bwp = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
- NR_ControlResourceSet_t *coreset = get_coreset_config(0, curr_bwp, bitmap);
+ int bwp_size = NRRIV2BW(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
+ int bwp_start = NRRIV2PRBOFFSET(genericParameters->locationAndBandwidth, MAX_BWP_SIZE);
+ NR_ControlResourceSet_t *coreset = get_coreset_config(0, bwp_start, bwp_size, bitmap);
asn1cSeqAdd(&pdcch_Config->controlResourceSetToAddModList->list, coreset);
int css_num_agg_level_candidates[NUM_PDCCH_AGG_LEVELS];
@@ -3517,19 +3520,6 @@ static NR_SpCellConfig_t *get_initial_SpCellConfig(int uid,
asn1cCallocOne(pdsch_servingcellconfig->nrofHARQ_ProcessesForPDSCH, NR_PDSCH_ServingCellConfig__nrofHARQ_ProcessesForPDSCH_n16);
pdsch_servingcellconfig->pucch_Cell = NULL;
set_dl_maxmimolayers(pdsch_servingcellconfig, scc, NULL, configuration->maxMIMO_layers);
- if (configuration->disable_harq) {
- if (!pdsch_servingcellconfig->ext3)
- pdsch_servingcellconfig->ext3 = calloc(1, sizeof(*pdsch_servingcellconfig->ext3));
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17 = calloc(1, sizeof(*pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17));
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->present = NR_SetupRelease_DownlinkHARQ_FeedbackDisabled_r17_PR_setup;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf = calloc(4, sizeof(uint8_t));
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.size = 4;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.bits_unused = 0;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[0] = 0xFF;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[1] = 0xFF;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[2] = 0xFF;
- pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[3] = 0xFF;
- }
uint64_t bitmap = get_ssb_bitmap(scc);
int first_active_bwp = 0;
@@ -3826,14 +3816,12 @@ NR_CellGroupConfig_t *update_cellGroupConfig_for_BWP_switch(NR_CellGroupConfig_t
// we temporarily need to keep both the old and the new BWP in the CG used by the gNB
// while removing the old from the CG sent to the UE
- if (old_bwp > 0) {
- NR_CellGroupConfig_t *clone_cg = NULL;
- const int copy_result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&clone_cg, cellGroupConfig);
- AssertFatal(copy_result == 0, "unable to copy NR_CellGroupConfig for cloning\n");
+ NR_CellGroupConfig_t *clone_cg = NULL;
+ const int copy_result = asn_copy(&asn_DEF_NR_CellGroupConfig, (void **)&clone_cg, cellGroupConfig);
+ AssertFatal(copy_result == 0, "unable to copy NR_CellGroupConfig for cloning\n");
+ if (old_bwp > 0)
clean_bwp_structures(clone_cg->spCellConfig);
- return clone_cg;
- }
- return NULL;
+ return clone_cg;
}
void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
@@ -3853,6 +3841,20 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
NR_PDSCH_ServingCellConfig_t *pdsch_servingcellconfig = spCellConfigDedicated->pdsch_ServingCellConfig->choice.setup;
set_dl_maxmimolayers(pdsch_servingcellconfig, scc, uecap, configuration->maxMIMO_layers);
+ if (configuration->disable_harq) {
+ if (!pdsch_servingcellconfig->ext3)
+ pdsch_servingcellconfig->ext3 = calloc(1, sizeof(*pdsch_servingcellconfig->ext3));
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17 = calloc(1, sizeof(*pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17));
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->present = NR_SetupRelease_DownlinkHARQ_FeedbackDisabled_r17_PR_setup;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf = calloc(4, sizeof(uint8_t));
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.size = 4;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.bits_unused = 0;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[0] = 0xFF;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[1] = 0xFF;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[2] = 0xFF;
+ pdsch_servingcellconfig->ext3->downlinkHARQ_FeedbackDisabled_r17->choice.setup.buf[3] = 0xFF;
+ }
+
NR_CSI_MeasConfig_t *csi_MeasConfig = spCellConfigDedicated->csi_MeasConfig->choice.setup;
for (int report = 0; report < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; report++) {
NR_CSI_ReportConfig_t *csirep = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[report];
@@ -3932,11 +3934,6 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
}
}
-void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig)
-{
- ASN_STRUCT_FREE(asn_DEF_NR_CellGroupConfig, cellGroupConfig);
-}
-
int encode_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, uint8_t *buffer, int max_buffer_size)
{
asn_enc_rval_t enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig, NULL, cellGroupConfig, buffer, max_buffer_size);
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h
index b776d667d6..27cca60b26 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_radio_config.h
@@ -96,7 +96,6 @@ void update_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig,
const NR_UE_NR_Capability_t *uecap,
const nr_mac_config_t *configuration,
const NR_ServingCellConfigCommon_t *scc);
-void free_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig);
int encode_cellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, uint8_t *buffer, int max_buffer_size);
NR_CellGroupConfig_t *decode_cellGroupConfig(const uint8_t *buffer, int max_buffer_size);
diff --git a/radio/COMMON/common_lib.h b/radio/COMMON/common_lib.h
index b87a6a8abf..5812e63aa4 100644
--- a/radio/COMMON/common_lib.h
+++ b/radio/COMMON/common_lib.h
@@ -199,6 +199,8 @@ typedef struct split7_config {
/*! this is the exponent in 2^X for the FFT size */
uint16_t fftSize;
+ /*! this is the ceil of the exponent in 2^X for the prach FFT size */
+ uint16_t prach_fftSize;
// M-plane related parameters
uint16_t dl_k0[5];
uint16_t ul_k0[5];
@@ -491,12 +493,29 @@ struct openair0_device_t {
/*! \brief Called to send samples to the RF target
@param device pointer to the device structure specific to the RF hardware target
@param timestamp The timestamp at whicch the first sample MUST be sent
- @param buff Buffer which holds the samples (2 dimensional)
+ @param buff Buffer which holds the samples (3 dimensional)
@param nsamps number of samples to be sent
- @param number of antennas
+ @param nb_antennas_tx number of antennas
+ @param num_beams number of beams
@param flags flags must be set to true if timestamp parameter needs to be applied
*/
- int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int antenna_id, int flags);
+ int (*trx_write_beams_func)(openair0_device *device,
+ openair0_timestamp timestamp,
+ void ***buff,
+ int nsamps,
+ int nb_antennas_tx,
+ int num_beams,
+ int flags);
+
+ /*! \brief Called to send samples to the RF target
+ @param device pointer to the device structure specific to the RF hardware target
+ @param timestamp The timestamp at whicch the first sample MUST be sent
+ @param buff Buffer which holds the samples (2 dimensional)
+ @param nsamps number of samples to be sent
+ @param nb_antennas_tx number of antennas
+ @param flags flags must be set to true if timestamp parameter needs to be applied
+ */
+ int (*trx_write_func)(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int nb_antennas_tx, int flags);
/*! \brief Called to send samples to the RF target
@param device pointer to the device structure specific to the RF hardware target
@@ -518,7 +537,27 @@ struct openair0_device_t {
* antennas from which to receive samples \returns the number of sample read
*/
- int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int num_antennas);
+ int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int num_antennas);
+
+ /*! \brief Receive samples from hardware.
+ * Read nsamps samples from each channel to buffers. buff[0] is the array for
+ * the first channel. *ptimestamp is the time at which the first sample
+ * was received.
+ * \param device the hardware to use
+ * \param[out] ptimestamp the time at which the first sample was received.
+ * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of
+ * samples nsamps.
+ * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
+ * \param num_antennas number of antennas from which to receive samples
+ * \param num_beams number of beams from which to receive samples
+ * \returns the number of sample read
+ */
+ int (*trx_read_beams_func)(openair0_device *device,
+ openair0_timestamp *ptimestamp,
+ void ***buff,
+ int nsamps,
+ int num_antennas,
+ int num_beams);
/*! \brief Receive samples from hardware, this version provides a single antenna at a time and returns.
* Read nsamps samples from each channel to buffers. buff[0] is the array for
@@ -571,6 +610,37 @@ struct openair0_device_t {
*/
int (*trx_set_gains_func)(openair0_device *device, openair0_config_t *openair0_cfg);
+ /*! \brief Set tx/rx beams
+ *
+ * Set the tx/rx beams. This has to be done in advance of the reception in order to
+ * allow the underlying device to change receiver configuration. The exact time depends
+ * on the device.
+ *
+ * NOTICE: the samples returned from trx_read_func may belong to more than one beam. It is up
+ * to the application to determine the beam of the received samples.
+ *
+ * \param device the hardware to use
+ * \param beam_map the beams to receive
+ * \return 0 on success
+ */
+ int (*trx_set_beams)(openair0_device *device, uint64_t beam_map, openair0_timestamp timestamp);
+
+ /*! \brief Set tx/rx beams
+ *
+ * Set the tx/rx beams. This has to be done in advance of the reception in order to
+ * allow the underlying device to change receiver configuration. The exact time depends
+ * on the device.
+ *
+ * NOTICE: the samples returned from trx_read_func may belong to more than one beam. It is up
+ * to the application to determine the beam of the received samples.
+ *
+ * \param device the hardware to use
+ * \param beams pointer to array of beam ids
+ * \param num_beams number of beams
+ * \return 0 on success
+ */
+ int (*trx_set_beams2)(openair0_device *device, int* beams, int num_beams, openair0_timestamp timestamp);
+
/*! \brief RRU Configuration callback
* \param idx RU index
* \param arg pointer to capabilities or configuration
@@ -629,6 +699,7 @@ typedef struct {
uint64_t timestamp; // Timestamp value of first sample
uint32_t option_value; // Option value
uint32_t option_flag; // Option flag
+ uint64_t beam_map;
} samplesBlockHeader_t;
#ifdef __cplusplus
diff --git a/radio/fhi_72/oaioran.c b/radio/fhi_72/oaioran.c
index 31c754738d..b614ae99b5 100644
--- a/radio/fhi_72/oaioran.c
+++ b/radio/fhi_72/oaioran.c
@@ -338,7 +338,7 @@ int xran_fh_rx_read_slot(ru_info_t *ru, int *frame, int *slot)
const struct xran_fh_init *fh_init = get_xran_fh_init();
int nPRBs = fh_cfg->nULRBs;
- int fftsize = 1 << fh_cfg->ru_conf.fftSize;
+ int fftsize = 1 << fh_cfg->nULFftSize;
int slot_offset_rxdata = 3 & (*slot);
uint32_t slot_size = 4 * 14 * fftsize;
@@ -496,7 +496,7 @@ int xran_fh_tx_send_slot(ru_info_t *ru, int frame, int slot, uint64_t timestamp)
const struct xran_fh_init *fh_init = get_xran_fh_init();
const struct xran_fh_config *fh_cfg = get_xran_fh_config(0);
int nPRBs = fh_cfg->nDLRBs;
- int fftsize = 1 << fh_cfg->ru_conf.fftSize;
+ int fftsize = 1 << fh_cfg->nDLFftSize;
int nb_tx_per_ru = ru->nb_tx / fh_init->xran_ports;
int nb_rx_per_ru = ru->nb_rx / fh_init->xran_ports;
diff --git a/radio/fhi_72/oran-config.c b/radio/fhi_72/oran-config.c
index 684d44e7cf..51374e79fe 100644
--- a/radio/fhi_72/oran-config.c
+++ b/radio/fhi_72/oran-config.c
@@ -921,8 +921,8 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
fh_config->neAxc = RTE_MAX(oai0->tx_num_channels / num_rus, oai0->rx_num_channels / num_rus); // number of eAxc supported on one CC = max(PDSCH, PUSCH)
fh_config->neAxcUl = 0; // number of eAxc supported on one CC for UL direction = PUSCH; used only if XRAN_CATEGORY_B
fh_config->nAntElmTRx = 0; // number of antenna elements for TX and RX = SRS; used only if XRAN_CATEGORY_B
- fh_config->nDLFftSize = 0; // DL FFT size; not used in xran
- fh_config->nULFftSize = 0; // UL FFT size; not used in xran
+ fh_config->nDLFftSize = oai0->split7.fftSize; // DL FFT size; not used in xran
+ fh_config->nULFftSize = oai0->split7.fftSize; // UL FFT size; not used in xran
fh_config->nDLRBs = oai0->num_rb_dl; // DL PRB; used in oaioran.c/oran-init.c; not used in xran, neither in E nor in F release
fh_config->nULRBs = oai0->num_rb_dl; // UL PRB; used in oaioran.c/oran-init.c; in xran E release not used so the patch fixes it, but in xran F release this value is properly used
fh_config->nDLAbsFrePointA = 0; // Abs Freq Point A of the Carrier Center Frequency for in KHz Value; not used in xran
@@ -966,7 +966,7 @@ static bool set_fh_config(void *mplane_api, int ru_idx, int num_rus, enum xran_c
// fh_config->srs_conf = {0};
if (!set_fh_frame_config(oai0, &fh_config->frame_conf))
return false;
- if (!set_fh_ru_config(mplane_api, rup, oai0->split7.fftSize, nru, xran_cat, &fh_config->ru_conf))
+ if (!set_fh_ru_config(mplane_api, rup, oai0->split7.prach_fftSize, nru, xran_cat, &fh_config->ru_conf))
return false;
fh_config->bbdev_enc = NULL; // call back to poll BBDev encoder
diff --git a/radio/rfsimulator/CMakeLists.txt b/radio/rfsimulator/CMakeLists.txt
index ad4d92f108..2b04f7dd89 100644
--- a/radio/rfsimulator/CMakeLists.txt
+++ b/radio/rfsimulator/CMakeLists.txt
@@ -1,5 +1,5 @@
add_library(rfsimulator MODULE
- simulator.c
+ simulator.cpp
apply_channelmod.c
../../openair1/PHY/TOOLS/signal_energy.c
)
diff --git a/radio/rfsimulator/README.md b/radio/rfsimulator/README.md
index 40688b755a..298c7ecfda 100644
--- a/radio/rfsimulator/README.md
+++ b/radio/rfsimulator/README.md
@@ -209,3 +209,55 @@ to reduce the amount of transported samples:
A possible, unimplemented optimization would be to compress samples.
You can further [tune your machine](../../doc/tuning_and_security.md)
+
+# Beam simulation
+
+RFsimulator supports beam domain simulation.
+
+## Configuration
+
+Several new CLI parameters were added
+
+* `--rfsimulator.enable_beams` : enable beam domain simulation. Should match on server and all clients.
+* `--rfsimulator.beam_gains ` : define a matrix of additional pathloss values (in dB)
+to simulate the effect of different beam combinations in the RF simulator. You provide a comma-separated
+list of numbers, which forms the first row of a square matrix. The rest of the matrix is filled by projecting
+these values onto the diagonals, making it symmetric.
+
+ Example list: `0,-2,-3`
+ Resulting matrix:
+ ```
+ [[0,-2,-3],
+ [-2,0,-2],
+ [-3,-2,0]]
+ ```
+
+ The beam gain matrix will be used during beam combining. RX beam selects the row and TX beam selects column.
+ Using the example above, if gNB is receiving in beam 1 and the UE is transmitting in beam 1, an additional
+ 2 dB pathloss will be applied on top of the pathloss from the channel model (if present).
+
+* `--rfsimulator.beam_map ` : where `` is a `uint64_t` value where each bit is an enabled TX/RX beam.
+ For gNB: Initial beam_map, i.e. which beams gNB transmits/receives before calling beam APIs.
+ For UE: Beam position in beam space in the simulation. The UE is not expected to use the beam APIs for now.
+* `--rfsimulator.beam_ids ` : where `` is a comma separated list. Same as above but added for convenience.
+
+## Runtime commands
+
+### Moving the UE in beam space
+
+Use telnet command `rfsimu setbeams ` or `rfsimu setbeamids `. They correspond to the CLI parameters described
+above and work the same way.
+
+### Modifying the gNB beam
+
+It is possible to test the beam domain simulation without implementing the beam APIs. The same telnet command can be used
+to modify the tx/rx beam of the gNB. The gNB does not need to be beam-aware and use the new APIs.
+
+## Programming guide
+
+RFsimulator is attempting to simulate hardware device operation, but there are differences. Like with real hardware,
+it is expected that you provide the configured beams in `set_beams` function ahead of sample reception. This is due
+to the fact that a hardware device will buffer received samples before the driver requests them.
+
+For rfsimulator, as long as the call to `set_beams` with timestamp `n` is done before `trx_read` which is expected
+to return sample `n` the beam switch command will apply to the received samples.
diff --git a/radio/rfsimulator/apply_channelmod.c b/radio/rfsimulator/apply_channelmod.c
index aca8a6b030..3f2e8d85c1 100644
--- a/radio/rfsimulator/apply_channelmod.c
+++ b/radio/rfsimulator/apply_channelmod.c
@@ -1,26 +1,25 @@
/*
-* 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.1 (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
-*
-* Author and copyright: Laurent Thomas, open-cells.com
-*
-* 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
-*/
-
+ * 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.1 (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
+ *
+ * Author and copyright: Laurent Thomas, open-cells.com
+ *
+ * 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
#include
@@ -28,36 +27,17 @@
#include "openair2/LAYER2/NR_MAC_gNB/mac_config.h"
#include "rfsimulator.h"
-/*
- Legacy study:
- The parameters are:
- gain&loss (decay, signal power, ...)
- either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
- => don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
- will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
- lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
- a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
-
- multi_path (auto convolution, ISI, ...)
- either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
- legacy: we regenerate each sub frame in UL, and each frame only in DL
-*/
-void rxAddInput(const c16_t *input_sig,
- cf_t *after_channel_sig,
- int rxAnt,
- channel_desc_t *channelDesc,
- int nbSamples,
- uint64_t TS,
- uint32_t CirSize,
- bool add_noise)
+void update_channel_model(channel_desc_t *channelDesc, uint64_t TS)
{
static uint64_t last_TS = 0;
-
- if ((channelDesc->sat_height > 0) && (channelDesc->enable_dynamic_delay || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit
+ if ((channelDesc->sat_height > 0)
+ && (channelDesc->enable_dynamic_delay
+ || channelDesc->enable_dynamic_Doppler)) { // model for transparent satellite on circular orbit
/* assumptions:
- The Earth is spherical, the ground station is static, and that the Earth does not rotate.
- An access or link is possible from the satellite to the ground station at all times.
- - The ground station is located at the North Pole (positive Zaxis), and the satellite starts from the initial elevation angle 0° in the second quadrant of the YZplane.
+ - The ground station is located at the North Pole (positive Zaxis), and the satellite starts from the initial elevation angle
+ 0° in the second quadrant of the YZplane.
- Satellite moves in the clockwise direction in its circular orbit.
*/
const double radius_earth = 6377900; // m
@@ -78,7 +58,7 @@ void rxAddInput(const c16_t *input_sig,
const double pos_sat_z = radius_sat * cos(w_sat * t);
const double vel_sat_x = 0;
- const double vel_sat_y = w_sat * radius_sat * cos(w_sat * t);
+ const double vel_sat_y = w_sat * radius_sat * cos(w_sat * t);
const double vel_sat_z = -w_sat * radius_sat * sin(w_sat * t);
const double pos_ue_x = 0;
@@ -157,9 +137,17 @@ void rxAddInput(const c16_t *input_sig,
if (channelDesc->enable_dynamic_Doppler)
channelDesc->Doppler_phase_inc = 2 * M_PI * f_Doppler_shift_ue_sat / channelDesc->sampling_rate;
- if(TS - last_TS >= channelDesc->sampling_rate) {
+ if (TS - last_TS >= channelDesc->sampling_rate) {
last_TS = TS;
- LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z);
+ LOG_I(HW,
+ "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n",
+ t,
+ pos_sat_x,
+ pos_sat_y,
+ pos_sat_z,
+ vel_sat_x,
+ vel_sat_y,
+ vel_sat_z);
LOG_I(HW, "Uplink delay %f ms, Doppler shift UE->SAT %f kHz\n", prop_delay * 1000, f_Doppler_shift_ue_sat / 1000);
LOG_I(HW, "Satellite velocity towards gNB: %f m/s, acceleration towards gNB: %f m/s²\n", -vel_sat_gnb, acc_sat_gnb);
}
@@ -216,48 +204,70 @@ void rxAddInput(const c16_t *input_sig,
if (channelDesc->enable_dynamic_Doppler)
channelDesc->Doppler_phase_inc = 2 * M_PI * f_Doppler_shift_sat_ue / channelDesc->sampling_rate;
- if(TS - last_TS >= channelDesc->sampling_rate) {
+ if (TS - last_TS >= channelDesc->sampling_rate) {
last_TS = TS;
- LOG_I(HW, "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n", t, pos_sat_x, pos_sat_y, pos_sat_z, vel_sat_x, vel_sat_y, vel_sat_z);
+ LOG_I(HW,
+ "Satellite orbit: time %f s, Position = (%f, %f, %f), Velocity = (%f, %f, %f)\n",
+ t,
+ pos_sat_x,
+ pos_sat_y,
+ pos_sat_z,
+ vel_sat_x,
+ vel_sat_y,
+ vel_sat_z);
LOG_I(HW, "Downlink delay %f ms, Doppler shift SAT->UE %f kHz\n", prop_delay * 1000, f_Doppler_shift_sat_ue / 1000);
}
}
}
+}
+/*
+ Legacy study:
+ The parameters are:
+ gain&loss (decay, signal power, ...)
+ either a fixed gain in dB, a target power in dBm or ACG (automatic control gain) to a target average
+ => don't redo the AGC, as it was used in UE case, that must have a AGC inside the UE
+ will be better to handle the "set_gain()" called by UE to apply it's gain (enable test of UE power loop)
+ lin_amp = pow(10.0,.05*txpwr_dBm)/sqrt(nb_tx_antennas);
+ a lot of operations in legacy, grouped in one simulation signal decay: txgain*decay*rxgain
+
+ multi_path (auto convolution, ISI, ...)
+ either we regenerate the channel (call again random_channel(desc,0)), or we keep it over subframes
+ legacy: we regenerate each sub frame in UL, and each frame only in DL
+*/
+void rxAddInput(c16_t **input_sig,
+ cf_t *after_channel_sig,
+ int rxAnt,
+ channel_desc_t *channelDesc,
+ int nbSamples,
+ uint64_t TS)
+{
// channelDesc->path_loss_dB should contain the total path gain
// so, in actual RF: tx gain + path loss + rx gain (+antenna gain, ...)
// UE and NB gain control to be added
// Fixme: not sure when it is "volts" so dB is 20*log10(...) or "power", so dB is 10*log10(...)
- const double pathLossLinear = pow(10,channelDesc->path_loss_dB/20.0);
+ const double pathLossLinear = pow(10, channelDesc->path_loss_dB / 20.0);
// Energy in one sample to calibrate input noise
// the normalized OAI value seems to be 256 as average amplitude (numerical amplification = 1)
- const double noise_per_sample = add_noise ? pow(10,channelDesc->noise_power_dB/10.0) * 256 : 0;
- const uint64_t dd = channelDesc->channel_offset;
- const int nbTx=channelDesc->nb_tx;
+ const double noise_per_sample = pow(10, channelDesc->noise_power_dB / 10.0) * 256;
+ const int nbTx = channelDesc->nb_tx;
double Doppler_phase_cur = channelDesc->Doppler_phase_cur[rxAnt];
Doppler_phase_cur -= 2 * M_PI * round(Doppler_phase_cur / (2 * M_PI));
- for (int i=0; ich[rxAnt+(txAnt*channelDesc->nb_rx)];
+ for (int txAnt = 0; txAnt < nbTx; txAnt++) {
+ const struct complexd *channelModel = channelDesc->ch[rxAnt + (txAnt * channelDesc->nb_rx)];
- //const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
- for (int l = 0; l<(int)channelDesc->channel_length; l++) {
- // let's assume TS+i >= l
- // fixme: the rfsimulator current structure is interleaved antennas
- // this has been designed to not have to wait a full block transmission
- // but it is not very usefull
- // it would be better to split out each antenna in a separate flow
- // that will allow to mix ru antennas freely
- // (X + cirSize) % cirSize to ensure that index is positive
- const int idx = ((TS + i - l - dd) * nbTx + txAnt + CirSize) % CirSize;
- const struct complex16 tx16 = input_sig[idx];
+ // const struct complex *channelModelEnd=channelModel+channelDesc->channel_length;
+ for (int l = 0; l < (int)channelDesc->channel_length; l++) {
+ const int idx = i - l + channelDesc->channel_length - 1;
+ const struct complex16 tx16 = input_sig[txAnt][idx];
rx_tmp.r += tx16.r * channelModel[l].r - tx16.i * channelModel[l].i;
rx_tmp.i += tx16.i * channelModel[l].r + tx16.r * channelModel[l].i;
- } //l
+ } // l
}
if (channelDesc->Doppler_phase_inc != 0.0) {
@@ -279,12 +289,11 @@ void rxAddInput(const c16_t *input_sig,
channelDesc->Doppler_phase_cur[rxAnt] = Doppler_phase_cur;
- if ( (TS*nbTx)%CirSize+nbSamples <= CirSize )
- // Cast to a wrong type for compatibility !
- LOG_D(HW,"Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
- 10*log10((double)signal_energy((int32_t *)&input_sig[(TS*nbTx)%CirSize], nbSamples)),
- 10*log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
- channelDesc->path_loss_dB,
- 10*log10(noise_per_sample));
+ // Cast to a wrong type for compatibility !
+ LOG_D(HW,
+ "Input power %f, output power: %f, channel path loss %f, noise coeff: %f \n",
+ 10 * log10((double)signal_energy((int32_t *)&input_sig[0], nbSamples)),
+ 10 * log10((double)signal_energy((int32_t *)after_channel_sig, nbSamples)),
+ channelDesc->path_loss_dB,
+ 10 * log10(noise_per_sample));
}
-
diff --git a/radio/rfsimulator/rfsimulator.h b/radio/rfsimulator/rfsimulator.h
index 11a57193ca..802a2a2e34 100644
--- a/radio/rfsimulator/rfsimulator.h
+++ b/radio/rfsimulator/rfsimulator.h
@@ -1,37 +1,34 @@
/*
-* 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.1 (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
-*
-* Author and copyright: Laurent Thomas, open-cells.com
-*
-* 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
-*/
+ * 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.1 (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
+ *
+ * Author and copyright: Laurent Thomas, open-cells.com
+ *
+ * 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 __RFSIMULATOR_H
-#define __RFSIMULATOR_H
+#define __RFSIMULATOR_H
#include
-void rxAddInput( const c16_t *input_sig,
- cf_t *after_channel_sig,
- int rxAnt,
- channel_desc_t *channelDesc,
- int nbSamples,
- uint64_t TS,
- uint32_t CirSize,
- bool apply_noise
- );
-
+void rxAddInput(c16_t **input_sig,
+ cf_t *after_channel_sig,
+ int rxAnt,
+ channel_desc_t *channelDesc,
+ int nbSamples,
+ uint64_t TS);
+void update_channel_model(channel_desc_t *channelDesc, uint64_t TS);
#endif
diff --git a/radio/rfsimulator/simulator.c b/radio/rfsimulator/simulator.cpp
similarity index 51%
rename from radio/rfsimulator/simulator.c
rename to radio/rfsimulator/simulator.cpp
index c9093be912..a29001e0bf 100644
--- a/radio/rfsimulator/simulator.c
+++ b/radio/rfsimulator/simulator.cpp
@@ -27,6 +27,10 @@
* When the opposite side switch from passive reading to active R+Write, the synchro is not fully deterministic
*/
+#include "PHY/TOOLS/tools_defs.h"
+#include "PHY/defs_common.h"
+#include "utils.h"
+#include
#include
#include
#include
@@ -42,34 +46,30 @@
#include
#include
-#include
#include
#include
#include "common_lib.h"
#define CHANNELMOD_DYNAMICLOAD
+extern "C" {
+#include
#include
#include "rfsimulator.h"
+}
+#include
+#include
+#include
+#include
+#include
+#include
#define PORT 4043 // default TCP port for this simulator
-//
-// CirSize defines the number of samples inquired for a read cycle
-// It is bounded by a slot read capability (which depends on bandwidth and numerology)
-// up to multiple slots read to allow I/Q buffering of the I/Q TCP stream
-//
-// As a rule of thumb:
-// -it can't be less than the number of samples for a slot
-// -it can range up to multiple slots
-//
-// The default value is chosen for 10ms buffering which makes 23040*20 = 460800 samples
-// The previous value is kept below in comment it was computed for 100ms 1x 20MHz
-// #define CirSize 6144000 // 100ms SiSo 20MHz LTE
-#define minCirSize 460800 // 10ms SiSo 40Mhz 3/4 sampling NR78 FR1
#define sampleToByte(a, b) ((a) * (b) * sizeof(sample_t))
#define byteToSample(a, b) ((a) / (sizeof(sample_t) * (b)))
#define GENERATE_CHANNEL 10 // each frame (or slot?) in DL
#define MAX_FD_RFSIMU 250
#define SEND_BUFF_SIZE 100000000 // Socket buffer size
+#define MAX_BEAMS 64
// Simulator role
typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
@@ -78,37 +78,50 @@ typedef enum { SIMU_ROLE_SERVER = 1, SIMU_ROLE_CLIENT } simuRole;
#define RFSIMU_SECTION "rfsimulator"
#define RFSIMU_OPTIONS_PARAMNAME "options"
+#define RFSIMU_BEAM_GAINS "beam_gains"
+#define RFSIMU_BEAM_IDS "beam_ids"
#define RFSIM_CONFIG_HELP_OPTIONS \
" list of comma separated options to enable rf simulator functionalities. Available options: \n" \
" chanmod: enable channel modelisation\n" \
" saviq: enable saving written iqs to a file\n"
-// clang-format off
-/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
-/* configuration parameters for the rfsimulator device */
-/* optname helpstr paramflags XXXptr defXXXval type numelt */
-/*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define simOpt PARAMFLAG_NOFREE | PARAMFLAG_CMDLINE_NOPREFIXENABLED
+#define simBool PARAMFLAG_BOOL | PARAMFLAG_NOFREE | PARAMFLAG_CMDLINE_NOPREFIXENABLED
+// clang-format off
+/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
+/* configuration parameters for the rfsimulator device */
+/* optname helpstr paramflags XXXptr defXXXval */
+/*----------------------------------------------------------------------------------------------------------------------------------------------------*/
#define RFSIMULATOR_PARAMS_DESC { \
- {"serveraddr", "\n", simOpt, .strptr=&rfsimulator->ip, .defstrval="127.0.0.1", TYPE_STRING, 0 },\
- {"serverport", "\n", simOpt, .u16ptr = &(rfsimulator->port), .defuintval = PORT, TYPE_UINT16, 0}, \
- {RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, 0, .strlistptr = NULL, .defstrlistval = NULL, TYPE_STRINGLIST, 0}, \
- {"IQfile", "\n",simOpt, .strptr=&saveF, .defstrval="/tmp/rfsimulator.iqs",TYPE_STRING, 0 },\
- {"modelname", "\n", simOpt, .strptr = &modelname, .defstrval = "AWGN", TYPE_STRING, 0}, \
- {"ploss", "\n", simOpt, .dblptr = &(rfsimulator->chan_pathloss), .defdblval = 0, TYPE_DOUBLE, 0}, \
- {"forgetfact", "\n", simOpt, .dblptr=&(rfsimulator->chan_forgetfact),.defdblval=0, TYPE_DOUBLE, 0 },\
- {"offset", "\n", simOpt, .u64ptr = &(rfsimulator->chan_offset), .defint64val = 0, TYPE_UINT64, 0}, \
- {"prop_delay", "\n", simOpt, .dblptr=&(rfsimulator->prop_delay_ms), .defdblval=0.0, TYPE_DOUBLE, 0 },\
- {"wait_timeout", "\n", simOpt, .iptr=&(rfsimulator->wait_timeout), .defintval=1, TYPE_INT, 0 },\
- };
+ STRINGPARAM("serveraddr", "\n", simOpt, &rfsimulator->ip, "127.0.0.1"), \
+ UINT16PARAM("serverport", "\n", simOpt, &rfsimulator->port, PORT), \
+ STRLISTPARAM(RFSIMU_OPTIONS_PARAMNAME, RFSIM_CONFIG_HELP_OPTIONS, simOpt, NULL, NULL), \
+ STRINGPARAM("IQfile", "\n", simOpt, &saveF, "/tmp/rfsimulator.iqs"),\
+ STRINGPARAM("modelname", "\n", simOpt, &modelname, "AWGN"), \
+ DOUBLEPARAM("ploss", "\n", simOpt, &rfsimulator->chan_pathloss, 0), \
+ DOUBLEPARAM("forgetfact", "\n", simOpt, &rfsimulator->chan_forgetfact, 0), \
+ UINT64PARAM("offset", "\n", simOpt, &rfsimulator->chan_offset, 0L), \
+ DOUBLEPARAM("prop_delay", "\n", simOpt, &(rfsimulator->prop_delay_ms), 0.0), \
+ INTPARAM("wait_timeout", "\n", simOpt, &rfsimulator->wait_timeout, 1), \
+ BOOLPARAM("enable_beams", "\n", simBool,&(beam_ctrl->enable_beams), 0), \
+ INTPARAM("num_concurrent_beams", "\n", simOpt, &beam_ctrl->num_concurrent_beams, 1), \
+ UINT64PARAM("beam_map", "\n", simOpt, &beam_map, 1), \
+ STRINGPARAM(RFSIMU_BEAM_IDS, "\n", simOpt, NULL, NULL), \
+ STRINGPARAM(RFSIMU_BEAM_GAINS, "\n", simOpt, NULL, NULL), \
+};
// clang-format on
static void getset_currentchannels_type(char *buf, int debug, webdatadef_t *tdata, telnet_printfunc_t prnt);
-extern int get_currentchannels_type(char *buf, int debug, webdatadef_t *tdata, telnet_printfunc_t prnt); // in random_channel.c
+extern int get_currentchannels_type(const char *buf,
+ int debug,
+ webdatadef_t *tdata,
+ telnet_printfunc_t prnt); // in random_channel.c
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
+static int rfsimu_set_beam(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
+static int rfsimu_set_beamids(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
// clang-format off
static telnetshell_cmddef_t rfsimu_cmdarray[] = {
{"show models", "", (cmdfunc_t)rfsimu_setchanmod_cmd, {(webfunc_t)getset_currentchannels_type}, TELNETSRV_CMDFLAG_WEBSRVONLY | TELNETSRV_CMDFLAG_GETWEBTBLDATA, NULL},
@@ -116,28 +129,56 @@ static telnetshell_cmddef_t rfsimu_cmdarray[] = {
{"setdistance", " ", (cmdfunc_t)rfsimu_setdistance_cmd, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ | TELNETSRV_CMDFLAG_NEEDPARAM },
{"getdistance", "", (cmdfunc_t)rfsimu_getdistance_cmd, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
{"vtime", "", (cmdfunc_t)rfsimu_vtime_cmd, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ | TELNETSRV_CMDFLAG_AUTOUPDATE},
+ {"setbeam", "beam_map", (cmdfunc_t)rfsimu_set_beam, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
+ {"setbeamids", "beam_id1,beam_id2,...", (cmdfunc_t)rfsimu_set_beamids, {NULL}, TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
{"", "", NULL},
};
// clang-format on
static telnetshell_cmddef_t *setmodel_cmddef = &(rfsimu_cmdarray[1]);
static telnetshell_vardef_t rfsimu_vardef[] = {{"", 0, 0, NULL}};
-static uint64_t CirSize = minCirSize;
typedef c16_t sample_t; // 2*16 bits complex number
+typedef struct beam_switch_command_t {
+ std::vector beams;
+ openair0_timestamp timestamp;
+} beam_switch_command_t;
+
+typedef struct {
+ std::vector beams;
+ std::queue cmd_queue;
+ std::mutex mutex;
+} beam_state_t;
+
+typedef struct {
+ samplesBlockHeader_t header;
+ char payload[1];
+} rfsim_packet_t;
+
typedef struct buffer_s {
int conn_sock;
openair0_timestamp lastReceivedTS;
bool headerMode;
bool trashingPacket;
samplesBlockHeader_t th;
+ uint nbAnt;
char *transferPtr;
uint64_t remainToTransfer;
- char *circularBufEnd;
- sample_t *circularBuf;
channel_desc_t *channel_model;
+ rfsim_packet_t *packet_ptr;
+ size_t payload_sz;
+ size_t remainToTransferBeam;
+ std::queue received_packets;
} buffer_t;
+typedef struct {
+ int enable_beams;
+ int num_concurrent_beams;
+ std::vector> beam_gains;
+ beam_state_t tx;
+ beam_state_t rx;
+} rfsim_beam_ctrl_t;
+
typedef struct {
int listen_sock, epollfd;
pthread_mutex_t Sockmutex;
@@ -163,8 +204,122 @@ typedef struct {
poll_telnetcmdq_func_t poll_telnetcmdq;
int wait_timeout;
double prop_delay_ms;
+ rfsim_beam_ctrl_t *beam_ctrl;
} rfsimulator_state_t;
+/**
+ * @brief Get the current beam map for a given timestamp and number of samples.
+ *
+ * This function retrieves the beam map from the beam state, considering any queued beam switch commands.
+ *
+ * @param beam_state Pointer to the beam_state_t structure containing the current beam map and command queue.
+ * @param timestamp The timestamp for which the beam map is requested.
+ * @param nsamps The number of samples to process.
+ * @param nsamps_out output pointer to receive the number of samples until the next beam switch.
+ * @return The beam map (uint64_t) valid for the given timestamp.
+ */
+static std::vector get_beams(beam_state_t *beam_state, openair0_timestamp timestamp, uint32_t nsamps, uint32_t *nsamps_out)
+{
+ std::lock_guard lock(beam_state->mutex);
+ std::vector current_beams = beam_state->beams;
+ uint32_t samples_to_next_switch = nsamps;
+
+ // Find the latest beam_switch_command_t with timestamp <= requested timestamp
+ if (!beam_state->cmd_queue.empty()) {
+ // Copy queue to avoid modifying original
+ std::queue queue_copy = beam_state->cmd_queue;
+ while (!queue_copy.empty()) {
+ const beam_switch_command_t &cmd = queue_copy.front();
+ if (cmd.timestamp <= timestamp) {
+ current_beams = cmd.beams;
+ queue_copy.pop();
+ } else {
+ samples_to_next_switch = (cmd.timestamp > timestamp) ? (cmd.timestamp - timestamp) : nsamps;
+ break;
+ }
+ }
+ }
+
+ // Clamp samples_to_next_switch to nsamps
+ if (samples_to_next_switch > nsamps)
+ samples_to_next_switch = nsamps;
+
+ *nsamps_out = samples_to_next_switch;
+
+ return current_beams;
+}
+
+
+static std::vector beam_map_to_beams(uint64_t beam_map)
+{
+ int num_beams = __builtin_popcountll(beam_map);
+ AssertFatal(num_beams > 0, "Needs at least one beam\n");
+ std::vector beam_ids;
+ for (int i = 0; i < MAX_BEAMS; i++) {
+ if (beam_map & (1ULL << i)) {
+ beam_ids.push_back(i);
+ }
+ }
+ return beam_ids;
+}
+
+static uint64_t beams_to_beam_map(const std::vector &beam_ids)
+{
+ uint64_t beam_map = 0;
+ for (size_t i = 0; i < beam_ids.size(); i++) {
+ beam_map |= (1ULL << beam_ids[i]);
+ }
+ return beam_map;
+}
+
+
+/**
+ * @brief Clears outdated beam switch commands from the queue and updates the current beam map.
+ *
+ * This function processes the beam switch command queue in the given beam_state_t.
+ * For each command with a timestamp less than or equal to the provided timestamp,
+ * it updates the current beam_map and removes the command from the queue.
+ * The queue is left unchanged for commands with timestamps greater than the provided timestamp.
+ *
+ * @param beam_state Pointer to the beam_state_t structure containing the command queue and current beam map.
+ * @param timestamp The timestamp up to which commands should be processed and removed.
+ */
+static void clear_beam_queue(beam_state_t *beam_state, openair0_timestamp timestamp)
+{
+ std::lock_guard lock(beam_state->mutex);
+ while (!beam_state->cmd_queue.empty()) {
+ if (beam_state->cmd_queue.front().timestamp <= timestamp) {
+ beam_state->beams = beam_state->cmd_queue.front().beams;
+ beam_state->cmd_queue.pop();
+ } else {
+ break;
+ }
+ }
+}
+
+/**
+ * @brief Clears old packets from the received_packets queue based on a threshold timestamp.
+ *
+ * This function iterates through the received_packets queue and removes packets whose
+ * timestamp plus size is less than or equal to the provided threshold_timestamp.
+ * It frees the memory allocated for each removed packet.
+ *
+ * @param received_packets Reference to the queue of rfsim_packet_t pointers representing received packets.
+ * @param threshold_timestamp The timestamp threshold used to determine which packets to remove.
+ */
+static void clear_old_packets(std::queue &received_packets, uint64_t threshold_timestamp)
+{
+ while (!received_packets.empty()) {
+ rfsim_packet_t *pkt = received_packets.front();
+ if (pkt->header.timestamp + pkt->header.size <= threshold_timestamp) {
+ free(pkt);
+ received_packets.pop();
+ } else {
+ break;
+ }
+ }
+}
+
static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time);
static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock)
@@ -172,18 +327,13 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock)
uint64_t buff_index = bridge->next_buf++ % MAX_FD_RFSIMU;
buffer_t *ptr = &bridge->buf[buff_index];
bridge->nb_cnx++;
- ptr->circularBuf = calloc(1, sampleToByte(CirSize, 1));
- if (ptr->circularBuf == NULL) {
- LOG_E(HW, "malloc(%lu) failed\n", sampleToByte(CirSize, 1));
- return NULL;
- }
- ptr->circularBufEnd = ((char *)ptr->circularBuf) + sampleToByte(CirSize, 1);
ptr->conn_sock = sock;
ptr->lastReceivedTS = 0;
ptr->headerMode = true;
ptr->trashingPacket = true;
ptr->transferPtr = (char *)&ptr->th;
ptr->remainToTransfer = sizeof(samplesBlockHeader_t);
+ ptr->received_packets = std::queue();
int sendbuff = SEND_BUFF_SIZE;
if (setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff)) != 0) {
LOG_E(HW, "setsockopt(SO_SNDBUF) failed\n");
@@ -208,7 +358,7 @@ static buffer_t *allocCirBuf(rfsimulator_state_t *bridge, int sock)
ptr->channel_model = find_channel_desc_fromname(modelname); // path_loss in dB
if (!ptr->channel_model) {
// Use legacy method to find channel model - this will use the same channel model for all clients
- char *legacy_model_name = (bridge->role == SIMU_ROLE_SERVER) ? "rfsimu_channel_ue0" : "rfsimu_channel_enB0";
+ const char *legacy_model_name = (bridge->role == SIMU_ROLE_SERVER) ? "rfsimu_channel_ue0" : "rfsimu_channel_enB0";
ptr->channel_model = find_channel_desc_fromname(legacy_model_name);
if (!ptr->channel_model) {
LOG_E(HW, "Channel model %s/%s not found, check config file\n", modelname, legacy_model_name);
@@ -230,11 +380,11 @@ static void removeCirBuf(rfsimulator_state_t *bridge, buffer_t *buf)
LOG_E(HW, "epoll_ctl(EPOLL_CTL_DEL) failed\n");
}
close(buf->conn_sock);
- free(buf->circularBuf);
// Fixme: no free_channel_desc_scm(bridge->buf[sock].channel_model) implemented
// a lot of mem leaks
// free(bridge->buf[sock].channel_model);
- memset(buf, 0, sizeof(buffer_t));
+ clear_old_packets(buf->received_packets, INT64_MAX);
+ *buf = buffer_t{};
buf->conn_sock = -1;
bridge->nb_cnx--;
}
@@ -250,10 +400,7 @@ static void socketError(rfsimulator_state_t *bridge, buffer_t *buf)
}
}
-enum blocking_t {
- notBlocking,
- blocking
-};
+enum blocking_t { notBlocking, blocking };
static int setblocking(int sock, enum blocking_t active)
{
@@ -276,13 +423,14 @@ static int setblocking(int sock, enum blocking_t active)
return 0;
}
-static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) {
+static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t)
+{
if (t->saveIQfile != -1) {
if (write(t->saveIQfile, _buf, count) != count)
LOG_E(HW, "write() in save iq file failed (%d)\n", errno);
}
- char *buf = _buf;
+ char *buf = static_cast(_buf);
ssize_t l;
while (count) {
@@ -312,9 +460,70 @@ static void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t)
}
}
-static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
+static float get_rx_gain_db(rfsimulator_state_t *rfsimulator, uint rx_beam, uint tx_beam)
+{
+ if (!rfsimulator->beam_ctrl->enable_beams) {
+ return 0;
+ }
+ AssertFatal(rx_beam < rfsimulator->beam_ctrl->beam_gains.size() && tx_beam < rfsimulator->beam_ctrl->beam_gains[rx_beam].size(),
+ "Beam gain for this combination was not provided rx_beam %d tx_beam %d\n",
+ rx_beam,
+ tx_beam);
+ return rfsimulator->beam_ctrl->beam_gains[rx_beam][tx_beam];
+}
+
+static int rfsimulator_set_beams(openair0_device *device, uint64_t beam_map, openair0_timestamp timestamp)
+{
+ rfsimulator_state_t *s = static_cast(device->priv);
+ rfsim_beam_ctrl_t *beam_ctrl = s->beam_ctrl;
+ std::lock_guard lock_tx(beam_ctrl->tx.mutex);
+ std::lock_guard lock_rx(beam_ctrl->rx.mutex);
+ beam_switch_command_t command = {.beams = beam_map_to_beams(beam_map), .timestamp = timestamp};
+ beam_ctrl->rx.cmd_queue.emplace(command);
+ beam_ctrl->tx.cmd_queue.emplace(command);
+ return 0;
+}
+
+static int rfsimulator_set_beams_vector(openair0_device *device, int* beams, int num_beams, openair0_timestamp timestamp)
+{
+ rfsimulator_state_t *s = static_cast(device->priv);
+ rfsim_beam_ctrl_t *beam_ctrl = s->beam_ctrl;
+ std::lock_guard lock_tx(beam_ctrl->tx.mutex);
+ std::lock_guard lock_rx(beam_ctrl->rx.mutex);
+ beam_switch_command_t command = {.beams = std::vector(beams, beams + num_beams), .timestamp = timestamp};
+ beam_ctrl->rx.cmd_queue.emplace(command);
+ beam_ctrl->tx.cmd_queue.emplace(command);
+ return 0;
+}
+
+static void process_gains(char *str, rfsim_beam_ctrl_t *beam_ctrl)
+{
+ int num_gains = 0;
+ float gain_array[MAX_BEAMS];
+ std::stringstream ss(str);
+ std::string token;
+ while (std::getline(ss, token, ',') && num_gains < MAX_BEAMS) {
+ gain_array[num_gains++] = std::stof(token);
+ }
+
+ if (num_gains != 0) {
+ for (int i = 0; i < num_gains; i++) {
+ std::vector beam_gains;
+ for (int j = 0; j < num_gains; j++) {
+ int diag = abs(i - j);
+ beam_gains.push_back(gain_array[diag]);
+ }
+ beam_ctrl->beam_gains.push_back(beam_gains);
+ }
+ }
+}
+
+static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator)
+{
char *saveF = NULL;
char *modelname = NULL;
+ rfsim_beam_ctrl_t *beam_ctrl = rfsimulator->beam_ctrl;
+ uint64_t beam_map = 1;
paramdef_t rfsimu_params[] = RFSIMULATOR_PARAMS_DESC;
int p = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_OPTIONS_PARAMNAME);
int ret = config_get(config_get_if(), rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_SECTION);
@@ -336,7 +545,11 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
break;
} else if (strcmp(rfsimu_params[p].strlistptr[i], "chanmod") == 0) {
init_channelmod();
- load_channellist(rfsimulator->tx_num_channels, rfsimulator->rx_num_channels, rfsimulator->sample_rate, rfsimulator->rx_freq, rfsimulator->tx_bw);
+ load_channellist(rfsimulator->tx_num_channels,
+ rfsimulator->rx_num_channels,
+ rfsimulator->sample_rate,
+ rfsimulator->rx_freq,
+ rfsimulator->tx_bw);
rfsimulator->channelmod = true;
} else {
fprintf(stderr, "unknown rfsimulator option: %s\n", rfsimu_params[p].strlistptr[i]);
@@ -344,14 +557,68 @@ static void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
}
}
- if ( strncasecmp(rfsimulator->ip,"enb",3) == 0 ||
- strncasecmp(rfsimulator->ip,"server",3) == 0 )
+ int beam_gains_param_index = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_BEAM_GAINS);
+ if (rfsimu_params[beam_gains_param_index].strptr) {
+ process_gains(*rfsimu_params[beam_gains_param_index].strptr, beam_ctrl);
+ }
+
+ std::vector initial_beams = beam_map_to_beams(beam_map);
+ beam_ctrl->rx.beams = initial_beams;
+ beam_ctrl->tx.beams = initial_beams;
+
+ int beam_ids_param_index = config_paramidx_fromname(rfsimu_params, sizeofArray(rfsimu_params), RFSIMU_BEAM_IDS);
+ if (rfsimu_params[beam_ids_param_index].strptr) {
+ std::vector beam_ids;
+ std::stringstream ss(*rfsimu_params[beam_ids_param_index].strptr);
+ std::string token;
+ while (std::getline(ss, token, ',')) {
+ beam_ids.push_back(std::stoi(token));
+ }
+ beam_ctrl->rx.beams = beam_ids;
+ beam_ctrl->tx.beams = beam_ids;
+ }
+
+ if (strncasecmp(rfsimulator->ip, "enb", 3) == 0 || strncasecmp(rfsimulator->ip, "server", 3) == 0)
rfsimulator->role = SIMU_ROLE_SERVER;
else
rfsimulator->role = SIMU_ROLE_CLIENT;
}
-static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) {
+static int rfsimu_set_beam(char *buff, int debug, telnet_printfunc_t prnt, void *arg)
+{
+ rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
+ rfsim_beam_ctrl_t *beam_ctrl = t->beam_ctrl;
+ AssertFatal(beam_ctrl->enable_beams, "Beam simualtion is disabled, cannot set beams\n");
+ uint64_t beam_map = strtoull(buff, NULL, 0);
+ std::lock_guard lock_tx(beam_ctrl->tx.mutex);
+ std::lock_guard lock_rx(beam_ctrl->rx.mutex);
+ beam_ctrl->rx.beams = beam_map_to_beams(beam_map);
+ beam_ctrl->tx.beams = beam_map_to_beams(beam_map);
+ prnt("Beam map set to 0x%lx\n", beam_map);
+ return CMDSTATUS_FOUND;
+}
+
+static int rfsimu_set_beamids(char *buff, int debug, telnet_printfunc_t prnt, void *arg)
+{
+ rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
+ rfsim_beam_ctrl_t *beam_ctrl = t->beam_ctrl;
+ AssertFatal(beam_ctrl->enable_beams, "Beam simualtion is disabled, cannot set beams\n");
+ std::vector beam_ids;
+ std::stringstream ss(buff);
+ std::string token;
+ while (std::getline(ss, token, ',')) {
+ beam_ids.push_back(std::stoi(token));
+ }
+ std::lock_guard lock_tx(beam_ctrl->tx.mutex);
+ std::lock_guard lock_rx(beam_ctrl->rx.mutex);
+ beam_ctrl->rx.beams = beam_ids;
+ beam_ctrl->tx.beams = beam_ids;
+ prnt("Beam ids set\n");
+ return CMDSTATUS_FOUND;
+}
+
+static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg)
+{
char *modelname = NULL;
char *modeltype = NULL;
rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
@@ -384,7 +651,7 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
if (b->conn_sock >= 0 && (strcmp(b->channel_model->model_name, modelname) == 0)) {
channel_desc_t *newmodel = new_channel_desc_scm(t->tx_num_channels,
t->rx_num_channels,
- channelmod,
+ static_cast(channelmod),
t->sample_rate,
t->rx_freq,
t->tx_bw,
@@ -459,7 +726,8 @@ static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt
/* Set distance in rfsim and channel model, update channel and ringbuffer */
for (int i = 0; i < MAX_FD_RFSIMU; i++) {
buffer_t *b = &t->buf[i];
- if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL || strcmp(b->channel_model->model_name, modelname) != 0) {
+ if (b->conn_sock <= 0 || b->channel_model == NULL || b->channel_model->model_name == NULL
+ || strcmp(b->channel_model->model_name, modelname) != 0) {
if (b->channel_model != NULL && b->channel_model->model_name != NULL)
prnt(" %s: model %s unmodified\n", __func__, b->channel_model->model_name);
continue;
@@ -520,9 +788,9 @@ static int startServer(openair0_device *device)
snprintf(port, sizeof(port), "%d", t->port);
struct addrinfo hints = {
+ .ai_flags = AI_PASSIVE,
.ai_family = AF_INET6,
.ai_socktype = SOCK_STREAM,
- .ai_flags = AI_PASSIVE,
};
int s = getaddrinfo(NULL, port, &hints, &results);
@@ -619,7 +887,7 @@ static int client_try_connect(const char *host, uint16_t port)
static int startClient(openair0_device *device)
{
- rfsimulator_state_t *t = device->priv;
+ rfsimulator_state_t *t = static_cast(device->priv);
t->role = SIMU_ROLE_CLIENT;
int sock;
@@ -661,9 +929,10 @@ static int startClient(openair0_device *device)
static int rfsimulator_write_internal(rfsimulator_state_t *t,
openair0_timestamp timestamp,
- void **samplesVoid,
+ void ***samplesVoid,
int nsamps,
int nbAnt,
+ std::vector tx_beams,
int flags)
{
mutexlock(t->Sockmutex);
@@ -673,27 +942,24 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t,
buffer_t *b = &t->buf[i];
if (b->conn_sock >= 0) {
- samplesBlockHeader_t header = {nsamps, nbAnt, timestamp};
- if (!nbAnt)
- LOG_E(HW, "rfsimulator sending 0 tx antennas\n");
+ samplesBlockHeader_t header = {(uint32_t)nsamps, (uint32_t)nbAnt, (uint64_t)timestamp, 0, 0, beams_to_beam_map(tx_beams)};
fullwrite(b->conn_sock, &header, sizeof(header), t);
- if (nbAnt == 1) {
- fullwrite(b->conn_sock, samplesVoid[0], sampleToByte(nsamps, nbAnt), t);
- } else {
- sample_t tmpSamples[nsamps][nbAnt];
+ int num_beams = tx_beams.size();
+ // Send beams in order of beam index. This is required for beam_map to work correctly on the receiver side.
+ std::vector indices(tx_beams.size());
+ std::iota(indices.begin(), indices.end(), 0);
+ std::sort(indices.begin(), indices.end(), [&](size_t i, size_t j) { return tx_beams[i] < tx_beams[j]; });
+
+ AssertFatal(num_beams > 0, "Must set at least one bit in beam_map\n");
+ for (int beam = 0; beam < num_beams; beam++) {
for (int a = 0; a < nbAnt; a++) {
- sample_t *in = (sample_t *)samplesVoid[a];
- for (int s = 0; s < nsamps; s++)
- tmpSamples[s][a] = in[s];
+ sample_t *in = (sample_t *)samplesVoid[indices[beam]][a];
+ fullwrite(b->conn_sock, (void *)in, sampleToByte(nsamps, 1), t);
}
- fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps, nbAnt), t);
}
}
}
- if (t->lastWroteTS != 0 && fabs((double)t->lastWroteTS - timestamp) > (double)CirSize)
- LOG_W(HW, "Discontinuous TX gap too large Tx:%lu, %lu\n", t->lastWroteTS, timestamp);
-
if (t->lastWroteTS > timestamp)
LOG_W(HW, "Not supported to send Tx out of order %lu, %lu\n", t->lastWroteTS, timestamp);
@@ -712,23 +978,54 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t,
nsamps,
timestamp,
timestamp + nsamps,
- signal_energy(samplesVoid[0], nsamps));
+ signal_energy(static_cast(samplesVoid[0][0]), nsamps));
/* trace only first antenna */
- T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0], sampleToByte(nsamps, 1)));
+ T(T_USRP_TX_ANT0, T_INT(timestamp), T_BUFFER(samplesVoid[0], (int)sampleToByte(nsamps, 1)));
return nsamps;
}
-static int rfsimulator_write(openair0_device *device,
- openair0_timestamp timestamp,
- void **samplesVoid,
- int nsamps,
- int nbAnt,
- int flags)
+static int rfsimulator_write_beams(openair0_device *device,
+ openair0_timestamp timestamp,
+ void ***samplesVoid,
+ int nsamps,
+ int nbAnt,
+ int num_beams,
+ int flags)
{
timestamp -= device->openair0_cfg->command_line_sample_advance;
- return rfsimulator_write_internal(device->priv, timestamp, samplesVoid, nsamps, nbAnt, flags);
+ int nsamps_initial = nsamps;
+ rfsimulator_state_t *t = static_cast(device->priv);
+ void *samples[num_beams][nbAnt];
+ void **samples_ptr[num_beams];
+ for (int beam = 0; beam < num_beams; beam++) {
+ samples_ptr[beam] = samples[beam];
+ for (int aatx = 0; aatx < nbAnt; aatx++) {
+ samples[beam][aatx] = samplesVoid[beam][aatx];
+ }
+ }
+ while (nsamps > 0) {
+ uint32_t nsamps_beam_map;
+ std::vector beams = get_beams(&t->beam_ctrl->tx, timestamp, nsamps, &nsamps_beam_map);
+ rfsimulator_write_internal(t, timestamp, samples_ptr, nsamps_beam_map, nbAnt, beams, flags);
+ for (int beam = 0; beam < num_beams; beam++) {
+ for (int aatx = 0; aatx < nbAnt; aatx++) {
+ char *ptr = (char *)samples_ptr[beam][aatx];
+ samples_ptr[beam][aatx] = (void *)(ptr + nsamps_beam_map * sizeof(sample_t));
+ }
+ }
+ timestamp += nsamps_beam_map;
+ nsamps -= nsamps_beam_map;
+ }
+ clear_beam_queue(&t->beam_ctrl->tx, timestamp + nsamps);
+ return nsamps_initial;
+}
+
+static int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
+{
+ void **tmp = buff;
+ return rfsimulator_write_beams(device, timestamp, &tmp, nsamps, cc, 1, flags);
}
static bool add_client(rfsimulator_state_t *t)
@@ -758,7 +1055,7 @@ static bool add_client(rfsimulator_state_t *t)
void *samplesVoid[t->tx_num_channels];
for (int i = 0; i < t->tx_num_channels; i++)
samplesVoid[i] = (void *)&v;
- samplesBlockHeader_t header = {1, t->tx_num_channels, t->lastWroteTS};
+ samplesBlockHeader_t header = {1, (uint32_t)t->tx_num_channels, (uint64_t)t->lastWroteTS, 0, 0, 1};
fullwrite(conn_sock, &header, sizeof(header), t);
fullwrite(conn_sock, samplesVoid, sampleToByte(1, t->tx_num_channels), t);
@@ -770,69 +1067,121 @@ static bool add_client(rfsimulator_state_t *t)
static void process_recv_header(rfsimulator_state_t *t, buffer_t *b, bool first_time)
{
- // check the header and start block transfer
- if (b->remainToTransfer != 0)
- return;
-
b->headerMode = false; // We got the header
-
+ AssertFatal(b->th.nbAnt != 0, "Number of antennas not set\n");
+ if (b->nbAnt != b->th.nbAnt) {
+ LOG_A(HW, "RFsim: Number of antennas changed from %d to %d\n", b->nbAnt, b->th.nbAnt);
+ b->nbAnt = b->th.nbAnt;
+ }
if (first_time) {
b->lastReceivedTS = b->th.timestamp;
b->trashingPacket = true;
} else {
- if (b->lastReceivedTS < b->th.timestamp) {
- // We have a transmission hole to fill, like TDD
- // we create no signal samples up to the beginning of this reception
+ if (b->lastReceivedTS < (int64_t)b->th.timestamp) {
int nbAnt = b->th.nbAnt;
if (!nbAnt)
LOG_E(HW, "rfsimulator receive 0 rx antennas\n");
- if (b->th.timestamp - b->lastReceivedTS < CirSize) {
- // case we wrap at circular buffer end
- for (uint64_t index = b->lastReceivedTS; index < b->th.timestamp; index++) {
- for (int a = 0; a < nbAnt; a++) {
- b->circularBuf[(index * nbAnt + a) % CirSize] = (c16_t){0};
- }
- }
- } else {
- // case no circular buffer wrap
- memset(b->circularBuf, 0, sampleToByte(CirSize, 1));
- }
b->lastReceivedTS = b->th.timestamp;
- } else if (b->lastReceivedTS > b->th.timestamp) {
+ } else if (b->lastReceivedTS > (int64_t)b->th.timestamp) {
LOG_W(HW, "Received data in past: current is %lu, new reception: %lu!\n", b->lastReceivedTS, b->th.timestamp);
b->trashingPacket = true;
}
- // verify the time gap is not too large
- mutexlock(t->Sockmutex);
- if (t->lastWroteTS != 0 && (fabs((double)t->lastWroteTS - b->lastReceivedTS) > (double)CirSize))
- LOG_W(HW, "UEsock(%d) Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->conn_sock, t->lastWroteTS, b->lastReceivedTS);
- mutexunlock(t->Sockmutex);
}
- // move back the pointer to overwrite the header, we don't need it anymore
- b->transferPtr = (char *)&b->circularBuf[(b->lastReceivedTS * b->th.nbAnt) % CirSize];
- // we now need to read the samples
- b->remainToTransfer = sampleToByte(b->th.size, b->th.nbAnt);
- if (!b->remainToTransfer)
- b->headerMode = true; // We got a header with 0 antennas, no I/Q to read
+
+ int num_beams = __builtin_popcountll(b->th.beam_map);
+ AssertFatal(b->th.beam_map == 1ULL || t->beam_ctrl->enable_beams == 1,
+ "The transmitter has enabled beam simulation while this receiver has not\n");
+ size_t payload_sz = sampleToByte(b->th.size, b->th.nbAnt) * num_beams;
+ b->packet_ptr = static_cast(calloc_or_fail(1, payload_sz + sizeof(samplesBlockHeader_t)));
+ b->packet_ptr->header = b->th;
+ b->transferPtr = b->packet_ptr->payload;
+ b->remainToTransfer = payload_sz;
return;
}
-static void process_recv(rfsimulator_state_t *t, buffer_t *b, bool first_time)
+/**
+ * @brief Combines samples from received packets into a single buffer for the rx beam
+ *
+ * This function processes the received_packets queue and combines the transmitted beams
+ * into a single buffer for each antenna. It applies the appropriate gain and handles
+ * overlapping timestamps.
+ *
+ *
+ * @param t Pointer to the rfsimulator_state_t structure.
+ * @param received_packets Reference to the queue of rfsim_packet_t pointers representing received packets.
+ * @param start_timestamp The start timestamp for the combination process.
+ * @param num_aatx The number of antennas to process.
+ * @param num_samples The number of samples to process.
+ * @param rx_beam_id Receiver configured beam id for the timestamp
+ * @param samples Pointer to the output buffer where combined samples will be stored.
+ * @return A vector of vectors containing the combined samples for each antenna.
+ */
+static void combine_received_beams(rfsimulator_state_t *t,
+ std::queue &received_packets,
+ uint64_t start_timestamp,
+ int num_aatx,
+ size_t num_samples,
+ int rx_beam_id,
+ c16_t **samples)
{
- if (b->transferPtr == b->circularBufEnd)
- b->transferPtr = (char *)b->circularBuf;
+ // Assume received_packets is ordered by timestamp
+ std::queue packets_copy = received_packets;
+ while (!packets_copy.empty()) {
+ rfsim_packet_t *pkt = packets_copy.front();
+ if (pkt->header.timestamp + pkt->header.size <= start_timestamp) {
+ // This packet is before the start timestamp, discard it
+ packets_copy.pop();
+ continue;
+ }
+ if (pkt->header.timestamp > start_timestamp + num_samples) {
+ // This packet is after the end of the buffer, stop processing
+ break;
+ }
- if (!b->trashingPacket) {
- b->lastReceivedTS = b->th.timestamp + b->th.size - byteToSample(b->remainToTransfer, b->th.nbAnt);
- LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS);
- }
-
- if (b->remainToTransfer == 0) {
- LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS);
- b->headerMode = true;
- b->transferPtr = (char *)&b->th;
- b->remainToTransfer = sizeof(samplesBlockHeader_t);
- b->trashingPacket = false;
+ // The beams transmitted in are ordered by beam index
+ std::vector tx_beams = beam_map_to_beams(pkt->header.beam_map);
+ for (uint beam = 0; beam < tx_beams.size(); beam++) {
+ float gain_dB = get_rx_gain_db(t, rx_beam_id, tx_beams[beam]);
+ float gain_linear = powf(10, gain_dB / 20.0);
+ uint64_t overlap_start = std::max(start_timestamp, pkt->header.timestamp);
+ uint64_t overlap_end = std::min(start_timestamp + num_samples, pkt->header.timestamp + pkt->header.size);
+ int write_start_idx = overlap_start - start_timestamp;
+ int write_end_idx = overlap_end - start_timestamp;
+ int read_start_idx = overlap_start - pkt->header.timestamp;
+ for (int aatx = 0; aatx < num_aatx; aatx++) {
+ c16_t *buffer = (c16_t *)pkt->payload;
+ c16_t *tx_ant_buffer_in = &buffer[(num_aatx * beam + aatx) * pkt->header.size + read_start_idx];
+ if (beam == 0) {
+ // For the first beam, we can directly copy the samples
+ if (gain_dB == 0.0f) {
+ // If gain is 0 dB, we can use memcpy for efficiency
+ memcpy(&samples[aatx][write_start_idx], tx_ant_buffer_in, (write_end_idx - write_start_idx) * sizeof(c16_t));
+ } else {
+ for (int s = write_start_idx; s < write_end_idx; s++) {
+ samples[aatx][s].r = tx_ant_buffer_in->r * gain_linear;
+ samples[aatx][s].i = tx_ant_buffer_in->i * gain_linear;
+ tx_ant_buffer_in++;
+ }
+ }
+ } else {
+ // For subsequent beams, we need to ensure we accumulate the samples
+ if (gain_dB == 0.0f) {
+ for (int s = write_start_idx; s < write_end_idx; s++) {
+ samples[aatx][s].r += tx_ant_buffer_in->r;
+ samples[aatx][s].i += tx_ant_buffer_in->i;
+ tx_ant_buffer_in++;
+ }
+ } else {
+ for (int s = write_start_idx; s < write_end_idx; s++) {
+ samples[aatx][s].r += tx_ant_buffer_in->r * gain_linear;
+ samples[aatx][s].i += tx_ant_buffer_in->i * gain_linear;
+ tx_ant_buffer_in++;
+ }
+ }
+ }
+ }
+ }
+ packets_copy.pop();
}
}
@@ -850,7 +1199,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time)
}
for (int nbEv = 0; nbEv < nfds; ++nbEv) {
- buffer_t *b = events[nbEv].data.ptr;
+ buffer_t *b = static_cast(events[nbEv].data.ptr);
if (events[nbEv].events & EPOLLIN && b == NULL) {
bool ret = add_client(t);
@@ -864,19 +1213,12 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time)
}
}
- if (b->circularBuf == NULL) {
+ if (b->conn_sock == -1) {
LOG_E(HW, "Received data on not connected socket %d\n", events[nbEv].data.fd);
continue;
}
- ssize_t blockSz;
- if (b->headerMode)
- blockSz = b->remainToTransfer;
- else
- blockSz =
- b->transferPtr + b->remainToTransfer <= b->circularBufEnd ? b->remainToTransfer : b->circularBufEnd - b->transferPtr;
-
- ssize_t sz = recv(b->conn_sock, b->transferPtr, blockSz, MSG_DONTWAIT);
+ ssize_t sz = recv(b->conn_sock, b->transferPtr, b->remainToTransfer, MSG_DONTWAIT);
if (sz <= 0) {
if (sz < 0 && errno != EAGAIN)
LOG_E(HW, "recv() failed, errno(%d)\n", errno);
@@ -885,17 +1227,142 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, bool first_time)
LOG_D(HW, "Socket rcv %zd bytes\n", sz);
b->remainToTransfer -= sz;
b->transferPtr += sz;
- if (b->headerMode)
- process_recv_header(t, b, first_time);
- else
- process_recv(t, b, first_time);
+ if (b->remainToTransfer == 0) {
+ if (b->headerMode)
+ process_recv_header(t, b, first_time);
+ else {
+ LOG_D(HW, "UEsock: %d Completed block reception: %ld\n", b->conn_sock, b->lastReceivedTS);
+ b->headerMode = true;
+ b->transferPtr = (char *)&b->th;
+ b->remainToTransfer = sizeof(samplesBlockHeader_t);
+
+ if (!b->trashingPacket) {
+ b->lastReceivedTS = b->th.timestamp + b->th.size;
+ LOG_D(HW, "UEsock: %d Set b->lastReceivedTS %ld\n", b->conn_sock, b->lastReceivedTS);
+ b->received_packets.emplace(b->packet_ptr);
+ } else {
+ free(b->packet_ptr);
+ }
+ b->packet_ptr = NULL;
+ b->trashingPacket = false;
+ }
+ }
}
return nfds > 0;
}
-static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt)
+static void rfsimulator_read_internal(rfsimulator_state_t *t,
+ c16_t **samples,
+ openair0_timestamp timestamp,
+ int nsamps,
+ int nbAnt,
+ int rx_beam_id,
+ bool is_first_beam)
{
- rfsimulator_state_t *t = device->priv;
+ cf_t temp_array[nbAnt][nsamps];
+ bool channel_modelling = false;
+ // Add all input nodes signal in the output buffer
+ bool is_first_peer = true;
+ for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
+ buffer_t *ptr = &t->buf[sock];
+
+ if (ptr->conn_sock != -1 && !ptr->received_packets.empty()) {
+ AssertFatal(ptr->nbAnt != 0, "Number of antennas not set\n");
+ bool reGenerateChannel = false;
+
+ // fixme: when do we regenerate
+ // it seems legacy behavior is: never in UL, each frame in DL
+ if (reGenerateChannel)
+ random_channel(ptr->channel_model, 0);
+
+ if (ptr->channel_model != NULL) { // apply a channel model
+ if (!channel_modelling) {
+ memset(temp_array, 0, sizeof(temp_array));
+ channel_modelling = true;
+ }
+ const uint64_t channel_offset = ptr->channel_model->channel_offset;
+ const uint64_t channel_length = ptr->channel_model->channel_length;
+ std::vector> ant_buffers(ptr->nbAnt, std::vector(nsamps + channel_length - 1, {0, 0}));
+ c16_t *input[ant_buffers.size()];
+ for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
+ input[aatx] = ant_buffers[aatx].data();
+ }
+
+ combine_received_beams(t,
+ ptr->received_packets,
+ timestamp - channel_offset - (channel_length - 1),
+ ptr->nbAnt,
+ nsamps + channel_length - 1,
+ rx_beam_id,
+ input);
+
+ for (int aarx = 0; aarx < nbAnt; aarx++) {
+ rxAddInput(input, temp_array[aarx], aarx, ptr->channel_model, nsamps, timestamp);
+ }
+ } else {
+ if (is_first_beam && is_first_peer && (ptr->nbAnt == 1 || nbAnt == 1)) {
+ // optimization: The buffer is uninitialized so samples can be written directly in the buffer
+ combine_received_beams(t, ptr->received_packets, timestamp - t->chan_offset, 1, nsamps, rx_beam_id, samples);
+ } else {
+ std::vector> ant_buffers(ptr->nbAnt, std::vector(nsamps, {0, 0}));
+ c16_t *input[ant_buffers.size()];
+ for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
+ input[aatx] = ant_buffers[aatx].data();
+ }
+ combine_received_beams(t, ptr->received_packets, timestamp - t->chan_offset, ptr->nbAnt, nsamps, rx_beam_id, input);
+ for (int aarx = 0; aarx < nbAnt; aarx++) {
+ double H_awgn_mimo_coeff[ant_buffers.size()];
+ for (int aatx = 0; aatx < (int)ant_buffers.size(); aatx++) {
+ uint32_t ant_diff = std::abs(aatx - aarx);
+ H_awgn_mimo_coeff[aatx] = ant_diff ? (0.2 / ant_diff) : 1.0;
+ }
+
+ for (uint aatx = 0; aatx < ant_buffers.size(); aatx++) {
+ for (int i = 0; i < nsamps; i++) {
+ samples[aarx][i].r += ant_buffers[aatx][i].r * H_awgn_mimo_coeff[aatx];
+ samples[aarx][i].i += ant_buffers[aatx][i].i * H_awgn_mimo_coeff[aatx];
+ }
+ }
+ }
+ }
+ }
+ }
+ is_first_peer = false;
+ }
+
+ bool apply_global_noise = get_noise_power_dBFS() != INVALID_DBFS_VALUE;
+ if (apply_global_noise) {
+ if (!channel_modelling) {
+ memset(temp_array, 0, sizeof(temp_array));
+ channel_modelling = true;
+ }
+ int16_t noise_power = (int16_t)(32767.0 / powf(10.0, .05 * -get_noise_power_dBFS()));
+ for (int a = 0; a < nbAnt; a++) {
+ for (int i = 0; i < nsamps; i++) {
+ temp_array[a][i].r += noise_power + gaussZiggurat(0.0, 1.0);
+ temp_array[a][i].i += noise_power * gaussZiggurat(0.0, 1.0);
+ }
+ }
+ }
+
+ if (channel_modelling) {
+ for (int a = 0; a < nbAnt; a++) {
+ for (int i = 0; i < nsamps; i++) {
+ samples[a][i].r += lroundf(temp_array[a][i].r);
+ samples[a][i].i += lroundf(temp_array[a][i].i);
+ }
+ }
+ }
+}
+
+static int rfsimulator_read_beams(openair0_device *device,
+ openair0_timestamp *ptimestamp,
+ void ***samplesVoid,
+ int nsamps,
+ int nbAnt,
+ int num_beams)
+{
+ rfsimulator_state_t *t = static_cast(device->priv);
LOG_D(HW,
"Enter rfsimulator_read, expect %d samples, will release at TS: %ld, nbAnt %d\n",
nsamps,
@@ -907,7 +1374,7 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
int first_sock;
for (first_sock = 0; first_sock < MAX_FD_RFSIMU; first_sock++)
- if (t->buf[first_sock].circularBuf != NULL)
+ if (t->buf[first_sock].conn_sock != -1)
break;
if (first_sock == MAX_FD_RFSIMU) {
@@ -916,8 +1383,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
LOG_I(HW, "No connected device, generating void samples...\n");
if (!flushInput(t, t->wait_timeout, false)) {
- for (int x = 0; x < nbAnt; x++)
- memset(samplesVoid[x], 0, sampleToByte(nsamps, 1));
+ for (int beam = 0; beam < num_beams; beam++)
+ for (int x = 0; x < nbAnt; x++)
+ memset(samplesVoid[beam][x], 0, sampleToByte(nsamps, 1));
t->nextRxTstamp += nsamps;
@@ -934,9 +1402,9 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
buffer_t *b = NULL;
for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
b = &t->buf[sock];
- if (b->circularBuf && (t->nextRxTstamp + nsamps) > b->lastReceivedTS) {
- have_to_wait = true;
- break;
+ if (b->conn_sock != -1 && (t->nextRxTstamp + nsamps) > b->lastReceivedTS) {
+ have_to_wait = true;
+ break;
}
}
@@ -954,92 +1422,42 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
int ret = clock_gettime(CLOCK_REALTIME, &start_time);
AssertFatal(ret == 0, "clock_gettime() failed: errno %d, %s\n", errno, strerror(errno));
- // Clear the output buffer
- for (int a = 0; a < nbAnt; a++)
- memset(samplesVoid[a], 0, sampleToByte(nsamps, 1));
- cf_t temp_array[nbAnt][nsamps];
- bool apply_noise_per_channel = get_noise_power_dBFS() == INVALID_DBFS_VALUE;
- int num_chanmod_channels = 0;
- // Add all input nodes signal in the output buffer
for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
buffer_t *ptr = &t->buf[sock];
- if (ptr->circularBuf && !ptr->trashingPacket) {
- bool reGenerateChannel = false;
-
- // fixme: when do we regenerate
- // it seems legacy behavior is: never in UL, each frame in DL
- if (reGenerateChannel)
- random_channel(ptr->channel_model, 0);
-
- if (t->poll_telnetcmdq)
- t->poll_telnetcmdq(t->telnetcmd_qid, t);
-
- for (int a_rx = 0; a_rx < nbAnt; a_rx++) { // loop over number of Rx antennas
- if (ptr->channel_model != NULL) { // apply a channel model
- if (num_chanmod_channels == 0) {
- memset(temp_array, 0, sizeof(temp_array));
- }
- num_chanmod_channels++;
- rxAddInput(ptr->circularBuf,
- temp_array[a_rx],
- a_rx,
- ptr->channel_model,
- nsamps,
- t->nextRxTstamp,
- CirSize,
- apply_noise_per_channel);
- } else { // no channel modeling
- int nbAnt_tx = ptr->th.nbAnt; // number of Tx antennas
- int firstIndex = (CirSize + t->nextRxTstamp - t->chan_offset) % CirSize;
- sample_t *out = (sample_t *)samplesVoid[a_rx];
- if (nbAnt_tx == 1 && t->nb_cnx == 1) { // optimized for 1 Tx and 1 UE
- sample_t *firstSample = (sample_t *)&(ptr->circularBuf[firstIndex]);
- if (firstIndex + nsamps > CirSize) {
- int tailSz = CirSize - firstIndex;
- memcpy(out, firstSample, sampleToByte(tailSz, 1));
- memcpy(out + tailSz, &ptr->circularBuf[0], sampleToByte(nsamps - tailSz, 1));
- } else {
- memcpy(out, firstSample, sampleToByte(nsamps, 1));
- }
- } else {
- // SIMD (with simde) optimization might be added here later
- LOG_D(HW, "nbAnt_tx %d nbAnt %d\n", nbAnt_tx, nbAnt);
- double H_awgn_mimo_coeff[nbAnt_tx];
- for (int a_tx = 0; a_tx < nbAnt_tx; a_tx++) {
- uint32_t ant_diff = abs(a_tx - a_rx);
- H_awgn_mimo_coeff[a_tx] = ant_diff ? (0.2 / ant_diff) : 1.0;
- }
- for (int i = 0; i < nsamps; i++) { // loop over nsamps
- for (int a_tx = 0; a_tx < nbAnt_tx; a_tx++) { // sum up signals from nbAnt_tx antennas
- out[i].r += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].r * H_awgn_mimo_coeff[a_tx]);
- out[i].i += (short)(ptr->circularBuf[((firstIndex + i) * nbAnt_tx + a_tx) % CirSize].i * H_awgn_mimo_coeff[a_tx]);
- } // end for a_tx
- } // end for i (number of samps)
- } // end of 1 tx antenna optimization
- } // end of no channel modeling
- } // end for a (number of rx antennas)
+ if (ptr->conn_sock != -1 && ptr->channel_model != NULL) {
+ update_channel_model(ptr->channel_model, t->nextRxTstamp);
}
}
- if (apply_noise_per_channel && num_chanmod_channels > 0) {
- // Noise is already applied through the channel model
- for (int a = 0; a < nbAnt; a++) {
- sample_t *out = (sample_t *)samplesVoid[a];
- for (int i = 0; i < nsamps; i++) {
- out[i].r += lroundf(temp_array[a][i].r);
- out[i].i += lroundf(temp_array[a][i].i);
- }
+
+ if (t->poll_telnetcmdq)
+ t->poll_telnetcmdq(t->telnetcmd_qid, t);
+
+ // Clear the output buffer
+ for (int beam = 0; beam < num_beams; beam++)
+ for (int a = 0; a < nbAnt; a++)
+ memset(samplesVoid[beam][a], 0, sampleToByte(nsamps, 1));
+
+ openair0_timestamp timestamp = t->nextRxTstamp;
+ int nsamps_to_process = nsamps;
+ while (nsamps_to_process > 0) {
+ uint32_t nsamps_beam_map;
+ std::vector rx_beams = get_beams(&t->beam_ctrl->tx, timestamp, nsamps_to_process, &nsamps_beam_map);
+ if ((int)rx_beams.size() != num_beams) {
+ LOG_D(HW,
+ "Number of beams does not match application request num_beams %d, beam_map beams %lu\n",
+ num_beams,
+ rx_beams.size());
}
- } else if (num_chanmod_channels > 0) {
- // Apply noise from global setting
- int16_t noise_power = (int16_t)(32767.0 / powf(10.0, .05 * -get_noise_power_dBFS()));
- for (int a = 0; a < nbAnt; a++) {
- sample_t *out = (sample_t *)samplesVoid[a];
- for (int i = 0; i < nsamps; i++) {
- out[i].r += lroundf(temp_array[a][i].r + noise_power * gaussZiggurat(0.0, 1.0));
- out[i].i += lroundf(temp_array[a][i].i + noise_power * gaussZiggurat(0.0, 1.0));
+ for (int beam = 0; beam < num_beams && beam < (int)rx_beams.size(); beam++) {
+ c16_t *samples_beam[nbAnt];
+ for (int i = 0; i < nbAnt; i++) {
+ samples_beam[i] = (c16_t *)samplesVoid[beam][i] + timestamp - t->nextRxTstamp;
}
+ rfsimulator_read_internal(t, samples_beam, timestamp, nsamps_beam_map, nbAnt, rx_beams[beam], beam == 0);
}
+ timestamp += nsamps_beam_map;
+ nsamps_to_process -= nsamps_beam_map;
}
struct timespec end_time;
@@ -1055,32 +1473,59 @@ static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimest
*ptimestamp = t->nextRxTstamp; // return the time of the first sample
t->nextRxTstamp += nsamps;
+ clear_beam_queue(&t->beam_ctrl->rx, t->nextRxTstamp);
LOG_D(HW,
"Rx to upper layer: %d from %ld to %ld, energy in first antenna %d\n",
nsamps,
*ptimestamp,
t->nextRxTstamp,
- signal_energy(samplesVoid[0], nsamps));
+ signal_energy(static_cast(samplesVoid[0][0]), nsamps));
/* trace only first antenna */
- T(T_USRP_RX_ANT0, T_INT(t->nextRxTstamp), T_BUFFER(samplesVoid[0], sampleToByte(nsamps, 1)));
+ T(T_USRP_RX_ANT0, T_INT(t->nextRxTstamp), T_BUFFER(samplesVoid[0], (int)sampleToByte(nsamps, 1)));
+
+ for (int sock = 0; sock < MAX_FD_RFSIMU; sock++) {
+ buffer_t *ptr = &t->buf[sock];
+
+ if (ptr->conn_sock != -1 && !ptr->received_packets.empty()) {
+ openair0_timestamp timestamp_to_free = t->nextRxTstamp - 1;
+ if (ptr->channel_model) {
+ timestamp_to_free -=
+ (ptr->channel_model->channel_length - 1) + std::max(ptr->channel_model->channel_offset, t->chan_offset);
+ } else {
+ timestamp_to_free -= t->chan_offset;
+ }
+ clear_old_packets(ptr->received_packets, timestamp_to_free);
+ }
+ }
return nsamps;
}
-static int rfsimulator_get_stats(openair0_device *device) {
+static int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt)
+{
+ return rfsimulator_read_beams(device, ptimestamp, &samplesVoid, nsamps, nbAnt, 1);
+}
+
+static int rfsimulator_get_stats(openair0_device *device)
+{
return 0;
}
-static int rfsimulator_reset_stats(openair0_device *device) {
+static int rfsimulator_reset_stats(openair0_device *device)
+{
return 0;
}
-static void rfsimulator_end(openair0_device *device) {
- rfsimulator_state_t *s = device->priv;
+static void rfsimulator_end(openair0_device *device)
+{
+ rfsimulator_state_t *s = static_cast(device->priv);
for (int i = 0; i < MAX_FD_RFSIMU; i++) {
buffer_t *b = &s->buf[i];
if (b->conn_sock >= 0)
removeCirBuf(s, b);
}
+ clear_beam_queue(&s->beam_ctrl->tx, INT64_MAX);
+ clear_beam_queue(&s->beam_ctrl->rx, INT64_MAX);
+ delete s->beam_ctrl;
close(s->epollfd);
free(s);
}
@@ -1092,40 +1537,41 @@ static void stopServer(openair0_device *device)
rfsimulator_end(device);
}
-static int rfsimulator_stop(openair0_device *device) {
+static int rfsimulator_stop(openair0_device *device)
+{
return 0;
}
-static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg) {
- rfsimulator_state_t *s = device->priv;
+static int rfsimulator_set_freq(openair0_device *device, openair0_config_t *openair0_cfg)
+{
+ rfsimulator_state_t *s = static_cast(device->priv);
s->rx_freq = openair0_cfg->rx_freq[0];
return 0;
}
-static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
+static int rfsimulator_set_gains(openair0_device *device, openair0_config_t *openair0_cfg)
+{
return 0;
}
-static int rfsimulator_write_init(openair0_device *device) {
+static int rfsimulator_write_init(openair0_device *device)
+{
return 0;
}
-__attribute__((__visibility__("default")))
-int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
+extern "C" __attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg)
+{
// to change the log level, use this on command line
// --log_config.hw_log_level debug
- rfsimulator_state_t *rfsimulator = calloc(sizeof(rfsimulator_state_t), 1);
+ rfsimulator_state_t *rfsimulator = static_cast(calloc(sizeof(rfsimulator_state_t), 1));
// initialize channel simulation
rfsimulator->tx_num_channels = openair0_cfg->tx_num_channels;
rfsimulator->rx_num_channels = openair0_cfg->rx_num_channels;
rfsimulator->sample_rate = openair0_cfg->sample_rate;
rfsimulator->rx_freq = openair0_cfg->rx_freq[0];
rfsimulator->tx_bw = openair0_cfg->tx_bw;
+ rfsimulator->beam_ctrl = new rfsim_beam_ctrl_t;
rfsimulator_readconfig(rfsimulator);
if (rfsimulator->prop_delay_ms > 0.0)
rfsimulator->chan_offset = ceil(rfsimulator->sample_rate * rfsimulator->prop_delay_ms / 1000);
if (rfsimulator->chan_offset != 0) {
- if (CirSize < minCirSize + rfsimulator->chan_offset) {
- CirSize = minCirSize + rfsimulator->chan_offset;
- LOG_I(HW, "CirSize = %lu\n", CirSize);
- }
rfsimulator->prop_delay_ms = rfsimulator->chan_offset * 1000 / rfsimulator->sample_rate;
LOG_I(HW, "propagation delay %f ms, %lu samples\n", rfsimulator->prop_delay_ms, rfsimulator->chan_offset);
}
@@ -1143,12 +1589,18 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
device->trx_set_gains_func = rfsimulator_set_gains;
device->trx_write_func = rfsimulator_write;
device->trx_read_func = rfsimulator_read;
+ if (rfsimulator->beam_ctrl->enable_beams) {
+ device->trx_write_beams_func = rfsimulator_write_beams;
+ device->trx_read_beams_func = rfsimulator_read_beams;
+ }
/* let's pretend to be a b2x0 */
device->type = RFSIMULATOR;
openair0_cfg[0].rx_gain[0] = 0;
device->openair0_cfg = &openair0_cfg[0];
device->priv = rfsimulator;
device->trx_write_init = rfsimulator_write_init;
+ device->trx_set_beams = rfsimulator_set_beams;
+ device->trx_set_beams2 = rfsimulator_set_beams_vector;
for (int i = 0; i < MAX_FD_RFSIMU; i++)
rfsimulator->buf[i].conn_sock = -1;
diff --git a/radio/vrtsim/vrtsim.c b/radio/vrtsim/vrtsim.c
index 2b40f2f05d..38dea17d76 100644
--- a/radio/vrtsim/vrtsim.c
+++ b/radio/vrtsim/vrtsim.c
@@ -548,6 +548,18 @@ static int vrtsim_write(openair0_device *device, openair0_timestamp timestamp, v
: vrtsim_write_internal(vrtsim_state, timestamp, (c16_t *)samplesVoid[0], nsamps, 0, flags, 0);
}
+static int vrtsim_write_beams(openair0_device *device,
+ openair0_timestamp timestamp,
+ void ***buff,
+ int nsamps,
+ int nb_antennas_tx,
+ int num_beams,
+ int flags)
+{
+ vrtsim_write(device, timestamp, (void **)buff[0], nsamps, nb_antennas_tx, flags);
+ return nsamps;
+}
+
static int vrtsim_read(openair0_device *device, openair0_timestamp *ptimestamp, void **samplesVoid, int nsamps, int nbAnt)
{
vrtsim_state_t *vrtsim_state = (vrtsim_state_t *)device->priv;
@@ -657,6 +669,16 @@ static int vrtsim_set_freq(openair0_device *device, openair0_config_t *openair0_
return 0;
}
+static int vrtsim_set_beams(openair0_device *device, uint64_t beam_map, openair0_timestamp timestamp)
+{
+ return 0;
+}
+
+static int vrtsim_set_beams2(openair0_device *device, int *beam_ids, int num_beams, openair0_timestamp timestamp)
+{
+ return 0;
+}
+
__attribute__((__visibility__("default"))) int device_init(openair0_device *device, openair0_config_t *openair0_cfg)
{
randominit();
@@ -673,6 +695,9 @@ __attribute__((__visibility__("default"))) int device_init(openair0_device *devi
device->trx_set_gains_func = vrtsim_stub2;
device->trx_write_func = vrtsim_write;
device->trx_read_func = vrtsim_read;
+ device->trx_write_beams_func = vrtsim_write_beams;
+ device->trx_set_beams = vrtsim_set_beams;
+ device->trx_set_beams2 = vrtsim_set_beams2;
device->type = RFSIMULATOR;
device->openair0_cfg = &openair0_cfg[0];
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf
index 1d3e0e70d0..8c200c72fd 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci0.conf
@@ -19,7 +19,6 @@ gNBs =
////////// Physical parameters:
min_rxtxtime = 4;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf
index cdcd1a59fd..f87cc2bb8c 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band66.25prb.rfsim.pci1.conf
@@ -19,7 +19,6 @@ gNBs =
////////// Physical parameters:
min_rxtxtime = 4;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf
index 7a6becbd8c..1652758e4e 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.4x4-benetel650.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
force_UL256qam_off = 1;
# maxMIMO_layers = 2;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf
index 3dd36be9c7..eee6f875c9 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650-mplane.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 8;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
force_UL256qam_off = 1;
maxMIMO_layers = 2;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf
index 18829188e3..fdad2726c2 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-du.sa.band77.273prb.fhi72.8x8-benetel650_650.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 8;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
force_UL256qam_off = 1;
maxMIMO_layers = 2;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf
index aea3176456..467873a36f 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb-vnf.sa.band78.106prb.nfapi.conf
@@ -22,7 +22,6 @@ gNBs =
pusch_AntennaPorts = 1;
min_rxtxtime = 6;
enable_sdap = 0;
- #sib1_tda = 0;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf
index a6ca5decbe..10caa403d3 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band254.ntn.mu1.24prb.rfsim.conf
@@ -16,7 +16,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1;
cu_sibs = [2];
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf
index c811f0d64e..1684a375d0 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band255.ntn.mu0.25prb.rfsim.conf
@@ -16,7 +16,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1;
cu_sibs = [2];
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf
index 3a472ff7a2..c20188594d 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band256.ntn.mu0.25prb.rfsim.conf
@@ -16,7 +16,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
disable_harq = 1;
cu_sibs = [2];
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf
index 933cddfcb9..0c949fdccb 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band257.u3.32prb.usrpx410.conf
@@ -21,7 +21,6 @@ gNBs =
pusch_AntennaPorts = 1;
do_CSIRS = 1;
do_SRS = 1;
- sib1_tda = 15;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf
index a02394b5b2..bb5263aa9a 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.52PRB.usrpb210.conf
@@ -22,7 +22,6 @@ gNBs =
do_CSIRS = 1;
do_SRS = 1;
- sib1_tda = 15;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf
index 6b9b104bc0..f17e695e8a 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.24PRB.usrpx300.conf
@@ -32,7 +32,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
# disable_harq = 1;
# num_dlharq = 32;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf
index 560b33b0e9..d5b0559f0c 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.fr1.25PRB.usrpx300.conf
@@ -32,7 +32,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
# disable_harq = 1;
# num_dlharq = 32;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf
index 9458c2b272..428b6cb27c 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band66.u0.25prb.rfsim.conf
@@ -17,7 +17,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 5;
min_rxtxtime = 6;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf
index 753670a9eb..f7f8390b33 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.106prb.fhi72.4x4-vvdn.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf
index 38580730f2..d68e67c96f 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.2x2-vvdn.conf
@@ -21,7 +21,6 @@ gNBs =
pusch_AntennaPorts = 2;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf
index d55bc6dbda..7e13bf7dec 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band77.273prb.fhi72.4x4-vvdn.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf
index 75fe0e6fdd..715dcda78c 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x2-benetel550.conf
@@ -21,7 +21,6 @@ gNBs =
pusch_AntennaPorts = 2;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
# force_UL256qam_off = 1;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf
index ed996cac27..241ca9f23a 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550-mplane.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
# force_UL256qam_off = 1;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
index d8ca02a3be..2788e7f5f5 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-benetel550.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
# force_UL256qam_off = 1;
servingCellConfigCommon = (
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf
index 3c9780130f..2419df21bb 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-liteon.conf
@@ -23,7 +23,6 @@ gNBs =
pusch_AntennaPorts = 4;
do_CSIRS = 1;
do_SRS = 0;
- sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf
index 13617fb578..322d61b2b3 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.273prb.fhi72.4x4-metanoia.conf
@@ -21,7 +21,6 @@ gNBs =
do_CSIRS = 1;
do_SRS = 0;
force_UL256qam_off = 1;
- # sib1_tda = 15;
servingCellConfigCommon = (
{
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf
index 1398020417..63c63bd80e 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.24PRB.usrpb210.conf
@@ -17,7 +17,6 @@ gNBs =
////////// Physical parameters:
- sib1_tda = 15;
min_rxtxtime = 6;
servingCellConfigCommon = (