Commit c7bcf517 authored by Laurent's avatar Laurent

add raw capture from UHD examples and fix a rfsim bug

parent 36ba2a50
......@@ -780,7 +780,7 @@ void *UE_thread(void *arg) {
msgToPush->key=slot_nr;
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
// 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
......
......@@ -30,7 +30,7 @@
#include <forms.h>
#define TPUT_WINDOW_LENGTH 100
#define ScaleZone 4
#define localBuff(NaMe,SiZe) float NaMe[SiZe]; memset(NaMe,0,sizeof(NaMe));
int otg_enabled;
......@@ -57,6 +57,7 @@ typedef struct OAIgraph {
int h;
int waterFallh;
double *waterFallAvg;
boolean_t initDone;
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);
......@@ -104,8 +105,9 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
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;
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);
......@@ -129,8 +131,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
graph->maxY=0;
graph->minX=0;
graph->minY=0;
graph->initDone=false;
graph->iteration=0;
}
......@@ -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) {
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->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->minY=min(graph->minY,minY);
fl_set_xyplot_ybounds(graph->graph, graph->minY, graph->maxY);
fl_set_xyplot_xbounds(graph->graph, graph->minX, graph->maxX);
fl_set_xyplot_ybounds(graph->graph, graph->minY*1.2, graph->maxY*1.2);
}
}
......@@ -167,7 +179,6 @@ static void oai_xygraph_getbuff(OAIgraph_t *graph, float **x, float **y, int len
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);
......@@ -213,16 +224,17 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye
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));
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;
for (int i=0; i <graph->waterFallh; i++)
for (int i=0; i < displayPart; i++)
avg+=graph->waterFallAvg[i];
avg/=graph->waterFallh;
avg/=displayPart;
graph->waterFallAvg[row]=0;
for (int pix=0; pix<graph->w; pix++) {
......@@ -249,10 +261,22 @@ static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const in
if (val > avg*100 )
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++;
}
......@@ -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) {
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);
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
......@@ -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) {
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);
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) {
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+15;
curY+=h+20;
// LLR of PUSCH
fdui->graph[3] = gNBcommonGraph( puschLLR, FL_POINTS_XYPLOT, 0, curY, 500, 200,
"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
// 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);
phy_vars_ue->frame_parms.samples_per_frame,
phy_vars_ue->frame_parms.slots_per_frame,
"X axis: one frame time");
}
/* replaced by waterfall
......@@ -566,7 +596,9 @@ static void ueFreqWaterFall (OAIgraph_t *graph,PHY_VARS_NR_UE *phy_vars_ue, int
//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);
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
scopeSample_t *pbch_comp = (scopeSample_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
float *I, *Q;
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 base=0;
......@@ -651,7 +685,7 @@ static void uePbchIQ (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_i
}
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) {
......@@ -806,7 +840,7 @@ static OAI_phy_scope_t *create_phy_scope_nrue( int ID ) {
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+15;
curY+=h+20;
// LLR of PBCH
fdui->graph[3] = nrUEcommonGraph(uePbchLLR,
FL_POINTS_XYPLOT, 0, curY, 500, 100, "PBCH Log-Likelihood Ratios (LLR, mag)", FL_GREEN );
......@@ -892,9 +926,12 @@ static void *nrUEscopeThread(void *arg) {
OAI_phy_scope_t *form_nrue=create_phy_scope_nrue(0);
while (!oai_exit) {
fl_freeze_form(form_nrue->phy_scope);
phy_scope_nrUE(form_nrue,
ue,
0,0);
fl_unfreeze_form(form_nrue->phy_scope);
fl_redraw_form(form_nrue->phy_scope);
usleep(99*1000);
}
......
......@@ -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_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);
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);
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);
rx_ind.number_pdus = 1;
// 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
}
sib1 = bcch_message->message.choice.c1->choice.systemInformationBlockType1;
if (*(int64_t*)sib1 != 1) {
printf("%llx\n", *(int64_t*)sib1);
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1);
printf("%llx\n", *(int64_t*)sib1);
xer_fprint(stdout, &asn_DEF_NR_SIB1, (const void*)sib1);
}
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;
......
......@@ -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 ( 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
for (int i=0; i<cc; i++) {
......
......@@ -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 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},
};
static telnetshell_vardef_t rfsimu_vardef[] = {
{"",0,NULL}
};
};
pthread_mutex_t Sockmutex;
typedef struct complex16 sample_t; // 2*16 bits complex number
......@@ -170,11 +170,13 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
static bool init_done=false;
if (!init_done) {
uint64_t rand;
FILE *h=fopen("/dev/random","r");
uint64_t rand;
FILE *h=fopen("/dev/random","r");
if ( 1 != fread(&rand,sizeof(rand),1,h) )
LOG_W(HW, "Simulator can't read /dev/random\n");
fclose(h);
fclose(h);
randominit(rand);
tableNor(rand);
init_done=true;
......@@ -189,7 +191,6 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
bridge->chan_offset, // maybe used for TA
bridge->chan_pathloss); // path_loss in dB
set_channeldesc_owner(ptr->channel_model, RFSIMU_MODULEID);
random_channel(ptr->channel_model,false);
}
}
......@@ -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) {
char *modelname=NULL;
char *modelname=NULL;
int s = sscanf(buff,"%ms\n",&modelname);
if (s == 1) {
int channelmod=modelid_fromname(modelname);
if (channelmod<0)
prnt("ERROR: model %s unknown\n",modelname);
else {
rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
for (int i=0; i<FD_SETSIZE; i++) {
rfsimulator_state_t *t = (rfsimulator_state_t *)arg;
for (int i=0; i<FD_SETSIZE; i++) {
buffer_t *b=&t->buf[i];
if (b->conn_sock >= 0 ) {
channel_desc_t *newmodel=new_channel_desc_scm(t->tx_num_channels,t->rx_num_channels,
channelmod,
t->sample_rate,
t->tx_bw,
30e-9, // TDL delay-spread parameter
t->chan_forgetfact, // forgetting_factor
t->chan_offset, // maybe used for TA
t->chan_pathloss); // path_loss in dB
channelmod,
t->sample_rate,
t->tx_bw,
30e-9, // TDL delay-spread parameter
t->chan_forgetfact, // forgetting_factor
t->chan_offset, // maybe used for TA
t->chan_pathloss); // path_loss in dB
set_channeldesc_owner(newmodel, RFSIMU_MODULEID);
random_channel(newmodel,false);
channel_desc_t *oldmodel=b->channel_model;
......@@ -346,8 +351,9 @@ static int rfsimu_setchanmod_cmd(char *buff, int debug, telnet_printfunc_t prnt,
}
}
} else {
prnt("ERROR: no model specified\n");
prnt("ERROR: no model specified\n");
}
free(modelname);
return CMDSTATUS_FOUND;
}
......@@ -368,7 +374,7 @@ sin_addr:
};
bind(t->listen_sock, (struct sockaddr *)&addr, sizeof(addr));
AssertFatal(listen(t->listen_sock, 5) == 0, "");
struct epoll_event ev={0};
struct epoll_event ev= {0};
ev.events = EPOLLIN;
ev.data.fd = t->listen_sock;
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
if (t->lastWroteTS > timestamp+nsamps)
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;
......@@ -505,9 +511,9 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
if ( b->headerMode)
blockSz=b->remainToTransfer;
else
blockSz= b->transferPtr+b->remainToTransfer < b->circularBufEnd ?
blockSz= b->transferPtr + b->remainToTransfer <= b->circularBufEnd ?
b->remainToTransfer :
b->circularBufEnd - 1 - b->transferPtr ;
b->circularBufEnd - b->transferPtr ;
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
AssertFatal((b->remainToTransfer-=sz) >= 0, "");
b->transferPtr+=sz;
if (b->transferPtr==b->circularBufEnd - 1)
if (b->transferPtr==b->circularBufEnd )
b->transferPtr=(char *)b->circularBuf;
// check the header and start block transfer
......@@ -552,14 +558,13 @@ static bool flushInput(rfsimulator_state_t *t, int timeout, int nsamps_for_initi
}
}
} 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)
LOG_W(HW,"UEsock: %d gap of: %ld in reception\n", fd, b->th.timestamp-b->lastReceivedTS );
b->lastReceivedTS=b->th.timestamp;
} else if ( b->lastReceivedTS > b->th.timestamp && b->th.size == 1 ) {
LOG_W(HW,"Received Rx/Tx synchro out of order\n");
b->trashingPacket=true;
......@@ -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
pthread_mutex_unlock(&Sockmutex);
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++)
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",
t->lastWroteTS, t->nextTimestamp);
rfsimulator_write_internal(t, t->nextTimestamp,
samplesVoid, 1,
dummyS, 1,
t->tx_num_channels, 1, true);
} else {
pthread_mutex_unlock(&Sockmutex);
......@@ -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
if (reGenerateChannel)
random_channel(ptr->channel_model,0);
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
if ( ptr->channel_model != NULL ) // apply a channel model
......@@ -721,12 +727,13 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
else { // no channel modeling
sample_t *out=(sample_t *)samplesVoid[a];
int nbAnt_tx = ptr->th.nbAnt;//number of Tx antennas
//LOG_I(HW, "nbAnt_tx %d\n",nbAnt_tx);
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
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;
} // end for a_tx
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].i+=ptr->circularBuf[((t->nextTimestamp+i)*nbAnt_tx+a_tx)%CirSize].i;
} // end for a_tx
} // end for i (number of samps)
} // end of no channel modeling
} // end for a (number of rx antennas)
......@@ -804,18 +811,20 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
rfsimulator->tx_bw=openair0_cfg->tx_bw;
//randominit(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);
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);
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;
break;
}
}
}
}
}
return 0;
}
......@@ -34,7 +34,8 @@ int fullread(int fd, void *_buf, int count) {
while (count) {
l = read(fd, buf, count);
if (l <= 0) return -1;
if (l <= 0)
return -1;
count -= l;
buf += l;
......@@ -43,6 +44,44 @@ int fullread(int fd, void *_buf, int count) {
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) {
char *buf = _buf;
......@@ -131,8 +170,8 @@ void setblocking(int sock, enum blocking_t active) {
}
int main(int argc, char *argv[]) {
if(argc != 4) {
printf("Need parameters: source file, server or destination IP, TCP port\n");
if(argc < 4) {
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);
}
......@@ -147,10 +186,21 @@ int main(int argc, char *argv[]) {
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;
int bufSize=100000;
void *buff=malloc(bufSize);
uint64_t readTS=0;
uint64_t timestamp=0;
const int blockSize=1000;
while (1) {
//Rewind the file to loop on the samples
......@@ -159,10 +209,21 @@ int main(int argc, char *argv[]) {
// Read one block and send it
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));
int dataSize=sizeof(int32_t)*header.size*header.nbAnt;
uint64_t wroteTS=header.timestamp;
if (dataSize>bufSize) {
void *new_buff = realloc(buff, dataSize);
......@@ -176,21 +237,28 @@ int main(int argc, char *argv[]) {
}
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);
// Purge incoming samples
setblocking(serviceSock, blocking);
setblocking(serviceSock, notBlocking);
int ret;
do {
char buff[64000];
ret=read(serviceSock, buff, 64000);
while(readTS < wroteTS) {
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
) {
if ( ret<0 && !( errno == EAGAIN || errno == EWOULDBLOCK ) ) {
printf("error: %s\n", strerror(errno));
exit(1);
}
readTS=header.timestamp;
}
} while ( ret > 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