Commit ebccfe51 authored by Laurent's avatar Laurent

add raw capture from UHD examples and fix a rfsim bug

parent c4a91bcc
...@@ -780,7 +780,7 @@ void *UE_thread(void *arg) { ...@@ -780,7 +780,7 @@ void *UE_thread(void *arg) {
msgToPush->key=slot_nr; msgToPush->key=slot_nr;
pushTpool(Tpool, msgToPush); pushTpool(Tpool, msgToPush);
if ( getenv("RFSIMULATOR") ||IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR") if ( IS_SOFTMODEM_RFSIM || IS_SOFTMODEM_NOS1) { //getenv("RFSIMULATOR")
// FixMe: Wait previous thread is done, because race conditions seems too bad // FixMe: Wait previous thread is done, because race conditions seems too bad
// in case of actual RF board, the overlap between threads mitigate the issue // in case of actual RF board, the overlap between threads mitigate the issue
// We must receive one message, that proves the slot processing is done // We must receive one message, that proves the slot processing is done
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#include <forms.h> #include <forms.h>
#define TPUT_WINDOW_LENGTH 100 #define TPUT_WINDOW_LENGTH 100
#define ScaleZone 4
#define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe)); #define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe));
int otg_enabled; int otg_enabled;
...@@ -57,6 +57,7 @@ typedef struct OAIgraph { ...@@ -57,6 +57,7 @@ typedef struct OAIgraph {
int h; int h;
int waterFallh; int waterFallh;
double *waterFallAvg; double *waterFallAvg;
boolean_t initDone;
int iteration; int iteration;
void (*gNBfunct) (struct OAIgraph *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int UE_id); 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); void (*nrUEfunct)(struct OAIgraph *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id);
...@@ -104,8 +105,9 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_ ...@@ -104,8 +105,9 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
if (type==WATERFALL) { if (type==WATERFALL) {
graph->waterFallh=h-15; graph->waterFallh=h-15;
graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh); graph->waterFallAvg=malloc(sizeof(*graph->waterFallAvg) * graph->waterFallh);
for (int i=0; i< graph->waterFallh; i++)
graph->waterFallAvg[i]=0; 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->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); graph->text=fl_add_text(FL_NORMAL_TEXT, x, y+graph->waterFallh, w, 15, label);
...@@ -129,8 +131,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_ ...@@ -129,8 +131,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
graph->maxY=0; graph->maxY=0;
graph->minX=0; graph->minX=0;
graph->minY=0; graph->minY=0;
graph->initDone=false;
graph->iteration=0; graph->iteration=0;
} }
...@@ -153,13 +154,24 @@ static OAIgraph_t nrUEcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_NR ...@@ -153,13 +154,24 @@ static OAIgraph_t nrUEcommonGraph( void (*funct) (OAIgraph_t *graph, PHY_VARS_NR
} }
static void setRange(OAIgraph_t *graph, float minX, float maxX, float minY, float maxY) { static void setRange(OAIgraph_t *graph, float minX, float maxX, float minY, float maxY) {
if ( maxX > graph->maxX || maxY > graph->maxY || minX < graph->minX || minY < graph->minY ) { if ( maxX > graph->maxX || minX < graph->minX ||
abs(maxX-graph->maxX)>abs(graph->maxX)/2 ||
abs(maxX-graph->maxX)>abs(graph->maxX)/2 ) {
graph->maxX/=2;
graph->minX/=2;
graph->maxX=max(graph->maxX,maxX); graph->maxX=max(graph->maxX,maxX);
graph->minX=min(graph->minX,minX); graph->minX=min(graph->minX,minX);
fl_set_xyplot_xbounds(graph->graph, graph->minX*1.2, graph->maxX*1.2);
}
if ( maxY > graph->maxY || minY < graph->minY ||
abs(maxY-graph->maxY)>abs(graph->maxY)/2 ||
abs(maxY-graph->maxY)>abs(graph->maxY)/2 ) {
graph->maxY/=2;
graph->minY/=2;
graph->maxY=max(graph->maxY,maxY); graph->maxY=max(graph->maxY,maxY);
graph->minY=min(graph->minY,minY); graph->minY=min(graph->minY,minY);
fl_set_xyplot_ybounds(graph->graph, graph->minY, graph->maxY); fl_set_xyplot_ybounds(graph->graph, graph->minY*1.2, graph->maxY*1.2);
fl_set_xyplot_xbounds(graph->graph, graph->minX, graph->maxX);
} }
} }
...@@ -167,7 +179,6 @@ static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len ...@@ -167,7 +179,6 @@ static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len
float *old_x; float *old_x;
float *old_y; float *old_y;
int old_len=-1; int old_len=-1;
//LOG_E(HW,"enter oai_xygraph_getbuff, it=%d\n",graph->iteration);
if (graph->iteration >1) if (graph->iteration >1)
fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len); fl_get_xyplot_data_pointer(graph->graph, layer, &old_x, &old_y, &old_len);
...@@ -213,16 +224,17 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye ...@@ -213,16 +224,17 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye
graph->iteration++; graph->iteration++;
} }
static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize) { static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) {
fl_winset(FL_ObjWin(graph->graph)); fl_winset(FL_ObjWin(graph->graph));
const int samplesPerPixel=datasize/graph->w; const int samplesPerPixel=datasize/graph->w;
int row=graph->iteration%(graph->waterFallh); int displayPart=graph->waterFallh-ScaleZone;
int row=graph->iteration%displayPart;
double avg=0; double avg=0;
for (int i=0; i <graph->waterFallh; i++) for (int i=0; i < displayPart; i++)
avg+=graph->waterFallAvg[i]; avg+=graph->waterFallAvg[i];
avg/=graph->waterFallh; avg/=displayPart;
graph->waterFallAvg[row]=0; graph->waterFallAvg[row]=0;
for (int pix=0; pix<graph->w; pix++) { for (int pix=0; pix<graph->w; pix++) {
...@@ -249,10 +261,22 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in ...@@ -249,10 +261,22 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in
if (val > avg*100 ) if (val > avg*100 )
col=3; col=3;
fl_point(pix, graph->iteration%(graph->waterFallh), water_colors[col]); fl_point(pix, graph->iteration%displayPart, water_colors[col]);
} }
fl_set_object_label_f(graph->text, "average I/Q module: %4.1f", sqrt(avg)); if (graph->initDone==false) {
for ( int i=0; i < graph->waterFallh; i++ )
for ( int j = 0 ; j < graph->w ; j++ )
fl_point(j, i, FL_BLACK);
for ( int i=1; i<divisions; i++)
for (int j= displayPart; j<graph->waterFallh; j++)
fl_point(i*(graph->w/divisions),j, FL_WHITE);
graph->initDone=true;
}
fl_set_object_label_f(graph->text, "%s, avg I/Q pow: %4.1f", label, sqrt(avg));
graph->iteration++; graph->iteration++;
} }
...@@ -298,7 +322,9 @@ static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const sc ...@@ -298,7 +322,9 @@ 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) { 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; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
//use 1st antenna //use 1st antenna
genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdata[0], frame_parms->samples_per_frame); genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdata[0],
frame_parms->samples_per_frame, frame_parms->slots_per_frame,
"X axis:one frame in time");
} }
/* replaced by waterfall /* replaced by waterfall
...@@ -336,7 +362,9 @@ static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *p ...@@ -336,7 +362,9 @@ 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) { 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; NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
//use 1st antenna //use 1st antenna
genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdataF[0], frame_parms->samples_per_frame_wCP); genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdataF[0], frame_parms->samples_per_frame_wCP,
frame_parms->slots_per_frame,
"X axis: Frequency domain, one frame");
} }
/* /*
...@@ -453,7 +481,7 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) { ...@@ -453,7 +481,7 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) {
fdui->graph[2] = gNBcommonGraph( gNBfreqWaterFall, WATERFALL, 0, curY, 800, 100, fdui->graph[2] = gNBcommonGraph( gNBfreqWaterFall, WATERFALL, 0, curY, 800, 100,
"Channel Frequency domain (RE, one frame)", FL_RED ); "Channel Frequency domain (RE, one frame)", FL_RED );
fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h); fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h);
curY+=h+15; curY+=h+20;
// LLR of PUSCH // LLR of PUSCH
fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200, fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200,
"PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW ); "PUSCH Log-Likelihood Ratios (LLR, mag)", FL_YELLOW );
...@@ -542,7 +570,9 @@ static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eN ...@@ -542,7 +570,9 @@ static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eN
// Received signal in time domain of receive antenna 0 // Received signal in time domain of receive antenna 0
genericWaterFall(graph, genericWaterFall(graph,
(scopeSample_t *) phy_vars_ue->common_vars.rxdata[0], (scopeSample_t *) phy_vars_ue->common_vars.rxdata[0],
phy_vars_ue->frame_parms.samples_per_frame); phy_vars_ue->frame_parms.samples_per_frame,
phy_vars_ue->frame_parms.slots_per_frame,
"X axis: one frame time");
} }
/* replaced by waterfall /* replaced by waterfall
...@@ -566,7 +596,9 @@ static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int ...@@ -566,7 +596,9 @@ static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int
//use 1st antenna //use 1st antenna
genericWaterFall(graph, genericWaterFall(graph,
(scopeSample_t *)phy_vars_ue->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0], (scopeSample_t *)phy_vars_ue->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0],
frame_parms->samples_per_slot_wCP); frame_parms->samples_per_slot_wCP,
phy_vars_ue->frame_parms.slots_per_frame,
"X axis: one frame frequency" );
} }
/* /*
...@@ -629,6 +661,8 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i ...@@ -629,6 +661,8 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0]; scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
float *I, *Q; float *I, *Q;
oai_xygraph_getbuff(graph, &I, &Q, 180*3, 0); oai_xygraph_getbuff(graph, &I, &Q, 180*3, 0);
memset(I,0,180*3*sizeof(*I));
memset(Q,0,180*3*sizeof(*Q));
int first_symbol=1; int first_symbol=1;
int base=0; int base=0;
...@@ -651,7 +685,7 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i ...@@ -651,7 +685,7 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
} }
AssertFatal(base <= 180*3,""); AssertFatal(base <= 180*3,"");
oai_xygraph(graph,I,Q,base,0,10); oai_xygraph(graph,I,Q,base,0, 10);
} }
static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) { static void uePcchLLR (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
...@@ -806,7 +840,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) { ...@@ -806,7 +840,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
fdui->graph[2] = nrUEcommonGraph(ueFreqWaterFall, fdui->graph[2] = nrUEcommonGraph(ueFreqWaterFall,
WATERFALL, 0, curY, 800, 100, "Channel Frequency (RE, one slot)", FL_RED ); WATERFALL, 0, curY, 800, 100, "Channel Frequency (RE, one slot)", FL_RED );
fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h); fl_get_object_bbox(fdui->graph[2].graph,&x, &y,&w, &h);
curY+=h+15; curY+=h+20;
// LLR of PBCH // LLR of PBCH
fdui->graph[3] = nrUEcommonGraph(uePbchLLR, fdui->graph[3] = nrUEcommonGraph(uePbchLLR,
FL_POINTS_XYPLOT, 0, curY, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN ); FL_POINTS_XYPLOT, 0, curY, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN );
...@@ -892,9 +926,12 @@ static void *nrUEscopeThread(void *arg) { ...@@ -892,9 +926,12 @@ static void *nrUEscopeThread(void *arg) {
OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0); OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0);
while (!oai_exit) { while (!oai_exit) {
fl_freeze_form(form_nrue->phy_scope);
phy_scope_nrUE(form_nrue, phy_scope_nrUE(form_nrue,
ue, ue,
0,0); 0,0);
fl_unfreeze_form(form_nrue->phy_scope);
fl_redraw_form(form_nrue->phy_scope);
usleep(99*1000); usleep(99*1000);
} }
......
...@@ -1236,10 +1236,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, ...@@ -1236,10 +1236,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
rx_ind.rx_indication_body[0].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b; rx_ind.rx_indication_body[0].pdsch_pdu.pdu = dlsch0->harq_processes[harq_pid]->b;
rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS>>3; rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length = dlsch0->harq_processes[harq_pid]->TBS>>3;
LOG_W(PHY, "PDU length in bits: %d, in bytes: %d \n", dlsch0->harq_processes[harq_pid]->TBS, rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length); LOG_D(PHY, "PDU length in bits: %d, in bytes: %d \n", dlsch0->harq_processes[harq_pid]->TBS, rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length);
for (int i=0; i< rx_ind.rx_indication_body[0].pdsch_pdu.pdu_length ; i++)
printf("%x:", dlsch0->harq_processes[harq_pid]->b[i]);
printf ("ret: %d\n", ret);
rx_ind.number_pdus = 1; rx_ind.number_pdus = 1;
// send to mac // send to mac
......
...@@ -1500,11 +1500,11 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index ...@@ -1500,11 +1500,11 @@ int8_t nr_rrc_ue_decode_NR_SIB1_Message(module_id_t module_id, uint8_t gNB_index
} }
sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1; sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
if (*(int64_t*)sib1 != 1) { if (*(int64_t*)sib1 != 1) {
printf("%llx\n", *(int64_t*)sib1); printf("%llx\n", *(int64_t*)sib1);
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1); xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1);
} }
else else
LOG_E(PHY, "sib1 is starting by 8 times 0\n"); LOG_E(PHY, "sib1 is starting by 8 times 0\n");
} }
return 0; return 0;
......
...@@ -657,12 +657,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -657,12 +657,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
} }
if (samples_received == nsamps) s->wait_for_first_pps=0; if (samples_received == nsamps) s->wait_for_first_pps=0;
} }
if ( getenv("recorded") ) {
static int h=-1;
if (h==-1)
h=open(getenv("recorded"), O_RDONLY, 0);
read(h, buff_tmp[0], nsamps*4);
}
// bring RX data into 12 LSBs for softmodem RX // bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) { for (int i=0; i<cc; i++) {
......
...@@ -91,13 +91,13 @@ extern RAN_CONTEXT_t RC; ...@@ -91,13 +91,13 @@ extern RAN_CONTEXT_t RC;
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 telnetshell_cmddef_t rfsimu_cmdarray[] = { static telnetshell_cmddef_t rfsimu_cmdarray[] = {
{"setmodel","<model name>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ}, {"setmodel","<model name>",(cmdfunc_t)rfsimu_setchanmod_cmd,TELNETSRV_CMDFLAG_PUSHINTPOOLQ},
{"","",NULL}, {"","",NULL},
}; };
static telnetshell_vardef_t rfsimu_vardef[] = { static telnetshell_vardef_t rfsimu_vardef[] = {
{"",0,NULL} {"",0,NULL}
}; };
pthread_mutex_t Sockmutex; pthread_mutex_t Sockmutex;
typedef struct complex16 sample_t; // 2*16 bits complex number typedef struct complex16 sample_t; // 2*16 bits complex number
...@@ -170,11 +170,13 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -170,11 +170,13 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
static bool init_done=false; static bool init_done=false;
if (!init_done) { if (!init_done) {
uint64_t rand; uint64_t rand;
FILE *h=fopen("/dev/random","r"); FILE *h=fopen("/dev/random","r");
if ( 1 != fread(&rand,sizeof(rand),1,h) ) if ( 1 != fread(&rand,sizeof(rand),1,h) )
LOG_W(HW, "Simulator can't read /dev/random\n"); LOG_W(HW, "Simulator can't read /dev/random\n");
fclose(h);
fclose(h);
randominit(rand); randominit(rand);
tableNor(rand); tableNor(rand);
init_done=true; init_done=true;
...@@ -189,7 +191,6 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) { ...@@ -189,7 +191,6 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
bridge->chan_offset, // maybe used for TA bridge->chan_offset, // maybe used for TA
bridge->chan_pathloss); // path_loss in dB bridge->chan_pathloss); // path_loss in dB
set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID); set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID);
random_channel(ptr->channel_model,false); random_channel(ptr->channel_model,false);
} }
} }
...@@ -317,25 +318,29 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) { ...@@ -317,25 +318,29 @@ void rfsimulator_readconfig(rfsimulator_state_t *rfsimulator) {
} }
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) {
char *modelname=NULL; char *modelname=NULL;
int s = sscanf(buff,"%ms\n",&modelname); int s = sscanf(buff,"%ms\n",&modelname);
if (s == 1) { if (s == 1) {
int channelmod=modelid_fromname(modelname); int channelmod=modelid_fromname(modelname);
if (channelmod<0) if (channelmod<0)
prnt("ERROR: model %s unknown\n",modelname); prnt("ERROR: model %s unknown\n",modelname);
else { else {
rfsimulator_state_t *t = (rfsimulator_state_t *)arg; rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
for (int i=0; i<FD_SETSIZE; i++) {
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *b=&t->buf[i]; buffer_t *b=&t->buf[i];
if (b->conn_sock >= 0 ) { if (b->conn_sock >= 0 ) {
channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels, channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels,
channelmod, channelmod,
t->sample_rate, t->sample_rate,
t->tx_bw, t->tx_bw,
30e-9, // TDL delay-spread parameter 30e-9, // TDL delay-spread parameter
t->chan_forgetfact, // forgetting_factor t->chan_forgetfact, // forgetting_factor
t->chan_offset, // maybe used for TA t->chan_offset, // maybe used for TA
t->chan_pathloss); // path_loss in dB t->chan_pathloss); // path_loss in dB
set_channeldesc_owner(newmodel, RFSIMU_MODULEID); set_channeldesc_owner(newmodel, RFSIMU_MODULEID);
random_channel(newmodel,false); random_channel(newmodel,false);
channel_desc_t *oldmodel=b->channel_model; channel_desc_t *oldmodel=b->channel_model;
...@@ -346,8 +351,9 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt, ...@@ -346,8 +351,9 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
} }
} }
} else { } else {
prnt("ERROR: no model specified\n"); prnt("ERROR: no model specified\n");
} }
free(modelname); free(modelname);
return CMDSTATUS_FOUND; return CMDSTATUS_FOUND;
} }
...@@ -368,7 +374,7 @@ sin_addr: ...@@ -368,7 +374,7 @@ sin_addr:
}; };
bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr)); bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
AssertFatal(listen(t->listen_sock, 5) == 0, ""); AssertFatal(listen(t->listen_sock, 5) == 0, "");
struct epoll_event ev={0}; struct epoll_event ev= {0};
ev.events = EPOLLIN; ev.events = EPOLLIN;
ev.data.fd = t->listen_sock; ev.data.fd = t->listen_sock;
AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, ""); AssertFatal(epoll_ctl(t->epollfd, EPOLL_CTL_ADD, t->listen_sock, &ev) != -1, "");
...@@ -440,7 +446,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp ...@@ -440,7 +446,7 @@ static int rfsimulator_write_internal(rfsimulator_state_t *t, openair0_timestamp
if (t->lastWroteTS > timestamp+nsamps) if (t->lastWroteTS > timestamp+nsamps)
LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n", LOG_E(HW,"Not supported to send Tx out of order (same in USRP) %lu, %lu\n",
t->lastWroteTS, timestamp); t->lastWroteTS, timestamp);
t->lastWroteTS=timestamp+nsamps; t->lastWroteTS=timestamp+nsamps;
...@@ -505,9 +511,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi ...@@ -505,9 +511,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
if ( b->headerMode) if ( b->headerMode)
blockSz=b->remainToTransfer; blockSz=b->remainToTransfer;
else else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ? blockSz= b->transferPtr + b->remainToTransfer <= b->circularBufEnd ?
b->remainToTransfer : b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ; b->circularBufEnd - b->transferPtr ;
ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT); ssize_t sz=recv(fd, b->transferPtr, blockSz, MSG_DONTWAIT);
...@@ -523,7 +529,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi ...@@ -523,7 +529,7 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
AssertFatal((b->remainToTransfer-=sz) >= 0, ""); AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz; b->transferPtr+=sz;
if (b->transferPtr==b->circularBufEnd - 1) if (b->transferPtr==b->circularBufEnd )
b->transferPtr=(char *)b->circularBuf; b->transferPtr=(char *)b->circularBuf;
// check the header and start block transfer // check the header and start block transfer
...@@ -552,14 +558,13 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi ...@@ -552,14 +558,13 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
} }
} }
} else { } else {
memset(b->circularBuf, 0, sampleToByte(CirSize,1)); memset(b->circularBuf, 0, sampleToByte(CirSize,1));
} }
if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS < 1000) if (b->lastReceivedTS != 0 && b->th.timestamp-b->lastReceivedTS < 1000)
LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS ); LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS );
b->lastReceivedTS=b->th.timestamp; b->lastReceivedTS=b->th.timestamp;
} else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) { } else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) {
LOG_W(HW,"Received Rx/Tx synchro out of order\n"); LOG_W(HW,"Received Rx/Tx synchro out of order\n");
b->trashingPacket=true; b->trashingPacket=true;
...@@ -650,15 +655,15 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -650,15 +655,15 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
// assuming this should have been done earlier if a Tx would exist // assuming this should have been done earlier if a Tx would exist
pthread_mutex_unlock(&Sockmutex); pthread_mutex_unlock(&Sockmutex);
struct complex16 v= {0}; struct complex16 v= {0};
void *samplesVoid[t->tx_num_channels]; void *dummyS[t->tx_num_channels];
for ( int i=0; i < t->tx_num_channels; i++) for ( int i=0; i < t->tx_num_channels; i++)
samplesVoid[i]=(void *)&v; dummyS[i]=(void *)&v;
LOG_I(HW, "No samples Tx occured, so we send 1 sample to notify it: Tx:%lu, Rx:%lu\n", LOG_I(HW, "No samples Tx occured, so we send 1 sample to notify it: Tx:%lu, Rx:%lu\n",
t->lastWroteTS, t->nextTimestamp); t->lastWroteTS, t->nextTimestamp);
rfsimulator_write_internal(t, t->nextTimestamp, rfsimulator_write_internal(t, t->nextTimestamp,
samplesVoid, 1, dummyS, 1,
t->tx_num_channels, 1, true); t->tx_num_channels, 1, true);
} else { } else {
pthread_mutex_unlock(&Sockmutex); pthread_mutex_unlock(&Sockmutex);
...@@ -706,8 +711,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -706,8 +711,9 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
// it seems legacy behavior is: never in UL, each frame in DL // it seems legacy behavior is: never in UL, each frame in DL
if (reGenerateChannel) if (reGenerateChannel)
random_channel(ptr->channel_model,0); random_channel(ptr->channel_model,0);
if (t->poll_telnetcmdq) if (t->poll_telnetcmdq)
t->poll_telnetcmdq(t->telnetcmd_qid,t); t->poll_telnetcmdq(t->telnetcmd_qid,t);
for (int a=0; a<nbAnt; a++) {//loop over number of Rx antennas for (int a=0; a<nbAnt; a++) {//loop over number of Rx antennas
if ( ptr->channel_model != NULL ) // apply a channel model if ( ptr->channel_model != NULL ) // apply a channel model
...@@ -721,12 +727,13 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ...@@ -721,12 +727,13 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
else { // no channel modeling else { // no channel modeling
sample_t *out=(sample_t *)samplesVoid[a]; sample_t *out=(sample_t *)samplesVoid[a];
int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas
//LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx); //LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx);
for (int i=0; i < nsamps; i++) {//loop over nsamps for (int i=0; i < nsamps; i++) {//loop over nsamps
for (int a_tx=0; a_tx<nbAnt_tx; a_tx++){//sum up signals from nbAnt_tx antennas for (int a_tx=0; a_tx<nbAnt_tx; a_tx++) { //sum up signals from nbAnt_tx antennas
out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r; out[i].r+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].r;
out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i; out[i].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i;
} // end for a_tx } // end for a_tx
} // end for i (number of samps) } // end for i (number of samps)
} // end of no channel modeling } // end of no channel modeling
} // end for a (number of rx antennas) } // end for a (number of rx antennas)
...@@ -804,18 +811,20 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { ...@@ -804,18 +811,20 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
rfsimulator->tx_bw=openair0_cfg->tx_bw; rfsimulator->tx_bw=openair0_cfg->tx_bw;
//randominit(0); //randominit(0);
set_taus_seed(0); set_taus_seed(0);
/* look for telnet server, if it is loaded, add the channel modeling commands to it */ /* look for telnet server, if it is loaded, add the channel modeling commands to it */
add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME); add_telnetcmd_func_t addcmd = (add_telnetcmd_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_ADDCMD_FNAME);
if (addcmd != NULL) { if (addcmd != NULL) {
rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME); rfsimulator->poll_telnetcmdq = (poll_telnetcmdq_func_t)get_shlibmodule_fptr("telnetsrv", TELNET_POLLCMDQ_FNAME);
addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray); addcmd("rfsimu",rfsimu_vardef,rfsimu_cmdarray);
for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) { for(int i=0; rfsimu_cmdarray[i].cmdfunc != NULL; i++) {
if ( rfsimu_cmdarray[i].qptr != NULL) { if ( rfsimu_cmdarray[i].qptr != NULL) {
rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr; rfsimulator->telnetcmd_qid = rfsimu_cmdarray[i].qptr;
break; break;
} }
} }
} }
return 0; return 0;
} }
...@@ -34,7 +34,8 @@ int fullread(int fd, void *_buf, int count) { ...@@ -34,7 +34,8 @@ int fullread(int fd, void *_buf, int count) {
while (count) { while (count) {
l = read(fd, buf, count); l = read(fd, buf, count);
if (l <= 0) return -1; if (l <= 0)
return -1;
count -= l; count -= l;
buf += l; buf += l;
...@@ -43,6 +44,44 @@ int fullread(int fd, void *_buf, int count) { ...@@ -43,6 +44,44 @@ int fullread(int fd, void *_buf, int count) {
return ret; return ret;
} }
#define shift 4
int32_t signal_energy(int32_t *input,uint32_t length) {
int32_t i;
int32_t temp,temp2;
register __m64 mm0,mm1,mm2,mm3;
__m64 *in = (__m64 *)input;
mm0 = _mm_setzero_si64();//pxor(mm0,mm0);
mm3 = _mm_setzero_si64();//pxor(mm3,mm3);
for (i=0; i<length>>1; i++) {
mm1 = in[i];
mm2 = mm1;
mm1 = _m_pmaddwd(mm1,mm1);
mm1 = _m_psradi(mm1,shift);// shift any 32 bits blocs of the word by the value shift
mm0 = _m_paddd(mm0,mm1);// add the two 64 bits words 4 bytes by 4 bytes
// mm2 = _m_psrawi(mm2,shift_DC);
mm3 = _m_paddw(mm3,mm2);// add the two 64 bits words 2 bytes by 2 bytes
}
mm1 = mm0;
mm0 = _m_psrlqi(mm0,32);
mm0 = _m_paddd(mm0,mm1);
temp = _m_to_int(mm0);
temp/=length;
temp<<=shift; // this is the average of x^2
// now remove the DC component
mm2 = _m_psrlqi(mm3,32);
mm2 = _m_paddw(mm2,mm3);
mm2 = _m_pmaddwd(mm2,mm2);
temp2 = _m_to_int(mm2);
temp2/=(length*length);
// temp2<<=(2*shift_DC);
temp -= temp2;
_mm_empty();
_m_empty();
return((temp>0)?temp:1);
}
void fullwrite(int fd, void *_buf, int count) { void fullwrite(int fd, void *_buf, int count) {
char *buf = _buf; char *buf = _buf;
...@@ -131,8 +170,8 @@ void setblocking(int sock, enum blocking_t active) { ...@@ -131,8 +170,8 @@ void setblocking(int sock, enum blocking_t active) {
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
if(argc != 4) { if(argc < 4) {
printf("Need parameters: source file, server or destination IP, TCP port\n"); printf("Need parameters: source file, server or destination IP, TCP port (4043), 'UL|DL' if raw 2*16bits format: UL for UL IQ, DL for DL IQs \n");
exit(1); exit(1);
} }
...@@ -147,10 +186,21 @@ int main(int argc, char *argv[]) { ...@@ -147,10 +186,21 @@ int main(int argc, char *argv[]) {
serviceSock=client_start(argv[2],atoi(argv[3])); serviceSock=client_start(argv[2],atoi(argv[3]));
} }
uint64_t typeStamp=ENB_MAGICDL_FDD;
boolean_t raw=false;
if ( argc == 5 ) {
raw=true;
if (strcmp(argv[4],"UL") == 0 )
typeStamp=UE_MAGICDL_FDD;
}
samplesBlockHeader_t header; samplesBlockHeader_t header;
int bufSize=100000; int bufSize=100000;
void *buff=malloc(bufSize); void *buff=malloc(bufSize);
uint64_t readTS=0; uint64_t timestamp=0;
const int blockSize=1000;
while (1) { while (1) {
//Rewind the file to loop on the samples //Rewind the file to loop on the samples
...@@ -159,10 +209,21 @@ int main(int argc, char *argv[]) { ...@@ -159,10 +209,21 @@ int main(int argc, char *argv[]) {
// Read one block and send it // Read one block and send it
setblocking(serviceSock, blocking); setblocking(serviceSock, blocking);
AssertFatal(read(fd,&header,sizeof(header)), "");
if ( raw ) {
header.magic=typeStamp;
header.size=blockSize;
header.nbAnt=1;
header.timestamp=timestamp;
timestamp+=blockSize;
header.option_value=0;
header.option_flag=0;
} else {
AssertFatal(read(fd,&header,sizeof(header)), "");
}
fullwrite(serviceSock, &header, sizeof(header)); fullwrite(serviceSock, &header, sizeof(header));
int dataSize=sizeof(int32_t)*header.size*header.nbAnt; int dataSize=sizeof(int32_t)*header.size*header.nbAnt;
uint64_t wroteTS=header.timestamp;
if (dataSize>bufSize) { if (dataSize>bufSize) {
void *new_buff = realloc(buff, dataSize); void *new_buff = realloc(buff, dataSize);
...@@ -176,21 +237,28 @@ int main(int argc, char *argv[]) { ...@@ -176,21 +237,28 @@ int main(int argc, char *argv[]) {
} }
AssertFatal(read(fd,buff,dataSize) == dataSize, ""); AssertFatal(read(fd,buff,dataSize) == dataSize, "");
if (raw) // UHD shifts the 12 ADC values in MSB
for (int i=0; i<header.size*header.nbAnt*2; i++)
((int16_t *)buff)[i]/=16;
usleep(1000);
printf("sending at ts: %lu, number of samples: %d, energy: %d\n",
header.timestamp, header.size, signal_energy(buff, header.size));
fullwrite(serviceSock, buff, dataSize); fullwrite(serviceSock, buff, dataSize);
// Purge incoming samples // Purge incoming samples
setblocking(serviceSock, blocking); setblocking(serviceSock, notBlocking);
int ret;
do {
char buff[64000];
ret=read(serviceSock, buff, 64000);
while(readTS < wroteTS) { if ( ret<0 && !( errno == EAGAIN || errno == EWOULDBLOCK ) ) {
if ( fullread(serviceSock, &header,sizeof(header)) != sizeof(header) ||
fullread(serviceSock, buff, sizeof(int32_t)*header.size*header.nbAnt) !=
sizeof(int32_t)*header.size*header.nbAnt
) {
printf("error: %s\n", strerror(errno)); printf("error: %s\n", strerror(errno));
exit(1); exit(1);
} }
} while ( ret > 0 ) ;
readTS=header.timestamp;
}
} }
return 0; return 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment