|
|
|
@@ -30,16 +30,13 @@
|
|
|
|
|
#include <forms.h>
|
|
|
|
|
|
|
|
|
|
#define TPUT_WINDOW_LENGTH 100
|
|
|
|
|
|
|
|
|
|
#define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe));
|
|
|
|
|
|
|
|
|
|
int otg_enabled;
|
|
|
|
|
|
|
|
|
|
FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW};
|
|
|
|
|
|
|
|
|
|
float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_ue_max[NUMBER_OF_UE_MAX] = {0};
|
|
|
|
|
const FL_COLOR rx_antenna_colors[4] = {FL_RED,FL_BLUE,FL_GREEN,FL_YELLOW};
|
|
|
|
|
const FL_COLOR water_colors[4] = {FL_BLUE,FL_GREEN,FL_YELLOW,FL_RED};
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
int16_t r;
|
|
|
|
@@ -49,10 +46,17 @@ typedef struct {
|
|
|
|
|
|
|
|
|
|
typedef struct OAIgraph {
|
|
|
|
|
FL_OBJECT *graph;
|
|
|
|
|
FL_OBJECT *text;
|
|
|
|
|
float maxX;
|
|
|
|
|
float maxY;
|
|
|
|
|
float minX;
|
|
|
|
|
float minY;
|
|
|
|
|
int x;
|
|
|
|
|
int y;
|
|
|
|
|
int w;
|
|
|
|
|
int h;
|
|
|
|
|
int waterFallh;
|
|
|
|
|
double *waterFallAvg;
|
|
|
|
|
int iteration;
|
|
|
|
|
void (*gNBfunct) (struct OAIgraph *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id);
|
|
|
|
|
void (*nrUEfunct)(struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id);
|
|
|
|
@@ -94,38 +98,57 @@ static void dl_traffic_on_off( FL_OBJECT *button, long arg) {
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
static FL_OBJECT *commonGraph( int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
|
|
|
|
|
FL_OBJECT *graph;
|
|
|
|
|
graph=fl_add_xyplot(type, x, y, w, h, label);
|
|
|
|
|
fl_set_object_lcolor(graph, FL_WHITE ); // Label color
|
|
|
|
|
fl_set_object_color(graph, FL_BLACK, pointColor);
|
|
|
|
|
fl_set_xyplot_symbol(graph, -1, drawsymbol);
|
|
|
|
|
return graph;
|
|
|
|
|
#define WATERFALL 10000
|
|
|
|
|
|
|
|
|
|
static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
|
|
|
|
|
if (type==WATERFALL) {
|
|
|
|
|
graph->waterFallh=h-15;
|
|
|
|
|
graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh);
|
|
|
|
|
for (int i=0; i< graph->waterFallh; i++)
|
|
|
|
|
graph->waterFallAvg[i]=0;
|
|
|
|
|
|
|
|
|
|
graph->graph=fl_add_canvas(FL_NORMAL_CANVAS, x, y, w, graph->waterFallh, label);
|
|
|
|
|
graph->text=fl_add_text(FL_NORMAL_TEXT, x, y+graph->waterFallh, w, 15, label);
|
|
|
|
|
fl_set_object_lcolor(graph->text,FL_WHITE);
|
|
|
|
|
fl_set_object_color(graph->text, FL_BLACK, FL_BLACK);
|
|
|
|
|
fl_set_object_lalign(graph->text, FL_ALIGN_CENTER );
|
|
|
|
|
} else {
|
|
|
|
|
graph->graph=fl_add_xyplot(type, x, y, w, h, label);
|
|
|
|
|
fl_set_object_lcolor(graph->graph, FL_WHITE ); // Label color
|
|
|
|
|
fl_set_object_color(graph->graph, FL_BLACK, pointColor);
|
|
|
|
|
|
|
|
|
|
for (int i=0; i< FL_MAX_XYPLOTOVERLAY; i++)
|
|
|
|
|
fl_set_xyplot_symbol(graph->graph, i, drawsymbol);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
graph->x=x;
|
|
|
|
|
graph->y=y;
|
|
|
|
|
graph->w=w;
|
|
|
|
|
graph->h=h;
|
|
|
|
|
graph->maxX=0;
|
|
|
|
|
graph->maxY=0;
|
|
|
|
|
graph->minX=0;
|
|
|
|
|
graph->minY=0;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
graph->iteration=0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static OAIgraph_t gNBcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id),
|
|
|
|
|
int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
|
|
|
|
|
OAIgraph_t graph;
|
|
|
|
|
graph.graph=commonGraph(type, x, y, w, h, label, pointColor);
|
|
|
|
|
commonGraph(&graph, type, x, y, w, h, label, pointColor);
|
|
|
|
|
graph.gNBfunct=funct;
|
|
|
|
|
graph.nrUEfunct=NULL;
|
|
|
|
|
graph.maxX=0;
|
|
|
|
|
graph.maxY=0;
|
|
|
|
|
graph.minX=0;
|
|
|
|
|
graph.minY=0;
|
|
|
|
|
return graph;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static OAIgraph_t nrUEcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id),
|
|
|
|
|
int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
|
|
|
|
|
OAIgraph_t graph;
|
|
|
|
|
graph.graph=commonGraph(type, x, y, w, h, label, pointColor);
|
|
|
|
|
commonGraph(&graph, type, x, y, w, h, label, pointColor);
|
|
|
|
|
graph.gNBfunct=NULL;
|
|
|
|
|
graph.nrUEfunct=funct;
|
|
|
|
|
graph.maxX=0;
|
|
|
|
|
graph.maxY=0;
|
|
|
|
|
graph.minX=0;
|
|
|
|
|
graph.minY=0;
|
|
|
|
|
return graph;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -140,11 +163,39 @@ static void setRange(OAIgraph_t *graph, float minX, float maxX, float minY, floa
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, int NoAutoScale) {
|
|
|
|
|
if (layer==0)
|
|
|
|
|
fl_set_xyplot_data(graph->graph,x,y,len,"","","");
|
|
|
|
|
else
|
|
|
|
|
fl_add_xyplot_overlay(graph->graph,layer,x,y,len,rx_antenna_colors[layer]);
|
|
|
|
|
static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len, int layer) {
|
|
|
|
|
float *old_x;
|
|
|
|
|
float *old_y;
|
|
|
|
|
int old_len=-1;
|
|
|
|
|
//LOG_E(HW,"enter oai_xygraph_getbuff, it=%d\n",graph->iteration);
|
|
|
|
|
|
|
|
|
|
if (graph->iteration >1)
|
|
|
|
|
fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len);
|
|
|
|
|
|
|
|
|
|
if (old_len != len) {
|
|
|
|
|
LOG_W(HW,"allocating graph of %d scope\n", len);
|
|
|
|
|
float values[len];
|
|
|
|
|
float time[len];
|
|
|
|
|
|
|
|
|
|
// make time in case we will use it
|
|
|
|
|
for (int i=0; i<len; i++)
|
|
|
|
|
time[i] = values[i] = i;
|
|
|
|
|
|
|
|
|
|
if (layer==0)
|
|
|
|
|
fl_set_xyplot_data(graph->graph,time,values,len,"","","");
|
|
|
|
|
else
|
|
|
|
|
fl_add_xyplot_overlay(graph->graph,layer,time,values,len,rx_antenna_colors[layer]);
|
|
|
|
|
|
|
|
|
|
fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len);
|
|
|
|
|
AssertFatal(old_len==len,"");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*x=old_x;
|
|
|
|
|
*y=old_y;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int layer, boolean_t NoAutoScale) {
|
|
|
|
|
fl_redraw_object(graph->graph);
|
|
|
|
|
|
|
|
|
|
if ( NoAutoScale && graph->iteration%NoAutoScale == 0) {
|
|
|
|
|
float maxX=0, maxY=0, minX=0, minY=0;
|
|
|
|
@@ -156,46 +207,87 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye
|
|
|
|
|
minY=min(minY,y[k]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
setRange(graph,minX,maxX, minY, maxY);
|
|
|
|
|
setRange(graph, minX-5, maxX+5, minY-5, maxY+5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
graph->iteration++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize) {
|
|
|
|
|
fl_winset(FL_ObjWin(graph->graph));
|
|
|
|
|
const int samplesPerPixel=datasize/graph->w;
|
|
|
|
|
int row=graph->iteration%(graph->waterFallh);
|
|
|
|
|
double avg=0;
|
|
|
|
|
|
|
|
|
|
for (int i=0; i <graph->waterFallh; i++)
|
|
|
|
|
avg+=graph->waterFallAvg[i];
|
|
|
|
|
|
|
|
|
|
avg/=graph->waterFallh;
|
|
|
|
|
graph->waterFallAvg[row]=0;
|
|
|
|
|
|
|
|
|
|
for (int pix=0; pix<graph->w; pix++) {
|
|
|
|
|
scopeSample_t *end=values+(pix+1)*samplesPerPixel;
|
|
|
|
|
end-=2;
|
|
|
|
|
AssertFatal(end <= values+datasize,"diff : %ld", end-values+datasize);
|
|
|
|
|
double val=0;
|
|
|
|
|
|
|
|
|
|
for (scopeSample_t *s=values+(pix)*samplesPerPixel;
|
|
|
|
|
s <end;
|
|
|
|
|
s++)
|
|
|
|
|
val += SquaredNorm(*s);
|
|
|
|
|
|
|
|
|
|
val/=samplesPerPixel;
|
|
|
|
|
graph->waterFallAvg[row]+=val/graph->w;
|
|
|
|
|
int col=0;
|
|
|
|
|
|
|
|
|
|
if (val > avg*2 )
|
|
|
|
|
col=1;
|
|
|
|
|
|
|
|
|
|
if (val > avg*10 )
|
|
|
|
|
col=2;
|
|
|
|
|
|
|
|
|
|
if (val > avg*100 )
|
|
|
|
|
col=3;
|
|
|
|
|
|
|
|
|
|
fl_point(pix, graph->iteration%(graph->waterFallh), water_colors[col]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fl_set_object_label_f(graph->text, "average I/Q module: %4.1f", sqrt(avg));
|
|
|
|
|
graph->iteration++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void genericLogPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) {
|
|
|
|
|
float *values=malloc(len*sizeof(*values));
|
|
|
|
|
float *time=malloc(len*sizeof(*time));
|
|
|
|
|
float *values, *time;
|
|
|
|
|
oai_xygraph_getbuff(graph, &time, &values, len, 0);
|
|
|
|
|
|
|
|
|
|
for (int ant=0; ant<nb_ant; ant++) {
|
|
|
|
|
if (data[ant] != NULL) {
|
|
|
|
|
float *values, *time;
|
|
|
|
|
oai_xygraph_getbuff(graph, &time, &values, len, ant);
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<len; i+=8) {
|
|
|
|
|
float *vals=values+i;
|
|
|
|
|
float *tim=time+i;
|
|
|
|
|
const scopeSample_t *in=&(data[ant][i]);
|
|
|
|
|
|
|
|
|
|
// TRY AUTOMATIC simd BY GCC
|
|
|
|
|
for (int k=0; k<8; k++ ) {
|
|
|
|
|
vals[k] = 10*log10(1.0+SquaredNorm(in[k]));
|
|
|
|
|
tim[k] = i+k;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,time,values, len, ant, 10);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
free(values);
|
|
|
|
|
free(time);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const scopeSample_t **data, const int len) {
|
|
|
|
|
float values[len];
|
|
|
|
|
float time[len];
|
|
|
|
|
float *values, *time;
|
|
|
|
|
oai_xygraph_getbuff(graph, &time, &values, len, 0);
|
|
|
|
|
|
|
|
|
|
for (int ant=0; ant<nb_ant; ant++) {
|
|
|
|
|
if (data[ant] != NULL) {
|
|
|
|
|
for (int i=0; i<len; i++) {
|
|
|
|
|
values[i] = SquaredNorm(data[ant][i]);
|
|
|
|
|
time[i] = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,time,values, len, ant, 10);
|
|
|
|
@@ -203,6 +295,13 @@ static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const sc
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gNBWaterFall (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
|
|
|
|
|
//use 1st antenna
|
|
|
|
|
genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdata[0], frame_parms->samples_per_frame);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* replaced by waterfall
|
|
|
|
|
static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, const int nb_UEs) {
|
|
|
|
|
// Received signal in time domain of receive antenna 0
|
|
|
|
|
if (!phy_vars_ru->common.rxdata)
|
|
|
|
@@ -213,11 +312,12 @@ static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy
|
|
|
|
|
(const scopeSample_t **)phy_vars_ru->common.rxdata,
|
|
|
|
|
frame_parms->samples_per_frame);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size;
|
|
|
|
|
float values[len];
|
|
|
|
|
float time[len];
|
|
|
|
|
float *values, *time;
|
|
|
|
|
oai_xygraph_getbuff(graph, &time, &values, len, 0);
|
|
|
|
|
const int ant=0; // display antenna 0 for each UE
|
|
|
|
|
|
|
|
|
|
for (int ue=0; ue<nb_UEs; ue++) {
|
|
|
|
@@ -226,7 +326,6 @@ static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *p
|
|
|
|
|
if (data != NULL) {
|
|
|
|
|
for (int i=0; i<len; i++) {
|
|
|
|
|
values[i] = SquaredNorm(data[i]);
|
|
|
|
|
time[i] = i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,time,values, len, ue, 10);
|
|
|
|
@@ -234,26 +333,33 @@ static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *p
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void gNBfreqWaterFall (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
|
|
|
|
|
//use 1st antenna
|
|
|
|
|
genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdataF[0], frame_parms->samples_per_frame_wCP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
static void frequencyResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
|
|
|
|
|
genericLogPowerPerAntena(graph, frame_parms->nb_antennas_rx,
|
|
|
|
|
(const scopeSample_t **)phy_vars_ru->common.rxdataF,
|
|
|
|
|
frame_parms->samples_per_slot_wCP);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void puschLLR (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
//int Qm = 2;
|
|
|
|
|
int coded_bits_per_codeword =3*8*6144+12; // (8*((3*8*6144)+12)); // frame_parms->N_RB_UL*12*Qm*frame_parms->symbols_per_tti;
|
|
|
|
|
float llr[coded_bits_per_codeword];
|
|
|
|
|
float bit[coded_bits_per_codeword];
|
|
|
|
|
|
|
|
|
|
for (int ue=0; ue<nb_UEs; ue++) {
|
|
|
|
|
int16_t *pusch_llr = (int16_t *)phy_vars_gnb->pusch_vars[ue]->llr;
|
|
|
|
|
float *llr, *bit;
|
|
|
|
|
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword, ue);
|
|
|
|
|
|
|
|
|
|
if (pusch_llr) {
|
|
|
|
|
for (int i=0; i<coded_bits_per_codeword; i++) {
|
|
|
|
|
llr[i] = (float) pusch_llr[i];
|
|
|
|
|
bit[i] = (float) i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,bit,llr,coded_bits_per_codeword,ue,10);
|
|
|
|
@@ -264,10 +370,11 @@ static void puschLLR (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_v
|
|
|
|
|
static void puschIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
|
|
|
|
|
int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot;
|
|
|
|
|
float I[sz], Q[sz];
|
|
|
|
|
|
|
|
|
|
for (int ue=0; ue<nb_UEs; ue++) {
|
|
|
|
|
scopeSample_t *pusch_comp = (scopeSample_t *) phy_vars_gnb->pusch_vars[ue]->rxdataF_comp[0];
|
|
|
|
|
float *I, *Q;
|
|
|
|
|
oai_xygraph_getbuff(graph, &I, &Q, sz, ue);
|
|
|
|
|
|
|
|
|
|
if (pusch_comp) {
|
|
|
|
|
for (int k=0; k<sz; k++ ) {
|
|
|
|
@@ -312,6 +419,9 @@ static void pucchIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_va
|
|
|
|
|
static void puschThroughtput (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
|
|
|
|
|
// PUSCH Throughput
|
|
|
|
|
/*
|
|
|
|
|
float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
|
|
|
|
|
memmove( tput_time_enb[UE_id], &tput_time_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) );
|
|
|
|
|
memmove( tput_enb[UE_id], &tput_enb[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) );
|
|
|
|
|
tput_time_enb[UE_id][TPUT_WINDOW_LENGTH-1] = (float) 0;
|
|
|
|
@@ -332,18 +442,18 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) {
|
|
|
|
|
fl_set_object_color( obj, FL_BLACK, FL_WHITE );
|
|
|
|
|
int curY=0,x,y,w,h;
|
|
|
|
|
// Received signal
|
|
|
|
|
fdui->graph[0] = gNBcommonGraph( timeSignal, FL_NORMAL_XYPLOT, 0, curY, 400, 100,
|
|
|
|
|
"Received Signal (Time-Domain, dB)", FL_RED );
|
|
|
|
|
fdui->graph[0] = gNBcommonGraph( gNBWaterFall, WATERFALL, 0, curY, 400, 100,
|
|
|
|
|
"Received Signal (Time-Domain, one frame)", FL_RED );
|
|
|
|
|
// Time-domain channel response
|
|
|
|
|
fdui->graph[1] = gNBcommonGraph( timeResponse, FL_NORMAL_XYPLOT, 410, curY, 400, 100,
|
|
|
|
|
"SRS Frequency Response (samples, abs)", FL_RED );
|
|
|
|
|
fl_get_object_bbox(fdui->graph[0].graph,&x, &y,&w, &h);
|
|
|
|
|
fl_get_object_bbox(fdui->graph[1].graph,&x, &y,&w, &h);
|
|
|
|
|
curY+=h;
|
|
|
|
|
// Frequency-domain channel response
|
|
|
|
|
fdui->graph[2] = gNBcommonGraph( frequencyResponse, FL_NORMAL_XYPLOT, 0, curY, 800, 100,
|
|
|
|
|
"Channel Frequency Response (RE, dB)", FL_RED );
|
|
|
|
|
fdui->graph[2] = gNBcommonGraph( gNBfreqWaterFall, WATERFALL, 0, curY, 800, 100,
|
|
|
|
|
"Channel Frequency domain (RE, one frame)", FL_RED );
|
|
|
|
|
fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h);
|
|
|
|
|
curY+=h;
|
|
|
|
|
curY+=h+15;
|
|
|
|
|
// LLR of PUSCH
|
|
|
|
|
fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200,
|
|
|
|
|
"PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW );
|
|
|
|
@@ -376,14 +486,15 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
|
|
|
|
|
PHY_VARS_gNB *phy_vars_gnb,
|
|
|
|
|
RU_t *phy_vars_ru,
|
|
|
|
|
int UE_id) {
|
|
|
|
|
static OAI_phy_scope_t *remeberForm=NULL;
|
|
|
|
|
static OAI_phy_scope_t *rememberForm=NULL;
|
|
|
|
|
|
|
|
|
|
if (form==NULL)
|
|
|
|
|
form=remeberForm;
|
|
|
|
|
form=rememberForm;
|
|
|
|
|
else
|
|
|
|
|
remeberForm=form;
|
|
|
|
|
rememberForm=form;
|
|
|
|
|
|
|
|
|
|
if (form==NULL) return;
|
|
|
|
|
if (form==NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int i=0;
|
|
|
|
|
|
|
|
|
@@ -392,7 +503,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fl_check_forms();
|
|
|
|
|
//fl_check_forms();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void *scope_thread_gNB(void *arg) {
|
|
|
|
@@ -406,7 +517,9 @@ static void *scope_thread_gNB(void *arg) {
|
|
|
|
|
pthread_attr_getstacksize(&atr, &stksize);
|
|
|
|
|
pthread_attr_setstacksize(&atr,32*1024*1024 );
|
|
|
|
|
sleep(3); // no clean interthread barriers
|
|
|
|
|
fl_initialize (p->argc, p->argv, NULL, 0, 0);
|
|
|
|
|
int fl_argc=1;
|
|
|
|
|
char *name="5G-gNB-scope";
|
|
|
|
|
fl_initialize (&fl_argc, &name, NULL, 0, 0);
|
|
|
|
|
int nb_ue=min(NUMBER_OF_UE_MAX, scope_enb_num_ue);
|
|
|
|
|
OAI_phy_scope_t *form_gnb = create_phy_scope_gnb();
|
|
|
|
|
|
|
|
|
@@ -425,12 +538,21 @@ void gNBinitScope(scopeParms_t *p) {
|
|
|
|
|
threadCreate(&forms_thread, scope_thread_gNB, &parms, "scope", -1, OAI_PRIORITY_RT_LOW);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
// Received signal in time domain of receive antenna 0
|
|
|
|
|
genericWaterFall(graph,
|
|
|
|
|
(scopeSample_t *) phy_vars_ue->common_vars.rxdata[0],
|
|
|
|
|
phy_vars_ue->frame_parms.samples_per_frame);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* replaced by waterfall
|
|
|
|
|
static void ueTimeResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
// Received signal in time domain of receive antenna 0
|
|
|
|
|
genericLogPowerPerAntena(graph, phy_vars_ue->frame_parms.nb_antennas_rx,
|
|
|
|
|
(const scopeSample_t **) phy_vars_ue->common_vars.rxdata,
|
|
|
|
|
phy_vars_ue->frame_parms.samples_per_frame);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void ueChannelResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
// Channel Impulse Response
|
|
|
|
@@ -439,6 +561,15 @@ static void ueChannelResponse (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue,
|
|
|
|
|
phy_vars_ue->frame_parms.ofdm_symbol_size>>3);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id ) {
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_ue->frame_parms;
|
|
|
|
|
//use 1st antenna
|
|
|
|
|
genericWaterFall(graph,
|
|
|
|
|
(scopeSample_t *)phy_vars_ue->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0],
|
|
|
|
|
frame_parms->samples_per_slot_wCP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
// Channel Frequency Response (includes 5 complex sample for filter)
|
|
|
|
|
if (!phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates)
|
|
|
|
@@ -449,12 +580,13 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue
|
|
|
|
|
uint8_t nb_antennas_tx = frame_parms->nb_antenna_ports_gNB;
|
|
|
|
|
scopeSample_t **chest_f = (scopeSample_t **) phy_vars_ue->pbch_vars[eNB_id]->dl_ch_estimates;
|
|
|
|
|
int ind = 0;
|
|
|
|
|
float chest_f_abs[frame_parms->ofdm_symbol_size];
|
|
|
|
|
float freq[frame_parms->ofdm_symbol_size];
|
|
|
|
|
float *freq, *chest_f_abs;
|
|
|
|
|
oai_xygraph_getbuff(graph, &freq, &chest_f_abs, frame_parms->ofdm_symbol_size, 0);
|
|
|
|
|
|
|
|
|
|
for (int atx=0; atx<nb_antennas_tx; atx++) {
|
|
|
|
|
for (int arx=0; arx<nb_antennas_rx; arx++) {
|
|
|
|
|
if (chest_f[(atx<<1)+arx] != NULL) {
|
|
|
|
|
|
|
|
|
|
for (int k=0; k<frame_parms->ofdm_symbol_size; k++) {
|
|
|
|
|
freq[ind] = (float)ind;
|
|
|
|
|
chest_f_abs[ind] = (short)10*log10(1.0+SquaredNorm(chest_f[(atx<<1)+arx][6144+k]));
|
|
|
|
@@ -471,6 +603,7 @@ static void uePbchFrequencyResp (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue
|
|
|
|
|
//fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR);
|
|
|
|
|
oai_xygraph(graph,freq,chest_f_abs,frame_parms->ofdm_symbol_size,0,10);
|
|
|
|
|
}
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
static void uePbchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
// PBCH LLRs
|
|
|
|
@@ -478,11 +611,11 @@ static void uePbchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int16_t *pbch_llr = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->llr;
|
|
|
|
|
float llr_pbch[864], bit_pbch[864];
|
|
|
|
|
float *llr_pbch, *bit_pbch;
|
|
|
|
|
oai_xygraph_getbuff(graph, &bit_pbch, &llr_pbch, 864, 0);
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<864; i++) {
|
|
|
|
|
llr_pbch[i] = (float) pbch_llr[i];
|
|
|
|
|
bit_pbch[i] = (float) i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,bit_pbch,llr_pbch,864,0,10);
|
|
|
|
@@ -494,8 +627,8 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
|
|
|
|
|
localBuff(I,180*3);
|
|
|
|
|
localBuff(Q,180*3);
|
|
|
|
|
float *I, *Q;
|
|
|
|
|
oai_xygraph_getbuff(graph, &I, &Q, 180*3, 0);
|
|
|
|
|
int first_symbol=1;
|
|
|
|
|
int base=0;
|
|
|
|
|
|
|
|
|
@@ -517,6 +650,7 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
|
|
|
|
|
base+=nb_re;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal(base <= 180*3,"");
|
|
|
|
|
oai_xygraph(graph,I,Q,base,0,10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -528,8 +662,8 @@ static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
|
|
|
|
int num_re = 4*273*12; // 12*frame_parms->N_RB_DL*num_pdcch_symbols
|
|
|
|
|
int Qm = 2;
|
|
|
|
|
int coded_bits_per_codeword = num_re*Qm;
|
|
|
|
|
localBuff(llr,coded_bits_per_codeword*RX_NB_TH_MAX);
|
|
|
|
|
localBuff(bit,coded_bits_per_codeword*RX_NB_TH_MAX);
|
|
|
|
|
float *llr, *bit;
|
|
|
|
|
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword*RX_NB_TH_MAX, 0);
|
|
|
|
|
int base=0;
|
|
|
|
|
|
|
|
|
|
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
|
|
|
|
@@ -537,12 +671,12 @@ static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
|
|
|
|
|
|
|
|
|
for (int i=0; i<coded_bits_per_codeword; i++) {
|
|
|
|
|
llr[base+i] = (float) pdcch_llr[i];
|
|
|
|
|
bit[base+i] = (float) base+i;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
base+=coded_bits_per_codeword;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, "");
|
|
|
|
|
oai_xygraph(graph,bit,llr,base,0,10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -552,8 +686,8 @@ static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
int nb=4*273*12; // 12*frame_parms->N_RB_DL*num_pdcch_symbols
|
|
|
|
|
localBuff(I,nb*RX_NB_TH_MAX);
|
|
|
|
|
localBuff(Q,nb*RX_NB_TH_MAX);
|
|
|
|
|
float *I, *Q;
|
|
|
|
|
oai_xygraph_getbuff(graph, &I, &Q, nb*RX_NB_TH_MAX, 0);
|
|
|
|
|
int base=0;
|
|
|
|
|
|
|
|
|
|
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
|
|
|
|
@@ -567,6 +701,7 @@ static void uePcchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
|
|
|
|
|
base+=nb;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal(base <= nb*RX_NB_TH_MAX, "");
|
|
|
|
|
oai_xygraph(graph,I,Q,base,0,10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -578,8 +713,8 @@ static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB
|
|
|
|
|
int num_re = 4500;
|
|
|
|
|
int Qm = 2;
|
|
|
|
|
int coded_bits_per_codeword = num_re*Qm;
|
|
|
|
|
localBuff(llr,coded_bits_per_codeword*RX_NB_TH_MAX);
|
|
|
|
|
localBuff(bit,coded_bits_per_codeword*RX_NB_TH_MAX);
|
|
|
|
|
float *llr, *bit;
|
|
|
|
|
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword*RX_NB_TH_MAX, 0);
|
|
|
|
|
int base=0;
|
|
|
|
|
|
|
|
|
|
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
|
|
|
|
@@ -593,6 +728,7 @@ static void uePdschLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB
|
|
|
|
|
base+=coded_bits_per_codeword;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
AssertFatal(base <= coded_bits_per_codeword*RX_NB_TH_MAX, "");
|
|
|
|
|
//fl_set_xyplot_xbounds(form->pdsch_llr,0,coded_bits_per_codeword);
|
|
|
|
|
oai_xygraph(graph,bit,llr,base,0,10);
|
|
|
|
|
}
|
|
|
|
@@ -604,9 +740,11 @@ static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
|
|
|
|
|
|
|
|
|
NR_DL_FRAME_PARMS *frame_parms = &phy_vars_ue->frame_parms;
|
|
|
|
|
int sz=7*2*frame_parms->N_RB_DL*12; // size of the malloced buffer
|
|
|
|
|
localBuff(I,sz*RX_NB_TH_MAX);
|
|
|
|
|
localBuff(Q,sz*RX_NB_TH_MAX);
|
|
|
|
|
float *I, *Q;
|
|
|
|
|
oai_xygraph_getbuff(graph, &I, &Q, sz*RX_NB_TH_MAX, 0);
|
|
|
|
|
int base=0;
|
|
|
|
|
memset(I+base, 0, sz*RX_NB_TH_MAX * sizeof(*I));
|
|
|
|
|
memset(Q+base, 0, sz*RX_NB_TH_MAX * sizeof(*Q));
|
|
|
|
|
|
|
|
|
|
for (int thr=0 ; thr < RX_NB_TH_MAX ; thr ++ ) {
|
|
|
|
|
scopeSample_t *pdsch_comp = (scopeSample_t *) phy_vars_ue->pdsch_vars[thr][eNB_id]->rxdataF_comp0[0];
|
|
|
|
@@ -619,11 +757,16 @@ static void uePdschIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_
|
|
|
|
|
base+=sz;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
oai_xygraph(graph,I,Q,base,0,10);
|
|
|
|
|
AssertFatal(base <= sz*RX_NB_TH_MAX, "");
|
|
|
|
|
oai_xygraph(graph,I,Q,sz*RX_NB_TH_MAX,0,10);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void uePdschThroughput (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
|
|
|
|
|
/*
|
|
|
|
|
float tput_time_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_ue[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
|
|
|
|
|
float tput_ue_max[NUMBER_OF_UE_MAX] = {0};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// PDSCH Throughput
|
|
|
|
|
memmove( tput_time_ue[UE_id], &tput_time_ue[UE_id][1], (TPUT_WINDOW_LENGTH-1)*sizeof(float) );
|
|
|
|
@@ -652,18 +795,18 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
|
|
|
|
|
fl_set_object_color( obj, FL_BLACK, FL_BLACK );
|
|
|
|
|
int curY=0,x,y,w,h;
|
|
|
|
|
// Received signal
|
|
|
|
|
fdui->graph[0] = nrUEcommonGraph(ueTimeResponse,
|
|
|
|
|
FL_NORMAL_XYPLOT, 0, curY, 400, 100, "Received Signal (Time-Domain, dB)", FL_RED );
|
|
|
|
|
fdui->graph[0] = nrUEcommonGraph(ueWaterFall,
|
|
|
|
|
WATERFALL, 0, curY, 400, 100, "Received Signal (Time-Domain, one frame)", FL_RED );
|
|
|
|
|
// Time-domain channel response
|
|
|
|
|
fdui->graph[1] = nrUEcommonGraph(ueChannelResponse,
|
|
|
|
|
FL_NORMAL_XYPLOT, 400, curY, 400, 100, "Channel Impulse Response (samples, abs)", FL_RED );
|
|
|
|
|
fl_get_object_bbox(fdui->graph[0].graph,&x, &y,&w, &h);
|
|
|
|
|
fl_get_object_bbox(fdui->graph[1].graph,&x, &y,&w, &h);
|
|
|
|
|
curY+=h;
|
|
|
|
|
// Frequency-domain channel response
|
|
|
|
|
fdui->graph[2] = nrUEcommonGraph(uePbchFrequencyResp,
|
|
|
|
|
FL_IMPULSE_XYPLOT, 0, curY, 800, 100, "Channel Frequency data (RE, dB)", FL_RED );
|
|
|
|
|
fdui->graph[2] = nrUEcommonGraph(ueFreqWaterFall,
|
|
|
|
|
WATERFALL, 0, curY, 800, 100, "Channel Frequency (RE, one slot)", FL_RED );
|
|
|
|
|
fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h);
|
|
|
|
|
curY+=h;
|
|
|
|
|
curY+=h+15;
|
|
|
|
|
// LLR of PBCH
|
|
|
|
|
fdui->graph[3] = nrUEcommonGraph(uePbchLLR,
|
|
|
|
|
FL_POINTS_XYPLOT, 0, curY, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN );
|
|
|
|
@@ -733,7 +876,7 @@ void phy_scope_nrUE(OAI_phy_scope_t *form,
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fl_check_forms();
|
|
|
|
|
//fl_check_forms();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -766,11 +909,11 @@ void nrUEinitScope(PHY_VARS_NR_UE *ue) {
|
|
|
|
|
|
|
|
|
|
void nrscope_autoinit(void *dataptr) {
|
|
|
|
|
AssertFatal( (IS_SOFTMODEM_GNB_BIT||IS_SOFTMODEM_5GUE_BIT),"Scope cannot find NRUE or GNB context");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (IS_SOFTMODEM_GNB_BIT)
|
|
|
|
|
gNBinitScope(dataptr);
|
|
|
|
|
gNBinitScope(dataptr);
|
|
|
|
|
else
|
|
|
|
|
nrUEinitScope(dataptr);
|
|
|
|
|
nrUEinitScope(dataptr);
|
|
|
|
|
}
|
|
|
|
|
// Kept to put back the functionality soon
|
|
|
|
|
#if 0
|
|
|
|
@@ -799,8 +942,6 @@ static void reset_stats_gNB(FL_OBJECT *button,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FD_stats_form *create_form_stats_form(int ID) {
|
|
|
|
|
FL_OBJECT *obj;
|
|
|
|
|
FD_stats_form *fdui = calloc(( sizeof *fdui ),1);
|
|
|
|
@@ -820,7 +961,3 @@ static FD_stats_form *create_form_stats_form(int ID) {
|
|
|
|
|
return fdui;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|