Merge branch 'integration_2025_w52' into 'develop'
Integration: `2025.w52` * !3809 [FHI72] Fix the PRACH FFT size * !3829 Hotfix for handling the case where the number of physical antennas is larger than the number of logical antennas * !3663 NR UE: calculate DL and UL Doppler based on SIB19 information in NTN mode, fixing LEO reestablishment * !3819 CORESET start multiple of 6 fix * !3641 automatic selection of SIB1 TDA * !3804 gNB: apply new NR_CellGroupConfig when RRCReconfiguration is acknowledged * !3833 Add missing CMakeLists entries for test_nr_frame_params * !3656 Rfsimulator beam reception/transmission Closes #1037 and #1002 See merge request oai/openairinterface5g!3830
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -16,8 +16,6 @@ gNBs =
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -18,8 +18,6 @@ gNBs =
|
||||
tr_s_preference = "local_mac"
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -16,8 +16,6 @@ gNBs =
|
||||
nr_cellid = 12345678L;
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
# force_UL256qam_off = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -32,6 +32,11 @@
|
||||
000003
|
||||
020001
|
||||
020002
|
||||
040001
|
||||
020022
|
||||
040002
|
||||
020001
|
||||
020002
|
||||
100001
|
||||
222222
|
||||
</TestCaseRequestedList>
|
||||
@@ -94,6 +99,33 @@
|
||||
<ping_packetloss_threshold>5</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040001">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Trigger Reestablishment</desc>
|
||||
<node>localhost</node>
|
||||
<command>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'</command>
|
||||
<command_fail>yes</command_fail>
|
||||
</testCase>
|
||||
|
||||
<testCase id="020022">
|
||||
<class>Ping</class>
|
||||
<desc>Ping ext-dn from NR-UE</desc>
|
||||
<id>rfsim5g_ue</id>
|
||||
<node>localhost</node>
|
||||
<svr_id>rfsim5g_ext_dn</svr_id>
|
||||
<svr_node>localhost</svr_node>
|
||||
<ping_args>-c 20 -i0.5 -w25</ping_args>
|
||||
<ping_packetloss_threshold>80</ping_packetloss_threshold>
|
||||
</testCase>
|
||||
|
||||
<testCase id="040002">
|
||||
<class>Custom_Command</class>
|
||||
<desc>Verify Reestablishment</desc>
|
||||
<node>localhost</node>
|
||||
<command>echo ci get_reestab_count | ncat 192.168.71.140 9090 | grep -E 'UE RNTI [0-9a-f]{4} reestab 1'</command>
|
||||
<command_fail>yes</command_fail>
|
||||
</testCase>
|
||||
|
||||
<testCase id="100001">
|
||||
<class>Undeploy_Object</class>
|
||||
<always_exec>true</always_exec>
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
<iperf_args>-t 10 -R</iperf_args>
|
||||
<id>idefix</id>
|
||||
<svr_id>sabox-nepes</svr_id>
|
||||
<iperf_tcp_rate_target>85</iperf_tcp_rate_target>
|
||||
<iperf_tcp_rate_target>65</iperf_tcp_rate_target>
|
||||
</testCase>
|
||||
|
||||
<testCase id="400003">
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 ; i<numparams ; i++) {
|
||||
@@ -84,7 +84,7 @@ void config_printhelp(paramdef_t *params,int numparams, char *prefix) {
|
||||
printf("--------------------------------------------------------------------\n\n");
|
||||
}
|
||||
|
||||
int config_execcheck(configmodule_interface_t *cfg, paramdef_t *params, int numparams, char *prefix)
|
||||
int config_execcheck(configmodule_interface_t *cfg, paramdef_t *params, int numparams, const char *prefix)
|
||||
{
|
||||
int st=0;
|
||||
|
||||
@@ -105,7 +105,7 @@ int config_execcheck(configmodule_interface_t *cfg, paramdef_t *params, int nump
|
||||
return st;
|
||||
}
|
||||
|
||||
int config_paramidx_fromname(paramdef_t *params, int numparams, char *name) {
|
||||
int config_paramidx_fromname(paramdef_t *params, int numparams, const char *name) {
|
||||
for (int i=0; i<numparams ; i++) {
|
||||
if (strcmp(name,params[i].optname) == 0)
|
||||
return i;
|
||||
@@ -115,7 +115,7 @@ int config_paramidx_fromname(paramdef_t *params, int numparams, char *name) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int config_get(configmodule_interface_t *cfgif, paramdef_t *params, int numparams, char *prefix)
|
||||
int config_get(configmodule_interface_t *cfgif, paramdef_t *params, int numparams, const char *prefix)
|
||||
{
|
||||
int ret= -1;
|
||||
|
||||
|
||||
@@ -49,17 +49,17 @@ extern configmodule_interface_t *uniqCfg;
|
||||
#define CONFIG_SETRTFLAG(P) if (config_get_if()) { config_get_if()->rtflags |= 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 */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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; i<loader_data.numshlibs && loader_data.shlibs[i].name != NULL; i++) {
|
||||
if ( strcmp(loader_data.shlibs[i].name, modname) == 0) {
|
||||
|
||||
@@ -82,7 +82,7 @@ extern loader_data_t loader_data;
|
||||
// clang-format on
|
||||
|
||||
int load_module_version_shlib(char *modname, char *version, loader_shlibfunc_t *farray, int numf, void *initfunc_arg);
|
||||
void *get_shlibmodule_fptr(char *modname, char *fname);
|
||||
void *get_shlibmodule_fptr(const char *modname, const char *fname);
|
||||
#define load_module_shlib(M, F, N, I) load_module_version_shlib(M, NULL, F, N, I)
|
||||
void loader_reset();
|
||||
#endif
|
||||
|
||||
@@ -76,7 +76,7 @@ typedef struct webdatadef {
|
||||
typedef void(*telnet_printfunc_t)(const char* format, ...);
|
||||
typedef int(*cmdfunc_t)(char*, int, telnet_printfunc_t prnt);
|
||||
typedef int (*webfunc_t)(char *cmdbuff, int debug, telnet_printfunc_t prnt, ...);
|
||||
typedef int (*webfunc_getdata_t)(char *cmdbuff, int debug, void *data, telnet_printfunc_t prnt);
|
||||
typedef int (*webfunc_getdata_t)(const char *cmdbuff, int debug, void *data, telnet_printfunc_t prnt);
|
||||
typedef int(*qcmdfunc_t)(char*, int, telnet_printfunc_t prnt,void *arg);
|
||||
|
||||
#define TELNETSRV_CMDFLAG_PUSHINTPOOLQ (1 << 0) // ask the telnet server to push the command in a thread pool queue
|
||||
@@ -195,7 +195,7 @@ VT escape sequence definition, for smarter display....
|
||||
#define TELNET_ADDCMD_FNAME "add_telnetcmd"
|
||||
#define TELNET_POLLCMDQ_FNAME "poll_telnetcmdq"
|
||||
#define TELNET_PUSHCMD_FNAME "telnet_pushcmd"
|
||||
typedef int(*add_telnetcmd_func_t)(char *, telnetshell_vardef_t *, telnetshell_cmddef_t *);
|
||||
typedef int(*add_telnetcmd_func_t)(const char *, telnetshell_vardef_t *, telnetshell_cmddef_t *);
|
||||
typedef void(*poll_telnetcmdq_func_t)(void *qid,void *arg);
|
||||
typedef void (*push_telnetcmd_func_t)(telnetshell_cmddef_t *cmd, char *cmdbuff, telnet_printfunc_t prnt);
|
||||
#ifdef TELNETSERVERCODE
|
||||
|
||||
+2
-1
@@ -355,7 +355,8 @@ These modes of operation are supported:
|
||||
- Different TA adjustemt algorithms between SIB19 receptions:
|
||||
- Autonomous TA adjustemt based on DL time tracking
|
||||
- Standard compliant epoch time based TA adjustment including orbital propagation
|
||||
- UL Doppler pre-compensation based on continuous DL FO estimation
|
||||
- DL Doppler compensation based on ntn-Config-r17 information
|
||||
- UL Doppler pre-compensation based on ntn-Config-r17 information and residual DL FO estimation
|
||||
* Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
|
||||
* Highly efficient 3GPP compliant polar encoder and decoder
|
||||
* Encoder and decoder for short block
|
||||
|
||||
@@ -255,8 +255,6 @@ configuration](../RRC/rrc-usage.md) as well for SIB configuration.
|
||||
* `pusch_AntennaPorts` (default 1): number of antenna ports in PUSCH
|
||||
* `maxMIMO_layers` (default -1=unlimited): maximum number of MIMO layers to use
|
||||
in downlink
|
||||
* `sib1_tda` (default 1): time domain allocation (TDA) indices to use for SIB1
|
||||
(38.214 section 5.1.2.1.1)
|
||||
* `do_CSIRS` (default 0): flag whether to use channel-state information
|
||||
reference signal (CSI-RS)
|
||||
* `do_SRS` (default 0): flag whether to use sounding reference signal (SRS)
|
||||
|
||||
+1
-2
@@ -135,7 +135,7 @@ Here are some useful command line options for the NR UE:
|
||||
|--------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| `--ue-scan-carrier` | Scan for cells in current bandwidth. This option can be used if the SSB position of the gNB is unknown. If multiple cells are detected, the UE will try to connect to the first cell. By default, this option is disabled and the UE attempts to only decode SSB given by `--ssb`. |
|
||||
| `--ue-fo-compensation` | Enables the initial frequency offset compensation at the UE. Useful when running over the air and/or without an external clock/time source. |
|
||||
| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. |
|
||||
| `--cont-fo-comp` | Enables the continuous frequency offset (FO) estimation and compensation. Parameter value `1` specifies that the main FO contribution comes from the local oscillator's (LO) accuracy. Parameter value `2` specifies that the main FO contribution comes from Doppler shift. Parameter value `3` specifies that no measured residual DL FO is considered for UL FO pre-compensation. |
|
||||
| `--initial-fo` | Sets the known initial frequency offset. Useful especially with large Doppler frequency, e.g. LEO satellite. |
|
||||
| `--freq-sync-P` | Sets the coefficient for the Proportional part of the PI-controller for the continuous frequency offset compensation. Default value 0.01. |
|
||||
| `--freq-sync-I` | Sets the coefficient for the Integrating part of the PI-controller for the continuous frequency offset compensation. Default value 0.001. |
|
||||
@@ -296,7 +296,6 @@ This allows to reuse HARQ processes immediately, but it breaks compatibility wit
|
||||
To enable this feature, the `disable_harq` flag has to be added to the gNB conf file in the section `gNBs.[0]`
|
||||
```
|
||||
...
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
disable_harq = 1; // <--
|
||||
|
||||
|
||||
@@ -896,6 +896,7 @@ static void fill_split7_2_config(split7_config_t *split7, const nfapi_nr_config_
|
||||
}
|
||||
}
|
||||
|
||||
split7->prach_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
|
||||
|
||||
+205
-67
@@ -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;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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],
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 "<channel index>"
|
||||
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; i<max_chan; i++) {
|
||||
if (defined_channels[i] != NULL) {
|
||||
if (strcmp(defined_channels[i]->model_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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 } }, \
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<<i);
|
||||
if (nr_of_candidates>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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_library(rfsimulator MODULE
|
||||
simulator.c
|
||||
simulator.cpp
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
)
|
||||
|
||||
@@ -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 <comma separated list>` : 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 <beam_map>` : where `<beam_map>` 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 <beam_ids>` : where `<beam_ids>` 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 <beam_map>` or `rfsimu setbeamids <beam_ids>`. 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.
|
||||
|
||||
@@ -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 <complex.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
@@ -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; i<nbSamples; i++) {
|
||||
for (int i = 0; i < nbSamples; i++) {
|
||||
cf_t *out_ptr = after_channel_sig + i;
|
||||
struct complexd rx_tmp= {0};
|
||||
struct complexd rx_tmp = {0};
|
||||
|
||||
for (int txAnt=0; txAnt < nbTx; txAnt++) {
|
||||
const struct complexd *channelModel= channelDesc->ch[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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <stdbool.h>
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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];
|
||||
|
||||
@@ -19,7 +19,6 @@ gNBs =
|
||||
////////// Physical parameters:
|
||||
|
||||
min_rxtxtime = 4;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -19,7 +19,6 @@ gNBs =
|
||||
////////// Physical parameters:
|
||||
|
||||
min_rxtxtime = 4;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
force_UL256qam_off = 1;
|
||||
# maxMIMO_layers = 2;
|
||||
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 8;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
force_UL256qam_off = 1;
|
||||
maxMIMO_layers = 2;
|
||||
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 8;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
force_UL256qam_off = 1;
|
||||
maxMIMO_layers = 2;
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 1;
|
||||
min_rxtxtime = 6;
|
||||
enable_sdap = 0;
|
||||
#sib1_tda = 0;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -16,7 +16,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
disable_harq = 1;
|
||||
cu_sibs = [2];
|
||||
|
||||
@@ -16,7 +16,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
disable_harq = 1;
|
||||
cu_sibs = [2];
|
||||
|
||||
@@ -16,7 +16,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
disable_harq = 1;
|
||||
cu_sibs = [2];
|
||||
|
||||
@@ -21,7 +21,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 1;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -22,7 +22,6 @@ gNBs =
|
||||
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 1;
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -32,7 +32,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
# disable_harq = 1;
|
||||
# num_dlharq = 32;
|
||||
|
||||
@@ -32,7 +32,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
# disable_harq = 1;
|
||||
# num_dlharq = 32;
|
||||
|
||||
@@ -17,7 +17,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 5;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 2;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
# force_UL256qam_off = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
-1
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
# force_UL256qam_off = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
# force_UL256qam_off = 1;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
@@ -23,7 +23,6 @@ gNBs =
|
||||
pusch_AntennaPorts = 4;
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -21,7 +21,6 @@ gNBs =
|
||||
do_CSIRS = 1;
|
||||
do_SRS = 0;
|
||||
force_UL256qam_off = 1;
|
||||
# sib1_tda = 15;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
{
|
||||
|
||||
@@ -17,7 +17,6 @@ gNBs =
|
||||
|
||||
////////// Physical parameters:
|
||||
|
||||
sib1_tda = 15;
|
||||
min_rxtxtime = 6;
|
||||
|
||||
servingCellConfigCommon = (
|
||||
|
||||
Reference in New Issue
Block a user