diff --git a/common/utils/telnetsrv/telnetsrv.c b/common/utils/telnetsrv/telnetsrv.c index aab8c843685c524778c66aeb2b96671927578620..cbabc1d1ad51234027135e1bb1bbafd5943de3e8 100644 --- a/common/utils/telnetsrv/telnetsrv.c +++ b/common/utils/telnetsrv/telnetsrv.c @@ -510,7 +510,7 @@ int process_command(char *buf) { cmddata->cmdfunc=(qcmdfunc_t)telnetparams.CmdParsers[i].cmd[k].cmdfunc; cmddata->prnt=client_printf; cmddata->debug=telnetparams.telnetdbg; - cmddata->cmdbuff=strdup(cmdb); + cmddata->cmdbuff=cmdb ? strdup(cmdb) : NULL; pushNotifiedFIFO(telnetparams.CmdParsers[i].cmd[k].qptr, msg); } else { telnetparams.CmdParsers[i].cmd[k].cmdfunc(cmdb, telnetparams.telnetdbg, client_printf); @@ -845,33 +845,42 @@ int telnetsrv_autoinit(void) { * function at init time. the telnet server is delivered with a set of commands which * will be loaded or not depending on the telnet section of the config file */ -int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd) { - int i; - notifiedFIFO_t *afifo=NULL; - +int add_telnetcmd(char *modulename, telnetshell_vardef_t *var, telnetshell_cmddef_t *cmd) +{ if( modulename == NULL || var == NULL || cmd == NULL) { fprintf(stderr,"[TELNETSRV] Telnet server, add_telnetcmd: invalid parameters\n"); return -1; } + int i; for (i=0; i<TELNET_MAXCMD ; i++) { - if (telnetparams.CmdParsers[i].var == NULL) { - strncpy(telnetparams.CmdParsers[i].module,modulename,sizeof(telnetparams.CmdParsers[i].module)-1); - telnetparams.CmdParsers[i].cmd = cmd; - telnetparams.CmdParsers[i].var = var; - if (cmd->cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { - if (afifo == NULL) { - afifo = malloc(sizeof(notifiedFIFO_t)); - initNotifiedFIFO(afifo); - } - cmd->qptr = afifo; - } + cmdparser_t *CmdParser = &telnetparams.CmdParsers[i]; + if (CmdParser->var == NULL) { + strncpy(CmdParser->module, modulename, sizeof(CmdParser->module) - 1); + CmdParser->cmd = cmd; + CmdParser->var = var; printf("[TELNETSRV] Telnet server: module %i = %s added to shell\n", - i,telnetparams.CmdParsers[i].module); + i, CmdParser->module); break; } } + if (i == TELNET_MAXCMD) { + fprintf(stderr, "[TELNETSRV] TELNET_MAXCMD reached, cannot add new module %s\n", modulename); + return -1; + } + + notifiedFIFO_t *afifo = NULL; + for (int k = 0; cmd[k].cmdfunc != NULL ; k++) { + if (cmd[k].cmdflags & TELNETSRV_CMDFLAG_PUSHINTPOOLQ) { + if (afifo == NULL) { + afifo = malloc(sizeof(notifiedFIFO_t)); + initNotifiedFIFO(afifo); + } + cmd[k].qptr = afifo; + } + } + return 0; } diff --git a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c index a8925a2df9e894c45dd88ec3411b84742a50baf5..969521b3c5c02a34db8617c44c0488a450b65bd6 100644 --- a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c +++ b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c @@ -58,12 +58,14 @@ void measurcmd_display_rlcstats(telnet_printfunc_t prnt); void measurcmd_display_phycpu(telnet_printfunc_t prnt); void measurcmd_display_maccpu(telnet_printfunc_t prnt); void measurcmd_display_pdcpcpu(telnet_printfunc_t prnt); +void measurcmd_display_phyta(telnet_printfunc_t prnt); static telnet_measurgroupdef_t nrUEmeasurgroups[] = { // {"ue", GROUP_LTESTATS,0, measurcmd_display_macstats, {NULL}}, // {"rlc", GROUP_LTESTATS,0, measurcmd_display_rlcstats, {NULL}}, {"phycpu",GROUP_CPUSTATS,0, measurcmd_display_phycpu, {NULL}}, + {"phyta", GROUP_CPUSTATS, 0, measurcmd_display_phyta, {NULL}}, // {"maccpu",GROUP_CPUSTATS,0, measurcmd_display_maccpu, {NULL}}, // {"pdcpcpu",GROUP_CPUSTATS,0, measurcmd_display_pdcpcpu, {NULL}}, }; @@ -89,6 +91,17 @@ void measurcmd_display_phycpu(telnet_printfunc_t prnt) { PRINT_CPUMEAS_STATE,HDR); measurcmd_display_cpumeasures(prnt, cpumeasur, sizeof(cpumeasur)/sizeof(telnet_cpumeasurdef_t)); } +void measurcmd_display_phyta(telnet_printfunc_t prnt) +{ + PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0]; + prnt("%s PHY TA stats\n", HDR); + prnt("N_TA_offset %d\n", UE->N_TA_offset); + for (int i = 0; i < UE->n_connected_gNB; ++i) { + NR_UL_TIME_ALIGNMENT_t *ta = &UE->ul_time_alignment[i]; + prnt("gNB %d TA command %d TA total %d TAG ID %d\n", i, ta->ta_command, ta->ta_total, ta->tag_id); + } + prnt("timing_advance %d (samples)\n", UE->timing_advance); +} /* void measurcmd_display_maccpu(telnet_printfunc_t prnt) { eNB_MAC_INST *macvars = RC.mac[eNB_id]; diff --git a/executables/nr-ru.c b/executables/nr-ru.c index 71e7a4f4b1f18b6ded46eac09f32978ff2cbacb8..cbc351511d74f75c3c22e70ee15ffbaf45a311ce 100644 --- a/executables/nr-ru.c +++ b/executables/nr-ru.c @@ -865,12 +865,13 @@ void fill_rf_config(RU_t *ru, char *rf_config_file) { cfg->tx_gain[i] = ru->att_tx; cfg->rx_gain[i] = ru->max_rxgain-ru->att_rx; cfg->configFilename = rf_config_file; - LOG_I(PHY, "Channel %d: setting tx_gain offset %.0f, rx_gain offset %.0f, tx_freq %.0f Hz, rx_freq %.0f Hz, tune_offset %.0f Hz\n", + LOG_I(PHY, "Channel %d: setting tx_gain offset %.0f, rx_gain offset %.0f, tx_freq %.0f Hz, rx_freq %.0f Hz, tune_offset %.0f Hz, sample_rate %.0f Hz\n", i, cfg->tx_gain[i], cfg->rx_gain[i], cfg->tx_freq[i], cfg->rx_freq[i], - cfg->tune_offset); + cfg->tune_offset, + cfg->sample_rate); } } diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c index aef01413eeece7ffcd607e45d4530c8083d5d505..b3613c9d627885ac5262742fb10de2278fdb264d 100644 --- a/openair1/PHY/INIT/nr_parms.c +++ b/openair1/PHY/INIT/nr_parms.c @@ -193,8 +193,8 @@ void set_scs_parameters (NR_DL_FRAME_PARMS *fp, int mu, int N_RB_DL) fp->first_carrier_offset = fp->ofdm_symbol_size - (N_RB_DL * 12 / 2); fp->nb_prefix_samples = fp->ofdm_symbol_size / 128 * 9; fp->nb_prefix_samples0 = fp->ofdm_symbol_size / 128 * (9 + (1 << mu)); - LOG_I(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d\n", - N_RB_DL,fp->first_carrier_offset,fp->nb_prefix_samples,fp->nb_prefix_samples0); + LOG_W(PHY,"Init: N_RB_DL %d, first_carrier_offset %d, nb_prefix_samples %d,nb_prefix_samples0 %d, ofdm_symbol_size %d\n", + N_RB_DL,fp->first_carrier_offset,fp->nb_prefix_samples,fp->nb_prefix_samples0, fp->ofdm_symbol_size); } uint32_t get_samples_per_slot(int slot, NR_DL_FRAME_PARMS* fp) @@ -417,6 +417,8 @@ void nr_init_frame_parms_ue_sa(NR_DL_FRAME_PARMS *frame_parms, uint64_t downlink frame_parms->get_samples_slot_timestamp = &get_samples_slot_timestamp; frame_parms->samples_per_frame = 10 * frame_parms->samples_per_subframe; + LOG_W(PHY, "samples_per_subframe %d/per second %d, wCP %d\n", frame_parms->samples_per_subframe, 1000*frame_parms->samples_per_subframe, frame_parms->samples_per_subframe_wCP); + } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 6febce47066d9096934f835d284f0516fd447258..bbe2a1dfcdbc551edf185a4de367b7263e60722b 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -642,6 +642,7 @@ typedef struct NR_UL_TIME_ALIGNMENT { char ta_slot; /// TA command and TAGID received from the gNB uint16_t ta_command; + uint32_t ta_total; uint8_t tag_id; } NR_UL_TIME_ALIGNMENT_t; diff --git a/openair1/SIMULATION/TOOLS/random_channel.c b/openair1/SIMULATION/TOOLS/random_channel.c index 5884348a78c466d0517370a68473a2125e254277..17d34fed1a538a7362bf3924216e6eb12571b013 100644 --- a/openair1/SIMULATION/TOOLS/random_channel.c +++ b/openair1/SIMULATION/TOOLS/random_channel.c @@ -1944,9 +1944,10 @@ static int channelmod_show_cmd(char *buff, int debug, telnet_printfunc_t prnt) { } else if ( strcmp(subcmd,"current") == 0) { for (int i=0; i < max_chan ; i++) { if (defined_channels[i] != NULL) { - prnt("model %i %s type %s: \n----------------\n", i, (defined_channels[i]->model_name !=NULL)?defined_channels[i]->model_name:"(no name set)", + prnt("model %i %s type %s:\n", i, (defined_channels[i]->model_name !=NULL)?defined_channels[i]->model_name:"(no name set)", map_int_to_str(channelmod_names,defined_channels[i]->modelid)); display_channelmodel(defined_channels[i],debug,prnt); + prnt("----------------\n"); } } } else { diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c index 161cdb7079a82afe2a6b63829e1f09b375deacc0..76f43eab5840ba00c6cd74d2f9d515c55fc42a6b 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c @@ -3699,9 +3699,12 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, /*uint8_t ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; uint8_t tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID;*/ + const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; + const int tag = ((NR_MAC_CE_TA *)pduP)[1].TAGID; ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND; - ul_time_alignment->tag_id = ((NR_MAC_CE_TA *)pduP)[1].TAGID; + ul_time_alignment->ta_command = ta; //here + ul_time_alignment->ta_total += ta - 31; + ul_time_alignment->tag_id = tag; /* #ifdef DEBUG_HEADER_PARSING @@ -3709,7 +3712,10 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info, #endif */ - LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d\n", frameP, slot, ul_time_alignment->ta_command, ul_time_alignment->tag_id, CC_id); + if (ta == 31) + LOG_D(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total); + else + LOG_I(NR_MAC, "[%d.%d] Received TA_COMMAND %u TAGID %u CC_id %d TA total %d\n", frameP, slot, ta, tag, CC_id, ul_time_alignment->ta_total); break; case DL_SCH_LCID_CON_RES_ID: @@ -4082,7 +4088,10 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t // TA command ul_time_alignment->apply_ta = 1; - ul_time_alignment->ta_command = 31 + rar->TA2 + (rar->TA1 << 5); + const int ta = rar->TA2 + (rar->TA1 << 5); + ul_time_alignment->ta_command = 31 + ta; + ul_time_alignment->ta_total = ta; + LOG_W(MAC, "received TA command %d\n", ul_time_alignment->ta_command); #ifdef DEBUG_RAR // CSI diff --git a/sdr/rfsimulator/apply_channelmod.c b/sdr/rfsimulator/apply_channelmod.c index 5cb16803bbf3ee4d4b0fe28fff76d4420abdf513..42ae11e6b13c6dffb0279112869b257105f4d210 100644 --- a/sdr/rfsimulator/apply_channelmod.c +++ b/sdr/rfsimulator/apply_channelmod.c @@ -68,13 +68,11 @@ void rxAddInput( const c16_t *input_sig, // 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 = pow(10,channelDesc->noise_power_dB/10.0) * 256; - // Fixme: we don't fill the offset length samples at begining ? - // anyway, in today code, channel_offset=0 const int dd = abs(channelDesc->channel_offset); const int nbTx=channelDesc->nb_tx; - for (int i=0; i<((int)nbSamples-dd); i++) { - c16_t *out_ptr=after_channel_sig+dd+i; + for (int i=0; i<nbSamples; i++) { + struct complex16 *out_ptr=after_channel_sig+i; struct complexd rx_tmp= {0}; for (int txAnt=0; txAnt < nbTx; txAnt++) { @@ -88,7 +86,9 @@ void rxAddInput( const c16_t *input_sig, // 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 - c16_t tx16=input_sig[((TS+i-l)*nbTx+txAnt)%CirSize]; + // (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]; 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 diff --git a/sdr/rfsimulator/simulator.c b/sdr/rfsimulator/simulator.c index a395f3ca8561617d3b699708bf573dfaf37aee20..b9b2223bdb7e22a47ec32d983d70c8b389804544 100644 --- a/sdr/rfsimulator/simulator.c +++ b/sdr/rfsimulator/simulator.c @@ -90,8 +90,14 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); +static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg); static telnetshell_cmddef_t rfsimu_cmdarray[] = { {"setmodel","<model name> <model type>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"setdistance","<model name> <distance>", (cmdfunc_t)rfsimu_setdistance_cmd, TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"getdistance","<model name>", (cmdfunc_t) rfsimu_getdistance_cmd, TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, + {"vtime","", (cmdfunc_t) rfsimu_vtime_cmd, TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, {"","",NULL}, }; @@ -369,6 +375,164 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, return CMDSTATUS_FOUND; } +//static void print_cirBuf(struct complex16 *circularBuf, +// uint64_t firstSample, +// uint32_t cirSize, +// int neg, +// int pos, +// int nbTx) +//{ +// for (int i = -neg; i < pos ; ++i) { +// for (int txAnt = 0; txAnt < nbTx; txAnt++) { +// const int idx = ((firstSample + i) * nbTx + txAnt + cirSize) % cirSize; +// if (i == 0) +// printf("->"); +// printf("%08x%08x\n", circularBuf[idx].r, circularBuf[idx].i); +// } +// } +// printf("\n"); +//} + +static void rfsimu_offset_change_cirBuf(struct complex16 *circularBuf, + uint64_t firstSample, + uint32_t cirSize, + int old_offset, + int new_offset, + int nbTx) +{ + //int start = max(new_offset, old_offset) + 10; + //int end = 10; + //printf("new_offset %d old_offset %d start %d end %d\n", new_offset, old_offset, start, end); + //printf("ringbuffer before:\n"); + //print_cirBuf(circularBuf, firstSample, cirSize, start, end, nbTx); + + int doffset = new_offset - old_offset; + if (doffset > 0) { + /* Moving away, creating a gap. We need to insert "zero" samples between + * the previous (end of the) slot and the new slot (at the ringbuffer + * index) to prevent that the receiving side detects things that are not + * in the channel (e.g., samples that have already been delivered). */ + for (int i = new_offset; i > 0; --i) { + for (int txAnt = 0; txAnt < nbTx; txAnt++) { + const int newidx = ((firstSample - i) * nbTx + txAnt + cirSize) % cirSize; + if (i > doffset) { + // shift samples not read yet + const int oldidx = (newidx + doffset) % cirSize; + circularBuf[newidx] = circularBuf[oldidx]; + } else { + // create zero samples between slots + const struct complex16 nullsample = {0, 0}; + circularBuf[newidx] = nullsample; + } + } + } + } else { + /* Moving closer, creating overlap between samples. For simplicity, we + * simply drop `doffset` samples at the end of the previous slot + * (this is, in a sense, arbitrary). In a real channel, there would be + * some overlap between samples, e.g., for `doffset == 1` we could add + * two samples. I think that we cannot do that for multiple samples, + * though, and so we just drop some */ + // drop the last -doffset samples of the previous slot + for (int i = old_offset; i > -doffset; --i) { + for (int txAnt = 0; txAnt < nbTx; txAnt++) { + const int oldidx = ((firstSample - i) * nbTx + txAnt + cirSize) % cirSize; + const int newidx = (oldidx - doffset) % cirSize; + circularBuf[newidx] = circularBuf[oldidx]; + } + } + } + + //printf("ringbuffer after:\n"); + //print_cirBuf(circularBuf, firstSample, cirSize, start, end, nbTx); +} + +static int rfsimu_setdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) +{ + if (debug) + prnt("%s() buffer \"%s\"\n", __func__, buff); + + char *modelname; + int distance; + int s = sscanf(buff,"%m[^ ] %d\n", &modelname, &distance); + if (s != 2) { + prnt("require exact two parameters\n"); + return CMDSTATUS_VARNOTFOUND; + } + + rfsimulator_state_t *t = (rfsimulator_state_t *)arg; + const double sample_rate = t->sample_rate; + const double c = 299792458; /* 3e8 */ + + const int new_offset = (double) distance * sample_rate / c; + const double new_distance = (double) new_offset * c / sample_rate; + + prnt("\nnew_offset %d new (exact) distance %.3f m\n", new_offset, new_distance); + + /* Set distance in rfsim and channel model, update channel and ringbuffer */ + for (int i=0; i<FD_SETSIZE; i++) { + buffer_t *b=&t->buf[i]; + if (b->conn_sock <= 0 + || b->channel_model == NULL + || b->channel_model->model_name == NULL + || strcmp(b->channel_model->model_name, modelname) != 0) + continue; + + channel_desc_t *cd = b->channel_model; + const int old_offset = cd->channel_offset; + cd->channel_offset = new_offset; + + const int nbTx = cd->nb_tx; + rfsimu_offset_change_cirBuf(b->circularBuf, t->nextRxTstamp, CirSize, old_offset, new_offset, nbTx); + } + + free(modelname); + + return CMDSTATUS_FOUND; +} + +static int rfsimu_getdistance_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) +{ + if (debug) + prnt("%s() buffer \"%s\"\n", __func__, buff); + + char *modelname; + int s = sscanf(buff,"%ms\n", &modelname); + if (s != 1) { + prnt("require exact two parameters\n"); + return CMDSTATUS_VARNOTFOUND; + } + + rfsimulator_state_t *t = (rfsimulator_state_t *)arg; + const double sample_rate = t->sample_rate; + const double c = 299792458; /* 3e8 */ + + for (int i=0; i<FD_SETSIZE; i++) { + buffer_t *b=&t->buf[i]; + if (b->conn_sock <= 0 + || b->channel_model == NULL + || b->channel_model->model_name == NULL + || strcmp(b->channel_model->model_name, modelname) != 0) + continue; + + channel_desc_t *cd = b->channel_model; + const int offset = cd->channel_offset; + const double distance = (double) offset * c / sample_rate; + prnt("\noffset %d distance %.3f m\n", offset, distance); + } + + return CMDSTATUS_FOUND; +} + +static int rfsimu_vtime_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg) +{ + rfsimulator_state_t *t = (rfsimulator_state_t *)arg; + const openair0_timestamp ts = t->nextRxTstamp; + const double sample_rate = t->sample_rate; + prnt("vtime measurement: TS %llu sample_rate %.3f\n", ts, sample_rate); + return CMDSTATUS_FOUND; +} + static int startServer(openair0_device *device) { rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv; t->typeStamp=ENB_MAGICDL; @@ -772,6 +936,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { rfsimulator->sample_rate=openair0_cfg->sample_rate; rfsimulator->tx_bw=openair0_cfg->tx_bw; rfsimulator_readconfig(rfsimulator); + LOG_W(HW, "rfsim: sample_rate %f\n", rfsimulator->sample_rate); pthread_mutex_init(&Sockmutex, NULL); LOG_I(HW,"rfsimulator: running as %s\n", rfsimulator-> typeStamp == ENB_MAGICDL ? "server waiting opposite rfsimulators to connect" : "client: will connect to a rfsimulator server side"); device->trx_start_func = rfsimulator->typeStamp == ENB_MAGICDL ?