mirror of
https://gitlab.eurecom.fr/oai/openairinterface5g.git
synced 2026-07-16 22:20:31 +00:00
Compare commits
12 Commits
develop
...
beams-logs
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e696734b18 | ||
|
|
5ed7833abe | ||
|
|
0612fe27c9 | ||
|
|
d0ca4982cd | ||
|
|
8aed7cd4ce | ||
|
|
9c711a9d9a | ||
|
|
ca3a624678 | ||
|
|
704c67a000 | ||
|
|
ccc8fe2dfa | ||
|
|
f0b23b853c | ||
|
|
ff6f0b3ced | ||
|
|
f22fe94756 |
@@ -50,7 +50,7 @@ gNBs =
|
||||
initialDLBWPsubcarrierSpacing = 3;
|
||||
#pdcch-ConfigCommon
|
||||
initialDLBWPcontrolResourceSetZero = 1;
|
||||
initialDLBWPsearchSpaceZero = 0;
|
||||
initialDLBWPsearchSpaceZero = 1;
|
||||
|
||||
#uplinkConfigCommon
|
||||
#frequencyInfoUL
|
||||
@@ -70,7 +70,7 @@ gNBs =
|
||||
initialULBWPsubcarrierSpacing = 3;
|
||||
#rach-ConfigCommon
|
||||
#rach-ConfigGeneric
|
||||
prach_ConfigurationIndex = 52;
|
||||
prach_ConfigurationIndex = 70;
|
||||
#prach_msg1_FDM
|
||||
#0 = one, 1=two, 2=four, 3=eight
|
||||
prach_msg1_FDM = 0;
|
||||
@@ -112,7 +112,7 @@ gNBs =
|
||||
hoppingId = 40;
|
||||
p0_nominal = -90;
|
||||
|
||||
ssb_PositionsInBurst_Bitmap = 1;
|
||||
ssb_PositionsInBurst_Bitmap = 85;
|
||||
|
||||
# ssb_periodicityServingCell
|
||||
# 0 = ms5, 1=ms10, 2=ms20, 3=ms40, 4=ms80, 5=ms160, 6=spare2, 7=spare1
|
||||
@@ -175,7 +175,7 @@ MACRLCs = ({
|
||||
set_analog_beamforming = 1;
|
||||
beam_duration = 1;
|
||||
beams_per_period = 1;
|
||||
beam_weights = [0]; // single SSB -> one analog beam
|
||||
beam_weights = [0, 1, 2, 3]; // single SSB -> one analog beam
|
||||
});
|
||||
|
||||
L1s = (
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -112,18 +112,17 @@ static void tx_func(processingData_L1tx_t *info)
|
||||
syncMsg->timestamp_tx = info->timestamp_tx;
|
||||
res->key = slot_rx;
|
||||
pushNotifiedFIFO(&gNB->resp_L1, res);
|
||||
processingData_RU_t syncMsgRU;
|
||||
syncMsgRU.frame_tx = frame_tx;
|
||||
syncMsgRU.slot_tx = slot_tx;
|
||||
syncMsgRU.ru = gNB->RU_list[0];
|
||||
syncMsgRU.timestamp_tx = info->timestamp_tx;
|
||||
ru_ctrl_func((void *)&syncMsgRU);
|
||||
|
||||
int tx_slot_type = nr_slot_select(cfg, frame_tx, slot_tx);
|
||||
if (tx_slot_type == NR_DOWNLINK_SLOT || tx_slot_type == NR_MIXED_SLOT || get_softmodem_params()->continuous_tx || IS_SOFTMODEM_RFSIM) {
|
||||
start_meas(&info->gNB->phy_proc_tx);
|
||||
phy_procedures_gNB_TX(info, frame_tx, slot_tx, 1);
|
||||
|
||||
PHY_VARS_gNB *gNB = info->gNB;
|
||||
processingData_RU_t syncMsgRU;
|
||||
syncMsgRU.frame_tx = frame_tx;
|
||||
syncMsgRU.slot_tx = slot_tx;
|
||||
syncMsgRU.ru = gNB->RU_list[0];
|
||||
syncMsgRU.timestamp_tx = info->timestamp_tx;
|
||||
LOG_D(PHY, "gNB: %d.%d : calling RU TX function\n", syncMsgRU.frame_tx, syncMsgRU.slot_tx);
|
||||
ru_tx_func((void *)&syncMsgRU);
|
||||
stop_meas(&info->gNB->phy_proc_tx);
|
||||
|
||||
@@ -714,7 +714,36 @@ static radio_tx_gpio_flag_t get_gpio_flags(RU_t *ru, int slot)
|
||||
return flags_gpio;
|
||||
}
|
||||
|
||||
void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
static void ctrl_rf(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
uint64_t beam_map = 0;
|
||||
for (int i = 0; i < ru->num_beams_period; i++) {
|
||||
int beam = -1;
|
||||
for (int j = 0; j < fp->symbols_per_slot; j++) {
|
||||
if (ru->common.beam_id[i][slot * fp->symbols_per_slot + j] == -1)
|
||||
continue;
|
||||
AssertFatal(beam == -1 || beam == ru->common.beam_id[i][slot * fp->symbols_per_slot + j],
|
||||
"Cannot handle more than 1 beam per slot");
|
||||
beam = ru->common.beam_id[i][slot * fp->symbols_per_slot + j];
|
||||
}
|
||||
if (beam != -1)
|
||||
beam_map += 1 << beam;
|
||||
}
|
||||
|
||||
// TODO in TX function we have timestamp + ru->ts_offset - sf_extension
|
||||
// do I need to do the same?
|
||||
if (beam_map != 0) {
|
||||
static uint64_t old_beam_map = 0;
|
||||
if (beam_map != old_beam_map) {
|
||||
LOG_I(HW, "frame %d slot %d, beam_map changed from 0x%lx to 0x%lx\n", frame, slot, old_beam_map, beam_map);
|
||||
old_beam_map = beam_map;
|
||||
}
|
||||
ru->rfdevice.trx_set_beams(&ru->rfdevice, beam_map, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_rf(RU_t *ru, int frame, int slot, uint64_t timestamp)
|
||||
{
|
||||
RU_proc_t *proc = &ru->proc;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
@@ -729,7 +758,6 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
int sf_extension = 0;
|
||||
int siglen=fp->get_samples_per_slot(slot,fp);
|
||||
radio_tx_burst_flag_t flags_burst = TX_BURST_INVALID;
|
||||
radio_tx_gpio_flag_t flags_gpio = 0;
|
||||
|
||||
if (cfg->cell_config.frame_duplex_type.value == TDD && !get_softmodem_params()->continuous_tx && !IS_SOFTMODEM_RFSIM) {
|
||||
int slot_type = nr_slot_select(cfg,frame,slot%fp->slots_per_frame);
|
||||
@@ -773,30 +801,31 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
flags_burst = proc->first_tx == 1 ? TX_BURST_START : TX_BURST_MIDDLE;
|
||||
}
|
||||
|
||||
if (ru->openair0_cfg.gpio_controller != RU_GPIO_CONTROL_NONE)
|
||||
flags_gpio = get_gpio_flags(ru, slot);
|
||||
|
||||
const int flags = flags_burst | (flags_gpio << 4);
|
||||
proc->first_tx = 0;
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_WRITE_FLAGS, flags_burst);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame);
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot);
|
||||
|
||||
int nt = ru->nb_tx * ru->num_beams_period;
|
||||
void *txp[nt];
|
||||
for (int i = 0; i < nt; i++)
|
||||
txp[i] = (void *)&ru->common.txdata[i][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
void **txpBeam[ru->num_beams_period];
|
||||
void *txp[ru->num_beams_period][ru->nb_tx];
|
||||
for (int b = 0; b < ru->num_beams_period; b++) {
|
||||
txpBeam[b] = txp[b];
|
||||
for (int i = 0; i < ru->nb_tx; i++)
|
||||
txp[b][i] = (void *)&ru->common.txdata[i * b][fp->get_samples_slot_timestamp(slot, fp, 0)] - sf_extension * sizeof(int32_t);
|
||||
}
|
||||
|
||||
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp + ru->ts_offset) & 0xffffffff);
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1);
|
||||
// prepare tx buffer pointers
|
||||
uint32_t txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
|
||||
timestamp + ru->ts_offset - sf_extension,
|
||||
txp,
|
||||
siglen + sf_extension,
|
||||
nt,
|
||||
flags);
|
||||
uint32_t txs = ru->rfdevice.trx_write_beams(&ru->rfdevice,
|
||||
timestamp + ru->ts_offset - sf_extension,
|
||||
(void ***)txpBeam,
|
||||
siglen + sf_extension,
|
||||
nt,
|
||||
1,
|
||||
flags_burst);
|
||||
LOG_D(PHY,
|
||||
"[TXPATH] RU %d tx_rf, writing to TS %lu, %d.%d, unwrapped_frame %d, slot %d, flags %d, siglen+sf_extension %d, "
|
||||
"returned %d, E %f\n",
|
||||
@@ -806,10 +835,10 @@ void tx_rf(RU_t *ru, int frame,int slot, uint64_t timestamp)
|
||||
slot,
|
||||
proc->frame_tx_unwrap,
|
||||
slot,
|
||||
flags,
|
||||
flags_burst,
|
||||
siglen + sf_extension,
|
||||
txs,
|
||||
10 * log10((double)signal_energy(txp[0], siglen + sf_extension)));
|
||||
10 * log10((double)signal_energy(txp[0][0], siglen + sf_extension)));
|
||||
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0);
|
||||
}
|
||||
|
||||
@@ -965,6 +994,25 @@ int setup_RU_buffers(RU_t *ru)
|
||||
return(0);
|
||||
}
|
||||
|
||||
void ru_ctrl_func(void *param)
|
||||
{
|
||||
processingData_RU_t *info = (processingData_RU_t *) param;
|
||||
int frame = info->frame_tx;
|
||||
int slot = info->slot_tx;
|
||||
LOG_D(PHY,"ru_ctrl_func: frame = %d, slot = %d\n", frame, slot);
|
||||
RU_t *ru = info->ru;
|
||||
NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->num_beams_period; i++) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot * fp->symbols_per_slot],
|
||||
(void*) &ru->gNB_list[0]->common_vars.beam_id[i][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
if (ru->fh_south_ctrl)
|
||||
ru->fh_south_ctrl(ru, frame, slot, info->timestamp_tx);
|
||||
}
|
||||
|
||||
void ru_tx_func(void *param)
|
||||
{
|
||||
processingData_RU_t *info = (processingData_RU_t *) param;
|
||||
@@ -1498,6 +1546,7 @@ void set_function_spec_param(RU_t *ru)
|
||||
ru->rfdevice.host_type = RAU_HOST;
|
||||
ru->fh_south_in = rx_rf; // local synchronous RF RX
|
||||
ru->fh_south_out = tx_rf; // local synchronous RF TX
|
||||
ru->fh_south_ctrl = ctrl_rf; // local sunchronous RF control
|
||||
ru->start_rf = start_rf; // need to start the local RF interface
|
||||
ru->stop_rf = stop_rf;
|
||||
ru->start_write_thread = start_write_thread; // starting RF TX in different thread
|
||||
|
||||
@@ -574,7 +574,8 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
const int maxWriteBlockSize = fp->get_samples_per_slot(proc->nr_slot_tx, fp);
|
||||
while (writeBlockSize > maxWriteBlockSize) {
|
||||
const int dummyBlockSize = min(writeBlockSize - maxWriteBlockSize, maxWriteBlockSize);
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, dummyBlockSize, fp->nb_antennas_tx, flags);
|
||||
void **tx = (void **)txp;
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, &tx, dummyBlockSize, fp->nb_antennas_tx, 1, flags);
|
||||
AssertFatal(tmp == dummyBlockSize, "");
|
||||
|
||||
writeTimestamp += dummyBlockSize;
|
||||
@@ -589,8 +590,8 @@ static void RU_write(nr_rxtx_thread_data_t *rxtxD, bool sl_tx_action, c16_t **tx
|
||||
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);
|
||||
}
|
||||
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, (void **)txp, writeBlockSize, fp->nb_antennas_tx, flags);
|
||||
void **tx = (void **)txp;
|
||||
int tmp = openair0_write_reorder(&UE->rfdevice, writeTimestamp, &tx, writeBlockSize, fp->nb_antennas_tx, 1, flags);
|
||||
AssertFatal(tmp == writeBlockSize, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -354,7 +354,7 @@ extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
|
||||
extern int usrp_tx_thread;
|
||||
extern int sf_ahead;
|
||||
extern int oai_exit;
|
||||
|
||||
void ru_ctrl_func(void *param);
|
||||
void ru_tx_func(void *param);
|
||||
void configure_ru(void *, void *arg);
|
||||
void configure_rru(void *, void *arg);
|
||||
|
||||
@@ -220,9 +220,11 @@ void nr_ue_ssb_rsrp_measurements(PHY_VARS_NR_UE *ue,
|
||||
int SNRtimes10 = dB_fixed_x10(signal_pwr) - dB_fixed_x10(ue->measurements.n0_power_avg);
|
||||
ue->measurements.ssb_sinr_dB[ssb_index] = SNRtimes10 / 10.0;
|
||||
|
||||
LOG_D(PHY,
|
||||
"[UE %d] ssb %d SS-RSRP: %d dBm/RE (%f dB/RE), SS-SINR: %f dB\n",
|
||||
LOG_I(PHY,
|
||||
"[UE %d] frame.slot %d.%d ssb %d SS-RSRP: %d dBm/RE (%f dB/RE), SS-SINR: %f dB\n",
|
||||
ue->Mod_id,
|
||||
proc->frame_rx,
|
||||
proc->nr_slot_rx,
|
||||
ssb_index,
|
||||
ue->measurements.ssb_rsrp_dBm[ssb_index],
|
||||
rsrp_db_per_re,
|
||||
|
||||
@@ -533,6 +533,8 @@ typedef struct RU_t_s {
|
||||
void (*fh_south_in)(struct RU_t_s *ru, int *frame, int *subframe);
|
||||
/// function pointer to synchronous TX fronthaul function
|
||||
void (*fh_south_out)(struct RU_t_s *ru, int frame_tx, int tti_tx, uint64_t timestamp_tx);
|
||||
/// function pointer to synchronous control fronthaul function
|
||||
void (*fh_south_ctrl)(struct RU_t_s *ru, int frame, int slot, uint64_t timestamp);
|
||||
/// function pointer to synchronous RX fronthaul function (RRU)
|
||||
void (*fh_north_in)(struct RU_t_s *ru, int *frame, int *subframe);
|
||||
/// function pointer to synchronous RX fronthaul function (RRU)
|
||||
|
||||
@@ -188,14 +188,6 @@ 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;
|
||||
|
||||
if (gNB->common_vars.analog_bf) {
|
||||
for (int i = 0; i < ru->num_beams_period; i++) {
|
||||
memcpy((void*) &ru->common.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(void*) &gNB->common_vars.beam_id[i][slot_tx * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
}
|
||||
|
||||
// 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++) {
|
||||
@@ -234,12 +226,6 @@ void nr_feptx(void *arg)
|
||||
if (tx_idx == 0)
|
||||
start_meas(&ru->precoding_stats);
|
||||
|
||||
if (ru->gNB_list[0]->common_vars.analog_bf) {
|
||||
memcpy(&ru->common.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
&ru->gNB_list[0]->common_vars.beam_id[bb][slot * fp->symbols_per_slot],
|
||||
(fp->symbols_per_slot) * sizeof(int));
|
||||
}
|
||||
|
||||
// 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)
|
||||
memcpy((void*)&ru->common.txdataF_BF[tx_idx][txdataF_BF_offset],
|
||||
|
||||
@@ -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[] = {
|
||||
@@ -1701,7 +1701,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)
|
||||
@@ -2034,7 +2034,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__);
|
||||
@@ -2116,7 +2116,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);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
@@ -175,7 +175,8 @@ int openair0_transport_load(openair0_device *device,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void writerEnqueue(re_order_t *ctx, openair0_timestamp timestamp, void **txp, int nsamps, int nbAnt, int flags)
|
||||
static void
|
||||
writerEnqueue(re_order_t *ctx, openair0_timestamp timestamp, void ***txp, int nsamps, int nbAnt, int num_beams, int flags)
|
||||
{
|
||||
pthread_mutex_lock(&ctx->mutex_store);
|
||||
LOG_D(HW, "Enqueue write for TS: %lu\n", timestamp);
|
||||
@@ -187,9 +188,11 @@ static void writerEnqueue(re_order_t *ctx, openair0_timestamp timestamp, void **
|
||||
ctx->queue[i].nsamps = nsamps;
|
||||
ctx->queue[i].nbAnt = nbAnt;
|
||||
ctx->queue[i].flags = flags;
|
||||
ctx->queue[i].num_beams = num_beams;
|
||||
AssertFatal(nbAnt <= NB_ANTENNAS_TX, "");
|
||||
for (int j = 0; j < nbAnt; j++)
|
||||
ctx->queue[i].txp[j] = txp[j];
|
||||
for (int b = 0; b < num_beams; b++)
|
||||
for (int j = 0; j < nbAnt; j++)
|
||||
ctx->queue[i].txp[b][j] = txp[b][j];
|
||||
break;
|
||||
}
|
||||
AssertFatal(i < WRITE_QUEUE_SZ, "Write queue full\n");
|
||||
@@ -210,15 +213,19 @@ static void writerProcessWaitingQueue(openair0_device *device)
|
||||
int nsamps = ctx->queue[i].nsamps;
|
||||
int nbAnt = ctx->queue[i].nbAnt;
|
||||
int flags = ctx->queue[i].flags;
|
||||
void *txp[NB_ANTENNAS_TX];
|
||||
AssertFatal(nbAnt <= NB_ANTENNAS_TX, "");
|
||||
for (int j = 0; j < nbAnt; j++)
|
||||
txp[j] = ctx->queue[i].txp[j];
|
||||
int num_beams = ctx->queue[i].num_beams;
|
||||
void **txpBeams[num_beams];
|
||||
void *txp[num_beams][nbAnt];
|
||||
for (int b = 0; b < num_beams; b++) {
|
||||
txpBeams[b] = txp[b];
|
||||
for (int j = 0; j < nbAnt; j++)
|
||||
txp[b][j] = ctx->queue[i].txp[b][j];
|
||||
}
|
||||
ctx->queue[i].active = false;
|
||||
pthread_mutex_unlock(&ctx->mutex_store);
|
||||
found = true;
|
||||
if (flags || IS_SOFTMODEM_RFSIM) {
|
||||
int wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags);
|
||||
int wroteSamples = device->trx_write_beams(device, timestamp, txpBeams, nsamps, nbAnt, num_beams, flags);
|
||||
if (wroteSamples != nsamps)
|
||||
LOG_E(HW, "Failed to write to rf\n");
|
||||
}
|
||||
@@ -235,7 +242,13 @@ static void writerProcessWaitingQueue(openair0_device *device)
|
||||
// but to make zerocopy and agnostic design, we need to make a proper ring buffer with mutex protection
|
||||
// mutex (or atomic flags) will be mandatory because this out order system root cause is there are several writer threads
|
||||
|
||||
int openair0_write_reorder(openair0_device *device, openair0_timestamp timestamp, void **txp, int nsamps, int nbAnt, int flags)
|
||||
int openair0_write_reorder(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void ***txp,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int num_beams,
|
||||
int flags)
|
||||
{
|
||||
int wroteSamples = 0;
|
||||
re_order_t *ctx = &device->reOrder;
|
||||
@@ -250,19 +263,19 @@ int openair0_write_reorder(openair0_device *device, openair0_timestamp timestamp
|
||||
// We have the write exclusivity
|
||||
if (llabs(timestamp - ctx->nextTS) < MAX_GAP) { // We are writing in sequence of the previous write
|
||||
if (flags || IS_SOFTMODEM_RFSIM)
|
||||
wroteSamples = device->trx_write_func(device, timestamp, txp, nsamps, nbAnt, flags);
|
||||
wroteSamples = device->trx_write_beams(device, timestamp, txp, nsamps, nbAnt, num_beams, flags);
|
||||
else
|
||||
wroteSamples = nsamps;
|
||||
ctx->nextTS = timestamp + nsamps;
|
||||
|
||||
} else {
|
||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, num_beams, flags);
|
||||
}
|
||||
writerProcessWaitingQueue(device);
|
||||
pthread_mutex_unlock(&ctx->mutex_write);
|
||||
return wroteSamples ? wroteSamples : nsamps;
|
||||
}
|
||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, flags);
|
||||
writerEnqueue(ctx, timestamp, txp, nsamps, nbAnt, num_beams, flags);
|
||||
if (pthread_mutex_trylock(&ctx->mutex_write) == 0) {
|
||||
writerProcessWaitingQueue(device);
|
||||
pthread_mutex_unlock(&ctx->mutex_write);
|
||||
|
||||
@@ -401,9 +401,10 @@ typedef struct {
|
||||
struct {
|
||||
bool active;
|
||||
openair0_timestamp timestamp;
|
||||
void *txp[NB_ANTENNAS_TX];
|
||||
void *txp[64][NB_ANTENNAS_TX];
|
||||
int nsamps;
|
||||
int nbAnt;
|
||||
int num_beams;
|
||||
int flags;
|
||||
} queue[WRITE_QUEUE_SZ];
|
||||
} re_order_t;
|
||||
@@ -493,10 +494,27 @@ struct openair0_device_t {
|
||||
@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 number of antennas
|
||||
@param antenna_id
|
||||
@param num_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)(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void ***buff,
|
||||
int nsamps,
|
||||
int antenna_id,
|
||||
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 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 antenna_id, 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 +536,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 +609,21 @@ 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 RRU Configuration callback
|
||||
* \param idx RU index
|
||||
* \param arg pointer to capabilities or configuration
|
||||
@@ -629,6 +682,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
|
||||
@@ -678,7 +732,13 @@ extern int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **r
|
||||
/*! \brief store recorded iqs from memory to file. */
|
||||
extern void iqrecorder_end(openair0_device *device);
|
||||
|
||||
int openair0_write_reorder(openair0_device *device, openair0_timestamp timestamp, void **txp, int nsamps, int nbAnt, int flags);
|
||||
int openair0_write_reorder(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void ***txp,
|
||||
int nsamps,
|
||||
int nbAnt,
|
||||
int num_beams,
|
||||
int flags);
|
||||
void openair0_write_reorder_clear_context(openair0_device *device);
|
||||
#include <unistd.h>
|
||||
#ifndef gettid
|
||||
|
||||
@@ -423,12 +423,15 @@ static void trx_usrp_end(openair0_device *device) {
|
||||
@param antenna_id index of the antenna if the device has multiple antennas
|
||||
@param flags flags must be set to true if timestamp parameter needs to be applied
|
||||
*/
|
||||
static int trx_usrp_write(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void **buff,
|
||||
int nsamps,
|
||||
int cc,
|
||||
int flags) {
|
||||
|
||||
static int usrp_write_beams(openair0_device *device,
|
||||
openair0_timestamp timestamp,
|
||||
void ***buff,
|
||||
int nsamps,
|
||||
int cc,
|
||||
int num_beams,
|
||||
int flags)
|
||||
{
|
||||
int ret=0;
|
||||
usrp_state_t *s = (usrp_state_t *)device->priv;
|
||||
timestamp -= device->openair0_cfg->command_line_sample_advance + device->openair0_cfg->tx_sample_advance;
|
||||
@@ -481,10 +484,10 @@ static int trx_usrp_write(openair0_device *device,
|
||||
// bring RX data into 12 LSBs for softmodem RX
|
||||
for (int i = 0; i < cc; i++) {
|
||||
for (int j = 0; j < nsamps2; j++) {
|
||||
if ((((uintptr_t)buff[i]) & 0x1F) == 0) {
|
||||
buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[i])[j], 4);
|
||||
if ((((uintptr_t)buff[0][i]) & 0x1F) == 0) {
|
||||
buff_tx[i][j] = simde_mm256_slli_epi16(((simde__m256i *)buff[0][i])[j], 4);
|
||||
} else {
|
||||
simde__m256i tmp = simde_mm256_loadu_si256(((simde__m256i *)buff[i]) + j);
|
||||
simde__m256i tmp = simde_mm256_loadu_si256(((simde__m256i *)buff[0][i]) + j);
|
||||
buff_tx[i][j] = simde_mm256_slli_epi16(tmp, 4);
|
||||
}
|
||||
}
|
||||
@@ -541,7 +544,7 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
|
||||
write_package[end].last_packet = last_packet_state;
|
||||
write_package[end].flags_gpio = flags_gpio;
|
||||
for (int i = 0; i < cc; i++)
|
||||
write_package[end].buff[i] = buff[i];
|
||||
write_package[end].buff[i] = buff[0][i];
|
||||
write_thread->count_write++;
|
||||
write_thread->end = (write_thread->end + 1) % MAX_WRITE_THREAD_PACKAGE;
|
||||
LOG_D(HW, "Signaling TX TS %llu\n", (unsigned long long)timestamp);
|
||||
@@ -550,7 +553,11 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags)
|
||||
{
|
||||
void **tmp = buff;
|
||||
return usrp_write_beams(device, timestamp, &tmp, nsamps, cc, 1, flags);
|
||||
}
|
||||
//-----------------------start--------------------------
|
||||
/*! \brief Called to send samples to the USRP RF target
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
@@ -1537,6 +1544,7 @@ extern "C" {
|
||||
std::cout << boost::format("Using Device: %s") % s->usrp->get_pp_string() << std::endl;
|
||||
LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
|
||||
device->trx_write_func = trx_usrp_write;
|
||||
device->trx_write_beams = usrp_write_beams;
|
||||
device->trx_read_func = trx_usrp_read;
|
||||
s->sample_rate = openair0_cfg[0].sample_rate;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
add_library(rfsimulator MODULE
|
||||
simulator.c
|
||||
simulator.cpp
|
||||
apply_channelmod.c
|
||||
../../openair1/PHY/TOOLS/signal_energy.c
|
||||
)
|
||||
|
||||
@@ -1,26 +1,25 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Author and copyright: Laurent Thomas, open-cells.com
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
#include <complex.h>
|
||||
#include <common/utils/LOG/log.h>
|
||||
@@ -42,22 +41,23 @@
|
||||
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,
|
||||
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)
|
||||
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 +78,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;
|
||||
@@ -124,9 +124,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);
|
||||
}
|
||||
@@ -183,9 +191,17 @@ 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);
|
||||
}
|
||||
}
|
||||
@@ -195,36 +211,28 @@ void rxAddInput(const c16_t *input_sig,
|
||||
// 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) {
|
||||
@@ -246,12 +254,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(const c16_t **input_sig,
|
||||
cf_t *after_channel_sig,
|
||||
int rxAnt,
|
||||
channel_desc_t *channelDesc,
|
||||
int nbSamples,
|
||||
uint64_t TS);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user