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 ) {
// end of CI modifications
//getchar();
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
load_softscope("enb", NULL);
itti_wait_tasks_end();
......@@ -1327,7 +1327,7 @@ int main ( int argc, char **argv ) {
// stop threads
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
end_forms();
LOG_I(ENB_APP,"stopping MODEM threads\n");
......
......@@ -89,7 +89,7 @@ static int DEFBFW[] = {0x00007fff};
#include "s1ap_eNB.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
#include "T.h"
......@@ -1593,7 +1593,8 @@ void *ru_thread( void *param ) {
for (aa=0;aa<ru->nb_rx;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));
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
int prach_id=find_nr_prach_ru(ru,proc->frame_rx,proc->tti_rx,SEARCH_EXIST);
......
......@@ -900,7 +900,7 @@ if(!IS_SOFTMODEM_NOS1)
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)
printf("ALL RUs ready - init gNBs\n");
if(IS_SOFTMODEM_DOFORMS) {
if(IS_SOFTMODEM_DOSCOPE) {
sleep(1);
scopeParms_t p;
p.argc=&argc;
......
......@@ -551,7 +551,7 @@ int main( int argc, char **argv ) {
configure_linux();
mlockall(MCL_CURRENT | MCL_FUTURE);
if(IS_SOFTMODEM_DOFORMS) {
if(IS_SOFTMODEM_DOSCOPE) {
load_softscope("nr",PHY_vars_UE_g[0][0]);
}
......
......@@ -996,7 +996,7 @@ int main( int argc, char **argv ) {
(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]};
load_softscope("nr",&tmp);
}
......
......@@ -140,7 +140,7 @@ void get_common_options(uint32_t execmask) {
}
if (do_forms) {
set_softmodem_optmask(SOFTMODEM_DOFORMS_BIT);
set_softmodem_optmask(SOFTMODEM_DOSCOPE_BIT);
}
if(parallel_config != NULL) set_parallel_conf(parallel_config);
......
......@@ -188,7 +188,7 @@ extern "C"
#define SOFTMODEM_RFSIM_BIT (1<<10)
#define SOFTMODEM_BASICSIM_BIT (1<<11)
#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_ENB_BIT (1<<20)
#define SOFTMODEM_GNB_BIT (1<<21)
......@@ -204,7 +204,7 @@ extern "C"
#define IS_SOFTMODEM_RFSIM ( get_softmodem_optmask() & SOFTMODEM_RFSIM_BIT)
#define IS_SOFTMODEM_BASICSIM ( get_softmodem_optmask() & SOFTMODEM_BASICSIM_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_ENB_BIT ( get_softmodem_optmask() & SOFTMODEM_ENB_BIT)
#define IS_SOFTMODEM_GNB_BIT ( get_softmodem_optmask() & SOFTMODEM_GNB_BIT)
......
......@@ -56,7 +56,7 @@ typedef struct OAIgraph {
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 (*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);
} OAIgraph_t;
......@@ -132,7 +132,7 @@ static void commonGraph(OAIgraph_t *graph, int type, FL_Coord x, FL_Coord y, FL_
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) {
OAIgraph_t graph;
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
static void genericWaterFall (OAIgraph_t *graph, scopeSample_t *values, const int datasize, const int divisions, const char *label) {
if ( values == NULL )
return;
return;
fl_winset(FL_ObjWin(graph->graph));
const int samplesPerPixel=datasize/graph->w;
int displayPart=graph->waterFallh-ScaleZone;
......@@ -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) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
static void gNBWaterFall (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms;
//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,
"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
}
*/
static void timeResponse (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
const int len=2*phy_vars_gnb->frame_parms.ofdm_symbol_size;
static void timeResponse (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
const int len=2*p->gNB->frame_parms.ofdm_symbol_size;
float *values, *time;
oai_xygraph_getbuff(graph, &time, &values, len, 0);
const int ant=0; // display antenna 0 for each UE
for (int ue=0; ue<nb_UEs; ue++) {
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) {
for (int i=0; i<len; i++) {
values[i] = SquaredNorm(data[i]);
oai_xygraph(graph,time,values, len, ue, 10);
}
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) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
static void gNBfreqWaterFall (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&p->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 *)p->rxdataF, frame_parms->samples_per_frame_wCP,
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
}
*/
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 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++) {
int16_t *pusch_llr = (int16_t *)phy_vars_gnb->pusch_vars[ue]->llr;
float *llr, *bit;
oai_xygraph_getbuff(graph, &bit, &llr, coded_bits_per_codeword, ue);
if ( p->gNB->pusch_vars &&
p->gNB->pusch_vars[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++) {
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
}
}
static void puschIQ (OAIgraph_t *graph, PHY_VARS_gNB *phy_vars_gnb, RU_t *phy_vars_ru, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&phy_vars_gnb->frame_parms;
static void puschIQ (OAIgraph_t *graph, scopeData_t *p, int nb_UEs) {
NR_DL_FRAME_PARMS *frame_parms=&p->gNB->frame_parms;
int sz=frame_parms->N_RB_UL*12*frame_parms->symbols_per_slot;
for (int ue=0; ue<nb_UEs; ue++) {
scopeSample_t *pusch_comp = (scopeSample_t *) phy_vars_gnb->pusch_vars[ue]->rxdataF_comp[0];
float *I, *Q;
oai_xygraph_getbuff(graph, &I, &Q, sz, ue);
if ( p->gNB->pusch_vars &&
p->gNB->pusch_vars[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++ ) {
I[k] = pusch_comp[k].r;
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
}
}
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
/*
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
*/
}
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
/*
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) {
static const int scope_enb_num_ue = 1;
void phy_scope_gNB(OAI_phy_scope_t *form,
PHY_VARS_gNB *phy_vars_gnb,
RU_t *phy_vars_ru,
scopeData_t *p,
int UE_id) {
static OAI_phy_scope_t *rememberForm=NULL;
......@@ -526,7 +535,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
int i=0;
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++;
}
......@@ -534,7 +543,7 @@ void phy_scope_gNB(OAI_phy_scope_t *form,
}
static void *scope_thread_gNB(void *arg) {
scopeParms_t *p=(scopeParms_t *) arg;
scopeData_t *p=(scopeData_t *) arg;
//# ifdef ENABLE_XFORMS_WRITE_STATS
// FILE *gNB_stats = fopen("gNB_stats.txt", "w");
//#endif
......@@ -543,12 +552,6 @@ static void *scope_thread_gNB(void *arg) {
pthread_attr_init(&atr);
pthread_attr_getstacksize(&atr, &stksize);
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
int fl_argc=1;
char *name="5G-gNB-scope";
......@@ -557,18 +560,31 @@ static void *scope_thread_gNB(void *arg) {
OAI_phy_scope_t *form_gnb = create_phy_scope_gnb();
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);
}
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) {
static scopeParms_t parms;
memcpy(&parms,p,sizeof(parms));
AssertFatal(p->gNB->scopeData=malloc(sizeof(scopeData_t)),"");
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;
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) {
......
......@@ -33,13 +33,7 @@
//#include "PHY/impl_defs_top.h"
#include "PHY/defs_nr_UE.h"
typedef struct {
int *argc;
char **argv;
RU_t *ru;
PHY_VARS_gNB *gNB;
} scopeParms_t;
#include <openair1/PHY/TOOLS/phy_scope_interface.h>
extern RAN_CONTEXT_t RC;
#endif
......@@ -35,6 +35,7 @@
#include "phy_scope_interface.h"
#define SOFTSCOPE_ENDFUNC_IDX 0
static loader_shlibfunc_t scope_fdesc[]= {{"end_forms",NULL}};
int load_softscope(char *exectype, void *initarg) {
......
......@@ -29,7 +29,26 @@
* \note
* \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 end_forms(void) ;
#endif
......@@ -68,8 +68,10 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_
*recplay_conf=NULL;
}
if (u_sf_replay == 1) return RECPLAY_REPLAYMODE;
else if (u_sf_record == 1) return RECPLAY_RECORDMODE;
if (u_sf_replay == 1)
return RECPLAY_REPLAYMODE;
else if (u_sf_record == 1)
return RECPLAY_RECORDMODE;
return 0;
}
......@@ -80,7 +82,7 @@ int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_
*/
void iqrecorder_end(openair0_device *device) {
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_conf_t *rc = device->openair0_cfg[0].recplay_conf;
rs->pFile = fopen (rc->u_sf_filename,"wb+");
......@@ -91,16 +93,20 @@ void iqrecorder_end(openair0_device *device) {
unsigned int i = 0;
unsigned int modu = 0;
if ((modu = rs->nb_samples % 10) != 0) {
rs->nb_samples -= modu; // store entire number of frames
if ((modu = rs->nbSamplesBlocks % 10) != 0) {
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 );
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++) {
fwrite(rs->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), rs->pFile);
for (i = 0; i < rs->nbSamplesBlocks; i++) {
int blockBytes=sizeof(iqrec_t)+((iqrec_t *)ptr)->nbBytes;
fwrite(ptr, sizeof(unsigned char), blockBytes, rs->pFile);
ptr+=blockBytes;
}
fclose (rs->pFile);
......@@ -112,4 +118,4 @@ void iqrecorder_end(openair0_device *device) {
rs->ms_sample = NULL;
}
}
}
\ No newline at end of file
}
......@@ -46,21 +46,22 @@ extern "C"
#define BELL_LABS_IQ_HEADER 0xabababababababab
#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 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 {
uint64_t devtype;
uint64_t tx_sample_advance;
double bw;
unsigned int nbSamplesBlocks;
char oaiid[4];
} iqfile_header_t;
typedef struct {
int64_t header;
int64_t ts;
int64_t rfu1;
int64_t nbBytes;
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;
#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
......@@ -114,14 +115,16 @@ typedef struct {
int use_mmap; // default is to use mmap
size_t mapsize;
FILE *pFile;
int mmapfd;
int iqfd;
int fd;
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;
#ifdef __cplusplus
}
#endif
......
......@@ -272,11 +272,10 @@ static int sync_to_gps(openair0_device *device) {
*/
static int trx_usrp_start(openair0_device *device) {
usrp_state_t *s = (usrp_state_t *)device->priv;
// setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output
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);
//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);
......@@ -285,26 +284,24 @@ static int trx_usrp_start(openair0_device *device) {
s->usrp->set_gpio_attr("FP0", "ATR_XX", (1<<5), 0x7f);
// set the output pins to 1
s->usrp->set_gpio_attr("FP0", "OUT", 7<<7, 0xf80);
s->wait_for_first_pps = 1;
s->rx_count = 0;
s->tx_count = 0;
//s->first_tx = 1;
//s->first_rx = 1;
s->rx_timestamp = 0;
s->usrp->set_time_next_pps(uhd::time_spec_t(0.0));
// wait for the pps to change
uhd::time_spec_t 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));
}
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
s->rx_stream->issue_stream_cmd(cmd);
return 0;
}
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources
......@@ -315,12 +312,11 @@ static void trx_usrp_end(openair0_device *device) {
return;
usrp_state_t *s = (usrp_state_t *)device->priv;
if (s == NULL)
return;
iqrecorder_end(device);
iqrecorder_end(device);
}
/*! \brief Called to send samples to the USRP RF target
......@@ -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
*/
static int trx_usrp_write(openair0_device *device,
openair0_timestamp timestamp,
void **buff,
int nsamps,
int cc,
int flags) {
openair0_timestamp timestamp,
void **buff,
int nsamps,
int cc,
int flags) {
int ret=0;
usrp_state_t *s = (usrp_state_t *)device->priv;
int nsamps2; // aligned to upper 32 or 16 byte boundary
int flags_lsb = flags&0xff;
int flags_msb = (flags>>8)&0xff;
int end;
openair0_thread_t *write_thread = &device->write_thread;
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);
boolean_t first_packet_state=false,last_packet_state=false;
if (flags_lsb == 2) { // start of burst
// s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = false;
first_packet_state = true;
last_packet_state = false;
} else if (flags_lsb == 3) { // end of burst
//s->tx_md.start_of_burst = false;
//s->tx_md.end_of_burst = true;
first_packet_state = false;
last_packet_state = true;
} else if (flags_lsb == 4) { // start and end
boolean_t first_packet_state=false,last_packet_state=false;
if (flags_lsb == 2) { // start of burst
// s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = false;
first_packet_state = true;
last_packet_state = false;
} else if (flags_lsb == 3) { // end of burst
//s->tx_md.start_of_burst = false;
//s->tx_md.end_of_burst = true;
first_packet_state = false;
last_packet_state = true;
} else if (flags_lsb == 4) { // start and end
// s->tx_md.start_of_burst = true;
// s->tx_md.end_of_burst = true;
first_packet_state = true;
last_packet_state = true;
} else if (flags_lsb==1) { // middle of burst
first_packet_state = true;
last_packet_state = true;
} else if (flags_lsb==1) { // middle of burst
// s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = false;
first_packet_state = false;
last_packet_state = false;
}
else if (flags_lsb==10) { // fail safe mode
// s->tx_md.has_time_spec = false;
// s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = true;
first_packet_state = false;
last_packet_state = true;
}
first_packet_state = false;
last_packet_state = false;
} else if (flags_lsb==10) { // fail safe mode
// s->tx_md.has_time_spec = false;
// s->tx_md.start_of_burst = false;
// s->tx_md.end_of_burst = true;
first_packet_state = false;
last_packet_state = true;
}
if(usrp_tx_thread == 0){
if(usrp_tx_thread == 0) {
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[8][nsamps2];
#else
#ifdef __AVX2__
nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[8][nsamps2];
#else
nsamps2 = (nsamps+3)>>2;
__m128i buff_tx[8][nsamps2];
#endif
#endif
#elif defined(__arm__)
nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tx[8][nsamps2];
......@@ -417,8 +408,8 @@ static int trx_usrp_write(openair0_device *device,
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_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)
if (flags_msb&8) {
// 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
s->usrp->set_gpio_attr("FP0", "OUT", gpio789, 0x380);
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) {
std::vector<void *> buff_ptrs;
......@@ -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]));
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);
}
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;
}
else{
} else {
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);
write_thread->end = write_thread->start;
write_thread->count_write = 0;
......@@ -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].last_packet = last_packet_state;
write_package[end].flags_msb = flags_msb;
for (int i = 0; i < cc; i++)
write_package[end].buff[i] = buff[i];
write_thread->count_write++;
write_thread->end = (write_thread->end + 1)% MAX_WRITE_THREAD_PACKAGE;
pthread_cond_signal(&write_thread->cond_write);
pthread_mutex_unlock(&write_thread->mutex_write);
return 0;
}
}
//-----------------------start--------------------------
......@@ -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 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;
openair0_device *device=(openair0_device *)arg;
openair0_thread_t *write_thread = &device->write_thread;
openair0_write_package_t *write_package = write_thread->write_package;
usrp_state_t *s;
int nsamps2; // aligned to upper 32 or 16 byte boundary
int start;
......@@ -497,11 +489,13 @@ void *trx_usrp_write_thread(void * arg){
signed char last_packet;
int flags_msb;
while(1){
while(1) {
pthread_mutex_lock(&write_thread->mutex_write);
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
}
VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 1 );
s = (usrp_state_t *)device->priv;
start = write_thread->start;
......@@ -518,38 +512,36 @@ void *trx_usrp_write_thread(void * arg){
/*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);
}*/
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[8][nsamps2];
#else
nsamps2 = (nsamps+3)>>2;
__m128i buff_tx[8][nsamps2];
#endif
#elif defined(__arm__)
nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tx[8][nsamps2];
#else
#error Unsupported CPU architecture, USRP device cannot be built
#endif
#if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__
nsamps2 = (nsamps+7)>>3;
__m256i buff_tx[8][nsamps2];
#else
nsamps2 = (nsamps+3)>>2;
__m128i buff_tx[8][nsamps2];
#endif
#elif defined(__arm__)
nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tx[8][nsamps2];
#else
#error Unsupported CPU architecture, USRP device cannot be built
#endif
// 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__)
#ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
#else
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif
#elif defined(__arm__)
buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
#endif
#if defined(__x86_64__) || defined(__i386__)
#ifdef __AVX2__
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
#else
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
#endif
#elif defined(__arm__)
buff_tx[i][j] = vshlq_n_s16(((int16x8_t *)buff[i])[j],4);
#endif
}
}
s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = (s->tx_count==0) ? true : first_packet;
s->tx_md.end_of_burst = last_packet;
......@@ -572,34 +564,32 @@ void *trx_usrp_write_thread(void * arg){
buff_ptrs.push_back(&(((int16_t *)buff_tx[i])[0]));
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);
}
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_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_THREAD, 0 );
if(0) break;
if(0)
break;
}
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);
openair0_thread_t *write_thread = &device->write_thread;
printf("initializing tx write thread\n");
write_thread->start = 0;
write_thread->end = 0;
write_thread->count_write = 0;
printf("end of tx write thread\n");
pthread_create(&write_thread->pthread_write,NULL,trx_usrp_write_thread,(void *)device);
return(0);
}
......@@ -633,57 +623,60 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
int16x8_t buff_tmp[2][nsamps2];
#endif
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
std::vector<void *> buff_ptrs;
if (cc>1) {
// receive multiple channels (e.g. RF A and RF B)
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);
} else {
// receive a single channel (e.g. from connector RF A)
samples_received=0;
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
} else {
// receive a single channel (e.g. from connector RF A)
samples_received=0;
while (samples_received != nsamps) {
samples_received += s->rx_stream->recv((void*)((int32_t*)buff_tmp[0]+samples_received),
nsamps-samples_received, s->rx_md);
while (samples_received != nsamps) {
samples_received += s->rx_stream->recv((void *)((int32_t *)buff_tmp[0]+samples_received),
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))
break;
if ((s->wait_for_first_pps == 0) && (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE))
break;
if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
printf("sleep...\n"); //usleep(100);
}
if ((s->wait_for_first_pps == 1) && (samples_received != nsamps)) {
printf("sleep...\n"); //usleep(100);
}
if (samples_received == nsamps) s->wait_for_first_pps=0;
}
// bring RX data into 12 LSBs for softmodem RX
for (int i=0; i<cc; i++) {
for (int j=0; j<nsamps2; j++) {
if (samples_received == nsamps)
s->wait_for_first_pps=0;
}
// 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__)
#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) {
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
} else {
((__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);
}
if ((((uintptr_t) buff[i])&0x1F)==0) {
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
} else {
((__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);
}
#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
#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
}
}
}
if (samples_received < nsamps) {
LOG_E(HW,"[recv] received %d samples out of %d\n",samples_received,nsamps);
}
if (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)
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
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
// 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_gpio_attr("FP0", "OUT", gpio789<<7, 0x380);
s->usrp->clear_command_time();
gpio789 = (gpio789+1)&7;*/
/*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->clear_command_time();
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)
if (device->recplay_state->nb_samples < device->openair0_cfg->recplay_conf->u_sf_max) {
(device->recplay_state->ms_sample+device->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER;
(device->recplay_state->ms_sample+device->recplay_state->nb_samples)->ts = *ptimestamp;
memcpy((device->recplay_state->ms_sample+device->recplay_state->nb_samples)->samples, buff[0], nsamps*4);
device->recplay_state->nb_samples++;
} else exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n");
if (recPlay->nbSamplesBlocks < device->openair0_cfg->recplay_conf->u_sf_max &&
recPlay->maxSizeBytes > (recPlay->currentPtr-(uint8_t *)recPlay->ms_sample) +
sizeof(iqrec_t) + nsamps*4 ) {
iqrec_t *hdr=(iqrec_t *)recPlay->currentPtr;
hdr->header = BELL_LABS_IQ_HEADER;
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;
......@@ -937,32 +937,30 @@ extern "C" {
device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains;
device->trx_write_init = trx_usrp_write_init;
// hotfix! to be checked later
uhd::set_thread_priority_safe(1.0);
// Initialize USRP device
int vers=0,subvers=0,subsubvers=0;
int bw_gain_adjust=0;
if (device->openair0_cfg->recplay_mode == RECPLAY_RECORDMODE) {
std::cerr << "USRP device initialized in subframes record mode" << std::endl;
}
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
LOG_I(HW,"UHD version %s (%d.%d.%d)\n",
uhd::get_version_string().c_str(),vers,subvers,subsubvers);
std::string args;
if (openair0_cfg[0].sdr_addrs == NULL) {
args = "type=b200";
} else {
args = 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);
if (device_adds.size() == 0) {
LOG_E(HW,"No USRP Device Found.\n ");
free(s);
......@@ -972,375 +970,367 @@ extern "C" {
free(s);
return -1;
}
LOG_I(HW,"Found USRP %s\n", device_adds[0].get("type").c_str());
double usrp_master_clock;
if (device_adds[0].get("type") == "b200") {
device->type = USRP_B200_DEV;
usrp_master_clock = 30.72e6;
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" ;
}
if (device_adds[0].get("type") == "n3xx") {
printf("Found USRP n300\n");
device->type=USRP_N300_DEV;
device->type=USRP_N300_DEV;
usrp_master_clock = 122.88e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
//args += ", send_buff_size=33554432";
}
if (device_adds[0].get("type") == "x300") {
printf("Found USRP x300\n");
device->type=USRP_X300_DEV;
usrp_master_clock = 184.32e6;
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
// 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") )
LOG_W(HW,"Can't set kernel parameters for X3xx\n");
}
s->usrp = uhd::usrp::multi_usrp::make(args);
if (args.find("clock_source")==std::string::npos) {
if (openair0_cfg[0].clock_source == internal) {
s->usrp->set_clock_source("internal");
LOG_D(HW,"Setting clock source to internal\n");
}
else if (openair0_cfg[0].clock_source == external ) {
s->usrp->set_clock_source("external");
LOG_D(HW,"Setting clock source to external\n");
}
else if (openair0_cfg[0].clock_source==gpsdo) {
s->usrp->set_clock_source("gpsdo");
LOG_D(HW,"Setting clock source to gpsdo\n");
}
else {
LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\n");
}
if (openair0_cfg[0].clock_source == internal) {
s->usrp->set_clock_source("internal");
LOG_D(HW,"Setting clock source to internal\n");
} else if (openair0_cfg[0].clock_source == external ) {
s->usrp->set_clock_source("external");
LOG_D(HW,"Setting clock source to external\n");
} else if (openair0_cfg[0].clock_source==gpsdo) {
s->usrp->set_clock_source("gpsdo");
LOG_D(HW,"Setting clock source to gpsdo\n");
} else {
LOG_W(HW,"Clock source set neither in usrp_args nor on command line, using default!\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");
}
}
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 (openair0_cfg[0].time_source == internal) {
s->usrp->set_time_source("internal");
LOG_D(HW,"Setting time source to internal\n");
}
else if (openair0_cfg[0].time_source == external ) {
s->usrp->set_time_source("external");
LOG_D(HW,"Setting time source to external\n");
}
else if (openair0_cfg[0].time_source==gpsdo) {
s->usrp->set_time_source("gpsdo");
LOG_D(HW,"Setting time source to gpsdo\n");
}
else {
LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\n");
}
if (openair0_cfg[0].time_source == internal) {
s->usrp->set_time_source("internal");
LOG_D(HW,"Setting time source to internal\n");
} else if (openair0_cfg[0].time_source == external ) {
s->usrp->set_time_source("external");
LOG_D(HW,"Setting time source to external\n");
} else if (openair0_cfg[0].time_source==gpsdo) {
s->usrp->set_time_source("gpsdo");
LOG_D(HW,"Setting time source to gpsdo\n");
} else {
LOG_W(HW,"Time source set neither in usrp_args nor on command line, using default!\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");
}
}
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") {
s->use_gps = 1;
if (sync_to_gps(device)==EXIT_SUCCESS) {
LOG_I(HW,"USRP synced with GPS!\n");
} else {
LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n");
exit(EXIT_FAILURE);
if (s->usrp->get_clock_source(0) == "gpsdo") {
s->use_gps = 1;
if (sync_to_gps(device)==EXIT_SUCCESS) {
LOG_I(HW,"USRP synced with GPS!\n");
} else {
LOG_I(HW,"USRP fails to sync with GPS. Exiting.\n");
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)) {
LOG_I(HW,"USRP locked to external reference!\n");
} else {
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_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) {
openair0_cfg[0].rx_gain_calib_table = calib_table_n310;
std::cerr << "-- Using calibration table: calib_table_n310" << std::endl;
}
if (device->type==USRP_N300_DEV) {
openair0_cfg[0].rx_gain_calib_table = calib_table_n310;
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) {
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
switch ((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 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;
case 92160000:
// 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;
case 61440000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 46080000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 30720000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].rx_bw = 10e6;
break;
case 7680000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].rx_bw = 5e6;
break;
case 1920000:
//openair0_cfg[0].samples_per_packet = 2048;
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;
case 92160000:
// 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;
case 61440000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 46080000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 40e6;
openair0_cfg[0].rx_bw = 40e6;
break;
case 30720000:
// from usrp_time_offset
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 15;
openair0_cfg[0].tx_bw = 20e6;
openair0_cfg[0].rx_bw = 20e6;
break;
case 15360000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 45;
openair0_cfg[0].tx_bw = 10e6;
openair0_cfg[0].rx_bw = 10e6;
break;
case 7680000:
//openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
openair0_cfg[0].rx_bw = 5e6;
break;
case 1920000:
//openair0_cfg[0].samples_per_packet = 2048;
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 ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0;
std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
} else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
if (device->type == USRP_B200_DEV) {
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0;
std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
} else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
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) {
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;
/* device specific */
//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
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) {
if (i<openair0_cfg[0].rx_num_channels) {
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],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());
}
}
}
/* device specific */
//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
openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
for(int i=0; i<((int) s->usrp->get_rx_num_channels()); i++) {
if (i<openair0_cfg[0].rx_num_channels) {
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],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());
LOG_D(HW, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels());
LOG_D(HW, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels);
for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) {
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i);
if (i<openair0_cfg[0].tx_num_channels) {
s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i);
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[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]);
}
}
}
LOG_D(HW, "usrp->get_tx_num_channels() == %zd\n", s->usrp->get_tx_num_channels());
LOG_D(HW, "openair0_cfg[0].tx_num_channels == %d\n", openair0_cfg[0].tx_num_channels);
for(int i=0; i<((int) s->usrp->get_tx_num_channels()); i++) {
::uhd::gain_range_t gain_range_tx = s->usrp->get_tx_gain_range(i);
if (i<openair0_cfg[0].tx_num_channels) {
s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i);
s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i);
s->usrp->set_tx_gain(gain_range_tx.stop()-openair0_cfg[0].tx_gain[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]);
//s->usrp->set_clock_source("external");
//s->usrp->set_time_source("external");
// display USRP settings
LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
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());
sleep(1);
// create tx & rx streamer
uhd::stream_args_t stream_args_rx("sc16", "sc16");
int samples=openair0_cfg[0].sample_rate;
int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps();
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 );
}
}
//s->usrp->set_clock_source("external");
//s->usrp->set_time_source("external");
// display USRP settings
LOG_I(HW,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
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());
sleep(1);
// create tx & rx streamer
uhd::stream_args_t stream_args_rx("sc16", "sc16");
int samples=openair0_cfg[0].sample_rate;
int max=s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps();
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->get_rx_stream(stream_args_rx)->get_max_num_samps());
for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++)
stream_args_rx.channels.push_back(i);
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
uhd::stream_args_t stream_args_tx("sc16", "sc16");
for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
stream_args_tx.channels.push_back(i);
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */
for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++)
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++)
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);
LOG_I(HW,"rx_max_num_samps %zu\n",
s->usrp->get_rx_stream(stream_args_rx)->get_max_num_samps());
for (int i = 0; i<openair0_cfg[0].rx_num_channels; i++)
stream_args_rx.channels.push_back(i);
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
uhd::stream_args_t stream_args_tx("sc16", "sc16");
for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
stream_args_tx.channels.push_back(i);
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */
for(int i=0; i<((int) s->usrp->get_tx_num_channels()) && i<openair0_cfg[0].tx_num_channels; i++)
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++)
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());
}
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 */
......@@ -40,18 +40,15 @@
#include "assertions.h"
#include "common/utils/LOG/log.h"
static void parse_iqfile_header(openair0_device *device, iqfile_header_t *iq_fh) {
AssertFatal((memcmp(iq_fh->oaiid,OAIIQFILE_ID,sizeof(OAIIQFILE_ID)) == 0),
"iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n",
iq_fh->oaiid);
char tmp[4]=OAIIQFILE_ID;
AssertFatal((memcmp(iq_fh->oaiid,tmp,sizeof(iq_fh->oaiid)) == 0),
"iqfile doesn't seem to be compatible with oai (invalid id %.4s in header)\n",
iq_fh->oaiid);
device->type = iq_fh->devtype;
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->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);
}
......@@ -63,89 +60,73 @@ static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair
recplay_state_t *s = device->recplay_state;
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) {
// 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;
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) ;
s->ms_sample = (iqrec_t *) ( mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->mmapfd, 0) + sizeof(iqfile_header_t));
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->fd, 0) + sizeof(iqfile_header_t));
if (mptr != MAP_FAILED) {
parse_iqfile_header(device, (iqfile_header_t *)mptr);
s->ms_sample = (iqrec_t *)((char *)mptr + sizeof(iqfile_header_t));
s->nb_samples = ((sb.st_size-sizeof(iqfile_header_t)) / sizeof(iqrec_t));
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);
}
LOG_I(HW,"Loaded %u subframes.\n",s->nbSamplesBlocks );
} else {
LOG_E(HW,"Cannot mmap file, exiting.\n");
close(s->mmapfd);
close(s->fd);
exit(-1);
}
} else {
LOG_E( HW,"Cannot open %s exiting.\n", c->u_sf_filename );
exit(-1);
}
} 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) {
struct stat sb;
iqfile_header_t fh;
size_t hs = read(s->iqfd,&fh,sizeof(fh));
if (hs == sizeof(fh)) {
parse_iqfile_header(device, &fh);
fstat(s->iqfd, &sb);
if (hs == sizeof(fh)) {
parse_iqfile_header(device, &fh);
fstat(s->fd, &sb);
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->nb_samples, c->u_sf_filename,(uint64_t)sb.st_size);
LOG_I(HW, "Loading %u subframes from %s,size=%lu bytes ...\n",s->nbSamplesBlocks, c->u_sf_filename,(uint64_t)sb.st_size);
// 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) {
LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" );
close(s->iqfd);
close(s->fd);
exit(-1);
}
memset(s->ms_sample, 0, sizeof(iqrec_t));
// 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" );
} else {
LOG_I(HW,"Problem initial seek at beginning of the file\n");
}
} else {
LOG_E(HW,"Cannot read header in %s exiting.\n",c->u_sf_filename );
close(s->iqfd);
close(s->fd);
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;
}
/*! \brief start the oai iq player
* \param device, the hardware used
*/
static int trx_iqplayer_start(openair0_device *device){
return 0;
static int trx_iqplayer_start(openair0_device *device) {
return 0;
}
/*! \brief Terminate operation of the oai iq player
......@@ -157,28 +138,22 @@ static void trx_iqplayer_end(openair0_device *device) {
if (device->recplay_state == NULL)
return;
if (device->recplay_state->use_mmap) {
if (device->recplay_state->ms_sample != MAP_FAILED) {
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 {
if (device->recplay_state->ms_sample != NULL) {
free(device->recplay_state->ms_sample);
device->recplay_state->ms_sample = NULL;
}
if (device->recplay_state->iqfd != 0) {
close(device->recplay_state->iqfd);
device->recplay_state->iqfd = 0;
}
}
}
device->recplay_state->ms_sample = NULL;
if (device->recplay_state->fd >= 0) {
close(device->recplay_state->fd);
device->recplay_state->fd = -1;
}
}
/*! \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
......@@ -208,93 +183,68 @@ static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timest
* \returns the number of sample read
*/
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;
if (cur_samples == s->nb_samples) {
cur_samples = 0;
wrap_count++;
if (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);
if (s->curSamplesBlock==0 && s->wrap_count==0 )
s->currentTs=s->ms_sample->ts;
if (s->curSamplesBlock == s->nbSamplesBlocks) {
LOG_I(HW, "wrapping on iq file (%ld)\n", s->wrap_count);
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");
}
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 (lseek(device->recplay_state->iqfd, 0, SEEK_SET) == 0) {
LOG_I(HW,"Seeking at the beginning of IQ file");
} else {
LOG_I(HW, "Problem seeking at the beginning of IQ file");
if (!s->use_mmap) {
if (lseek(device->recplay_state->fd, 0, SEEK_SET) != 0) {
LOG_E(HW, "Problem seeking at the beginning of IQ file");
}
}
}
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 {
if (!s->use_mmap) {
// read sample from file
if (read(s->iqfd, s->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*cur_samples );
close(s->iqfd);
free(s->ms_sample);
s->ms_sample = NULL;
s->iqfd = 0;
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)*s->curSamplesBlock );
exit(-1);
}
if (cur_samples < s->nb_samples) {
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));
} else {
if (read(s->fd, s->ms_sample+1, s->ms_sample->nbBytes) != s->ms_sample->nbBytes) {
LOG_E(HW,"pb reading iqfile at index %lu\n",sizeof(iqrec_t)*s->curSamplesBlock );
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_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000;
nanosleep(&req, NULL);
LOG_D(HW, "returning %d samples at ts %lu\n", nsamps, *ptimestamp);
return nsamps;
return samples_received;
}
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
device->openair0_cfg = openair0_cfg;
device->trx_start_func = trx_iqplayer_start;
......@@ -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);
return 0;
}
/*@}*/
......@@ -727,7 +727,7 @@ int main ( int argc, char **argv )
fflush(stderr);
// end of CI modifications
//getchar();
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
load_softscope("enb",NULL);
itti_wait_tasks_end();
oai_exit=1;
......@@ -735,7 +735,7 @@ int main ( int argc, char **argv )
// stop threads
if (RC.nb_inst == 0 || !NODE_IS_CU(node_type)) {
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
end_forms();
LOG_I(ENB_APP,"stopping MODEM threads\n");
......
......@@ -758,7 +758,7 @@ int main( int argc, char **argv ) {
PHY_vars_UE_g[0][0]->no_timing_correction = 1;
}
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
load_softscope("ue",NULL);
config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
......@@ -783,7 +783,7 @@ int main( int argc, char **argv ) {
printf("oai_exit=%d\n",oai_exit);
// stop threads
if(IS_SOFTMODEM_DOFORMS)
if(IS_SOFTMODEM_DOSCOPE)
end_forms();
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