Implement RFsim setdistance/getdistance telnet cmd
This commit is contained in:
@@ -90,8 +90,12 @@
|
|||||||
|
|
||||||
|
|
||||||
static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, void *arg);
|
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 telnetshell_cmddef_t rfsimu_cmdarray[] = {
|
static telnetshell_cmddef_t rfsimu_cmdarray[] = {
|
||||||
{"setmodel","<model name> <model type>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
|
{"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},
|
||||||
{"","",NULL},
|
{"","",NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -369,6 +373,155 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
|
|||||||
return CMDSTATUS_FOUND;
|
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 startServer(openair0_device *device) {
|
static int startServer(openair0_device *device) {
|
||||||
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
rfsimulator_state_t *t = (rfsimulator_state_t *) device->priv;
|
||||||
t->typeStamp=ENB_MAGICDL;
|
t->typeStamp=ENB_MAGICDL;
|
||||||
|
|||||||
Reference in New Issue
Block a user