Commit eadcba95 authored by gabrielC's avatar gabrielC

Merge branch 'develop-realtime-lts' into develop_integration_w07

Conflicts:
	targets/RT/USER/lte-enb.c
	targets/RT/USER/lte-softmodem.c
	targets/RT/USER/lte-ue.c
parents 10a50563 be0541aa
...@@ -1664,18 +1664,6 @@ endif() ...@@ -1664,18 +1664,6 @@ endif()
message ("NETTLE VERSION_INSTALLED = ${NETTLE_VERSION}") message ("NETTLE VERSION_INSTALLED = ${NETTLE_VERSION}")
string(REGEX REPLACE "([0-9]+).*" "\\1" NETTLE_VERSION_MAJOR ${NETTLE_VERSION})
string(REGEX REPLACE "[0-9]+\\.([0-9]+).*" "\\1" NETTLE_VERSION_MINOR ${NETTLE_VERSION})
message ("NETTLE_VERSION_MAJOR = ${NETTLE_VERSION_MAJOR}")
message ("NETTLE_VERSION_MINOR = ${NETTLE_VERSION_MINOR}")
if ("${NETTLE_VERSION_MAJOR}" STREQUAL "" OR "${NETTLE_VERSION_MINOR}" STREQUAL "")
message( FATAL_ERROR "The nettle version not detected properly. Try to run build_oai -I again" )
endif()
add_definitions("-DNETTLE_VERSION_MAJOR=${NETTLE_VERSION_MAJOR}")
add_definitions("-DNETTLE_VERSION_MINOR=${NETTLE_VERSION_MINOR}")
pkg_search_module(XPM xpm) pkg_search_module(XPM xpm)
if(NOT ${XPM_FOUND}) if(NOT ${XPM_FOUND})
message("PACKAGE xpm not found: some targets will fail") message("PACKAGE xpm not found: some targets will fail")
......
...@@ -65,7 +65,7 @@ _Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX " ...@@ -65,7 +65,7 @@ _Assert_(cOND, _Assert_Exit_, #vALUE1 ": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3) (intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3)
#define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \ #define DevCheck4(cOND, vALUE1, vALUE2, vALUE3, vALUE4) \
_Assert_(cOND, _Assert_Exit_, #vALUE1": %"PRIdMAX"\n"#vALUE2": %"PRIdMAX"\n"#vALUE3": %"PRIdMAX"\n"#vALUE4": %"PRIdMAX"\n\n", \ _Assert_(cOND, _Assert_Exit_, #vALUE1": %" PRIdMAX "\n" #vALUE2 ": %" PRIdMAX "\n" #vALUE3 ": %" PRIdMAX "\n" #vALUE4 ": %" PRIdMAX "\n\n", \
(intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4) (intmax_t)vALUE1, (intmax_t)vALUE2, (intmax_t)vALUE3, (intmax_t)vALUE4)
#define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3) #define DevParam(vALUE1, vALUE2, vALUE3) DevCheck(0, vALUE1, vALUE2, vALUE3)
......
...@@ -40,6 +40,8 @@ ...@@ -40,6 +40,8 @@
#include "SCHED/defs.h" #include "SCHED/defs.h"
#include "defs.h" #include "defs.h"
#include "UTIL/LOG/vcd_signal_dumper.h" #include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/LOG/log.h"
#include <syscall.h>
//#define DEBUG_DLSCH_CODING //#define DEBUG_DLSCH_CODING
//#define DEBUG_DLSCH_FREE 1 //#define DEBUG_DLSCH_FREE 1
...@@ -347,6 +349,8 @@ int dlsch_encoding_2threads0(te_params *tep) { ...@@ -347,6 +349,8 @@ int dlsch_encoding_2threads0(te_params *tep) {
extern int oai_exit; extern int oai_exit;
void *te_thread(void *param) { void *te_thread(void *param) {
pthread_setname_np( pthread_self(),"te processing");
LOG_I(PHY,"thread te created id=%ld", syscall(__NR_gettid));
eNB_proc_t *proc = &((te_params *)param)->eNB->proc; eNB_proc_t *proc = &((te_params *)param)->eNB->proc;
while (!oai_exit) { while (!oai_exit) {
......
...@@ -418,6 +418,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) { ...@@ -418,6 +418,7 @@ int ulsch_decoding_data_2thread0(td_params* tdp) {
extern int oai_exit; extern int oai_exit;
void *td_thread(void *param) { void *td_thread(void *param) {
pthread_setname_np( pthread_self(), "td processing");
PHY_VARS_eNB *eNB = ((td_params*)param)->eNB; PHY_VARS_eNB *eNB = ((td_params*)param)->eNB;
eNB_proc_t *proc = &eNB->proc; eNB_proc_t *proc = &eNB->proc;
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#ifndef __PHY_DEFS__H__ #ifndef __PHY_DEFS__H__
#define __PHY_DEFS__H__ #define __PHY_DEFS__H__
#define _GNU_SOURCE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <malloc.h> #include <malloc.h>
...@@ -391,6 +392,9 @@ typedef struct { ...@@ -391,6 +392,9 @@ typedef struct {
pthread_mutex_t mutex_rxtx; pthread_mutex_t mutex_rxtx;
/// scheduling parameters for RXn-TXnp4 thread /// scheduling parameters for RXn-TXnp4 thread
struct sched_param sched_param_rxtx; struct sched_param sched_param_rxtx;
int sub_frame_start;
int sub_frame_step;
unsigned long long gotIQs;
} UE_rxtx_proc_t; } UE_rxtx_proc_t;
/// Context data structure for eNB subframe processing /// Context data structure for eNB subframe processing
......
...@@ -2603,6 +2603,7 @@ extern int oai_exit; ...@@ -2603,6 +2603,7 @@ extern int oai_exit;
static void *fep_thread(void *param) { static void *fep_thread(void *param) {
pthread_setname_np( pthread_self(), "UEfep");
PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param; PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
eNB_proc_t *proc = &eNB->proc; eNB_proc_t *proc = &eNB->proc;
while (!oai_exit) { while (!oai_exit) {
......
...@@ -264,7 +264,7 @@ typedef struct protocol_ctxt_s { ...@@ -264,7 +264,7 @@ typedef struct protocol_ctxt_s {
(Ctxt_Pp)->subframe = sUBfRAME; \ (Ctxt_Pp)->subframe = sUBfRAME; \
PROTOCOL_CTXT_COMPUTE_MODULE_ID(Ctxt_Pp) PROTOCOL_CTXT_COMPUTE_MODULE_ID(Ctxt_Pp)
#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %"PRIx16"]" #define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %" PRIx16 "]"
#define PROTOCOL_CTXT_ARGS(CTXT_Pp) \ #define PROTOCOL_CTXT_ARGS(CTXT_Pp) \
(CTXT_Pp)->frame, \ (CTXT_Pp)->frame, \
((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB":" UE", \ ((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB":" UE", \
......
...@@ -43,6 +43,13 @@ ...@@ -43,6 +43,13 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdarg.h> #include <stdarg.h>
#include <time.h>
#include <stdint.h>
#include <inttypes.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <pthread.h>
#else #else
#include "rtai_fifos.h" #include "rtai_fifos.h"
#endif #endif
...@@ -76,41 +83,197 @@ extern "C" { ...@@ -76,41 +83,197 @@ extern "C" {
* @ingroup _macro * @ingroup _macro
* @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8 * @brief LOG defines 9 levels of messages for users. Importance of these levels decrease gradually from 0 to 8
* @{*/ * @{*/
#ifndef LOG_EMERG
# define LOG_EMERG 0 /*!< \brief system is unusable */ # define LOG_EMERG 0 /*!< \brief system is unusable */
#endif
#ifndef LOG_ALERT
# define LOG_ALERT 1 /*!< \brief action must be taken immediately */ # define LOG_ALERT 1 /*!< \brief action must be taken immediately */
#endif
#ifndef LOG_CRIT
# define LOG_CRIT 2 /*!< \brief critical conditions */ # define LOG_CRIT 2 /*!< \brief critical conditions */
#endif
#ifndef LOG_ERR
# define LOG_ERR 3 /*!< \brief error conditions */ # define LOG_ERR 3 /*!< \brief error conditions */
#endif
#ifndef LOG_WARNING
# define LOG_WARNING 4 /*!< \brief warning conditions */ # define LOG_WARNING 4 /*!< \brief warning conditions */
#endif
#ifndef LOG_NOTICE
# define LOG_NOTICE 5 /*!< \brief normal but significant condition */ # define LOG_NOTICE 5 /*!< \brief normal but significant condition */
#endif
#ifndef LOG_INFO
# define LOG_INFO 6 /*!< \brief informational */ # define LOG_INFO 6 /*!< \brief informational */
#endif
#ifndef LOG_DEBUG
# define LOG_DEBUG 7 /*!< \brief debug-level messages */ # define LOG_DEBUG 7 /*!< \brief debug-level messages */
#endif
#ifndef LOG_FILE
# define LOG_FILE 8 /*!< \brief message sequence chart -level */ # define LOG_FILE 8 /*!< \brief message sequence chart -level */
#endif
#ifndef LOG_TRACE
# define LOG_TRACE 9 /*!< \brief trace-level messages */ # define LOG_TRACE 9 /*!< \brief trace-level messages */
#endif
#define NUM_LOG_LEVEL 10 /*!< \brief the number of message levels users have with LOG */ #define NUM_LOG_LEVEL 10 /*!< \brief the number of message levels users have with LOG */
/* @}*/ /* @}*/
/** @defgroup _log_format Defined log format
* @ingroup _macro
* @brief Macro of log formats defined by LOG
* @{*/
/* .log_format = 0x13 uncolored standard messages
* .log_format = 0x93 colored standard messages */
#define LOG_RED "\033[1;31m" /*!< \brief VT100 sequence for bold red foreground */
#define LOG_GREEN "\033[32m" /*!< \brief VT100 sequence for green foreground */
#define LOG_ORANGE "\033[93m" /*!< \brief VT100 sequence for orange foreground */
#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */
#define LOG_CYBL "\033[40;36m" /*!< \brief VT100 sequence for cyan foreground on black background */
#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */
/* @}*/
/** @defgroup _syslog_conf Macros for write in syslog.conf
* @ingroup _macro
* @brief Macros used to write lines (local/remote) in syslog.conf
* @{*/
#define LOG_LOCAL 0x01
#define LOG_REMOTE 0x02
#define FLAG_COLOR 0x001 /*!< \brief defaults */
#define FLAG_PID 0x002 /*!< \brief defaults */
#define FLAG_COMP 0x004
#define FLAG_THREAD 0x008 /*!< \brief all : 255/511 */
#define FLAG_LEVEL 0x010
#define FLAG_FUNCT 0x020
#define FLAG_FILE_LINE 0x040
#define FLAG_TIME 0x100
#define LOG_NONE 0x00
#define LOG_LOW 0x5
#define LOG_MED 0x15
#define LOG_HIGH 0x35
#define LOG_FULL 0x75
#define OAI_OK 0 /*!< \brief all ok */
#define OAI_ERR 1 /*!< \brief generic error */
#define OAI_ERR_READ_ONLY 2 /*!< \brief tried to write to read-only item */
#define OAI_ERR_NOTFOUND 3 /*!< \brief something wasn't found */
/* @}*/
//static char *log_level_highlight_start[] = {LOG_RED, LOG_RED, LOG_RED, LOG_RED, LOG_BLUE, "", "", "", LOG_GREEN}; /*!< \brief Optional start-format strings for highlighting */
//static char *log_level_highlight_end[] = {LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, "", "", "", LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
typedef enum {
MIN_LOG_COMPONENTS = 0,
PHY = MIN_LOG_COMPONENTS,
MAC,
EMU,
OCG,
OMG,
OPT,
OTG,
OTG_LATENCY,
OTG_LATENCY_BG,
OTG_GP,
OTG_GP_BG,
OTG_JITTER,
RLC,
PDCP,
RRC,
NAS,
PERF,
OIP,
CLI,
MSC,
OCM,
UDP_,
GTPU,
SPGW,
S1AP,
SCTP,
HW,
OSA,
RAL_ENB,
RAL_UE,
ENB_APP,
FLEXRAN_AGENT,
TMR,
USIM,
LOCALIZE,
RRH,
X2AP,
MAX_LOG_COMPONENTS,
}
comp_name_t;
//#define msg printf
typedef struct {
char *name; /*!< \brief string name of item */
int value; /*!< \brief integer value of mapping */
} mapping;
typedef struct {
const char *name;
int level;
int flag;
int interval;
int fd;
int filelog;
char *filelog_name;
/* SR: make the log buffer component relative */
char log_buffer[MAX_LOG_TOTAL];
} log_component_t;
typedef struct {
unsigned int remote_ip;
unsigned int audit_ip;
int remote_level;
int facility;
int audit_facility;
int format;
} log_config_t;
typedef struct {
log_component_t log_component[MAX_LOG_COMPONENTS];
log_config_t config;
char* level2string[NUM_LOG_LEVEL];
int level;
int onlinelog;
int flag;
int syslog;
int filelog;
char* filelog_name;
} log_t;
typedef struct LOG_params {
const char *file;
const char *func;
int line;
int comp;
int level;
const char *format;
char l_buff_info [MAX_LOG_INFO];
int len;
} LOG_params;
#if defined(ENABLE_ITTI)
typedef enum log_instance_type_e {
LOG_INSTANCE_UNKNOWN,
LOG_INSTANCE_ENB,
LOG_INSTANCE_UE,
} log_instance_type_t;
void log_set_instance_type (log_instance_type_t instance);
#endif
/*--- INCLUDES ---------------------------------------------------------------*/
# include "log_if.h"
/*----------------------------------------------------------------------------*/
int logInit (void);
void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...);
void logRecord(const char *file, const char *func, int line,int comp, int level, const char *format, ...);
int set_comp_log(int component, int level, int verbosity, int interval);
int set_log(int component, int level, int interval);
void set_glog(int level, int verbosity);
void set_log_syslog(int enable);
void set_log_onlinelog(int enable);
void set_log_filelog(int enable);
void set_component_filelog(int comp);
int map_str_to_int(mapping *map, const char *str);
char *map_int_to_str(mapping *map, int val);
void logClean (void);
int is_newline( char *str, int size);
void *log_thread_function(void * list);
/** @defgroup _logIt logIt function /** @defgroup _logIt logIt function
* @ingroup _macro * @ingroup _macro
* @brief Macro used to call tr_log_full_ex with file, function and line information * @brief Macro used to call tr_log_full_ex with file, function and line information
...@@ -186,169 +349,107 @@ extern "C" { ...@@ -186,169 +349,107 @@ extern "C" {
#define LOG_RETURN(c,x) do {uint32_t __rv;__rv=(unsigned int)(x);LOG_T(c,"Returning %08x\n", __rv);return((typeof(x))__rv);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */ #define LOG_RETURN(c,x) do {uint32_t __rv;__rv=(unsigned int)(x);LOG_T(c,"Returning %08x\n", __rv);return((typeof(x))__rv);}while(0) /*!< \brief Macro to log a function exit, including integer value, then to return a value to the calling function */
/* @}*/ /* @}*/
static __inline__ uint64_t rdtsc(void) {
/** @defgroup _log_format Defined log format uint64_t a, d;
* @ingroup _macro __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
* @brief Macro of log formats defined by LOG return (d<<32) | a;
* @{*/
/* .log_format = 0x13 uncolored standard messages
* .log_format = 0x93 colored standard messages */
#define LOG_RED "\033[1;31m" /*!< \brief VT100 sequence for bold red foreground */
#define LOG_GREEN "\033[32m" /*!< \brief VT100 sequence for green foreground */
#define LOG_ORANGE "\033[93m" /*!< \brief VT100 sequence for orange foreground */
#define LOG_BLUE "\033[34m" /*!< \brief VT100 sequence for blue foreground */
#define LOG_CYBL "\033[40;36m" /*!< \brief VT100 sequence for cyan foreground on black background */
#define LOG_RESET "\033[0m" /*!< \brief VT100 sequence for reset (black) foreground */
/* @}*/
/** @defgroup _syslog_conf Macros for write in syslog.conf
* @ingroup _macro
* @brief Macros used to write lines (local/remote) in syslog.conf
* @{*/
#define LOG_LOCAL 0x01
#define LOG_REMOTE 0x02
#define FLAG_COLOR 0x001 /*!< \brief defaults */
#define FLAG_PID 0x002 /*!< \brief defaults */
#define FLAG_COMP 0x004
#define FLAG_THREAD 0x008 /*!< \brief all : 255/511 */
#define FLAG_LEVEL 0x010
#define FLAG_FUNCT 0x020
#define FLAG_FILE_LINE 0x040
#define FLAG_TIME 0x100
#define LOG_NONE 0x00
#define LOG_LOW 0x5
#define LOG_MED 0x15
#define LOG_HIGH 0x35
#define LOG_FULL 0x75
#define OAI_OK 0 /*!< \brief all ok */
#define OAI_ERR 1 /*!< \brief generic error */
#define OAI_ERR_READ_ONLY 2 /*!< \brief tried to write to read-only item */
#define OAI_ERR_NOTFOUND 3 /*!< \brief something wasn't found */
/* @}*/
//static char *log_level_highlight_start[] = {LOG_RED, LOG_RED, LOG_RED, LOG_RED, LOG_BLUE, "", "", "", LOG_GREEN}; /*!< \brief Optional start-format strings for highlighting */
//static char *log_level_highlight_end[] = {LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, LOG_RESET, "", "", "", LOG_RESET}; /*!< \brief Optional end-format strings for highlighting */
typedef enum {
MIN_LOG_COMPONENTS = 0,
PHY = MIN_LOG_COMPONENTS,
MAC,
EMU,
OCG,
OMG,
OPT,
OTG,
OTG_LATENCY,
OTG_LATENCY_BG,
OTG_GP,
OTG_GP_BG,
OTG_JITTER,
RLC,
PDCP,
RRC,
NAS,
PERF,
OIP,
CLI,
MSC,
OCM,
UDP_,
GTPU,
SPGW,
S1AP,
SCTP,
HW,
OSA,
RAL_ENB,
RAL_UE,
ENB_APP,
FLEXRAN_AGENT,
TMR,
USIM,
LOCALIZE,
RRH,
X2AP,
MAX_LOG_COMPONENTS,
} }
comp_name_t;
//#define msg printf
typedef struct {
char *name; /*!< \brief string name of item */
int value; /*!< \brief integer value of mapping */
} mapping;
typedef struct { #define DEBUG_REALTIME 1
const char *name; #if DEBUG_REALTIME
int level;
int flag; extern double cpuf;
int interval;
int fd; static inline uint64_t checkTCPU(int timeout, char * file, int line) {
int filelog; static uint64_t __thread lastCPUTime=0;
char *filelog_name; static uint64_t __thread last=0;
uint64_t cur=rdtsc();
/* SR: make the log buffer component relative */ struct timespec CPUt;
char log_buffer[MAX_LOG_TOTAL]; clock_gettime(CLOCK_THREAD_CPUTIME_ID, &CPUt);
} log_component_t; uint64_t CPUTime=CPUt.tv_sec*1000*1000+CPUt.tv_nsec/1000;
double microCycles=(double)(cpuf*1000);
typedef struct { int duration=(int)((cur-last)/microCycles);
unsigned int remote_ip; if ( last!=0 && duration > timeout ) {
unsigned int audit_ip; //struct timespec ts;
int remote_level; //clock_gettime(CLOCK_MONOTONIC, &ts);
int facility; printf("%s:%d lte-ue delay %d (exceed %d), CPU for this period: %lld\n", file, line,
int audit_facility; duration, timeout, (long long)CPUTime-lastCPUTime );
int format; }
} log_config_t; last=cur;
lastCPUTime=CPUTime;
return cur;
}
static inline unsigned long long checkT(int timeout, char * file, int line) {
static unsigned long long __thread last=0;
unsigned long long cur=rdtsc();
int microCycles=(int)(cpuf*1000);
int duration=(int)((cur-last)/microCycles);
if ( last!=0 && duration > timeout )
printf("%s:%d lte-ue delay %d (exceed %d)\n", file, line,
duration, timeout);
last=cur;
return cur;
}
typedef struct { typedef struct m {
log_component_t log_component[MAX_LOG_COMPONENTS]; uint64_t iterations;
log_config_t config; uint64_t sum;
char* level2string[NUM_LOG_LEVEL]; uint64_t maxArray[11];
int level; } Meas;
int onlinelog;
int flag; static inline void printMeas(char * txt, Meas *M, int period) {
int syslog; if (M->iterations%period == 0 ) {
int filelog; char txt2[512];
char* filelog_name; sprintf(txt2,"%s avg=%" PRIu64 " iterations=%" PRIu64 " max=%"
} log_t; PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 ":%" PRIu64 "\n",
txt,
M->sum/M->iterations,
M->iterations,
M->maxArray[1],M->maxArray[2], M->maxArray[3],M->maxArray[4], M->maxArray[5],
M->maxArray[6],M->maxArray[7], M->maxArray[8],M->maxArray[9],M->maxArray[10]);
LOG_W(PHY,txt2);
}
}
typedef struct LOG_params { static inline int cmpint(const void* a, const void* b) {
const char *file; uint64_t* aa=(uint64_t*)a;
const char *func; uint64_t* bb=(uint64_t*)b;
int line; return (int)(*aa-*bb);
int comp; }
int level;
const char *format;
char l_buff_info [MAX_LOG_INFO];
int len;
} LOG_params;
static inline void updateTimes(uint64_t start, Meas *M, int period, char * txt) {
if (start!=0) {
uint64_t end=rdtsc();
long long diff=(end-start)/(cpuf*1000);
M->maxArray[0]=diff;
M->sum+=diff;
M->iterations++;
qsort(M->maxArray, 11, sizeof(uint64_t), cmpint);
printMeas(txt,M,period);
}
}
#if defined(ENABLE_ITTI) #define check(a) do { checkT(a,__FILE__,__LINE__); } while (0)
typedef enum log_instance_type_e { #define checkcpu(a) do { checkTCPU(a,__FILE__,__LINE__); } while (0)
LOG_INSTANCE_UNKNOWN, #define initRefTimes(a) static __thread Meas a= {0}
LOG_INSTANCE_ENB, #define pickTime(a) uint64_t a=rdtsc()
LOG_INSTANCE_UE, #define readTime(a) a
} log_instance_type_t; #define initStaticTime(a) static __thread uint64_t a={0}
#define pickStaticTime(a) do { a=rdtsc(); } while (0)
void log_set_instance_type (log_instance_type_t instance); #else
#define check(a) do {} while (0)
#define checkcpu(a) do {} while (0)
#define initRefTimes(a) do {} while (0)
#define initStaticTime(a) do {} while (0)
#define pickTime(a) do {} while (0)
#define readTime(a) 0
#define pickStaticTime(a) do {} while (0)
#define updateTimes(a,b,c,d) do {} while (0)
#define printMeas(a,b,c) do {} while (0)
#endif #endif
int logInit (void);
/*--- INCLUDES ---------------------------------------------------------------*/
# include "log_if.h"
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
......
...@@ -27,59 +27,8 @@ ...@@ -27,59 +27,8 @@
* \warning This component can be runned only in user-space * \warning This component can be runned only in user-space
* @ingroup routing * @ingroup routing
*/ */
#ifndef __LOG_IF_H__
# define __LOG_IF_H__
/*--- INCLUDES ---------------------------------------------------------------*/
# include "log.h"
/*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
# ifdef COMPONENT_LOG
# ifdef COMPONENT_LOG_IF
# define private_log_if(x) x
# define friend_log_if(x) x
# define public_log_if(x) x
# else
# define private_log_if(x)
# define friend_log_if(x) extern x
# define public_log_if(x) extern x
# endif
# else
# define private_log_if(x)
# define friend_log_if(x)
# define public_log_if(x) extern x
# endif
/** @defgroup _log_if Interfaces of LOG
* @{*/
//public_log_if( log_t *g_log;)
public_log_if( int logInit (void);)
public_log_if( void logRecord_mt(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));)
public_log_if( void logRecord(const char *file, const char *func, int line,int comp, int level, const char *format, ...) __attribute__ ((format (printf, 6, 7)));)
public_log_if( int set_comp_log(int component, int level, int verbosity, int interval);)
public_log_if( int set_log(int component, int level, int interval);)
public_log_if( void set_glog(int level, int verbosity);)
public_log_if( void set_log_syslog(int enable);)
public_log_if( void set_log_onlinelog(int enable);)
public_log_if( void set_log_filelog(int enable);)
public_log_if( void set_component_filelog(int comp);)
public_log_if( int map_str_to_int(mapping *map, const char *str);)
public_log_if( char *map_int_to_str(mapping *map, int val);)
public_log_if( void logClean (void); )
public_log_if( int is_newline( char *str, int size);)
public_log_if( void *log_thread_function(void * list);)
/* @}*/
#ifdef __cplusplus
}
#endif
#endif
// LTS: kept this file for compatibility
// this file was probably a trial to separate internal functions and external ones
// but it has never been finished, most source code include directly log.h (not log_if.h)
#include "log.h"
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <nettle/nettle-meta.h> #include <nettle/nettle-meta.h>
#include <nettle/aes.h> #include <nettle/aes.h>
#include <nettle/ctr.h> #include <nettle/ctr.h>
#include <nettle/bignum.h>
#include "UTIL/LOG/log.h" #include "UTIL/LOG/log.h"
...@@ -191,7 +192,7 @@ int stream_encrypt_eea2(stream_cipher_t *stream_cipher, uint8_t **out) ...@@ -191,7 +192,7 @@ int stream_encrypt_eea2(stream_cipher_t *stream_cipher, uint8_t **out)
} }
#endif #endif
#if NETTLE_VERSION_MAJOR < 3 #if !defined(NETTLE_VERSION_MAJOR) || NETTLE_VERSION_MAJOR < 3
nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length, nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length,
stream_cipher->key); stream_cipher->key);
#else #else
......
...@@ -224,6 +224,7 @@ static void *_nas_user_mngr(void *args) ...@@ -224,6 +224,7 @@ static void *_nas_user_mngr(void *args)
{ {
LOG_FUNC_IN; LOG_FUNC_IN;
pthread_setname_np( pthread_self(), "nas_user_mngr");
int exit_loop = FALSE; int exit_loop = FALSE;
int *fd = (int *) args; int *fd = (int *) args;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <nettle/nettle-meta.h> #include <nettle/nettle-meta.h>
#include <nettle/aes.h> #include <nettle/aes.h>
#include <nettle/ctr.h> #include <nettle/ctr.h>
#include <nettle/bignum.h>
#include "assertions.h" #include "assertions.h"
#include "conversions.h" #include "conversions.h"
...@@ -78,7 +79,7 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out) ...@@ -78,7 +79,7 @@ int nas_stream_encrypt_eea2(nas_stream_cipher_t *stream_cipher, uint8_t *out)
} }
#endif #endif
#if NETTLE_VERSION_MAJOR < 3 #if !defined(NETTLE_VERSION_MAJOR) || NETTLE_VERSION_MAJOR < 3
nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length, nettle_aes128.set_encrypt_key(ctx, stream_cipher->key_length,
stream_cipher->key); stream_cipher->key);
#else #else
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <nettle/nettle-meta.h> #include <nettle/nettle-meta.h>
#include <nettle/aes.h> #include <nettle/aes.h>
#include <nettle/ctr.h> #include <nettle/ctr.h>
#include <nettle/bignum.h>
static static
void test_uncipher_ctr(const struct nettle_cipher *cipher, const uint8_t *key, void test_uncipher_ctr(const struct nettle_cipher *cipher, const uint8_t *key,
...@@ -41,7 +42,7 @@ void test_uncipher_ctr(const struct nettle_cipher *cipher, const uint8_t *key, ...@@ -41,7 +42,7 @@ void test_uncipher_ctr(const struct nettle_cipher *cipher, const uint8_t *key,
uint8_t *data = malloc(length); uint8_t *data = malloc(length);
uint8_t *ctr = malloc(cipher->block_size); uint8_t *ctr = malloc(cipher->block_size);
#if NETTLE_VERSION_MAJOR < 3 #if !defined(NETTLE_VERSION_MAJOR) || NETTLE_VERSION_MAJOR < 3
cipher->set_encrypt_key(ctx, key_length, key); cipher->set_encrypt_key(ctx, key_length, key);
#else #else
cipher->set_encrypt_key(ctx, key); cipher->set_encrypt_key(ctx, key);
......
...@@ -40,10 +40,12 @@ ...@@ -40,10 +40,12 @@
#include <time.h> #include <time.h>
#include "UTIL/LOG/log_extern.h" #include "UTIL/LOG/log_extern.h"
#include "common_lib.h" #include "common_lib.h"
#include "assertions.h"
#ifdef __SSE4_1__ #ifdef __SSE4_1__
# include <smmintrin.h> # include <smmintrin.h>
#endif #endif
#ifdef __AVX2__ #ifdef __AVX2__
# include <immintrin.h> # include <immintrin.h>
#endif #endif
...@@ -56,180 +58,133 @@ ...@@ -56,180 +58,133 @@
* @{ * @{
*/ */
/*! \brief USRP Configuration */ /*! \brief USRP Configuration */
typedef struct typedef struct {
{
// --------------------------------
// -------------------------------- // variables for USRP configuration
// variables for USRP configuration // --------------------------------
// -------------------------------- //! USRP device pointer
//! USRP device pointer uhd::usrp::multi_usrp::sptr usrp;
uhd::usrp::multi_usrp::sptr usrp;
//uhd::usrp::multi_usrp::sptr rx_usrp; //create a send streamer and a receive streamer
//! USRP TX Stream
//create a send streamer and a receive streamer uhd::tx_streamer::sptr tx_stream;
//! USRP TX Stream //! USRP RX Stream
uhd::tx_streamer::sptr tx_stream; uhd::rx_streamer::sptr rx_stream;
//! USRP RX Stream
uhd::rx_streamer::sptr rx_stream; //! USRP TX Metadata
uhd::tx_metadata_t tx_md;
//! USRP TX Metadata //! USRP RX Metadata
uhd::tx_metadata_t tx_md; uhd::rx_metadata_t rx_md;
//! USRP RX Metadata
uhd::rx_metadata_t rx_md; //! Sampling rate
double sample_rate;
//! USRP Timestamp Information
uhd::time_spec_t tm_spec; //! TX forward samples. We use usrp_time_offset to get this value
int tx_forward_nsamps; //166 for 20Mhz
//setup variables and allocate buffer
//! USRP Metadata // --------------------------------
uhd::async_metadata_t async_md; // Debug and output control
// --------------------------------
//! Sampling rate int num_underflows;
double sample_rate; int num_overflows;
int num_seq_errors;
//! time offset between transmiter timestamp and receiver timestamp; int64_t tx_count;
double tdiff; int64_t rx_count;
//! timestamp of RX packet
//! TX forward samples. We use usrp_time_offset to get this value openair0_timestamp rx_timestamp;
int tx_forward_nsamps; //166 for 20Mhz
// --------------------------------
// Debug and output control
// --------------------------------
//! Number of underflows
int num_underflows;
//! Number of overflows
int num_overflows;
//! Number of sequential errors
int num_seq_errors;
//! tx count
int64_t tx_count;
//! rx count
int64_t rx_count;
//! timestamp of RX packet
openair0_timestamp rx_timestamp;
} usrp_state_t; } usrp_state_t;
/*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error /*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error
@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
*/ */
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;
// init recv and send streaming
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05);
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate); usrp_state_t *s = (usrp_state_t*)device->priv;
s->tx_md.has_time_spec = true;
s->tx_md.start_of_burst = true;
s->tx_md.end_of_burst = false;
// init recv and send streaming
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = s->usrp->get_time_now() + uhd::time_spec_t(0.05);
cmd.stream_now = false; // start at constant delay
s->rx_stream->issue_stream_cmd(cmd);
s->rx_count = 0; s->tx_md.time_spec = cmd.time_spec + uhd::time_spec_t(1-(double)s->tx_forward_nsamps/s->sample_rate);
s->tx_count = 0; s->tx_md.has_time_spec = true;
s->rx_timestamp = 0; s->tx_md.start_of_burst = true;
s->tx_md.end_of_burst = false;
return 0; s->rx_count = 0;
s->tx_count = 0;
s->rx_timestamp = 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
* \param device the hardware to use * \param device the hardware to use
*/ */
static void trx_usrp_end(openair0_device *device) static void trx_usrp_end(openair0_device *device) {
{ usrp_state_t *s = (usrp_state_t*)device->priv;
usrp_state_t *s = (usrp_state_t*)device->priv;
s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS); s->rx_stream->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
//send a mini EOB packet
s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false;
//send a mini EOB packet
s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false;
} }
/*! \brief Called to send samples to the USRP RF target /*! \brief Called to send samples to the USRP RF target
@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
@param timestamp The timestamp at whicch the first sample MUST be sent @param timestamp The timestamp at whicch the first sample MUST be sent
@param buff Buffer which holds the samples @param buff Buffer which holds the samples
@param nsamps number of samples to be sent @param nsamps number of samples to be sent
@param antenna_id index of the antenna if the device has multiple anteannas @param antenna_id index of the antenna if the device has multiple anteannas
@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, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
{ int ret=0;
static long long int loop=0; usrp_state_t *s = (usrp_state_t*)device->priv;
static long time_min=0, time_max=0, time_avg=0;
struct timespec tp_start, tp_end;
long time_diff;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start);
int ret=0, ret_i=0;
usrp_state_t *s = (usrp_state_t*)device->priv;
s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
if(flags>0)
s->tx_md.has_time_spec = true;
else
s->tx_md.has_time_spec = false;
if (flags == 2) { // start of burst s->tx_md.time_spec = uhd::time_spec_t::from_ticks(timestamp, s->sample_rate);
s->tx_md.start_of_burst = true; s->tx_md.has_time_spec = flags;
s->tx_md.end_of_burst = false;
}
else if (flags == 3) { // end of burst if(flags>0)
s->tx_md.start_of_burst = false; s->tx_md.has_time_spec = true;
s->tx_md.end_of_burst = true; else
} s->tx_md.has_time_spec = false;
else if (flags == 4) { // start and end
s->tx_md.start_of_burst = true; if (flags == 2) { // start of burst
s->tx_md.end_of_burst = true; s->tx_md.start_of_burst = true;
} s->tx_md.end_of_burst = false;
else if (flags==1) { // middle of burst } else if (flags == 3) { // end 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 = true;
} } else if (flags == 4) { // start and end
s->tx_md.start_of_burst = true;
if (cc>1) { s->tx_md.end_of_burst = true;
std::vector<void *> buff_ptrs; } else if (flags==1) { // middle of burst
for (int i=0;i<cc;i++) buff_ptrs.push_back(buff[i]); s->tx_md.start_of_burst = false;
ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3); s->tx_md.end_of_burst = false;
} }
else
ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3); if (cc>1) {
std::vector<void *> buff_ptrs;
for (int i=0; i<cc; i++)
buff_ptrs.push_back(buff[i]);
if (ret != nsamps) { ret = (int)s->tx_stream->send(buff_ptrs, nsamps, s->tx_md,1e-3);
printf("[xmit] tx samples %d != %d\n",ret,nsamps); } else
} ret = (int)s->tx_stream->send(buff[0], nsamps, s->tx_md,1e-3);
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end);
time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec);
if (time_min==0 ||loop==1 || time_min > time_diff) if (ret != nsamps)
time_min=time_diff; LOG_E(PHY,"[xmit] tx samples %d != %d\n",ret,nsamps);
if (time_max==0 ||loop==1 || time_max < time_diff)
time_max=time_diff; return ret;
if (time_avg ==0 ||loop==1)
time_avg= time_diff;
else
time_avg=(time_diff+time_avg) /2.0;
/* //prints statics of uhd every 10 seconds
if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0)
LOG_I(HW,"usrp_write: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg);
*/
loop++;
return ret;
} }
/*! \brief Receive samples from hardware. /*! \brief Receive samples from hardware.
...@@ -243,621 +198,535 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, ...@@ -243,621 +198,535 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
* \param antenna_id Index of antenna for which to receive samples * \param antenna_id Index of antenna for which to receive samples
* \returns the number of sample read * \returns the number of sample read
*/ */
static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
{ usrp_state_t *s = (usrp_state_t*)device->priv;
static long long int loop=0; int samples_received=0,i,j;
static long time_min=0, time_max=0, time_avg=0; int nsamps2; // aligned to upper 32 or 16 byte boundary
struct timespec tp_start, tp_end;
long time_diff;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start);
usrp_state_t *s = (usrp_state_t*)device->priv;
int samples_received=0,i,j;
int nsamps2; // aligned to upper 32 or 16 byte boundary
#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_tmp[2][nsamps2]; __m256i buff_tmp[2][nsamps2];
#else #else
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
__m128i buff_tmp[2][nsamps2]; __m128i buff_tmp[2][nsamps2];
#endif #endif
#elif defined(__arm__) #elif defined(__arm__)
nsamps2 = (nsamps+3)>>2; nsamps2 = (nsamps+3)>>2;
int16x8_t buff_tmp[2][nsamps2]; int16x8_t buff_tmp[2][nsamps2];
#endif #endif
if (device->type == USRP_B200_DEV) {
if (device->type == USRP_B200_DEV) { 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]);
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md);
for (int i=0;i<cc;i++) buff_ptrs.push_back(buff_tmp[i]); } else {
samples_received = s->rx_stream->recv(buff_ptrs, nsamps, s->rx_md); // receive a single channel (e.g. from connector RF A)
} else { samples_received=0;
// receive a single channel (e.g. from connector RF A) while (samples_received != nsamps) {
samples_received = s->rx_stream->recv(buff_tmp[0], nsamps, s->rx_md); samples_received += s->rx_stream->recv(buff_tmp[0]+samples_received,
} nsamps-samples_received, s->rx_md);
if (s->rx_md.error_code!=uhd::rx_metadata_t::ERROR_CODE_NONE)
// bring RX data into 12 LSBs for softmodem RX break;
for (int i=0;i<cc;i++) { }
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__
((__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])[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
} }
}
} else if (device->type == USRP_X300_DEV) {
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[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 = s->rx_stream->recv(buff[0], nsamps, s->rx_md);
}
} }
} else if (device->type == USRP_X300_DEV) { if (samples_received < nsamps)
if (cc>1) { LOG_E(PHY,"[recv] received %d samples out of %d\n",samples_received,nsamps);
// 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[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 = s->rx_stream->recv(buff[0], nsamps, s->rx_md);
}
}
if (samples_received < nsamps) {
printf("[recv] received %d samples out of %d\n",samples_received,nsamps);
}
//handle the error code
switch(s->rx_md.error_code){
case uhd::rx_metadata_t::ERROR_CODE_NONE:
break;
case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
printf("[recv] USRP RX OVERFLOW!\n");
s->num_overflows++;
break;
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
printf("[recv] USRP RX TIMEOUT!\n");
break;
default:
printf("[recv] Unexpected error on RX, Error code: 0x%x\n",s->rx_md.error_code);
break;
}
s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_end);
time_diff = (tp_end.tv_sec - tp_start.tv_sec) *1E09 + (tp_end.tv_nsec - tp_start.tv_nsec);
if (time_min==0 ||loop==1 || time_min > time_diff)
time_min=time_diff;
if (time_max==0 ||loop==1 || time_max < time_diff)
time_max=time_diff;
if (time_avg ==0 ||loop==1)
time_avg= time_diff;
else
time_avg=(time_diff+time_avg) /2.0;
/*
//prints statics of uhd every 10 seconds
if ( loop % (10 * ((int)device->openair0_cfg[0].sample_rate /(int)nsamps )) ==0)
LOG_I(HW,"usrp_read: min(ns)=%d, max(ns)=%d, avg(ns)=%d\n", (int)time_min, (int)time_max,(int)time_avg);
loop++;*/
return samples_received;
}
/*! \brief Get current timestamp of USRP if ( s->rx_md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE)
* \param device the hardware to use LOG_E(PHY,s->rx_md.to_pp_string(true).c_str());
*/
openair0_timestamp get_usrp_time(openair0_device *device) s->rx_count += nsamps;
{ s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp;
usrp_state_t *s = (usrp_state_t*)device->priv; return samples_received;
}
return s->usrp->get_time_now().to_ticks(s->sample_rate);
}
/*! \brief Compares two variables within precision /*! \brief Compares two variables within precision
* \param a first variable * \param a first variable
* \param b second variable * \param b second variable
*/ */
static bool is_equal(double a, double b) static bool is_equal(double a, double b) {
{ return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
return std::fabs(a-b) < std::numeric_limits<double>::epsilon();
} }
void *freq_thread(void *arg) { void *freq_thread(void *arg) {
openair0_device *device=(openair0_device *)arg; openair0_device *device=(openair0_device *)arg;
usrp_state_t *s = (usrp_state_t*)device->priv; usrp_state_t *s = (usrp_state_t*)device->priv;
s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]);
s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
} }
/*! \brief Set frequencies (TX/RX). Spawns a thread to handle the frequency change to not block the calling thread /*! \brief Set frequencies (TX/RX). Spawns a thread to handle the frequency change to not block the calling thread
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \param dummy dummy variable not used * \param dummy dummy variable not used
* \returns 0 in success * \returns 0 in success
*/ */
int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dont_block) { int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dont_block) {
usrp_state_t *s = (usrp_state_t*)device->priv; usrp_state_t *s = (usrp_state_t*)device->priv;
pthread_t f_thread; pthread_t f_thread;
printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]); printf("Setting USRP TX Freq %f, RX Freq %f\n",openair0_cfg[0].tx_freq[0],openair0_cfg[0].rx_freq[0]);
// spawn a thread to handle the frequency change to not block the calling thread // spawn a thread to handle the frequency change to not block the calling thread
if (dont_block == 1) if (dont_block == 1)
pthread_create(&f_thread,NULL,freq_thread,(void*)device); pthread_create(&f_thread,NULL,freq_thread,(void*)device);
else { else {
s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]); s->usrp->set_tx_freq(device->openair0_cfg[0].tx_freq[0]);
s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]); s->usrp->set_rx_freq(device->openair0_cfg[0].rx_freq[0]);
} }
return(0);
return(0);
} }
/*! \brief Set RX frequencies /*! \brief Set RX frequencies
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \returns 0 in success * \returns 0 in success
*/ */
int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) {
usrp_state_t *s = (usrp_state_t*)device->priv; usrp_state_t *s = (usrp_state_t*)device->priv;
static int first_call=1; static int first_call=1;
static double rf_freq,diff; static double rf_freq,diff;
uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]);
uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0];
rf_freq=openair0_cfg[0].rx_freq[0];
s->usrp->set_rx_freq(rx_tune_req);
rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; return(0);
rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0];
rf_freq=openair0_cfg[0].rx_freq[0];
s->usrp->set_rx_freq(rx_tune_req);
return(0);
} }
/*! \brief Set Gains (TX/RX) /*! \brief Set Gains (TX/RX)
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \returns 0 in success * \returns 0 in success
*/ */
int trx_usrp_set_gains(openair0_device* device, int trx_usrp_set_gains(openair0_device* device,
openair0_config_t *openair0_cfg) { openair0_config_t *openair0_cfg) {
usrp_state_t *s = (usrp_state_t*)device->priv; usrp_state_t *s = (usrp_state_t*)device->priv;
s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]); s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]);
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0);
// limit to maximum gain // limit to maximum gain
if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) { if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) {
LOG_E(PHY,"RX Gain 0 too high, reduce by %f dB\n",
printf("RX Gain 0 too high, reduce by %f dB\n", openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop());
openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop()); exit(-1);
exit(-1); }
} s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]);
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]); LOG_I(PHY,"Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n",
printf("Setting USRP RX gain to %f (rx_gain %f,gain_range.stop() %f)\n", openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],openair0_cfg[0].rx_gain[0],gain_range.stop()); openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],
openair0_cfg[0].rx_gain[0],gain_range.stop());
return(0);
return(0);
} }
/*! \brief Stop USRP /*! \brief Stop USRP
* \param card refers to the hardware index to use * \param card refers to the hardware index to use
*/ */
int trx_usrp_stop(openair0_device* device) { int trx_usrp_stop(openair0_device* device) {
return(0); return(0);
} }
/*! \brief USRPB210 RX calibration table */ /*! \brief USRPB210 RX calibration table */
rx_gain_calib_table_t calib_table_b210[] = { rx_gain_calib_table_t calib_table_b210[] = {
{3500000000.0,44.0}, {3500000000.0,44.0},
{2660000000.0,49.0}, {2660000000.0,49.0},
{2300000000.0,50.0}, {2300000000.0,50.0},
{1880000000.0,53.0}, {1880000000.0,53.0},
{816000000.0,58.0}, {816000000.0,58.0},
{-1,0}}; {-1,0}
};
/*! \brief USRPB210 RX calibration table */ /*! \brief USRPB210 RX calibration table */
rx_gain_calib_table_t calib_table_b210_38[] = { rx_gain_calib_table_t calib_table_b210_38[] = {
{3500000000.0,44.0}, {3500000000.0,44.0},
{2660000000.0,49.8}, {2660000000.0,49.8},
{2300000000.0,51.0}, {2300000000.0,51.0},
{1880000000.0,53.0}, {1880000000.0,53.0},
{816000000.0,57.0}, {816000000.0,57.0},
{-1,0}}; {-1,0}
};
/*! \brief USRPx310 RX calibration table */ /*! \brief USRPx310 RX calibration table */
rx_gain_calib_table_t calib_table_x310[] = { rx_gain_calib_table_t calib_table_x310[] = {
{3500000000.0,77.0}, {3500000000.0,77.0},
{2660000000.0,81.0}, {2660000000.0,81.0},
{2300000000.0,81.0}, {2300000000.0,81.0},
{1880000000.0,82.0}, {1880000000.0,82.0},
{816000000.0,85.0}, {816000000.0,85.0},
{-1,0}}; {-1,0}
};
/*! \brief Set RX gain offset
/*! \brief Set RX gain offset
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
* \param chain_index RF chain to apply settings to * \param chain_index RF chain to apply settings to
* \returns 0 in success * \returns 0 in success
*/ */
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) { void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) {
int i=0; int i=0;
// loop through calibration table to find best adjustment factor for RX frequency // loop through calibration table to find best adjustment factor for RX frequency
double min_diff = 6e9,diff,gain_adj=0.0; double min_diff = 6e9,diff,gain_adj=0.0;
if (bw_gain_adjust==1) { if (bw_gain_adjust==1) {
switch ((int)openair0_cfg[0].sample_rate) { switch ((int)openair0_cfg[0].sample_rate) {
case 30720000: case 30720000:
break; break;
case 23040000: case 23040000:
gain_adj=1.25; gain_adj=1.25;
break; break;
case 15360000: case 15360000:
gain_adj=3.0; gain_adj=3.0;
break; break;
case 7680000: case 7680000:
gain_adj=6.0; gain_adj=6.0;
break; break;
case 3840000: case 3840000:
gain_adj=9.0; gain_adj=9.0;
break; break;
case 1920000: case 1920000:
gain_adj=12.0; gain_adj=12.0;
break; break;
default: default:
printf("unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); LOG_E(PHY,"unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate);
exit(-1); exit(-1);
break; break;
}
} }
} while (openair0_cfg->rx_gain_calib_table[i].freq>0) {
while (openair0_cfg->rx_gain_calib_table[i].freq>0) { diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); LOG_I(PHY,"cal %d: freq %f, offset %f, diff %f\n",
printf("cal %d: freq %f, offset %f, diff %f\n", i,
i, openair0_cfg->rx_gain_calib_table[i].freq,
openair0_cfg->rx_gain_calib_table[i].freq, openair0_cfg->rx_gain_calib_table[i].offset,diff);
openair0_cfg->rx_gain_calib_table[i].offset,diff); if (min_diff > diff) {
if (min_diff > diff) { min_diff = diff;
min_diff = diff; openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj;
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj; }
i++;
} }
i++;
}
} }
/*! \brief print the USRP statistics /*! \brief print the USRP statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_usrp_get_stats(openair0_device* device) { int trx_usrp_get_stats(openair0_device* device) {
return(0);
return(0);
} }
/*! \brief Reset the USRP statistics /*! \brief Reset the USRP statistics
* \param device the hardware to use * \param device the hardware to use
* \returns 0 on success * \returns 0 on success
*/ */
int trx_usrp_reset_stats(openair0_device* device) { int trx_usrp_reset_stats(openair0_device* device) {
return(0);
return(0);
} }
extern "C" { extern "C" {
/*! \brief Initialize Openair USRP target. It returns 0 if OK /*! \brief Initialize Openair USRP target. It returns 0 if OK
* \param device the hardware to use * \param device the hardware to use
* \param openair0_cfg RF frontend parameters set by application * \param openair0_cfg RF frontend parameters set by application
*/ */
int device_init(openair0_device* device, openair0_config_t *openair0_cfg) { int device_init(openair0_device* device, openair0_config_t *openair0_cfg) {
uhd::set_thread_priority_safe(1.0);
uhd::set_thread_priority_safe(1.0); usrp_state_t *s = (usrp_state_t*)calloc(sizeof(usrp_state_t),1);
usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); // Initialize USRP device
memset(s, 0, sizeof(usrp_state_t)); device->openair0_cfg = openair0_cfg;
// Initialize USRP device
device->openair0_cfg = openair0_cfg;
std::string args = "type=b200";
uhd::device_addrs_t device_adds = uhd::device::find(args);
size_t i;
int vers=0,subvers=0,subsubvers=0;
int bw_gain_adjust=0;
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
printf("Checking for USRPs : UHD %s (%d.%d.%d)\n",uhd::get_version_string().c_str(),vers,subvers,subsubvers);
if(device_adds.size() == 0)
{
double usrp_master_clock = 184.32e6;
std::string args = "type=x300";
// workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
// args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
uhd::device_addrs_t device_adds = uhd::device::find(args);
if(device_adds.size() == 0)
{
std::cerr<<"No USRP Device Found. " << std::endl;
free(s);
return -1;
}
printf("Found USRP X300\n"); std::string args = "type=b200";
s->usrp = uhd::usrp::multi_usrp::make(args); uhd::device_addrs_t device_adds = uhd::device::find(args);
// s->usrp->set_rx_subdev_spec(rx_subdev);
// s->usrp->set_tx_subdev_spec(tx_subdev);
// lock mboard clocks int vers=0,subvers=0,subsubvers=0;
if (openair0_cfg[0].clock_source == internal) int bw_gain_adjust=0;
s->usrp->set_clock_source("internal");
else
s->usrp->set_clock_source("external");
//Setting device type to USRP X300/X310
device->type=USRP_X300_DEV;
// this is not working yet, master clock has to be set via constructor
// set master clock rate and sample rate for tx & rx for streaming
//s->usrp->set_master_clock_rate(usrp_master_clock);
openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
switch ((int)openair0_cfg[0].sample_rate) {
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:
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
exit(-1);
break;
}
} else { sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
printf("Found USRP B200"); LOG_I(PHY,"Checking for USRPs : UHD %s (%d.%d.%d)\n",
args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ; uhd::get_version_string().c_str(),vers,subvers,subsubvers);
s->usrp = uhd::usrp::multi_usrp::make(args);
// s->usrp->set_rx_subdev_spec(rx_subdev);
// s->usrp->set_tx_subdev_spec(tx_subdev);
// do not explicitly set the clock to "internal", because this will disable the gpsdo
// // lock mboard clocks
// s->usrp->set_clock_source("internal");
// set master clock rate and sample rate for tx & rx for streaming
// lock mboard clocks
if (openair0_cfg[0].clock_source == internal)
s->usrp->set_clock_source("internal");
else
s->usrp->set_clock_source("external");
device->type = USRP_B200_DEV; if(device_adds.size() == 0) {
double usrp_master_clock = 184.32e6;
std::string args = "type=x300";
// workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate
args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock);
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { // args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0;
}
else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
}
switch ((int)openair0_cfg[0].sample_rate) { // args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=4096, recv_frame_size=4096";
case 30720000: uhd::device_addrs_t device_adds = uhd::device::find(args);
s->usrp->set_master_clock_rate(30.72e6);
//openair0_cfg[0].samples_per_packet = 1024; if(device_adds.size() == 0) {
openair0_cfg[0].tx_sample_advance = 115; std::cerr<<"No USRP Device Found. " << std::endl;
openair0_cfg[0].tx_bw = 20e6; free(s);
openair0_cfg[0].rx_bw = 20e6; return -1;
break; }
case 23040000: LOG_I(PHY,"Found USRP X300\n");
s->usrp->set_master_clock_rate(23.04e6); //to be checked s->usrp = uhd::usrp::multi_usrp::make(args);
//openair0_cfg[0].samples_per_packet = 1024; // lock mboard clocks
openair0_cfg[0].tx_sample_advance = 113; if (openair0_cfg[0].clock_source == internal)
openair0_cfg[0].tx_bw = 20e6; s->usrp->set_clock_source("internal");
openair0_cfg[0].rx_bw = 20e6; else
break; s->usrp->set_clock_source("external");
case 15360000:
s->usrp->set_master_clock_rate(30.72e06); //Setting device type to USRP X300/X310
//openair0_cfg[0].samples_per_packet = 1024; device->type=USRP_X300_DEV;
openair0_cfg[0].tx_sample_advance = 103;
openair0_cfg[0].tx_bw = 20e6; // this is not working yet, master clock has to be set via constructor
openair0_cfg[0].rx_bw = 20e6; // set master clock rate and sample rate for tx & rx for streaming
break; //s->usrp->set_master_clock_rate(usrp_master_clock);
case 7680000:
s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
//openair0_cfg[0].samples_per_packet = 1024;
openair0_cfg[0].tx_sample_advance = 80; switch ((int)openair0_cfg[0].sample_rate) {
openair0_cfg[0].tx_bw = 20e6; case 30720000:
openair0_cfg[0].rx_bw = 20e6; // from usrp_time_offset
break; //openair0_cfg[0].samples_per_packet = 2048;
case 1920000: openair0_cfg[0].tx_sample_advance = 15;
s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].tx_bw = 20e6;
//openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].rx_bw = 20e6;
openair0_cfg[0].tx_sample_advance = 40; break;
openair0_cfg[0].tx_bw = 20e6; case 15360000:
openair0_cfg[0].rx_bw = 20e6; //openair0_cfg[0].samples_per_packet = 2048;
break; openair0_cfg[0].tx_sample_advance = 45;
default: openair0_cfg[0].tx_bw = 10e6;
printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); openair0_cfg[0].rx_bw = 10e6;
exit(-1); break;
break; case 7680000:
} //openair0_cfg[0].samples_per_packet = 2048;
} openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 5e6;
/* device specific */ openair0_cfg[0].rx_bw = 5e6;
//openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered break;
//openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered case 1920000:
openair0_cfg[0].iq_txshift = 4;//shift //openair0_cfg[0].samples_per_packet = 2048;
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs openair0_cfg[0].tx_sample_advance = 50;
openair0_cfg[0].tx_bw = 1.25e6;
for(i=0;i<s->usrp->get_rx_num_channels();i++) { openair0_cfg[0].rx_bw = 1.25e6;
if (i<openair0_cfg[0].rx_num_channels) { break;
s->usrp->set_rx_rate(openair0_cfg[0].sample_rate,i); default:
//s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); LOG_E(PHY,"Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate);
//printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); exit(-1);
s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); break;
set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); }
::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); } else {
// limit to maximum gain LOG_I(PHY,"Found USRP B200\n");
if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { args += ",num_send_frames=256,num_recv_frames=256, send_frame_size=15360, recv_frame_size=15360" ;
s->usrp = uhd::usrp::multi_usrp::make(args);
// s->usrp->set_rx_subdev_spec(rx_subdev);
// s->usrp->set_tx_subdev_spec(tx_subdev);
// do not explicitly set the clock to "internal", because this will disable the gpsdo
// // lock mboard clocks
// s->usrp->set_clock_source("internal");
// set master clock rate and sample rate for tx & rx for streaming
// lock mboard clocks
if (openair0_cfg[0].clock_source == internal)
s->usrp->set_clock_source("internal");
else
s->usrp->set_clock_source("external");
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;
} else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1;
}
switch ((int)openair0_cfg[0].sample_rate) {
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(PHY,"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<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(PHY,"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());
}
}
for(int i=0; i<s->usrp->get_tx_num_channels(); 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(openair0_cfg[0].tx_gain[i],i);
}
}
//s->usrp->set_clock_source("external");
//s->usrp->set_time_source("external");
// display USRP settings
LOG_I(PHY,"Actual master clock: %fMHz...\n",s->usrp->get_master_clock_rate()/1e6);
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(PHY,"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(PHY,"rx_max_num_samps %u\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);
printf("RX Gain %lu too high, lower by %f dB\n",i,openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); uhd::stream_args_t stream_args_tx("sc16", "sc16");
exit(-1); for (int i = 0; i<openair0_cfg[0].tx_num_channels; i++)
} stream_args_tx.channels.push_back(i);
s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); s->tx_stream = s->usrp->get_tx_stream(stream_args_tx);
printf("RX Gain %lu %f (%f) => %f (max %f)\n",i,
openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i], /* Setting TX/RX BW after streamers are created due to USRP calibration issue */
openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop()); for(int i=0; i<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(i=0;i<s->usrp->get_tx_num_channels();i++) { for(int i=0; i<s->usrp->get_rx_num_channels() && i<openair0_cfg[0].rx_num_channels; i++)
if (i<openair0_cfg[0].tx_num_channels) { s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i);
s->usrp->set_tx_rate(openair0_cfg[0].sample_rate,i);
//s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); s->usrp->set_time_now(uhd::time_spec_t(0.0));
//printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->usrp->get_tx_num_channels(),openair0_cfg[0].tx_bw/1e6,s->usrp->get_tx_bandwidth(i)/1e6);
s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); for (int i=0; i<openair0_cfg[0].rx_num_channels; i++) {
s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); LOG_I(PHY,"RX Channel %d\n",i);
} LOG_I(PHY," Actual RX sample rate: %fMSps...\n",s->usrp->get_rx_rate(i)/1e6);
} LOG_I(PHY," Actual RX frequency: %fGHz...\n", s->usrp->get_rx_freq(i)/1e9);
LOG_I(PHY," Actual RX gain: %f...\n", s->usrp->get_rx_gain(i));
LOG_I(PHY," Actual RX bandwidth: %fM...\n", s->usrp->get_rx_bandwidth(i)/1e6);
// display USRP settings LOG_I(PHY," Actual RX antenna: %s...\n", s->usrp->get_rx_antenna(i).c_str());
std::cout << boost::format("Actual master clock: %fMHz...") % (s->usrp->get_master_clock_rate()/1e6) << std::endl; }
sleep(1); for (int i=0; i<openair0_cfg[0].tx_num_channels; i++) {
LOG_I(PHY,"TX Channel %d\n",i);
// create tx & rx streamer LOG_I(PHY," Actual TX sample rate: %fMSps...\n", s->usrp->get_tx_rate(i)/1e6);
uhd::stream_args_t stream_args_rx("sc16", "sc16"); LOG_I(PHY," Actual TX frequency: %fGHz...\n", s->usrp->get_tx_freq(i)/1e9);
int samples=openair0_cfg[0].sample_rate; LOG_I(PHY," Actual TX gain: %f...\n", s->usrp->get_tx_gain(i));
samples/=24000; LOG_I(PHY," Actual TX bandwidth: %fM...\n", s->usrp->get_tx_bandwidth(i)/1e6);
// stream_args_rx.args["spp"] = str(boost::format("%d") % samples); LOG_I(PHY," Actual TX antenna: %s...\n", s->usrp->get_tx_antenna(i).c_str());
}
for (i = 0; i<openair0_cfg[0].rx_num_channels; i++)
stream_args_rx.channels.push_back(i); LOG_I(PHY,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
s->rx_stream = s->usrp->get_rx_stream(stream_args_rx);
std::cout << boost::format("rx_max_num_samps %u") % (s->rx_stream->get_max_num_samps()) << std::endl; device->priv = s;
//openair0_cfg[0].samples_per_packet = s->rx_stream->get_max_num_samps(); device->trx_start_func = trx_usrp_start;
device->trx_write_func = trx_usrp_write;
uhd::stream_args_t stream_args_tx("sc16", "sc16"); device->trx_read_func = trx_usrp_read;
//stream_args_tx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].tx_num_channels*openair0_cfg[0].samples_per_packet)); device->trx_get_stats_func = trx_usrp_get_stats;
for (i = 0; i<openair0_cfg[0].tx_num_channels; i++) device->trx_reset_stats_func = trx_usrp_reset_stats;
stream_args_tx.channels.push_back(i); device->trx_end_func = trx_usrp_end;
s->tx_stream = s->usrp->get_tx_stream(stream_args_tx); device->trx_stop_func = trx_usrp_stop;
std::cout << boost::format("tx_max_num_samps %u") % (s->tx_stream->get_max_num_samps()) << std::endl; device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains;
device->openair0_cfg = openair0_cfg;
/* Setting TX/RX BW after streamers are created due to USRP calibration issue */
for(i=0;i<s->usrp->get_tx_num_channels();i++) { s->sample_rate = openair0_cfg[0].sample_rate;
if (i<openair0_cfg[0].tx_num_channels) { // TODO:
s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); // init tx_forward_nsamps based usrp_time_offset ex
printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->usrp->get_tx_num_channels(),openair0_cfg[0].tx_bw/1e6,s->usrp->get_tx_bandwidth(i)/1e6); if(is_equal(s->sample_rate, (double)30.72e6))
} s->tx_forward_nsamps = 176;
} if(is_equal(s->sample_rate, (double)15.36e6))
for(i=0;i<s->usrp->get_rx_num_channels();i++) { s->tx_forward_nsamps = 90;
if (i<openair0_cfg[0].rx_num_channels) { if(is_equal(s->sample_rate, (double)7.68e6))
s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); s->tx_forward_nsamps = 50;
printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); return 0;
}
}
s->usrp->set_time_now(uhd::time_spec_t(0.0));
for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
if (i<openair0_cfg[0].rx_num_channels) {
printf("RX Channel %lu\n",i);
std::cout << boost::format("Actual RX sample rate: %fMSps...") % (s->usrp->get_rx_rate(i)/1e6) << std::endl;
std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq(i)/1e9) << std::endl;
std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain(i)) << std::endl;
std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth(i)/1e6) << std::endl;
std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna(i)) << std::endl;
}
}
for (i=0;i<openair0_cfg[0].tx_num_channels;i++) {
if (i<openair0_cfg[0].tx_num_channels) {
printf("TX Channel %lu\n",i);
std::cout << std::endl<<boost::format("Actual TX sample rate: %fMSps...") % (s->usrp->get_tx_rate(i)/1e6) << std::endl;
std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq(i)/1e9) << std::endl;
std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain(i)) << std::endl;
std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth(i)/1e6) << std::endl;
std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl;
} }
}
std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl;
device->priv = s;
device->trx_start_func = trx_usrp_start;
device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read;
device->trx_get_stats_func = trx_usrp_get_stats;
device->trx_reset_stats_func = trx_usrp_reset_stats;
device->trx_end_func = trx_usrp_end;
device->trx_stop_func = trx_usrp_stop;
device->trx_set_freq_func = trx_usrp_set_freq;
device->trx_set_gains_func = trx_usrp_set_gains;
device->openair0_cfg = openair0_cfg;
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;
return 0;
}
} }
/*@}*/ /*@}*/
...@@ -31,16 +31,16 @@ eNBs = ...@@ -31,16 +31,16 @@ eNBs =
tdd_config_s = 0; tdd_config_s = 0;
prefix_type = "NORMAL"; prefix_type = "NORMAL";
eutra_band = 7; eutra_band = 7;
downlink_frequency = 2660000000L; downlink_frequency = 2630000000L;
uplink_frequency_offset = -120000000; uplink_frequency_offset = -120000000;
Nid_cell = 0; Nid_cell = 0;
N_RB_DL = 25; N_RB_DL = 50;
Nid_cell_mbsfn = 0; Nid_cell_mbsfn = 0;
nb_antenna_ports = 1; nb_antenna_ports = 1;
nb_antennas_tx = 1; nb_antennas_tx = 1;
nb_antennas_rx = 1; nb_antennas_rx = 1;
tx_gain = 90; tx_gain = 90;
rx_gain = 125; rx_gain = 110;
prach_root = 0; prach_root = 0;
prach_config_index = 0; prach_config_index = 0;
prach_high_speed = "DISABLE"; prach_high_speed = "DISABLE";
......
This source diff could not be displayed because it is too large. You can view the blob instead.
#ifndef LTE_SOFTMODEM_H
#define LTE_SOFTMODEM_H
#define _GNU_SOURCE
#include <execinfo.h>
#include <fcntl.h>
#include <getopt.h>
#include <linux/sched.h>
#include "rt_wrapper.h"
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syscall.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/sysinfo.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/sysinfo.h>
#include "rt_wrapper.h"
#include "../../ARCH/COMMON/common_lib.h"
#undef MALLOC
#include "assertions.h"
#include "msc.h"
#include "PHY/types.h"
#include "PHY/defs.h"
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#if defined(ENABLE_ITTI)
#if defined(ENABLE_USE_MME)
#include "s1ap_eNB.h"
#ifdef PDCP_USE_NETLINK
#include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
#endif
#endif
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
extern uint32_t downlink_frequency[MAX_NUM_CCs][4];
extern int32_t uplink_frequency_offset[MAX_NUM_CCs][4];
extern int rx_input_level_dBm;
extern uint8_t exit_missed_slots;
extern uint64_t num_missed_slots; // counter for the number of missed slots
extern int oaisim_flag;
extern volatile int oai_exit;
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;
extern int transmission_mode;
extern double cpuf;
#if defined(ENABLE_ITTI)
extern volatile int start_eNB;
extern volatile int start_UE;
#endif
typedef struct threads_s {
int iq;
int odd;
int even;
} threads_t;
extern threads_t threads;
extern void exit_fun(const char* s);
// In lte-enb.c
extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg);
extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int,int);
extern void stop_eNB(int);
extern void kill_eNB_proc(int inst);
// In lte-ue.c
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
extern void fill_ue_band_info(void);
extern void init_UE(int);
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
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