Commit 9ce7f945 authored by Laurent Thomas's avatar Laurent Thomas

record/replay for 5G, nrscope bug fix

parent f5a22a74
...@@ -1318,7 +1318,7 @@ int main ( int argc, char **argv ) { ...@@ -1318,7 +1318,7 @@ int main ( int argc, char **argv ) {
// end of CI modifications // end of CI modifications
//getchar(); //getchar();
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
load_softscope("enb", NULL); load_softscope("enb", NULL);
itti_wait_tasks_end(); itti_wait_tasks_end();
...@@ -1327,7 +1327,7 @@ int main ( int argc, char **argv ) { ...@@ -1327,7 +1327,7 @@ int main ( int argc, char **argv ) {
// stop threads // stop threads
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
end_forms(); end_forms();
LOG_I(ENB_APP,"stopping MODEM threads\n"); LOG_I(ENB_APP,"stopping MODEM threads\n");
......
...@@ -89,7 +89,7 @@ static int DEFBFW[] = {0x00007fff}; ...@@ -89,7 +89,7 @@ static int DEFBFW[] = {0x00007fff};
#include "s1ap_eNB.h" #include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h" #include "SIMULATION/ETH_TRANSPORT/proto.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "T.h" #include "T.h"
...@@ -1593,7 +1593,8 @@ void *ru_thread( void *param ) { ...@@ -1593,7 +1593,8 @@ void *ru_thread( void *param ) {
for (aa=0;aa<ru->nb_rx;aa++) for (aa=0;aa<ru->nb_rx;aa++)
memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa], memcpy((void*)RC.gNB[0]->common_vars.rxdataF[aa],
(void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t)); (void*)ru->common.rxdataF[aa], fp->symbols_per_slot*fp->ofdm_symbol_size*sizeof(int32_t));
if (IS_SOFTMODEM_DOSCOPE && RC.gNB[0]->scopeData)
((scopeData_t*)RC.gNB[0]->scopeData)->slotFunc(ru->common.rxdataF[0],proc->tti_rx, RC.gNB[0]->scopeData);
// Do PRACH RU processing // Do PRACH RU processing
int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST); int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST);
......
...@@ -900,7 +900,7 @@ if(!IS_SOFTMODEM_NOS1) ...@@ -900,7 +900,7 @@ if(!IS_SOFTMODEM_NOS1)
printf("RC.nb_RU:%d\n", RC.nb_RU); printf("RC.nb_RU:%d\n", RC.nb_RU);
// once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration) // once all RUs are ready initialize the rest of the gNBs ((dependence on final RU parameters after configuration)
printf("ALL RUs ready - init gNBs\n"); printf("ALL RUs ready - init gNBs\n");
if(IS_SOFTMODEM_DOFORMS) { if(IS_SOFTMODEM_DOSCOPE) {
sleep(1); sleep(1);
scopeParms_t p; scopeParms_t p;
p.argc=&argc; p.argc=&argc;
......
...@@ -551,7 +551,7 @@ int main( int argc, char **argv ) { ...@@ -551,7 +551,7 @@ int main( int argc, char **argv ) {
configure_linux(); configure_linux();
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
if(IS_SOFTMODEM_DOFORMS) { if(IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr",PHY_vars_UE_g[0][0]); load_softscope("nr",PHY_vars_UE_g[0][0]);
} }
......
...@@ -996,7 +996,7 @@ int main( int argc, char **argv ) { ...@@ -996,7 +996,7 @@ int main( int argc, char **argv ) {
(void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW); (void *)NULL, "time_meas", -1, OAI_PRIORITY_RT_LOW);
} }
if(IS_SOFTMODEM_DOFORMS) { if(IS_SOFTMODEM_DOSCOPE) {
scopeParms_t tmp= {&argc, argv, &ru, RC.gNB[0]}; scopeParms_t tmp= {&argc, argv, &ru, RC.gNB[0]};
load_softscope("nr",&tmp); load_softscope("nr",&tmp);
} }
......
...@@ -140,7 +140,7 @@ void get_common_options(uint32_t execmask) { ...@@ -140,7 +140,7 @@ void get_common_options(uint32_t execmask) {
} }
if (do_forms) { if (do_forms) {
set_softmodem_optmask(SOFTMODEM_DOFORMS_BIT); set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT);
} }
if(parallel_config != NULL) set_parallel_conf(parallel_config); if(parallel_config != NULL) set_parallel_conf(parallel_config);
......
...@@ -188,7 +188,7 @@ extern "C" ...@@ -188,7 +188,7 @@ extern "C"
#define SOFTMODEM_RFSIM_BIT (1<<10) #define SOFTMODEM_RFSIM_BIT (1<<10)
#define SOFTMODEM_BASICSIM_BIT (1<<11) #define SOFTMODEM_BASICSIM_BIT (1<<11)
#define SOFTMODEM_SIML1_BIT (1<<12) #define SOFTMODEM_SIML1_BIT (1<<12)
#define SOFTMODEM_DOFORMS_BIT (1<<15) #define SOFTMODEM_DOSCOPE_BIT (1<<15)
#define SOFTMODEM_RECPLAY_BIT (1<<16) #define SOFTMODEM_RECPLAY_BIT (1<<16)
#define SOFTMODEM_ENB_BIT (1<<20) #define SOFTMODEM_ENB_BIT (1<<20)
#define SOFTMODEM_GNB_BIT (1<<21) #define SOFTMODEM_GNB_BIT (1<<21)
...@@ -204,7 +204,7 @@ extern "C" ...@@ -204,7 +204,7 @@ extern "C"
#define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT) #define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT)
#define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_BIT) #define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_BIT)
#define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT) #define IS_SOFTMODEM_SIML1 ( get_softmodem_optmask() & SOFTMODEM_SIML1_BIT)
#define IS_SOFTMODEM_DOFORMS ( get_softmodem_optmask() & SOFTMODEM_DOFORMS_BIT) #define IS_SOFTMODEM_DOSCOPE ( get_softmodem_optmask() & SOFTMODEM_DOSCOPE_BIT)
#define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT) #define IS_SOFTMODEM_IQPLAYER ( get_softmodem_optmask() & SOFTMODEM_RECPLAY_BIT)
#define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT) #define IS_SOFTMODEM_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT)
#define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT) #define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT)
......
...@@ -56,7 +56,7 @@ typedef struct OAIgraph { ...@@ -56,7 +56,7 @@ typedef struct OAIgraph {
double *waterFallAvg; double *waterFallAvg;
boolean_t initDone; 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, scopeData_t *p, 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);
} OAIgraph_t; } OAIgraph_t;
...@@ -132,7 +132,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_ ...@@ -132,7 +132,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
graph->iteration=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), static OAIgraph_t gNBcommonGraph( void (*funct) (OAIgraph_t *graph, scopeData_t *p, int UE_id),
int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) { int type, FL_Coord x, FL_Coord y, FL_Coord w, FL_Coord h, const char *label, FL_COLOR pointColor) {
OAIgraph_t graph; OAIgraph_t graph;
commonGraph(&graph, type, x, y, w, h, label, pointColor); commonGraph(&graph, type, x, y, w, h, label, pointColor);
...@@ -223,7 +223,8 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye ...@@ -223,7 +223,8 @@ static void oai_xygraph(OAIgraph_t *graph, float *x, float *y, int len, int laye
static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) { static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) {
if ( values == NULL ) if ( values == NULL )
return; return;
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 displayPart=graph->waterFallh-ScaleZone; int displayPart=graph->waterFallh-ScaleZone;
...@@ -318,10 +319,10 @@ static void genericPowerPerAntena(OAIgraph_t *graph, const int nb_ant, const sc ...@@ -318,10 +319,10 @@ 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, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms;
//use 1st antenna //use 1st antenna
genericWaterFall(graph, (scopeSample_t *)phy_vars_ru->common.rxdata[0], genericWaterFall(graph, (scopeSample_t *)p->ru->common.rxdata[0],
frame_parms->samples_per_frame, frame_parms->slots_per_frame, frame_parms->samples_per_frame, frame_parms->slots_per_frame,
"X axis:one frame in time"); "X axis:one frame in time");
} }
...@@ -339,31 +340,35 @@ static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy ...@@ -339,31 +340,35 @@ static void timeSignal (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy
} }
*/ */
static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { static void timeResponse (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size; const int len=2*p->gNB->frame_parms.ofdm_symbol_size;
float *values, *time; float *values, *time;
oai_xygraph_getbuff(graph, &time, &values, len, 0); oai_xygraph_getbuff(graph, &time, &values, len, 0);
const int ant=0; // display antenna 0 for each UE const int ant=0; // display antenna 0 for each UE
for (int ue=0; ue<nb_UEs; ue++) { for (int ue=0; ue<nb_UEs; ue++) {
scopeSample_t *data= (scopeSample_t *)phy_vars_gnb->pusch_vars[ue]->ul_ch_estimates_time[ant]; if ( p->gNB->pusch_vars && p->gNB->pusch_vars[ue] &&
p->gNB->pusch_vars[ue]->ul_ch_estimates_time &&
p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant] ) {
scopeSample_t *data= (scopeSample_t *)p->gNB->pusch_vars[ue]->ul_ch_estimates_time[ant];
if (data != NULL) {
for (int i=0; i<len; i++) {
values[i] = SquaredNorm(data[i]);
}
if (data != NULL) { oai_xygraph(graph,time,values, len, ue, 10);
for (int i=0; i<len; i++) {
values[i] = SquaredNorm(data[i]);
} }
oai_xygraph(graph,time,values, len, ue, 10);
} }
} }
} }
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, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; NR_DL_FRAME_PARMS *frame_parms=&p->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 *)p->rxdataF, frame_parms->samples_per_frame_wCP,
frame_parms->slots_per_frame, frame_parms->slots_per_frame,
"X axis: Frequency domain, one frame"); "X axis: Frequency domain, one subframe");
} }
/* /*
...@@ -375,16 +380,18 @@ static void frequencyResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU ...@@ -375,16 +380,18 @@ static void frequencyResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU
} }
*/ */
static void puschLLR (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { static void puschLLR (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
//int Qm = 2; //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; 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;
for (int ue=0; ue<nb_UEs; ue++) { for (int ue=0; ue<nb_UEs; ue++) {
int16_t *pusch_llr = (int16_t *)phy_vars_gnb->pusch_vars[ue]->llr; if ( p->gNB->pusch_vars &&
float *llr, *bit; p->gNB->pusch_vars[ue] &&
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword, ue); p->gNB->pusch_vars[ue]->llr ) {
int16_t *pusch_llr = (int16_t *)p->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++) { for (int i=0; i<coded_bits_per_codeword; i++) {
llr[i] = (float) pusch_llr[i]; llr[i] = (float) pusch_llr[i];
} }
...@@ -394,16 +401,19 @@ static void puschLLR (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_v ...@@ -394,16 +401,19 @@ 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) { static void puschIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms; NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms;
int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot; int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot;
for (int ue=0; ue<nb_UEs; ue++) { for (int ue=0; ue<nb_UEs; ue++) {
scopeSample_t *pusch_comp = (scopeSample_t *) phy_vars_gnb->pusch_vars[ue]->rxdataF_comp[0]; if ( p->gNB->pusch_vars &&
float *I, *Q; p->gNB->pusch_vars[ue] &&
oai_xygraph_getbuff(graph, &I, &Q, sz, ue); p->gNB->pusch_vars[ue]->rxdataF_comp &&
p->gNB->pusch_vars[ue]->rxdataF_comp[0] ) {
scopeSample_t *pusch_comp = (scopeSample_t *) p->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++ ) { for (int k=0; k<sz; k++ ) {
I[k] = pusch_comp[k].r; I[k] = pusch_comp[k].r;
Q[k] = pusch_comp[k].i; Q[k] = pusch_comp[k].i;
...@@ -414,7 +424,7 @@ static void puschIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_va ...@@ -414,7 +424,7 @@ static void puschIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_va
} }
} }
static void pucchEnergy (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { static void pucchEnergy (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
// PUSCH I/Q of MF Output // PUSCH I/Q of MF Output
/* /*
int32_t *pucch1ab_comp = (int32_t *) NULL; //phy_vars_gnb->pucch1ab_stats[UE_id]; int32_t *pucch1ab_comp = (int32_t *) NULL; //phy_vars_gnb->pucch1ab_stats[UE_id];
...@@ -440,10 +450,10 @@ static void pucchEnergy (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *ph ...@@ -440,10 +450,10 @@ static void pucchEnergy (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *ph
*/ */
} }
static void pucchIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { static void pucchIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
} }
static void puschThroughtput (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) { static void puschThroughtput (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
// PUSCH Throughput // PUSCH Throughput
/* /*
float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}}; float tput_time_enb[NUMBER_OF_UE_MAX][TPUT_WINDOW_LENGTH] = {{0}};
...@@ -510,8 +520,7 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) { ...@@ -510,8 +520,7 @@ static OAI_phy_scope_t *create_phy_scope_gnb(void) {
static const int scope_enb_num_ue = 1; static const int scope_enb_num_ue = 1;
void phy_scope_gNB(OAI_phy_scope_t *form, void phy_scope_gNB(OAI_phy_scope_t *form,
PHY_VARS_gNB *phy_vars_gnb, scopeData_t *p,
RU_t *phy_vars_ru,
int UE_id) { int UE_id) {
static OAI_phy_scope_t *rememberForm=NULL; static OAI_phy_scope_t *rememberForm=NULL;
...@@ -526,7 +535,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form, ...@@ -526,7 +535,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
int i=0; int i=0;
while (form->graph[i].graph) { while (form->graph[i].graph) {
form->graph[i].gNBfunct(form->graph+i, phy_vars_gnb, phy_vars_ru, UE_id); form->graph[i].gNBfunct(form->graph+i, p, UE_id);
i++; i++;
} }
...@@ -534,7 +543,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form, ...@@ -534,7 +543,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
} }
static void *scope_thread_gNB(void *arg) { static void *scope_thread_gNB(void *arg) {
scopeParms_t *p=(scopeParms_t *) arg; scopeData_t *p=(scopeData_t *) arg;
//# ifdef ENABLE_XFORMS_WRITE_STATS //# ifdef ENABLE_XFORMS_WRITE_STATS
// FILE *gNB_stats = fopen("gNB_stats.txt", "w"); // FILE *gNB_stats = fopen("gNB_stats.txt", "w");
//#endif //#endif
...@@ -543,12 +552,6 @@ static void *scope_thread_gNB(void *arg) { ...@@ -543,12 +552,6 @@ static void *scope_thread_gNB(void *arg) {
pthread_attr_init(&atr); pthread_attr_init(&atr);
pthread_attr_getstacksize(&atr, &stksize); pthread_attr_getstacksize(&atr, &stksize);
pthread_attr_setstacksize(&atr,32*1024*1024 ); pthread_attr_setstacksize(&atr,32*1024*1024 );
p.gNB->scopeData=calloc(sizeof(nrscope_t));
nrscope_t scope=(nrscope_t*) p.gNB->scopeData;
scope->rxdataF=(int32_t **)malloc16(Prx*sizeof(int32_t*));
for (int i=0; i < p.gNB->gNB_config.carrier_config.num_rx_ant.value; ; i++)
scope->rxdataF[i] = (scopeSample_t*)malloc16_clear(p->gNB.frme_parms.samples_per_frame_wCP*sizeof(scopeSample_t));
sleep(3); // no clean interthread barriers sleep(3); // no clean interthread barriers
int fl_argc=1; int fl_argc=1;
char *name="5G-gNB-scope"; char *name="5G-gNB-scope";
...@@ -557,18 +560,31 @@ static void *scope_thread_gNB(void *arg) { ...@@ -557,18 +560,31 @@ static void *scope_thread_gNB(void *arg) {
OAI_phy_scope_t *form_gnb = create_phy_scope_gnb(); OAI_phy_scope_t *form_gnb = create_phy_scope_gnb();
while (!oai_exit) { while (!oai_exit) {
phy_scope_gNB(form_gnb, p->gNB, p->ru, nb_ue); phy_scope_gNB(form_gnb, p, nb_ue);
usleep(99*1000); usleep(99*1000);
} }
return NULL; return NULL;
} }
static void copyRxdataF(int32_t *data, int slot, void *scopeData) {
scopeData_t *scope=(scopeData_t *)scopeData;
memcpy(scope->rxdataF + slot*scope->gNB->frame_parms.samples_per_slot_wCP,
data,
scope->gNB->frame_parms.samples_per_slot_wCP);
}
void gNBinitScope(scopeParms_t *p) { void gNBinitScope(scopeParms_t *p) {
static scopeParms_t parms; AssertFatal(p->gNB->scopeData=malloc(sizeof(scopeData_t)),"");
memcpy(&parms,p,sizeof(parms)); scopeData_t *scope=(scopeData_t *) p->gNB->scopeData;
scope->argc=p->argc;
scope->argv=p->argv;
scope->ru=p->ru;
scope->gNB=p->gNB;
scope->slotFunc=copyRxdataF;
AssertFatal(scope->rxdataF=(int32_t *) calloc(p->gNB->frame_parms.samples_per_frame_wCP*sizeof(int32_t),1),"");
pthread_t forms_thread; pthread_t forms_thread;
threadCreate(&forms_thread, scope_thread_gNB, &parms, "scope", -1, OAI_PRIORITY_RT_LOW); threadCreate(&forms_thread, scope_thread_gNB, p->gNB->scopeData, "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) { static void ueWaterFall (OAIgraph_t *graph, PHY_VARS_NR_UE *phy_vars_ue, int eNB_id, int UE_id) {
......
...@@ -33,13 +33,7 @@ ...@@ -33,13 +33,7 @@
//#include "PHY/impl_defs_top.h" //#include "PHY/impl_defs_top.h"
#include "PHY/defs_nr_UE.h" #include "PHY/defs_nr_UE.h"
typedef struct { #include <openair1/PHY/TOOLS/phy_scope_interface.h>
int *argc;
char **argv;
RU_t *ru;
PHY_VARS_gNB *gNB;
} scopeParms_t;
extern RAN_CONTEXT_t RC; extern RAN_CONTEXT_t RC;
#endif #endif
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include "phy_scope_interface.h" #include "phy_scope_interface.h"
#define SOFTSCOPE_ENDFUNC_IDX 0 #define SOFTSCOPE_ENDFUNC_IDX 0
static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}}; static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}};
int load_softscope(char *exectype, void *initarg) { int load_softscope(char *exectype, void *initarg) {
......
...@@ -29,7 +29,26 @@ ...@@ -29,7 +29,26 @@
* \note * \note
* \warning * \warning
*/ */
#ifndef __PHY_SCOPE_INTERFACE_H__
#define __PHY_SCOPE_INTERFACE_H__
#include <openair1/PHY/defs_gNB.h>
typedef struct {
int *argc;
char **argv;
RU_t *ru;
PHY_VARS_gNB *gNB;
} scopeParms_t;
typedef struct scopeData_s {
int *argc;
char **argv;
RU_t *ru;
PHY_VARS_gNB *gNB;
int32_t * rxdataF;
void (*slotFunc)(int32_t* data, int slot, void * scopeData);
} scopeData_t;
int load_softscope(char *exectype, void *initarg); int load_softscope(char *exectype, void *initarg);
int end_forms(void) ; int end_forms(void) ;
#endif
...@@ -68,8 +68,10 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ ...@@ -68,8 +68,10 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_
*recplay_conf=NULL; *recplay_conf=NULL;
} }
if (u_sf_replay == 1) return RECPLAY_REPLAYMODE; if (u_sf_replay == 1)
else if (u_sf_record == 1) return RECPLAY_RECORDMODE; return RECPLAY_REPLAYMODE;
else if (u_sf_record == 1)
return RECPLAY_RECORDMODE;
return 0; return 0;
} }
...@@ -80,7 +82,7 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_ ...@@ -80,7 +82,7 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_
*/ */
void iqrecorder_end(openair0_device *device) { void iqrecorder_end(openair0_device *device) {
if (device->recplay_state != NULL) { // subframes store if (device->recplay_state != NULL) { // subframes store
iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,OAIIQFILE_ID}; iqfile_header_t fh = {device->type,device->openair0_cfg->tx_sample_advance, device->openair0_cfg->rx_bw,0,OAIIQFILE_ID};
recplay_state_t *rs = device->recplay_state; recplay_state_t *rs = device->recplay_state;
recplay_conf_t *rc = device->openair0_cfg[0].recplay_conf; recplay_conf_t *rc = device->openair0_cfg[0].recplay_conf;
rs->pFile = fopen (rc->u_sf_filename,"wb+"); rs->pFile = fopen (rc->u_sf_filename,"wb+");
...@@ -91,16 +93,20 @@ void iqrecorder_end(openair0_device *device) { ...@@ -91,16 +93,20 @@ void iqrecorder_end(openair0_device *device) {
unsigned int i = 0; unsigned int i = 0;
unsigned int modu = 0; unsigned int modu = 0;
if ((modu = rs->nb_samples % 10) != 0) { if ((modu = rs->nbSamplesBlocks % 10) != 0) {
rs->nb_samples -= modu; // store entire number of frames rs->nbSamplesBlocks -= modu; // store entire number of frames
} }
fh.nbSamplesBlocks=rs->nbSamplesBlocks;
LOG_I(HW,"Writing file header to %s \n", rc->u_sf_filename ); LOG_I(HW,"Writing file header to %s \n", rc->u_sf_filename );
fwrite(&fh, sizeof(fh), 1, rs->pFile); fwrite(&fh, sizeof(fh), 1, rs->pFile);
LOG_UI(HW,"Writing %u subframes to %s \n",rs->nb_samples, rc->u_sf_filename ); LOG_UI(HW,"Writing %u subframes to %s \n",rs->nbSamplesBlocks, rc->u_sf_filename );
uint8_t *ptr=(uint8_t *)rs->ms_sample;
for (i = 0; i < rs->nb_samples; i++) { for (i = 0; i < rs->nbSamplesBlocks; i++) {
fwrite(rs->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), rs->pFile); int blockBytes=sizeof(iqrec_t)+((iqrec_t *)ptr)->nbBytes;
fwrite(ptr, sizeof(unsigned char), blockBytes, rs->pFile);
ptr+=blockBytes;
} }
fclose (rs->pFile); fclose (rs->pFile);
...@@ -112,4 +118,4 @@ void iqrecorder_end(openair0_device *device) { ...@@ -112,4 +118,4 @@ void iqrecorder_end(openair0_device *device) {
rs->ms_sample = NULL; rs->ms_sample = NULL;
} }
} }
} }
\ No newline at end of file
...@@ -46,21 +46,22 @@ extern "C" ...@@ -46,21 +46,22 @@ extern "C"
#define BELL_LABS_IQ_HEADER 0xabababababababab #define BELL_LABS_IQ_HEADER 0xabababababababab
#define BELL_LABS_IQ_PER_SF 7680 // Up to 5MHz bw for now #define BELL_LABS_IQ_PER_SF 7680 // Up to 5MHz bw for now
#define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4) #define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4)
#define MAX_BELL_LABS_IQ_BYTES_PER_SF BELL_LABS_IQ_BYTES_PER_SF*10
#define OAIIQFILE_ID "OIQF" #define OAIIQFILE_ID {'O', 'I','Q','F'}
typedef struct { typedef struct {
uint64_t devtype; uint64_t devtype;
uint64_t tx_sample_advance; uint64_t tx_sample_advance;
double bw; double bw;
unsigned int nbSamplesBlocks;
char oaiid[4]; char oaiid[4];
} iqfile_header_t; } iqfile_header_t;
typedef struct { typedef struct {
int64_t header; int64_t header;
int64_t ts; int64_t ts;
int64_t rfu1; int64_t nbBytes;
int64_t rfu2; // pad for 256 bits alignement required by AVX2 int64_t rfu2; // pad for 256 bits alignement required by AVX2
unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe
} iqrec_t; } iqrec_t;
#define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz) #define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz)
#define DEF_SF_FILE "/tmp/iqfile" // default subframes file name #define DEF_SF_FILE "/tmp/iqfile" // default subframes file name
...@@ -114,14 +115,16 @@ typedef struct { ...@@ -114,14 +115,16 @@ typedef struct {
int use_mmap; // default is to use mmap int use_mmap; // default is to use mmap
size_t mapsize; size_t mapsize;
FILE *pFile; FILE *pFile;
int mmapfd; int fd;
int iqfd;
iqrec_t *ms_sample; // memory for all subframes iqrec_t *ms_sample; // memory for all subframes
unsigned int nb_samples; unsigned int nbSamplesBlocks;
uint8_t *currentPtr;
uint64_t currentTs;
unsigned int curSamplesBlock;
int64_t wrap_count;
size_t maxSizeBytes;
} recplay_state_t; } recplay_state_t;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -272,11 +272,10 @@ static int sync_to_gps(openair0_device *device) { ...@@ -272,11 +272,10 @@ static int sync_to_gps(openair0_device *device) {
*/ */
static int trx_usrp_start(openair0_device *device) { static int trx_usrp_start(openair0_device *device) {
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
// setup GPIO for TDD, GPIO(4) = ATR_RX // setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output //set data direction register (DDR) to output
s->usrp->set_gpio_attr("FP0", "DDR", 0xfff, 0xfff); s->usrp->set_gpio_attr("FP0", "DDR", 0xfff, 0xfff);
//set lower 7 bits to be controlled automatically by ATR (the rest 5 bits are controlled manually) //set lower 7 bits to be controlled automatically by ATR (the rest 5 bits are controlled manually)
s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0xfff); s->usrp->set_gpio_attr("FP0", "CTRL", 0x7f,0xfff);
//set pins 4 (RX_TX_Switch) and 6 (Shutdown PA) to 1 when the radio is only receiving (ATR_RX) //set pins 4 (RX_TX_Switch) and 6 (Shutdown PA) to 1 when the radio is only receiving (ATR_RX)
s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f); s->usrp->set_gpio_attr("FP0", "ATR_RX", (1<<4)|(1<<6), 0x7f);
...@@ -285,26 +284,24 @@ static int trx_usrp_start(openair0_device *device) { ...@@ -285,26 +284,24 @@ static int trx_usrp_start(openair0_device *device) {
s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f); s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f);
// set the output pins to 1 // set the output pins to 1
s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80); s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80);
s->wait_for_first_pps = 1; s->wait_for_first_pps = 1;
s->rx_count = 0; s->rx_count = 0;
s->tx_count = 0; s->tx_count = 0;
//s->first_tx = 1; //s->first_tx = 1;
//s->first_rx = 1; //s->first_rx = 1;
s->rx_timestamp = 0; s->rx_timestamp = 0;
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0)); s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
// wait for the pps to change // wait for the pps to change
uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps(); uhd::time_spec_t time_last_pps = s->usrp->get_time_last_pps();
while (time_last_pps == s->usrp->get_time_last_pps()) { while (time_last_pps == s->usrp->get_time_last_pps()) {
boost::this_thread::sleep(boost::posix_time::milliseconds(1)); boost::this_thread::sleep(boost::posix_time::milliseconds(1));
} }
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS); uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = uhd::time_spec_t(1.0); cmd.time_spec = uhd::time_spec_t(1.0);
cmd.stream_now = false; // start at constant delay cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd); s->rx_stream->issue_stream_cmd(cmd);
return 0; return 0;
} }
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources /*! \brief Terminate operation of the USRP transceiver -- free all associated resources
...@@ -315,12 +312,11 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -315,12 +312,11 @@ static void trx_usrp_end(openair0_device *device) {
return; return;
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
if (s == NULL) if (s == NULL)
return; return;
iqrecorder_end(device);
iqrecorder_end(device);
} }
/*! \brief Called to send samples to the USRP RF target /*! \brief Called to send samples to the USRP RF target
...@@ -332,64 +328,59 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -332,64 +328,59 @@ static void trx_usrp_end(openair0_device *device) {
@param flags flags must be set to TRUE if timestamp parameter needs to be applied @param flags flags must be set to TRUE if timestamp parameter needs to be applied
*/ */
static int trx_usrp_write(openair0_device *device, static int trx_usrp_write(openair0_device *device,
openair0_timestamp timestamp, openair0_timestamp timestamp,
void **buff, void **buff,
int nsamps, int nsamps,
int cc, int cc,
int flags) { int flags) {
int ret=0; int ret=0;
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
int nsamps2; // aligned to upper 32 or 16 byte boundary int nsamps2; // aligned to upper 32 or 16 byte boundary
int flags_lsb = flags&0xff; int flags_lsb = flags&0xff;
int flags_msb = (flags>>8)&0xff; int flags_msb = (flags>>8)&0xff;
int end; int end;
openair0_thread_t *write_thread = &device->write_thread; openair0_thread_t *write_thread = &device->write_thread;
openair0_write_package_t *write_package = write_thread->write_package; openair0_write_package_t *write_package = write_thread->write_package;
AssertFatal( MAX_WRITE_THREAD_BUFFER_SIZE >= cc,"Do not support more than %d cc number\n", MAX_WRITE_THREAD_BUFFER_SIZE); AssertFatal( MAX_WRITE_THREAD_BUFFER_SIZE >= cc,"Do not support more than %d cc number\n", MAX_WRITE_THREAD_BUFFER_SIZE);
boolean_t first_packet_state=false,last_packet_state=false;
boolean_t first_packet_state=false,last_packet_state=false;
if (flags_lsb == 2) { // start of burst
if (flags_lsb == 2) { // start of burst // s->tx_md.start_of_burst = true;
// s->tx_md.start_of_burst = true; // s->tx_md.end_of_burst = false;
// s->tx_md.end_of_burst = false; first_packet_state = true;
first_packet_state = true; last_packet_state = false;
last_packet_state = false; } else if (flags_lsb == 3) { // end of burst
} else if (flags_lsb == 3) { // end of burst //s->tx_md.start_of_burst = false;
//s->tx_md.start_of_burst = false; //s->tx_md.end_of_burst = true;
//s->tx_md.end_of_burst = true; first_packet_state = false;
first_packet_state = false; last_packet_state = true;
last_packet_state = true; } else if (flags_lsb == 4) { // start and end
} else if (flags_lsb == 4) { // start and end
// s->tx_md.start_of_burst = true; // s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = true; // s->tx_md.end_of_burst = true;
first_packet_state = true; first_packet_state = true;
last_packet_state = true; last_packet_state = true;
} else if (flags_lsb==1) { // middle of burst } else if (flags_lsb==1) { // middle of burst
// s->tx_md.start_of_burst = false; // s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = false; // s->tx_md.end_of_burst = false;
first_packet_state = false; first_packet_state = false;
last_packet_state = false; last_packet_state = false;
} } else if (flags_lsb==10) { // fail safe mode
else if (flags_lsb==10) { // fail safe mode // s->tx_md.has_time_spec = false;
// s->tx_md.has_time_spec = false; // s->tx_md.start_of_burst = false;
// s->tx_md.start_of_burst = false; // s->tx_md.end_of_burst = true;
// s->tx_md.end_of_burst = true; first_packet_state = false;
first_packet_state = false; last_packet_state = true;
last_packet_state = true; }
}
if(usrp_tx_thread == 0){ if(usrp_tx_thread == 0) {
#if defined(__x86_64) || defined(__i386__) #if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
nsamps2 = (nsamps+7)>>3; nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[8][nsamps2]; __m256i buff_tx[8][nsamps2];
#else #else
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
__m128i buff_tx[8][nsamps2]; __m128i buff_tx[8][nsamps2];
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tx[8][nsamps2]; int16x8_t buff_tx[8][nsamps2];
...@@ -417,8 +408,8 @@ static int trx_usrp_write(openair0_device *device, ...@@ -417,8 +408,8 @@ static int trx_usrp_write(openair0_device *device,
s->tx_md.end_of_burst = last_packet_state; s->tx_md.end_of_burst = last_packet_state;
s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate); s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
s->tx_count++; s->tx_count++;
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,1);
// bit 3 enables gpio (for backward compatibility) // bit 3 enables gpio (for backward compatibility)
if (flags_msb&8) { if (flags_msb&8) {
// push GPIO bits 7-9 from flags_msb // push GPIO bits 7-9 from flags_msb
...@@ -427,7 +418,8 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI ...@@ -427,7 +418,8 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
s->usrp->set_gpio_attr("FP0", "OUT", gpio789, 0x380); s->usrp->set_gpio_attr("FP0", "OUT", gpio789, 0x380);
s->usrp->clear_command_time(); s->usrp->clear_command_time();
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,0);
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHING_GPIO,0);
if (cc>1) { if (cc>1) {
std::vector<void *> buff_ptrs; std::vector<void *> buff_ptrs;
...@@ -436,18 +428,18 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI ...@@ -436,18 +428,18 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0])); buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0]));
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md);
} } else {
else {
ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md);
} }
if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); if (ret != nsamps)
LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps);
return ret; return ret;
} } else {
else{
pthread_mutex_lock(&write_thread->mutex_write); pthread_mutex_lock(&write_thread->mutex_write);
if(write_thread->count_write >= MAX_WRITE_THREAD_PACKAGE){ if(write_thread->count_write >= MAX_WRITE_THREAD_PACKAGE) {
LOG_W(HW,"Buffer overflow, count_write = %d, start = %d end = %d, resetting write package\n", write_thread->count_write, write_thread->start, write_thread->end); LOG_W(HW,"Buffer overflow, count_write = %d, start = %d end = %d, resetting write package\n", write_thread->count_write, write_thread->start, write_thread->end);
write_thread->end = write_thread->start; write_thread->end = write_thread->start;
write_thread->count_write = 0; write_thread->count_write = 0;
...@@ -460,15 +452,16 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI ...@@ -460,15 +452,16 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
write_package[end].first_packet = first_packet_state; write_package[end].first_packet = first_packet_state;
write_package[end].last_packet = last_packet_state; write_package[end].last_packet = last_packet_state;
write_package[end].flags_msb = flags_msb; write_package[end].flags_msb = flags_msb;
for (int i = 0; i < cc; i++) for (int i = 0; i < cc; i++)
write_package[end].buff[i] = buff[i]; write_package[end].buff[i] = buff[i];
write_thread->count_write++; write_thread->count_write++;
write_thread->end = (write_thread->end + 1)% MAX_WRITE_THREAD_PACKAGE; write_thread->end = (write_thread->end + 1)% MAX_WRITE_THREAD_PACKAGE;
pthread_cond_signal(&write_thread->cond_write); pthread_cond_signal(&write_thread->cond_write);
pthread_mutex_unlock(&write_thread->mutex_write); pthread_mutex_unlock(&write_thread->mutex_write);
return 0; return 0;
} }
} }
//-----------------------start-------------------------- //-----------------------start--------------------------
...@@ -480,12 +473,11 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI ...@@ -480,12 +473,11 @@ VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_BEAM_SWITCHI
@param antenna_id index of the antenna if the device has multiple antennas @param antenna_id index of the antenna if the device has multiple antennas
@param flags flags must be set to TRUE if timestamp parameter needs to be applied @param flags flags must be set to TRUE if timestamp parameter needs to be applied
*/ */
void *trx_usrp_write_thread(void * arg){ void *trx_usrp_write_thread(void *arg) {
int ret=0; int ret=0;
openair0_device *device=(openair0_device *)arg; openair0_device *device=(openair0_device *)arg;
openair0_thread_t *write_thread = &device->write_thread; openair0_thread_t *write_thread = &device->write_thread;
openair0_write_package_t *write_package = write_thread->write_package; openair0_write_package_t *write_package = write_thread->write_package;
usrp_state_t *s; usrp_state_t *s;
int nsamps2; // aligned to upper 32 or 16 byte boundary int nsamps2; // aligned to upper 32 or 16 byte boundary
int start; int start;
...@@ -497,11 +489,13 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -497,11 +489,13 @@ void *trx_usrp_write_thread(void * arg){
signed char last_packet; signed char last_packet;
int flags_msb; int flags_msb;
while(1){ while(1) {
pthread_mutex_lock(&write_thread->mutex_write); pthread_mutex_lock(&write_thread->mutex_write);
while (write_thread->count_write == 0) { while (write_thread->count_write == 0) {
pthread_cond_wait(&write_thread->cond_write,&write_thread->mutex_write); // this unlocks mutex_rxtx while waiting and then locks it again pthread_cond_wait(&write_thread->cond_write,&write_thread->mutex_write); // this unlocks mutex_rxtx while waiting and then locks it again
} }
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 1 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 1 );
s = (usrp_state_t *)device->priv; s = (usrp_state_t *)device->priv;
start = write_thread->start; start = write_thread->start;
...@@ -518,38 +512,36 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -518,38 +512,36 @@ void *trx_usrp_write_thread(void * arg){
/*if(write_thread->count_write != 0){ /*if(write_thread->count_write != 0){
LOG_W(HW,"count write = %d, start = %d, end = %d\n", write_thread->count_write, write_thread->start, write_thread->end); LOG_W(HW,"count write = %d, start = %d, end = %d\n", write_thread->count_write, write_thread->start, write_thread->end);
}*/ }*/
#if defined(__x86_64) || defined(__i386__)
#if defined(__x86_64) || defined(__i386__) #ifdef __AVX2__
#ifdef __AVX2__ nsamps2 = (nsamps+7)>>3;
nsamps2 = (nsamps+7)>>3; __m256i buff_tx[8][nsamps2];
__m256i buff_tx[8][nsamps2]; #else
#else nsamps2 = (nsamps+3)>>2;
nsamps2 = (nsamps+3)>>2; __m128i buff_tx[8][nsamps2];
__m128i buff_tx[8][nsamps2]; #endif
#endif #elif defined(__arm__)
#elif defined(__arm__) nsamps2 = (nsamps+3)>>2;
nsamps2 = (nsamps+3)>>2; int16x8_t buff_tx[8][nsamps2];
int16x8_t buff_tx[8][nsamps2]; #else
#else #error Unsupported CPU architecture, USRP device cannot be built
#error Unsupported CPU architecture, USRP device cannot be built #endif
#endif
// 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++) {
for (int j=0; j<nsamps2; j++) { for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4); buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
#else #else
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4); buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4); buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
#endif #endif
} }
} }
s->tx_md.has_time_spec = true; s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet; s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet;
s->tx_md.end_of_burst = last_packet; s->tx_md.end_of_burst = last_packet;
...@@ -572,34 +564,32 @@ void *trx_usrp_write_thread(void * arg){ ...@@ -572,34 +564,32 @@ void *trx_usrp_write_thread(void * arg){
buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0])); buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0]));
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md);
} } else {
else {
ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md); ret = (int)s->tx_stream->send(&(((int16_t *)buff_tx[0])[0]), nsamps, s->tx_md);
} }
if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); if (ret != nsamps)
LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps);
VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_USRP_SEND_RETURN, ret ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_USRP_SEND_RETURN, ret );
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 0 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 0 );
if(0) break; if(0)
break;
} }
return NULL; return NULL;
} }
int trx_usrp_write_init(openair0_device *device){ int trx_usrp_write_init(openair0_device *device) {
uhd::set_thread_priority_safe(1.0); uhd::set_thread_priority_safe(1.0);
openair0_thread_t *write_thread = &device->write_thread; openair0_thread_t *write_thread = &device->write_thread;
printf("initializing tx write thread\n"); printf("initializing tx write thread\n");
write_thread->start = 0; write_thread->start = 0;
write_thread->end = 0; write_thread->end = 0;
write_thread->count_write = 0; write_thread->count_write = 0;
printf("end of tx write thread\n"); printf("end of tx write thread\n");
pthread_create(&write_thread->pthread_write,NULL,trx_usrp_write_thread,(void *)device); pthread_create(&write_thread->pthread_write,NULL,trx_usrp_write_thread,(void *)device);
return(0); return(0);
} }
...@@ -633,57 +623,60 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -633,57 +623,60 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
int16x8_t buff_tmp[2][nsamps2]; int16x8_t buff_tmp[2][nsamps2];
#endif #endif
if (cc>1) { if (cc>1) {
// receive multiple channels (e.g. RF A and RF B) // receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs; std::vector<void *> buff_ptrs;
for (int i=0; i<cc; i++) buff_ptrs.push_back(buff_tmp[i]); for (int i=0; i<cc; i++)
buff_ptrs.push_back(buff_tmp[i]);
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
} else { } else {
// receive a single channel (e.g. from connector RF A) // receive a single channel (e.g. from connector RF A)
samples_received=0; samples_received=0;
while (samples_received != nsamps) { while (samples_received != nsamps) {
samples_received += s->rx_stream->recv((void*)((int32_t*)buff_tmp[0]+samples_received), samples_received += s->rx_stream->recv((void *)((int32_t *)buff_tmp[0]+samples_received),
nsamps-samples_received, s->rx_md); nsamps-samples_received, s->rx_md);
if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)) if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
break; break;
if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) { if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
printf("sleep...\n"); //usleep(100); printf("sleep...\n"); //usleep(100);
}
} }
if (samples_received == nsamps) s->wait_for_first_pps=0;
} }
// bring RX data into 12 LSBs for softmodem RX if (samples_received == nsamps)
for (int i=0; i<cc; i++) { s->wait_for_first_pps=0;
for (int j=0; j<nsamps2; j++) { }
// bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) {
for (int j=0; j<nsamps2; j++) {
#if defined(__x86_64__) || defined(__i386__) #if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
// FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2 // FK: in some cases the buffer might not be 32 byte aligned, so we cannot use avx2
if ((((uintptr_t) buff[i])&0x1F)==0) { if ((((uintptr_t) buff[i])&0x1F)==0) {
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4); ((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
} else { } else {
((__m128i *)buff[i])[2*j] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j],4); ((__m128i *)buff[i])[2*j] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j],4);
((__m128i *)buff[i])[2*j+1] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j+1],4); ((__m128i *)buff[i])[2*j+1] = _mm_srai_epi16(((__m128i *)buff_tmp[i])[2*j+1],4);
} }
#else #else
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4); ((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
((int16x8_t *)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4); ((int16x8_t *)buff[i])[j] = vshrq_n_s16(buff_tmp[i][j],4);
#endif #endif
}
} }
}
if (samples_received < nsamps) { if (samples_received < nsamps) {
LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps); LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
} }
if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str()); LOG_E(HW, "%s\n", s->rx_md.to_pp_string(true).c_str());
...@@ -691,21 +684,28 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -691,21 +684,28 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_count += nsamps; s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp; *ptimestamp = s->rx_timestamp;
// push GPIO bits 7-9 from flags_msb // push GPIO bits 7-9 from flags_msb
/*s->usrp->set_command_time(uhd::time_spec_t::from_ticks((s->rx_timestamp+(2*nsamps)),s->sample_rate)); /*s->usrp->set_command_time(uhd::time_spec_t::from_ticks((s->rx_timestamp+(2*nsamps)),s->sample_rate));
s->usrp->set_gpio_attr("FP0", "OUT", gpio789<<7, 0x380); s->usrp->set_gpio_attr("FP0", "OUT", gpio789<<7, 0x380);
s->usrp->clear_command_time(); s->usrp->clear_command_time();
gpio789 = (gpio789+1)&7;*/ gpio789 = (gpio789+1)&7;*/
recplay_state_t *recPlay=device->recplay_state;
if (device->recplay_state != NULL) { // record mode if ( recPlay != NULL) { // record mode
// Copy subframes to memory (later dump on a file) // Copy subframes to memory (later dump on a file)
if (device->recplay_state->nb_samples < device->openair0_cfg->recplay_conf->u_sf_max) { if (recPlay->nbSamplesBlocks < device->openair0_cfg->recplay_conf->u_sf_max &&
(device->recplay_state->ms_sample+device->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER; recPlay->maxSizeBytes > (recPlay->currentPtr-(uint8_t *)recPlay->ms_sample) +
(device->recplay_state->ms_sample+device->recplay_state->nb_samples)->ts = *ptimestamp; sizeof(iqrec_t) + nsamps*4 ) {
memcpy((device->recplay_state->ms_sample+device->recplay_state->nb_samples)->samples, buff[0], nsamps*4); iqrec_t *hdr=(iqrec_t *)recPlay->currentPtr;
device->recplay_state->nb_samples++; hdr->header = BELL_LABS_IQ_HEADER;
} else exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n"); hdr->ts = *ptimestamp;
hdr->nbBytes=nsamps*4;
memcpy(hdr+1, buff[0], nsamps*4);
recPlay->currentPtr+=sizeof(iqrec_t)+nsamps*4;
recPlay->nbSamplesBlocks++;
LOG_D(HW,"recorded %d samples, for TS %lu, shift in buffer %ld\n", nsamps, hdr->ts, recPlay->currentPtr-(uint8_t *)recPlay->ms_sample);
} else
exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n");
} }
return samples_received; return samples_received;
...@@ -937,32 +937,30 @@ extern "C" { ...@@ -937,32 +937,30 @@ extern "C" {
device->trx_set_freq_func = trx_usrp_set_freq; device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains; device->trx_set_gains_func = trx_usrp_set_gains;
device->trx_write_init = trx_usrp_write_init; device->trx_write_init = trx_usrp_write_init;
// hotfix! to be checked later // hotfix! to be checked later
uhd::set_thread_priority_safe(1.0); uhd::set_thread_priority_safe(1.0);
// Initialize USRP device // Initialize USRP device
int vers=0,subvers=0,subsubvers=0; int vers=0,subvers=0,subsubvers=0;
int bw_gain_adjust=0; int bw_gain_adjust=0;
if (device->openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) { if (device->openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) {
std::cerr << "USRP device initialized in subframes record mode" << std::endl; std::cerr << "USRP device initialized in subframes record mode" << std::endl;
} }
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
LOG_I(HW,"UHD version %s (%d.%d.%d)\n", LOG_I(HW,"UHD version %s (%d.%d.%d)\n",
uhd::get_version_string().c_str(),vers,subvers,subsubvers); uhd::get_version_string().c_str(),vers,subvers,subsubvers);
std::string args; std::string args;
if (openair0_cfg[0].sdr_addrs == NULL) { if (openair0_cfg[0].sdr_addrs == NULL) {
args = "type=b200"; args = "type=b200";
} else { } else {
args = openair0_cfg[0].sdr_addrs; args = openair0_cfg[0].sdr_addrs;
LOG_I(HW,"Checking for USRP with args %s\n",openair0_cfg[0].sdr_addrs); LOG_I(HW,"Checking for USRP with args %s\n",openair0_cfg[0].sdr_addrs);
} }
uhd::device_addrs_t device_adds = uhd::device::find(args); uhd::device_addrs_t device_adds = uhd::device::find(args);
if (device_adds.size() == 0) { if (device_adds.size() == 0) {
LOG_E(HW,"No USRP Device Found.\n "); LOG_E(HW,"No USRP Device Found.\n ");
free(s); free(s);
...@@ -972,375 +970,367 @@ extern "C" { ...@@ -972,375 +970,367 @@ extern "C" {
free(s); free(s);
return -1; return -1;
} }
LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str()); LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str());
double usrp_master_clock; double usrp_master_clock;
if (device_adds[0].get("type") == "b200") { if (device_adds[0].get("type") == "b200") {
device->type = USRP_B200_DEV; device->type = USRP_B200_DEV;
usrp_master_clock = 30.72e6; usrp_master_clock = 30.72e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=7680, recv_frame_size=7680" ; args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=7680, recv_frame_size=7680" ;
} }
if (device_adds[0].get("type") == "n3xx") { if (device_adds[0].get("type") == "n3xx") {
printf("Found USRP n300\n"); printf("Found USRP n300\n");
device->type=USRP_N300_DEV; device->type=USRP_N300_DEV;
usrp_master_clock = 122.88e6; usrp_master_clock = 122.88e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
//args += ", send_buff_size=33554432"; //args += ", send_buff_size=33554432";
} }
if (device_adds[0].get("type") == "x300") { if (device_adds[0].get("type") == "x300") {
printf("Found USRP x300\n"); printf("Found USRP x300\n");
device->type=USRP_X300_DEV; device->type=USRP_X300_DEV;
usrp_master_clock = 184.32e6; usrp_master_clock = 184.32e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
// USRP recommended: https://files.ettus.com/manual/page_usrp_x3x0_config.html // USRP recommended: https://files.ettus.com/manual/page_usrp_x3x0_config.html
if ( 0 != system("sysctl -w net.core.rmem_max=33554432 net.core.wmem_max=33554432") ) if ( 0 != system("sysctl -w net.core.rmem_max=33554432 net.core.wmem_max=33554432") )
LOG_W(HW,"Can't set kernel parameters for X3xx\n"); LOG_W(HW,"Can't set kernel parameters for X3xx\n");
} }
s->usrp = uhd::usrp::multi_usrp::make(args); s->usrp = uhd::usrp::multi_usrp::make(args);
if (args.find("clock_source")==std::string::npos) { if (args.find("clock_source")==std::string::npos) {
if (openair0_cfg[0].clock_source == internal) { if (openair0_cfg[0].clock_source == internal) {
s->usrp->set_clock_source("internal"); s->usrp->set_clock_source("internal");
LOG_D(HW,"Setting clock source to internal\n"); LOG_D(HW,"Setting clock source to internal\n");
} } else if (openair0_cfg[0].clock_source == external ) {
else if (openair0_cfg[0].clock_source == external ) { s->usrp->set_clock_source("external");
s->usrp->set_clock_source("external"); LOG_D(HW,"Setting clock source to external\n");
LOG_D(HW,"Setting clock source to external\n"); } else if (openair0_cfg[0].clock_source==gpsdo) {
} s->usrp->set_clock_source("gpsdo");
else if (openair0_cfg[0].clock_source==gpsdo) { LOG_D(HW,"Setting clock source to gpsdo\n");
s->usrp->set_clock_source("gpsdo"); } else {
LOG_D(HW,"Setting clock source to gpsdo\n"); LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n");
} }
else { } else {
LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n"); if (openair0_cfg[0].clock_source != unset) {
} LOG_W(HW,"Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n");
}
} }
else {
if (openair0_cfg[0].clock_source != unset) {
LOG_W(HW,"Clock source set in both usrp_args and in clock_source, ingnoring the latter!\n");
}
}
if (args.find("time_source")==std::string::npos) { if (args.find("time_source")==std::string::npos) {
if (openair0_cfg[0].time_source == internal) { if (openair0_cfg[0].time_source == internal) {
s->usrp->set_time_source("internal"); s->usrp->set_time_source("internal");
LOG_D(HW,"Setting time source to internal\n"); LOG_D(HW,"Setting time source to internal\n");
} } else if (openair0_cfg[0].time_source == external ) {
else if (openair0_cfg[0].time_source == external ) { s->usrp->set_time_source("external");
s->usrp->set_time_source("external"); LOG_D(HW,"Setting time source to external\n");
LOG_D(HW,"Setting time source to external\n"); } else if (openair0_cfg[0].time_source==gpsdo) {
} s->usrp->set_time_source("gpsdo");
else if (openair0_cfg[0].time_source==gpsdo) { LOG_D(HW,"Setting time source to gpsdo\n");
s->usrp->set_time_source("gpsdo"); } else {
LOG_D(HW,"Setting time source to gpsdo\n"); LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n");
} }
else { } else {
LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n"); if (openair0_cfg[0].clock_source != unset) {
} LOG_W(HW,"Time source set in both usrp_args and in time_source, ingnoring the latter!\n");
}
} }
else {
if (openair0_cfg[0].clock_source != unset) {
LOG_W(HW,"Time source set in both usrp_args and in time_source, ingnoring the latter!\n");
}
}
if (s->usrp->get_clock_source(0) == "gpsdo") {
if (s->usrp->get_clock_source(0) == "gpsdo") { s->use_gps = 1;
s->use_gps = 1;
if (sync_to_gps(device)==EXIT_SUCCESS) {
if (sync_to_gps(device)==EXIT_SUCCESS) { LOG_I(HW,"USRP synced with GPS!\n");
LOG_I(HW,"USRP synced with GPS!\n"); } else {
} else { LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n");
LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n"); exit(EXIT_FAILURE);
exit(EXIT_FAILURE); }
} else if (s->usrp->get_clock_source(0) == "external") {
if (check_ref_locked(s,0)) {
LOG_I(HW,"USRP locked to external reference!\n");
} else {
LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
exit(EXIT_FAILURE);
}
} }
} else if (s->usrp->get_clock_source(0) == "external") {
if (check_ref_locked(s,0)) { if (device->type==USRP_X300_DEV) {
LOG_I(HW,"USRP locked to external reference!\n"); openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
} else { std::cerr << "-- Using calibration table: calib_table_x310" << std::endl;
LOG_I(HW,"Failed to lock to external reference. Exiting.\n");
exit(EXIT_FAILURE);
} }
}
if (device->type==USRP_X300_DEV) {
openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
std::cerr << "-- Using calibration table: calib_table_x310" << std::endl;
}
if (device->type==USRP_N300_DEV) { if (device->type==USRP_N300_DEV) {
openair0_cfg[0].rx_gain_calib_table = calib_table_n310; openair0_cfg[0].rx_gain_calib_table = calib_table_n310;
std::cerr << "-- Using calibration table: calib_table_n310" << std::endl; std::cerr << "-- Using calibration table: calib_table_n310" << std::endl;
} }
if (device->type==USRP_N300_DEV || device->type==USRP_X300_DEV) {
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
if (device->type==USRP_N300_DEV || device->type==USRP_X300_DEV) { switch ((int)openair0_cfg[0].sample_rate) {
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); case 122880000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15; //to be checked
openair0_cfg[0].tx_bw = 80e6;
openair0_cfg[0].rx_bw = 80e6;
break;
switch ((int)openair0_cfg[0].sample_rate) { case 92160000:
case 122880000: // from usrp_time_offset
// from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15; //to be checked
openair0_cfg[0].tx_sample_advance = 15; //to be checked openair0_cfg[0].tx_bw = 80e6;
openair0_cfg[0].tx_bw = 80e6; openair0_cfg[0].rx_bw = 80e6;
openair0_cfg[0].rx_bw = 80e6; break;
break;
case 61440000:
case 92160000: // from usrp_time_offset
// from usrp_time_offset //openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_sample_advance = 15; //to be checked openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].tx_bw = 80e6; openair0_cfg[0].rx_bw = 40e6;
openair0_cfg[0].rx_bw = 80e6; break;
break;
case 46080000:
case 61440000: //openair0_cfg[0].samples_per_packet = 2048;
// from usrp_time_offset openair0_cfg[0].tx_sample_advance = 15;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].rx_bw = 40e6;
openair0_cfg[0].tx_bw = 40e6; break;
openair0_cfg[0].rx_bw = 40e6;
break; case 30720000:
// from usrp_time_offset
case 46080000: //openair0_cfg[0].samples_per_packet = 2048;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].tx_bw = 40e6; openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].rx_bw = 40e6; break;
break;
case 15360000:
case 30720000: //openair0_cfg[0].samples_per_packet = 2048;
// from usrp_time_offset openair0_cfg[0].tx_sample_advance = 45;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].tx_sample_advance = 15; openair0_cfg[0].rx_bw = 10e6;
openair0_cfg[0].tx_bw = 20e6; break;
openair0_cfg[0].rx_bw = 20e6;
break; case 7680000:
//openair0_cfg[0].samples_per_packet = 2048;
case 15360000: openair0_cfg[0].tx_sample_advance = 50;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].tx_sample_advance = 45; openair0_cfg[0].rx_bw = 5e6;
openair0_cfg[0].tx_bw = 10e6; break;
openair0_cfg[0].rx_bw = 10e6;
break; case 1920000:
//openair0_cfg[0].samples_per_packet = 2048;
case 7680000: openair0_cfg[0].tx_sample_advance = 50;
//openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].tx_sample_advance = 50; openair0_cfg[0].rx_bw = 1.25e6;
openair0_cfg[0].tx_bw = 5e6; break;
openair0_cfg[0].rx_bw = 5e6;
break; default:
LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
case 1920000: exit(-1);
//openair0_cfg[0].samples_per_packet = 2048; break;
openair0_cfg[0].tx_sample_advance = 50; }
openair0_cfg[0].tx_bw = 1.25e6;
openair0_cfg[0].rx_bw = 1.25e6;
break;
default:
LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
} }
}
if (device->type == USRP_B200_DEV) {
if (device->type == USRP_B200_DEV) { if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
openair0_cfg[0].rx_gain_calib_table = calib_table_b210; bw_gain_adjust=0;
bw_gain_adjust=0; std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info } else {
} else { openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; bw_gain_adjust=1;
bw_gain_adjust=1; std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info }
switch ((int)openair0_cfg[0].sample_rate) {
case 46080000:
s->usrp->set_master_clock_rate(46.08e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 115;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 30720000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 115;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 23040000:
s->usrp->set_master_clock_rate(23.04e6); //to be checked
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 113;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
s->usrp->set_master_clock_rate(30.72e06);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 7680000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 1920000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 40;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
default:
LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
} }
switch ((int)openair0_cfg[0].sample_rate) { /* device specific */
case 46080000: //openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
s->usrp->set_master_clock_rate(46.08e6); //openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered
//openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6; for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) {
break; if (i<openair0_cfg[0].rx_num_channels) {
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i);
case 30720000: s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i);
s->usrp->set_master_clock_rate(30.72e6); set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust);
//openair0_cfg[0].samples_per_packet = 1024; ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i);
openair0_cfg[0].tx_sample_advance = 115; // limit to maximum gain
openair0_cfg[0].tx_bw = 20e6; AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(),
openair0_cfg[0].rx_bw = 20e6; "RX Gain too high, lower by %f dB\n",
break; openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop());
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i);
case 23040000: LOG_I(HW,"RX Gain %d %f (%f) => %f (max %f)\n",i,
s->usrp->set_master_clock_rate(23.04e6); //to be checked openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i],
//openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop());
openair0_cfg[0].tx_sample_advance = 113; }
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
s->usrp->set_master_clock_rate(30.72e06);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 7680000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 80;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 1920000:
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 40;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
default:
LOG_E(HW,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
} }
}
LOG_D(HW, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels());
/* device specific */ LOG_D(HW, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels);
//openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered
//openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) {
openair0_cfg[0].iq_txshift = 4;//shift ::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i);
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
if (i<openair0_cfg[0].tx_num_channels) {
for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) { s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i);
if (i<openair0_cfg[0].rx_num_channels) { s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i);
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i);
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); LOG_I(HW,"USRP TX_GAIN:%3.2lf gain_range:%3.2lf tx_gain:%3.2lf\n", gain_range_tx.stop()-openair0_cfg[0].tx_gain[i], gain_range_tx.stop(), openair0_cfg[0].tx_gain[i]);
set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); }
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i);
// limit to maximum gain
AssertFatal( openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] <= gain_range.stop(),
"RX Gain too high, lower by %f dB\n",
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop());
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i);
LOG_I(HW,"RX Gain %d %f (%f) => %f (max %f)\n",i,
openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i],
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop());
} }
}
//s->usrp->set_clock_source("external");
LOG_D(HW, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels()); //s->usrp->set_time_source("external");
LOG_D(HW, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels); // display USRP settings
LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) { LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str());
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i); LOG_I(HW,"Actual time source %s...\n",s->usrp->get_time_source(0).c_str());
sleep(1);
if (i<openair0_cfg[0].tx_num_channels) { // create tx & rx streamer
s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i); uhd::stream_args_t stream_args_rx("sc16", "sc16");
s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); int samples=openair0_cfg[0].sample_rate;
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[i],i); int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps();
LOG_I(HW,"USRP TX_GAIN:%3.2lf gain_range:%3.2lf tx_gain:%3.2lf\n", gain_range_tx.stop()-openair0_cfg[0].tx_gain[i], gain_range_tx.stop(), openair0_cfg[0].tx_gain[i]); samples/=10000;
LOG_I(HW,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples);
if ( samples < max ) {
stream_args_rx.args["spp"] = str(boost::format("%d") % samples );
} }
}
LOG_I(HW,"rx_max_num_samps %zu\n",
//s->usrp->set_clock_source("external"); s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps());
//s->usrp->set_time_source("external");
// display USRP settings for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++)
LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6); stream_args_rx.channels.push_back(i);
LOG_I(HW,"Actual clock source %s...\n",s->usrp->get_clock_source(0).c_str());
LOG_I(HW,"Actual time source %s...\n",s->usrp->get_time_source(0).c_str()); s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
sleep(1); uhd::stream_args_t stream_args_tx("sc16", "sc16");
// create tx & rx streamer
uhd::stream_args_t stream_args_rx("sc16", "sc16"); for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
int samples=openair0_cfg[0].sample_rate; stream_args_tx.channels.push_back(i);
int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps();
samples/=10000; s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
LOG_I(HW,"RF board max packet size %u, size for 100µs jitter %d \n", max, samples);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */
if ( samples < max ) { for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++)
stream_args_rx.args["spp"] = str(boost::format("%d") % samples ); s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i);
}
for(int i=0; i<((int) s->usrp->get_rx_num_channels()) && i<openair0_cfg[0].rx_num_channels; i++)
LOG_I(HW,"rx_max_num_samps %zu\n", s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps());
for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) {
for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++) LOG_I(HW,"RX Channel %d\n",i);
stream_args_rx.channels.push_back(i); LOG_I(HW," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6);
LOG_I(HW," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9);
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx); LOG_I(HW," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i));
uhd::stream_args_t stream_args_tx("sc16", "sc16"); LOG_I(HW," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6);
LOG_I(HW," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str());
for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++) }
stream_args_tx.channels.push_back(i);
for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) {
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); LOG_I(HW,"TX Channel %d\n",i);
LOG_I(HW," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */ LOG_I(HW," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9);
for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++) LOG_I(HW," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i));
s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); LOG_I(HW," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6);
LOG_I(HW," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str());
for(int i=0; i<((int) s->usrp->get_rx_num_channels()) && i<openair0_cfg[0].rx_num_channels; i++) LOG_I(HW," Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps());
s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) {
LOG_I(HW,"RX Channel %d\n",i);
LOG_I(HW," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6);
LOG_I(HW," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9);
LOG_I(HW," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i));
LOG_I(HW," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6);
LOG_I(HW," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str());
}
for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) {
LOG_I(HW,"TX Channel %d\n",i);
LOG_I(HW," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6);
LOG_I(HW," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9);
LOG_I(HW," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i));
LOG_I(HW," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6);
LOG_I(HW," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str());
LOG_I(HW," Actual TX packet size: %lu\n",s->tx_stream->get_max_num_samps());
}
LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read;
s->sample_rate = openair0_cfg[0].sample_rate;
// TODO:
// init tx_forward_nsamps based usrp_time_offset ex
if(is_equal(s->sample_rate, (double)30.72e6))
s->tx_forward_nsamps = 176;
if(is_equal(s->sample_rate, (double)15.36e6))
s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
if (device->recplay_state != NULL) { // record mode
device->recplay_state->ms_sample = (iqrec_t *) malloc(openair0_cfg[0].recplay_conf->u_sf_max * sizeof(iqrec_t));
if (device->recplay_state->ms_sample == NULL) {
std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
exit(-1);
} }
memset(device->recplay_state->ms_sample, 0, openair0_cfg[0].recplay_conf->u_sf_max * BELL_LABS_IQ_BYTES_PER_SF); LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read;
s->sample_rate = openair0_cfg[0].sample_rate;
// TODO:
// init tx_forward_nsamps based usrp_time_offset ex
if(is_equal(s->sample_rate, (double)30.72e6))
s->tx_forward_nsamps = 176;
if(is_equal(s->sample_rate, (double)15.36e6))
s->tx_forward_nsamps = 90;
if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50;
recplay_state_t *recPlay=device->recplay_state;
if (recPlay != NULL) { // record mode
recPlay->maxSizeBytes=openair0_cfg[0].recplay_conf->u_sf_max *
(sizeof(iqrec_t)+BELL_LABS_IQ_BYTES_PER_SF);
recPlay->ms_sample = (iqrec_t *) malloc(recPlay->maxSizeBytes);
recPlay->currentPtr= (uint8_t *)recPlay->ms_sample;
if (recPlay->ms_sample == NULL) {
std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
exit(-1);
}
}
return 0;
} }
return 0; /*@}*/
}
/*@}*/
}/* extern c */ }/* extern c */
...@@ -40,18 +40,15 @@ ...@@ -40,18 +40,15 @@
#include "assertions.h" #include "assertions.h"
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
static void parse_iqfile_header(openair0_device *device, iqfile_header_t *iq_fh) { static void parse_iqfile_header(openair0_device *device, iqfile_header_t *iq_fh) {
AssertFatal((memcmp(iq_fh->oaiid,OAIIQFILE_ID,sizeof(OAIIQFILE_ID)) == 0), char tmp[4]=OAIIQFILE_ID;
"iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n", AssertFatal((memcmp(iq_fh->oaiid,tmp,sizeof(iq_fh->oaiid)) == 0),
iq_fh->oaiid); "iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n",
iq_fh->oaiid);
device->type = iq_fh->devtype; device->type = iq_fh->devtype;
device->openair0_cfg[0].tx_sample_advance=iq_fh->tx_sample_advance; device->openair0_cfg[0].tx_sample_advance=iq_fh->tx_sample_advance;
device->openair0_cfg[0].tx_bw = device->openair0_cfg[0].rx_bw = iq_fh->bw; device->openair0_cfg[0].tx_bw = device->openair0_cfg[0].rx_bw = iq_fh->bw;
device->recplay_state->nbSamplesBlocks=iq_fh->nbSamplesBlocks;
LOG_UI(HW,"Replay iqs from %s device, bandwidth %e\n",get_devname(iq_fh->devtype),iq_fh->bw); LOG_UI(HW,"Replay iqs from %s device, bandwidth %e\n",get_devname(iq_fh->devtype),iq_fh->bw);
} }
...@@ -63,89 +60,73 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair ...@@ -63,89 +60,73 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair
recplay_state_t *s = device->recplay_state; recplay_state_t *s = device->recplay_state;
recplay_conf_t *c = openair0_cfg->recplay_conf; recplay_conf_t *c = openair0_cfg->recplay_conf;
struct stat sb;
s->fd = open(c->u_sf_filename, O_RDONLY );
if (s->fd >= 0 ) {
fstat(s->fd, &sb);
} else {
LOG_E( HW,"Cannot open %s exiting.\n", c->u_sf_filename );
exit(-1);
}
if (s->use_mmap) { if (s->use_mmap) {
// use mmap // use mmap
s->mmapfd = open(c->u_sf_filename, O_RDONLY );
if (s->mmapfd != 0) {
struct stat sb;
fstat(s->mmapfd, &sb);
s->mapsize=sb.st_size; s->mapsize=sb.st_size;
LOG_I(HW,"Loading subframes using mmap() from %s size=%lu bytes ...\n",c->u_sf_filename, (uint64_t)sb.st_size ); LOG_I(HW,"Loading subframes using mmap() from %s size=%lu bytes ...\n",c->u_sf_filename, (uint64_t)sb.st_size );
void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->mmapfd, 0) ; void *mptr = mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) ;
s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->mmapfd, 0) + sizeof(iqfile_header_t)); s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->fd, 0) + sizeof(iqfile_header_t));
if (mptr != MAP_FAILED) { if (mptr != MAP_FAILED) {
parse_iqfile_header(device, (iqfile_header_t *)mptr); parse_iqfile_header(device, (iqfile_header_t *)mptr);
s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t)); s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t));
s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t)) / sizeof(iqrec_t)); LOG_I(HW,"Loaded %u subframes.\n",s->nbSamplesBlocks );
int aligned = (((unsigned long)s->ms_sample & 31) == 0)? 1:0;
LOG_I(HW,"Loaded %u subframes.\n",s->nb_samples );
if (aligned == 0) {
LOG_E(HW, "mmap address is not 32 bytes aligned, exiting.\n" );
close(s->mmapfd);
exit(-1);
}
} else { } else {
LOG_E(HW,"Cannot mmap file, exiting.\n"); LOG_E(HW,"Cannot mmap file, exiting.\n");
close(s->mmapfd); close(s->fd);
exit(-1); exit(-1);
} }
} else {
LOG_E( HW,"Cannot open %s exiting.\n", c->u_sf_filename );
exit(-1);
}
} else { } else {
s->iqfd = open(c->u_sf_filename, O_RDONLY); iqfile_header_t fh;
size_t hs = read(s->fd,&fh,sizeof(fh));
if (s->iqfd != 0) { if (hs == sizeof(fh)) {
struct stat sb; parse_iqfile_header(device, &fh);
iqfile_header_t fh; fstat(s->fd, &sb);
size_t hs = read(s->iqfd,&fh,sizeof(fh));
if (hs == sizeof(fh)) {
parse_iqfile_header(device, &fh);
fstat(s->iqfd, &sb);
s->mapsize=sb.st_size; s->mapsize=sb.st_size;
s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t))/ sizeof(iqrec_t)); LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nbSamplesBlocks, c->u_sf_filename,(uint64_t)sb.st_size);
LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nb_samples, c->u_sf_filename,(uint64_t)sb.st_size);
// allocate buffer for 1 sample at a time // allocate buffer for 1 sample at a time
s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)); s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)+MAX_BELL_LABS_IQ_BYTES_PER_SF*4);
if (s->ms_sample == NULL) { if (s->ms_sample == NULL) {
LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" ); LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" );
close(s->iqfd); close(s->fd);
exit(-1); exit(-1);
} }
memset(s->ms_sample, 0, sizeof(iqrec_t)); memset(s->ms_sample, 0, sizeof(iqrec_t));
// point at beginning of iqs in file // point at beginning of iqs in file
if (lseek(s->iqfd,sizeof(iqfile_header_t), SEEK_SET) == 0) { if (lseek(s->fd,sizeof(iqfile_header_t), SEEK_SET) == 0) {
LOG_I(HW,"Initial seek at beginning of the file\n" ); LOG_I(HW,"Initial seek at beginning of the file\n" );
} else { } else {
LOG_I(HW,"Problem initial seek at beginning of the file\n"); LOG_I(HW,"Problem initial seek at beginning of the file\n");
} }
} else { } else {
LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename ); LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename );
close(s->iqfd); close(s->fd);
exit(-1); exit(-1);
} }
} else {
LOG_E(HW,"Cannot open %s exiting.\n",c->u_sf_filename );
exit(-1);
}
} }
s->currentPtr=(uint8_t *)s->ms_sample;
return 0; return 0;
} }
/*! \brief start the oai iq player /*! \brief start the oai iq player
* \param device, the hardware used * \param device, the hardware used
*/ */
static int trx_iqplayer_start(openair0_device *device){ static int trx_iqplayer_start(openair0_device *device) {
return 0; return 0;
} }
/*! \brief Terminate operation of the oai iq player /*! \brief Terminate operation of the oai iq player
...@@ -157,28 +138,22 @@ static void trx_iqplayer_end(openair0_device *device) { ...@@ -157,28 +138,22 @@ static void trx_iqplayer_end(openair0_device *device) {
if (device->recplay_state == NULL) if (device->recplay_state == NULL)
return; return;
if (device->recplay_state->use_mmap) { if (device->recplay_state->use_mmap) {
if (device->recplay_state->ms_sample != MAP_FAILED) { if (device->recplay_state->ms_sample != MAP_FAILED) {
munmap(device->recplay_state->ms_sample, device->recplay_state->mapsize); munmap(device->recplay_state->ms_sample, device->recplay_state->mapsize);
device->recplay_state->ms_sample = NULL; }
}
if (device->recplay_state->mmapfd != 0) {
close(device->recplay_state->mmapfd);
device->recplay_state->mmapfd = 0;
}
} else { } else {
if (device->recplay_state->ms_sample != NULL) { if (device->recplay_state->ms_sample != NULL) {
free(device->recplay_state->ms_sample); free(device->recplay_state->ms_sample);
device->recplay_state->ms_sample = NULL; }
} }
device->recplay_state->ms_sample = NULL;
if (device->recplay_state->iqfd != 0) { if (device->recplay_state->fd >= 0) {
close(device->recplay_state->iqfd); close(device->recplay_state->fd);
device->recplay_state->iqfd = 0; device->recplay_state->fd = -1;
}
} }
} }
/*! \brief Write iqs function when in replay mode, just introduce a delay, as configured at init time, /*! \brief Write iqs function when in replay mode, just introduce a delay, as configured at init time,
@param device pointer to the device structure specific to the RF hardware target @param device pointer to the device structure specific to the RF hardware target
...@@ -208,93 +183,68 @@ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timest ...@@ -208,93 +183,68 @@ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timest
* \returns the number of sample read * \returns the number of sample read
*/ */
static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { static int trx_iqplayer_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
int samples_received=0;
static unsigned int cur_samples;
static int64_t wrap_count;
static int64_t wrap_ts;
recplay_state_t *s = device->recplay_state; recplay_state_t *s = device->recplay_state;
if (cur_samples == s->nb_samples) { if (s->curSamplesBlock==0 && s->wrap_count==0 )
cur_samples = 0; s->currentTs=s->ms_sample->ts;
wrap_count++;
if (s->curSamplesBlock == s->nbSamplesBlocks) {
if (wrap_count == device->openair0_cfg->recplay_conf->u_sf_loops) { LOG_I(HW, "wrapping on iq file (%ld)\n", s->wrap_count);
LOG_W(HW, "iqplayer device terminating subframes replay after %u iteration\n",device->openair0_cfg->recplay_conf->u_sf_loops); s->curSamplesBlock = 0;
s->wrap_count++;
if (s->wrap_count == device->openair0_cfg->recplay_conf->u_sf_loops) {
LOG_W(HW, "iqplayer device terminating subframes replay after %u iteration\n",
device->openair0_cfg->recplay_conf->u_sf_loops);
exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n"); exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n");
} }
wrap_ts = wrap_count * (s->nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)); LOG_I(HW,"go back at the beginning of IQ file");
device->recplay_state->currentPtr=(uint8_t *)device->recplay_state->ms_sample;
if (!device->recplay_state->use_mmap) { if (!s->use_mmap) {
if (lseek(device->recplay_state->iqfd, 0, SEEK_SET) == 0) { if (lseek(device->recplay_state->fd, 0, SEEK_SET) != 0) {
LOG_I(HW,"Seeking at the beginning of IQ file"); LOG_E(HW, "Problem seeking at the beginning of IQ file");
} else {
LOG_I(HW, "Problem seeking at the beginning of IQ file");
} }
} }
} }
if (s->use_mmap) { if (!s->use_mmap) {
if (cur_samples < s->nb_samples) {
*ptimestamp = (s->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
if (cur_samples == 0) {
LOG_I(HW,"starting subframes file with wrap_count=%lu wrap_ts=%lu ts=%lu\n", wrap_count,wrap_ts,*ptimestamp);
}
memcpy(buff[0], &s->ms_sample[cur_samples].samples[0], nsamps*4);
cur_samples++;
}
} else {
// read sample from file // read sample from file
if (read(s->iqfd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) { if (read(s->fd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*cur_samples ); LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock );
close(s->iqfd);
free(s->ms_sample);
s->ms_sample = NULL;
s->iqfd = 0;
exit(-1); exit(-1);
} } else {
if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) {
if (cur_samples < s->nb_samples) { LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock );
static int64_t ts0 = 0;
if ((cur_samples == 0) && (wrap_count == 0)) {
ts0 = s->ms_sample->ts;
}
*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
if (cur_samples == 0) {
LOG_I(HW, "starting subframes file with wrap_count=%lu wrap_ts=%lu ts=%lu ",wrap_count,wrap_ts, *ptimestamp);
}
memcpy(buff[0], &s->ms_sample->samples[0], nsamps*4);
cur_samples++;
// Prepare for next read
off_t where = lseek(s->iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
if (where < 0) {
LOG_E(HW,"Cannot lseek in iqfile: %s\n",strerror(errno));
exit(-1); exit(-1);
} }
} }
} }
struct timespec req; iqrec_t *curHeader=(iqrec_t *)s->currentPtr;
AssertFatal(curHeader->header==BELL_LABS_IQ_HEADER,"" );
// the current timestamp is the stored timestamp until we wrap on input
// USRP shifts 1 sample time to time
AssertFatal(s->wrap_count !=0 || abs(curHeader->ts-s->currentTs) < 5 ,"");
AssertFatal(nsamps*4==curHeader->nbBytes,"");
*ptimestamp = s->currentTs;
memcpy(buff[0], curHeader+1, nsamps*4);
s->curSamplesBlock++;
// Prepare for next read
s->currentTs+=nsamps;
if (s->use_mmap)
s->currentPtr+=sizeof(iqrec_t)+s->ms_sample->nbBytes;
struct timespec req;
req.tv_sec = 0; req.tv_sec = 0;
req.tv_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000; req.tv_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000;
nanosleep(&req, NULL); nanosleep(&req, NULL);
LOG_D(HW, "returning %d samples at ts %lu\n", nsamps, *ptimestamp);
return nsamps; return nsamps;
return samples_received;
} }
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
device->openair0_cfg = openair0_cfg; device->openair0_cfg = openair0_cfg;
device->trx_start_func = trx_iqplayer_start; device->trx_start_func = trx_iqplayer_start;
...@@ -313,5 +263,4 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { ...@@ -313,5 +263,4 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
LOG_UI(HW,"iqplayer device initialized, replay %s for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops); LOG_UI(HW,"iqplayer device initialized, replay %s for %i iterations",openair0_cfg->recplay_conf->u_sf_filename,openair0_cfg->recplay_conf->u_sf_loops);
return 0; return 0;
} }
/*@}*/ /*@}*/
...@@ -727,7 +727,7 @@ int main ( int argc, char **argv ) ...@@ -727,7 +727,7 @@ int main ( int argc, char **argv )
fflush(stderr); fflush(stderr);
// end of CI modifications // end of CI modifications
//getchar(); //getchar();
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
load_softscope("enb",NULL); load_softscope("enb",NULL);
itti_wait_tasks_end(); itti_wait_tasks_end();
oai_exit=1; oai_exit=1;
...@@ -735,7 +735,7 @@ int main ( int argc, char **argv ) ...@@ -735,7 +735,7 @@ int main ( int argc, char **argv )
// stop threads // stop threads
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) { if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
end_forms(); end_forms();
LOG_I(ENB_APP,"stopping MODEM threads\n"); LOG_I(ENB_APP,"stopping MODEM threads\n");
......
...@@ -758,7 +758,7 @@ int main( int argc, char **argv ) { ...@@ -758,7 +758,7 @@ int main( int argc, char **argv ) {
PHY_vars_UE_g[0][0]->no_timing_correction = 1; PHY_vars_UE_g[0][0]->no_timing_correction = 1;
} }
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
load_softscope("ue",NULL); load_softscope("ue",NULL);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS); config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
...@@ -783,7 +783,7 @@ int main( int argc, char **argv ) { ...@@ -783,7 +783,7 @@ int main( int argc, char **argv ) {
printf("oai_exit=%d\n",oai_exit); printf("oai_exit=%d\n",oai_exit);
// stop threads // stop threads
if(IS_SOFTMODEM_DOFORMS) if(IS_SOFTMODEM_DOSCOPE)
end_forms(); end_forms();
printf("stopping MODEM threads\n"); printf("stopping MODEM threads\n");
......
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