merge develop,fix basic sim and warnings
This commit is contained in:
@@ -4,7 +4,7 @@ MODULE="riffa"
|
||||
KERNEL_VERSION=$(uname -r)
|
||||
RHR=/etc/redhat-release
|
||||
|
||||
sudo apt-get install -y --allow-unauthenticated linux-headers-`uname -r`
|
||||
sudo apt-get install -y linux-headers-`uname -r`
|
||||
|
||||
if lsmod | grep "$MODULE" &> /dev/null ; then
|
||||
echo "Previous SYRIQ is loaded!"
|
||||
|
||||
@@ -41,49 +41,22 @@
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "targets/RT/USER/lte-softmodem.h"
|
||||
|
||||
char *get_devname(int devtype) {
|
||||
char *devnames[MAX_RF_DEV_TYPE]=DEVTYPE_NAMES;
|
||||
if (devtype < MAX_RF_DEV_TYPE && devtype !=MIN_RF_DEV_TYPE )
|
||||
return devnames[devtype];
|
||||
return "none";
|
||||
}
|
||||
|
||||
int set_device(openair0_device *device)
|
||||
{
|
||||
switch (device->type) {
|
||||
case EXMIMO_DEV:
|
||||
LOG_I(HW,"[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case USRP_B200_DEV:
|
||||
LOG_I(HW,"[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case USRP_X300_DEV:
|
||||
LOG_I(HW,"[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case BLADERF_DEV:
|
||||
LOG_I(HW,"[%s] has loaded BLADERF device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case LMSSDR_DEV:
|
||||
LOG_I(HW,"[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case IRIS_DEV:
|
||||
LOG_I(HW,"[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case ADRV9371_ZC706_DEV:
|
||||
LOG_I(HW,"[%s] has loaded ADRV9371_ZC706 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case UEDv2_DEV:
|
||||
LOG_I(HW,"[%s] has loaded UEDv2 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
case NONE_DEV:
|
||||
LOG_I(HW,"[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
break;
|
||||
|
||||
default:
|
||||
char *devname = get_devname(device->type);
|
||||
if (strcmp(devname,"none") != 0) {
|
||||
LOG_I(HW,"[%s] has loaded %s device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"),devname);
|
||||
} else {
|
||||
LOG_E(HW,"[%s] invalid HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -108,7 +81,7 @@ int set_transport(openair0_device *device)
|
||||
}
|
||||
|
||||
typedef int(*devfunc_t)(openair0_device *, openair0_config_t *, eth_params_t *);
|
||||
//loader_shlibfunc_t shlib_fdesc[2];
|
||||
|
||||
|
||||
/* look for the interface library and load it */
|
||||
int load_lib(openair0_device *device,
|
||||
@@ -119,7 +92,14 @@ int load_lib(openair0_device *device,
|
||||
loader_shlibfunc_t shlib_fdesc[1];
|
||||
int ret=0;
|
||||
char *libname;
|
||||
if ( IS_SOFTMODEM_BASICSIM ) {
|
||||
|
||||
openair0_cfg->recplay_mode = read_recplayconfig(&(openair0_cfg->recplay_conf),&(device->recplay_state));
|
||||
|
||||
if ( openair0_cfg->recplay_mode == RECPLAY_REPLAYMODE ) {
|
||||
libname=OAI_IQPLAYER_LIBNAME;
|
||||
shlib_fdesc[0].fname="device_init";
|
||||
set_softmodem_optmask(SOFTMODEM_RECPLAY_BIT); // softmodem has to know we use the iqplayer to workaround randomized algorithms
|
||||
} else if ( IS_SOFTMODEM_BASICSIM ) {
|
||||
libname=OAI_BASICSIM_LIBNAME;
|
||||
shlib_fdesc[0].fname="device_init";
|
||||
} else if (IS_SOFTMODEM_RFSIM && flag == RAU_LOCAL_RADIO_HEAD) {
|
||||
|
||||
@@ -35,15 +35,19 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <openair1/PHY/TOOLS/tools_defs.h>
|
||||
#include "record_player.h"
|
||||
|
||||
/* name of shared library implementing the radio front end */
|
||||
/* default name of shared library implementing the radio front end */
|
||||
#define OAI_RF_LIBNAME "oai_device"
|
||||
/* name of shared library implementing the transport */
|
||||
#define OAI_TP_LIBNAME "oai_transpro"
|
||||
/* name of shared library implementing the basic/rf simulator */
|
||||
/* name of shared library implementing the rf simulator */
|
||||
#define OAI_RFSIM_LIBNAME "rfsimulator"
|
||||
/* name of shared library implementing the basic/rf simulator */
|
||||
/* name of shared library implementing the basic simulator */
|
||||
#define OAI_BASICSIM_LIBNAME "tcp_bridge_oai"
|
||||
/* name of shared library implementing the iq player */
|
||||
#define OAI_IQPLAYER_LIBNAME "oai_iqplayer"
|
||||
|
||||
/* flags for BBU to determine whether the attached radio head is local or remote */
|
||||
#define RAU_LOCAL_RADIO_HEAD 0
|
||||
#define RAU_REMOTE_RADIO_HEAD 1
|
||||
@@ -101,7 +105,7 @@ typedef enum {
|
||||
UEDv2_DEV,
|
||||
MAX_RF_DEV_TYPE
|
||||
} dev_type_t;
|
||||
|
||||
#define DEVTYPE_NAMES {"","EXMIMO","USRP B200","USRP X300","BLADERF","LMSSDR","IRIS","No HW","ADRV9371_ZC706","UEDv2"}
|
||||
/*!\brief transport protocol types
|
||||
*/
|
||||
typedef enum {
|
||||
@@ -145,6 +149,7 @@ typedef enum {
|
||||
gpsdo=2
|
||||
} clock_source_t;
|
||||
|
||||
|
||||
/*! \brief RF frontend parameters set by application */
|
||||
typedef struct {
|
||||
//! Module ID for this configuration
|
||||
@@ -219,15 +224,9 @@ typedef struct {
|
||||
char *my_addr;
|
||||
//! local port number for Ethernet interface (eNB/BBU, UE)
|
||||
unsigned int my_port;
|
||||
#if defined(USRP_REC_PLAY)
|
||||
unsigned short sf_mode; // 1=record, 2=replay
|
||||
char sf_filename[1024]; // subframes file path
|
||||
unsigned int sf_max; // max number of recorded subframes
|
||||
unsigned int sf_loops; // number of loops in replay mode
|
||||
unsigned int sf_read_delay; // read delay in replay mode
|
||||
unsigned int sf_write_delay; // write delay in replay mode
|
||||
unsigned int eth_mtu; // ethernet MTU
|
||||
#endif
|
||||
//! record player configuration, definition in record_player.h
|
||||
uint32_t recplay_mode;
|
||||
recplay_conf_t *recplay_conf;
|
||||
//! number of samples per tti
|
||||
unsigned int samples_per_tti;
|
||||
//! the sample rate for receive.
|
||||
@@ -298,7 +297,8 @@ struct openair0_device_t {
|
||||
|
||||
/* !brief ETH params set by application */
|
||||
eth_params_t *eth_params;
|
||||
|
||||
//! record player data, definition in record_player.h
|
||||
recplay_state_t *recplay_state;
|
||||
/* !brief Indicates if device already initialized */
|
||||
int is_init;
|
||||
|
||||
@@ -443,11 +443,13 @@ typedef struct {
|
||||
|
||||
#define OPTION_LZ4 0x00000001 // LZ4 compression (option_value is set to compressed size)
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/*! \brief get device name from device type */
|
||||
char *get_devname(int devtype);
|
||||
/*! \brief Initialize openair RF target. It returns 0 if OK */
|
||||
int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/*! \brief Initialize transport protocol . It returns 0 if OK */
|
||||
@@ -465,6 +467,11 @@ openair0_timestamp get_usrp_time(openair0_device *device);
|
||||
* \returns 0 in success
|
||||
*/
|
||||
int openair0_set_rx_frequencies(openair0_device *device, openair0_config_t *openair0_cfg);
|
||||
/*! \brief read the iq record/player configuration */
|
||||
extern int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state);
|
||||
/*! \brief store recorded iqs from memory to file. */
|
||||
extern void iqrecorder_end(openair0_device *device);
|
||||
|
||||
|
||||
#define gettid() syscall(__NR_gettid)
|
||||
/*@}*/
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** record_player.c
|
||||
*
|
||||
* \author: Nokia bellLabs B. Mongazon F. Taburet
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/resource.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
#include "common_lib.h"
|
||||
#include "record_player.h"
|
||||
|
||||
/*! \brief read the oai recorder or player configuration, called from common device code
|
||||
* \param recplay_conf: store parameters
|
||||
* recplay_state: store recorder or player data while the device runs
|
||||
*/
|
||||
int read_recplayconfig(recplay_conf_t **recplay_conf, recplay_state_t **recplay_state) {
|
||||
unsigned int u_sf_record = 0; // record mode
|
||||
unsigned int u_sf_replay = 0; // replay mode
|
||||
*recplay_conf = calloc(sizeof(recplay_conf_t),1);
|
||||
paramdef_t device_recplay_params[]=DEVICE_RECPLAY_PARAMS_DESC ;
|
||||
config_get(device_recplay_params,sizeof(device_recplay_params)/sizeof(paramdef_t),DEVICE_RECPLAY_SECTION);
|
||||
|
||||
if (u_sf_record || u_sf_replay ) {
|
||||
struct sysinfo systeminfo;
|
||||
*recplay_state = calloc(sizeof(recplay_state_t),1);
|
||||
|
||||
if ( *recplay_state == NULL) {
|
||||
LOG_E(HW,"calloc error in %s\n", __FILE__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Use mmap for IQ files for systems with less than 6GB total RAM
|
||||
sysinfo(&systeminfo);
|
||||
|
||||
if (systeminfo.totalram < 6144000000) {
|
||||
(*recplay_state)->use_mmap = 0;
|
||||
} else {
|
||||
(*recplay_state)->use_mmap = 1;
|
||||
}
|
||||
} else { /* record player enabled */
|
||||
free(*recplay_conf);
|
||||
*recplay_conf=NULL;
|
||||
}
|
||||
|
||||
if (u_sf_replay == 1) return RECPLAY_REPLAYMODE;
|
||||
else if (u_sf_record == 1) return RECPLAY_RECORDMODE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Terminate operation of the oai iq recorder. to be called by any device
|
||||
* used in record mode
|
||||
* \param device, the hardware used
|
||||
*/
|
||||
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};
|
||||
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+");
|
||||
|
||||
if (rs->pFile == NULL) {
|
||||
LOG_E(HW,"Cannot open %s\n", rc->u_sf_filename);
|
||||
} else {
|
||||
unsigned int i = 0;
|
||||
unsigned int modu = 0;
|
||||
|
||||
if ((modu = rs->nb_samples % 10) != 0) {
|
||||
rs->nb_samples -= modu; // store entire number of frames
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
for (i = 0; i < rs->nb_samples; i++) {
|
||||
fwrite(rs->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), rs->pFile);
|
||||
}
|
||||
|
||||
fclose (rs->pFile);
|
||||
LOG_UI(HW,"File %s closed\n",rc->u_sf_filename );
|
||||
}
|
||||
|
||||
if (rs->ms_sample != NULL) {
|
||||
free((void *)rs->ms_sample);
|
||||
rs->ms_sample = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef __USRP_LIB_H
|
||||
#define __USRP_LIB_H
|
||||
#ifndef __RECORD_PLAYER_H
|
||||
#define __RECORD_PLAYER_H
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
@@ -21,7 +21,7 @@
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** usrp_lib.h
|
||||
/** targets/ARCH/COMMON/record-player.h
|
||||
*
|
||||
* \author: bruno.mongazon-cazavet@nokia-bell-labs.com
|
||||
*/
|
||||
@@ -46,7 +46,7 @@ extern "C"
|
||||
/* command line parameters for USRP record/playback */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define USRP_DEVICE_PARAMS_DESC { \
|
||||
#define DEVICE_PARAMS_DESC { \
|
||||
{CONFIG_OPT_RECPLAY, CONFIG_HLP_RECPLAY, PARAMFLAG_BOOL, uptr:&enable_recplay, defuintval:0, TYPE_UINT, 0} \
|
||||
}
|
||||
|
||||
@@ -59,6 +59,15 @@ 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 OAIIQFILE_ID "OIQF"
|
||||
typedef struct {
|
||||
uint64_t devtype;
|
||||
uint64_t tx_sample_advance;
|
||||
double bw;
|
||||
char oaiid[4];
|
||||
} iqfile_header_t;
|
||||
|
||||
typedef struct {
|
||||
int64_t header;
|
||||
int64_t ts;
|
||||
@@ -75,8 +84,8 @@ typedef struct {
|
||||
|
||||
/* help strings definition for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
|
||||
#define CONFIG_HLP_SF_FILE "Path of the file used for subframes record or replay"
|
||||
#define CONFIG_HLP_SF_REC "Record subframes from USRP driver into a file for later replay"
|
||||
#define CONFIG_HLP_SF_REP "Replay subframes into USRP driver from a file"
|
||||
#define CONFIG_HLP_SF_REC "Record subframes from device driver into a file for later replay"
|
||||
#define CONFIG_HLP_SF_REP "Replay subframes from a file using the oai replay driver"
|
||||
#define CONFIG_HLP_SF_MAX "Maximum count of subframes to be recorded in subframe file"
|
||||
#define CONFIG_HLP_SF_LOOPS "Number of loops to replay of the entire subframes file"
|
||||
#define CONFIG_HLP_SF_RDELAY "Delay in microseconds to read a subframe in replay mode"
|
||||
@@ -91,41 +100,43 @@ typedef struct {
|
||||
#define CONFIG_OPT_SF_RDELAY "subframes-read-delay"
|
||||
#define CONFIG_OPT_SF_WDELAY "subframes-write-delay"
|
||||
|
||||
#define USRP_RECPLAY_SECTION "device.recplay"
|
||||
#define DEVICE_RECPLAY_SECTION "device.recplay"
|
||||
/* For information only - the macro is not usable in C++ */
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
/* command line parameters for USRP record/playback */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/* optname helpstr paramflags XXXptr defXXXval type numelt */
|
||||
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
|
||||
#define USRP_RECPLAY_PARAMS_DESC { \
|
||||
{CONFIG_OPT_SF_FILE, CONFIG_HLP_SF_FILE, 0, strptr:(char **)((*recplay_state)->u_sf_filename), defstrval:DEF_SF_FILE, TYPE_STRING, 1024}, \
|
||||
{CONFIG_OPT_SF_REC, CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&(u_sf_record), defuintval:0, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_REP, CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&(u_sf_replay), defuintval:0, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_MAX, CONFIG_HLP_SF_MAX, 0, uptr:&((*recplay_state)->u_sf_max), defintval:DEF_NB_SF, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_state)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_state)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_state)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \
|
||||
#define DEVICE_RECPLAY_PARAMS_DESC { \
|
||||
{CONFIG_OPT_SF_FILE, CONFIG_HLP_SF_FILE, 0, strptr:(char **)((*recplay_conf)->u_sf_filename), defstrval:DEF_SF_FILE, TYPE_STRING, 1024}, \
|
||||
{CONFIG_OPT_SF_REC, CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&(u_sf_record), defuintval:0, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_REP, CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&(u_sf_replay), defuintval:0, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_MAX, CONFIG_HLP_SF_MAX, 0, uptr:&((*recplay_conf)->u_sf_max), defintval:DEF_NB_SF, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_LOOPS, CONFIG_HLP_SF_LOOPS, 0, uptr:&((*recplay_conf)->u_sf_loops), defintval:DEF_SF_NB_LOOP, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_RDELAY, CONFIG_HLP_SF_RDELAY, 0, uptr:&((*recplay_conf)->u_sf_read_delay), defintval:DEF_SF_DELAY_READ, TYPE_UINT, 0}, \
|
||||
{CONFIG_OPT_SF_WDELAY, CONFIG_HLP_SF_WDELAY, 0, uptr:&((*recplay_conf)->u_sf_write_delay), defintval:DEF_SF_DELAY_WRITE, TYPE_UINT, 0}, \
|
||||
}/*! \brief USRP Configuration and state */
|
||||
|
||||
typedef struct {
|
||||
FILE *pFile;
|
||||
int mmapfd;
|
||||
int iqfd;
|
||||
int use_mmap; // default is to use mmap
|
||||
size_t mapsize;
|
||||
iqrec_t *ms_sample; // memory for all subframes
|
||||
unsigned int nb_samples;
|
||||
char u_sf_filename[1024]; // subframes file path
|
||||
unsigned int u_sf_max ; // max number of recorded subframes
|
||||
unsigned int u_sf_loops ; // number of loops in replay mode
|
||||
unsigned int u_sf_read_delay; // read delay in replay mode
|
||||
unsigned int u_sf_write_delay ; // write delay in replay mode
|
||||
} recplay_conf_t;
|
||||
|
||||
typedef struct {
|
||||
int use_mmap; // default is to use mmap
|
||||
size_t mapsize;
|
||||
FILE *pFile;
|
||||
int mmapfd;
|
||||
int iqfd;
|
||||
iqrec_t *ms_sample; // memory for all subframes
|
||||
unsigned int nb_samples;
|
||||
} recplay_state_t;
|
||||
|
||||
|
||||
extern int read_usrpconfig(uint32_t *recplay_mode, recplay_state_t **recplay_state);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __USRP_LIB_H
|
||||
#endif // __RECORD_PLAYER_H
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,73 +0,0 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** usrp_lib_config.c
|
||||
*
|
||||
* \author: HongliangXU : hong-liang-xu@agilent.com
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/sysinfo.h>
|
||||
#include <sys/resource.h>
|
||||
#include "common/utils/LOG/log.h"
|
||||
#include "assertions.h"
|
||||
#include "common_lib.h"
|
||||
#include "usrp_lib.h"
|
||||
|
||||
|
||||
int read_usrpconfig(uint32_t *recplay_mode, recplay_state_t **recplay_state) {
|
||||
unsigned int u_sf_record = 0; // record mode
|
||||
unsigned int u_sf_replay = 0; // replay mode
|
||||
uint32_t enable_recplay;
|
||||
|
||||
paramdef_t usrp_params[] = USRP_DEVICE_PARAMS_DESC;
|
||||
config_get(usrp_params,sizeof(usrp_params)/sizeof(paramdef_t),USRP_SECTION);
|
||||
if (enable_recplay) {
|
||||
*recplay_state = calloc(sizeof(recplay_state_t),1);
|
||||
paramdef_t usrp_recplay_params[]=USRP_RECPLAY_PARAMS_DESC ;
|
||||
struct sysinfo systeminfo;
|
||||
|
||||
// Use mmap for IQ files for systems with less than 6GB total RAM
|
||||
sysinfo(&systeminfo);
|
||||
|
||||
if (systeminfo.totalram < 6144000000) {
|
||||
(*recplay_state)->use_mmap = 0;
|
||||
} else {
|
||||
(*recplay_state)->use_mmap = 1;
|
||||
}
|
||||
|
||||
memset((*recplay_state)->u_sf_filename, 0, 1024);
|
||||
config_get(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),USRP_RECPLAY_SECTION);
|
||||
|
||||
if (strlen((*recplay_state)->u_sf_filename) == 0) {
|
||||
(void) strcpy((
|
||||
*recplay_state)->u_sf_filename, DEF_SF_FILE);
|
||||
}
|
||||
} /* record player enabled */
|
||||
if (u_sf_replay == 1) *recplay_mode = RECPLAY_REPLAYMODE;
|
||||
|
||||
if (u_sf_record == 1) *recplay_mode = RECPLAY_RECORDMODE;
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
# I/Q record-playback
|
||||
## using the iq recorder or iq player
|
||||
|
||||
This feature provides I/Q record-playback as presented in the 4th OAI workshop. Tests have only been performed with a eNB, but the implementation should allow any softmodem executable to use the iq's record/player.
|
||||
The I/Q record/playback feature is briefly described hereafter, it allows you to:
|
||||
* record subframes received by the USRP board in a file while the system is operating (for example you can record a full UE connection/traffic/ disconnection sequence). Today the oai USRP device is the only one supporting the recording feature.
|
||||
* replay subframes from a file to operate the system (possibly in multiple loops if the recorded sequence is convenient from the logical point of view).
|
||||
|
||||
The record/replay are activated and configured using oai configuration parameters
|
||||
|
||||
### Record mode
|
||||
options for record mode are:
|
||||
* `subframes-record` Activate record mode
|
||||
* `subframes-file` Path of the file used for subframes recording (default is `/tmp/iqfile`)
|
||||
* `subframes-max` Maximum count of subframes to be recorded in subframe file (default is 120000)
|
||||
|
||||
Note that the value of `--subframes-max` parameter needs to be tuned according to your RAM capabilities. The default value is 120000, which allows for 120 seconds of record/replay but will require ~3.6GB of RAM and disk space.
|
||||
If RAM does not allow for the parameter value, an error message will be displayed and the run will be aborted. In record mode, to minimize pzerformance impact,
|
||||
subframes are saved into memory and written to disk when the process is terminating . When you estimate the recorded sequence is achieved, you should terminate the eNB/RRU by typing `CTRL-C`. At that time, up to the value of `--subframes-max` subframes will be written on disk. The eNB/RRU will indicate the exact count of subframes written to disk, which may be less (but not higher) that the value of `--subframes-max` parameter (120000 by default). The number of subframes written to disk is rounded to an integral number of frames.
|
||||
Although it is possible to perform recording with a fronthaul setup, it is suggested to perform recording in full eNB mode and then replay in either monolithic or split eNB.
|
||||
The option can be used while operating full eNB or RCC/RRU linked by NGFI IF5/IF4p5 fronthaul techniques. One of the advantage of the record/replay technique is that you can replay on a fronthauling setup a file that has been recorded in full eNB mode. This can easily asserts that the fronthauling underlying set up or technique is correct.
|
||||
|
||||
>recording session example:
|
||||
```bash
|
||||
./lte-softmodem -O libconfig:/usr/local/oai/conf/enb.band7.tm1.20PRB.usrpb210.conf:dbgl5 --log_config.global_log_options level,thread --device.recplay.subframes-record 1
|
||||
............................................
|
||||
............................................
|
||||
[CONFIG] device.recplay.subframes-file set to default value "/tmp/iqfile"
|
||||
[CONFIG] subframes-record: 0
|
||||
[CONFIG] device.recplay.subframes-record set to default value
|
||||
[CONFIG] subframes-replay: 0
|
||||
[CONFIG] device.recplay.subframes-replay set to default value
|
||||
[CONFIG] subframes-max: 120000
|
||||
[CONFIG] device.recplay.subframes-max set to default value
|
||||
[CONFIG] subframes-loops: 5
|
||||
[CONFIG] device.recplay.subframes-loops set to default value
|
||||
[CONFIG] subframes-read-delay: 700
|
||||
[CONFIG] device.recplay.subframes-read-delay set to default value
|
||||
[CONFIG] subframes-write-delay: 15
|
||||
[CONFIG] device.recplay.subframes-write-delay set to default value
|
||||
[LIBCONFIG] device.recplay: 7/7 parameters successfully set, (7 to default value)
|
||||
[CONFIG] subframes-record: 1
|
||||
[CONFIG] device.recplay 1 options set from command line
|
||||
[CONFIG] loader.oai_device.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.oai_device: 2/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] loader.oai_device 0 options set from command line
|
||||
[LOADER] library liboai_device.so successfully loaded
|
||||
USRP device initialized in subframes record mode
|
||||
[HW]I lte-softmodem UHD version 3.14.1.1-release (3.14.1)
|
||||
...................................................
|
||||
...................................................
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 18, min_I0 12
|
||||
^C
|
||||
Run time: 0h 26s
|
||||
Time executing user inst.: 1s 865251us
|
||||
Time executing system inst.: 2s 805162us
|
||||
Max. Phy. memory usage: 4068328kB
|
||||
Page fault number (no io): 1008741
|
||||
Page fault number (requiring io): 15
|
||||
Number of file system read: 97672
|
||||
Number of filesystem write: 0
|
||||
Number of context switch (process origin, io...): 562871
|
||||
Number of context switch (os origin, priority...): 112
|
||||
Linux signal Interrupt...
|
||||
/usr/local/oai/develop/openairinterface5g/executables/softmodem-common.c:188 signal_handler() Exiting OAI softmodem: softmodem starting exit procedure
|
||||
Exiting ru_thread
|
||||
U[HW]I ru thread Writing file header to /tmp/iqfile
|
||||
[HW]I lte-softmodem Writing file header to /tmp/iqfile
|
||||
[HW]I ru thread Writing 19730 subframes to /tmp/iqfile
|
||||
[HW]I lte-softmodem Writing 19730 subframes to /tmp/iqfile
|
||||
[HW]I lte-softmodem File /tmp/iqfile closed
|
||||
[HW]I ru thread File /tmp/iqfile closed
|
||||
[PHY]I ru thread RU 0 rf device stopped
|
||||
```
|
||||
|
||||
### Playback/replay mode
|
||||
The option works only for 5MHz bandwidth because the information stored in the iq's file header regarding bandwidth is not yet properly processed.
|
||||
In this version, mismatch between file content and run time parameters might lead to unpredictable results. In addition a file recorded on a AVX2-capable processor cannot be replayed on a non-AVX2-capable processor (this is to be further investigated).
|
||||
options for replay mode are:
|
||||
* `subframes-replay` Activate replay mode
|
||||
* `subframes-file` Path of the file used for subframes replay (default is `/tmp/iqfile`)
|
||||
* `subframes-loops` Number of iterations to replay the entire subframes file (default is 5)
|
||||
* `subframes-read-delay` Delay in microseconds to read a subframe in replay mode (default 200)
|
||||
* `subframes-write-delay` Delay in milliseconds to write a subframe in replay mode (default 15)
|
||||
|
||||
>iq player session example:
|
||||
```bash
|
||||
./lte-softmodem -O libconfig:/usr/local/oai/conf/enb.nbiot.band7.tm1.50PRB.usrpb210.conf:dbgl5 --T_stdout 1 --log_config.global_log_options level,thread --eNBs.[0].component_carriers.[0].N_RB_DL 25 --device.recplay.subframes-replay 1
|
||||
[CONFIG] get parameters from libconfig /usr/local/oai/conf/enb.nbiot.band7.tm1.50PRB.usrpb210.conf , debug flags: 0x00000005
|
||||
................................
|
||||
..................................
|
||||
[PHY]I lte-softmodem rxdataF[0] 0x55f52df52f40 for RU 0
|
||||
[CONFIG] device.recplay.subframes-file set to default value "/tmp/iqfile"
|
||||
[CONFIG] subframes-record: 0
|
||||
[CONFIG] device.recplay.subframes-record set to default value
|
||||
[CONFIG] subframes-replay: 0
|
||||
[CONFIG] device.recplay.subframes-replay set to default value
|
||||
[CONFIG] subframes-max: 120000
|
||||
[CONFIG] device.recplay.subframes-max set to default value
|
||||
[CONFIG] subframes-loops: 5
|
||||
[CONFIG] device.recplay.subframes-loops set to default value
|
||||
[CONFIG] subframes-read-delay: 700
|
||||
[CONFIG] device.recplay.subframes-read-delay set to default value
|
||||
[CONFIG] subframes-write-delay: 15
|
||||
[CONFIG] device.recplay.subframes-write-delay set to default value
|
||||
[LIBCONFIG] device.recplay: 7/7 parameters successfully set, (7 to default value)
|
||||
[CONFIG] subframes-replay: 1
|
||||
[CONFIG] device.recplay 1 options set from command line
|
||||
[CONFIG] loader.oai_iqplayer.shlibversion set to default value ""
|
||||
[LIBCONFIG] loader.oai_iqplayer: 2/2 parameters successfully set, (1 to default value)
|
||||
[CONFIG] loader.oai_iqplayer 0 options set from command line
|
||||
[LOADER] library liboai_iqplayer.so successfully loaded
|
||||
[HW]I lte-softmodem Loading subframes using mmap() from /tmp/iqfile size=324433632 bytes ...
|
||||
[HW]I lte-softmodem Replay iqs from USRP B200 device, bandwidth 5.000000e+06
|
||||
[HW]I lte-softmodem Loaded 10550 subframes.
|
||||
[HW]I lte-softmodem iqplayer device initialized, replay /tmp/iqfile for 5 iterations[HW]I lte-softmodem [RAU] has loaded USRP B200 device.
|
||||
.............................................
|
||||
.............................................
|
||||
[PHY]I ru thread max_I0 18, min_I0 12
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 18, min_I0 0
|
||||
[HW]I ru thread starting subframes file with wrap_count=1 wrap_ts=81024000 ts=107616555
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 18, min_I0 12
|
||||
[HW]I ru thread starting subframes file with wrap_count=2 wrap_ts=162048000 ts=188640555
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 18, min_I0 0
|
||||
[HW]I ru thread starting subframes file with wrap_count=3 wrap_ts=243072000 ts=269664555
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 19, min_I0 12
|
||||
[HW]I ru thread starting subframes file with wrap_count=4 wrap_ts=324096000 ts=350688555
|
||||
[PHY]I lte-softmodem prach_I0 = 0.0 dB
|
||||
[PHY]I ru thread max_I0 18, min_I0 12
|
||||
[HW]W ru thread iqplayer device terminating subframes replay after 5 iteration
|
||||
/usr/local/oai/develop/openairinterface5g/targets/ARCH/iqplayer/iqplayer_lib.c:222 trx_iqplayer_read() Exiting OAI softmodem: replay ended, triggering process termination
|
||||
```
|
||||
|
||||
## iq recorder and iq player implementation overview
|
||||
|
||||
### configuration
|
||||
The iq's record/player is using the [configuration module](../../../../common/config/DOC/config.md). Configuration parameters supported by the record player are defined in the [record_player.h](../../COMMON/record_player.h) include file.
|
||||
There are no specific sections for the recorder or the replayer, parameters are defined under the `device.recplay`section and the `read_recplayconfig` function is common to both the recorder and the player. `device.recplay` configuration section is read from oai code common to all devices:
|
||||
Implemented in [record_player.c](../../COMMON/record_player.c), the `read_recplayconfig` function is called from `load_lib` and reads the configuration parameters, saving them in a `recplay_conf_t` sub-structure of the oai device. It also allocates a `recplay_state_t` structure which will save the recorder or player data.
|
||||
3GPP authentication algorithm doesn't allow session establishment via replaying iq's. When using the replayer, a softmodem parameter is set (`SOFTMODEM_RECPLAY_BIT` in the `optmask` bitmask of the `softmodem_params_t` structure. It allows bypassing or activating specific code in the softmodem to allow session establishment replay. This mechanism only works if in parallel specific code is also activated in the EPC, which is supported by the NOKIA LTE box.
|
||||
An easiest scenario is to use the record player in parallel with the noS1 mode, as described [here](../../../../doc/RUNMODEM.md)
|
||||
|
||||
### iq recorder
|
||||
most of the implementation is now located in the oai device common code:
|
||||
* The`load_lib` function in [common-lib.c](../../COMMON/common_lib.c) reads the record player parameters.
|
||||
* Recorder specific functions are implemented in `iqrecorder_end` saves the cached iq's to disk, it has to be called by the oai device in it's end function.
|
||||
* When recording is enabled, the device must implement iq's caching in it's read function. It also has to call the `iqrecorder_end ` function when terminating to write iqs to a file on disk. Look at the USRP device ( [../usrp_lib.cpp](../../USRP/USERSPACE/LIB/usrp_lib.cpp) ) for details.
|
||||
|
||||
### iq player
|
||||
The replay feature is implemented as a oai device.
|
||||
* The`load_lib` function in [common-lib.c](../../COMMON/common_lib.c) reads the record player parameters, this code is common with the recorder.
|
||||
* The player device is implemented in [iqplayer_lib.c](../iqplayer_lib.c) which at build time creates the `liboai_iqplayer.so` shared library. Thi
|
||||
* s device is automatically, dynamicaly loaded when the player feature is activated at runtime when the boolean `device.recplay.subframes-replay` option is set.
|
||||
|
||||
### iq's file format
|
||||
The recorder adds a header containing the device type, the bandwith and a format identifier. Using these information when replaying a file has not yet been implemented, so the player only supports USRP B2xx device and 5MHz bandwith.
|
||||
|
||||
[oai Wikis home](https://gitlab.eurecom.fr/oai/openairinterface5g/wikis/home)
|
||||
@@ -0,0 +1,307 @@
|
||||
/*
|
||||
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership.
|
||||
* The OpenAirInterface Software Alliance licenses this file to You under
|
||||
* the OAI Public License, Version 1.1 (the "License"); you may not use this file
|
||||
* except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.openairinterface.org/?page_id=698
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*-------------------------------------------------------------------------------
|
||||
* For more information about the OpenAirInterface (OAI) Software Alliance:
|
||||
* contact@openairinterface.org
|
||||
*/
|
||||
|
||||
/** iqplayer_lib.cpp
|
||||
*
|
||||
* \author:FrancoisTaburet: francois.taburet@nokia-bell-labs.com
|
||||
*/
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#include <string.h>
|
||||
#include <pthread.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <errno.h>
|
||||
#include "common_lib.h"
|
||||
#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 in header)\n");
|
||||
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;
|
||||
LOG_UI(HW,"Replay iqs from %s device, bandwidth %e\n",get_devname(iq_fh->devtype),iq_fh->bw);
|
||||
}
|
||||
|
||||
|
||||
/*! \brief Called to start the iqplayer device. Return 0 if OK, < 0 if error
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
*/
|
||||
static int iqplayer_loadfile(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||
recplay_state_t *s = device->recplay_state;
|
||||
recplay_conf_t *c = openair0_cfg->recplay_conf;
|
||||
|
||||
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));
|
||||
|
||||
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);
|
||||
}
|
||||
} else {
|
||||
LOG_E(HW,"Cannot mmap file, exiting.\n");
|
||||
close(s->mmapfd);
|
||||
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);
|
||||
|
||||
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);
|
||||
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);
|
||||
// allocate buffer for 1 sample at a time
|
||||
s->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t));
|
||||
|
||||
if (s->ms_sample == NULL) {
|
||||
LOG_E(HW,"Memory allocation failed for individual subframe replay mode.\n" );
|
||||
close(s->iqfd);
|
||||
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) {
|
||||
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);
|
||||
exit(-1);
|
||||
}
|
||||
} else {
|
||||
LOG_E(HW,"Cannot open %s exiting.\n",c->u_sf_filename );
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*! \brief Terminate operation of the oai iq player
|
||||
* \param device, the hardware used
|
||||
*/
|
||||
static void trx_iqplayer_end(openair0_device *device) {
|
||||
if (device == NULL)
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*! \brief Write iqs function when in replay mode, just introduce a delay, as configured at init time,
|
||||
@param device pointer to the device structure specific to the RF hardware target
|
||||
@param timestamp The timestamp at which the first sample MUST be sent
|
||||
@param buff Buffer which holds the samples
|
||||
@param nsamps number of samples to be sent
|
||||
@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
|
||||
*/
|
||||
static int trx_iqplayer_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||
struct timespec req;
|
||||
req.tv_sec = 0;
|
||||
req.tv_nsec = device->openair0_cfg->recplay_conf->u_sf_write_delay * 1000;
|
||||
nanosleep(&req, NULL);
|
||||
return nsamps;
|
||||
}
|
||||
|
||||
/*! \brief Receive samples from iq file.
|
||||
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
|
||||
* the first channel. *ptimestamp is the time at which the first sample
|
||||
* was received.
|
||||
* \param device the hardware to use
|
||||
* \param[out] ptimestamp the time at which the first sample was received.
|
||||
* \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
|
||||
* \param antenna_id Index of antenna for which to receive samples
|
||||
* \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);
|
||||
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));
|
||||
|
||||
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 (cur_samples < s->nb_samples) {
|
||||
*ptimestamp = (s->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
|
||||
|
||||
if (cur_samples == 0) {
|
||||
LOG_I(HW,"starting subframes file with wrap_count=%lu wrap_ts=%lu ts=%lu\n", wrap_count,wrap_ts,*ptimestamp);
|
||||
}
|
||||
|
||||
memcpy(buff[0], &s->ms_sample[cur_samples].samples[0], nsamps*4);
|
||||
cur_samples++;
|
||||
}
|
||||
} else {
|
||||
// read sample from file
|
||||
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;
|
||||
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));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct timespec req;
|
||||
|
||||
req.tv_sec = 0;
|
||||
|
||||
req.tv_nsec = (device->openair0_cfg[0].recplay_conf->u_sf_read_delay) * 1000;
|
||||
|
||||
nanosleep(&req, NULL);
|
||||
|
||||
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 = NULL;
|
||||
device->trx_get_stats_func = NULL;
|
||||
device->trx_reset_stats_func = NULL;
|
||||
device->trx_end_func = trx_iqplayer_end;
|
||||
device->trx_stop_func = NULL;
|
||||
device->trx_set_freq_func = NULL;
|
||||
device->trx_set_gains_func = NULL;
|
||||
// Replay subframes from from file
|
||||
// openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
|
||||
// bw_gain_adjust=1;
|
||||
device->trx_write_func = trx_iqplayer_write;
|
||||
device->trx_read_func = trx_iqplayer_read;
|
||||
iqplayer_loadfile(device, 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;
|
||||
}
|
||||
|
||||
/*@}*/
|
||||
@@ -22,12 +22,10 @@
|
||||
#ifndef CREATE_NR_TASKS_H_
|
||||
#define CREATE_NR_TASKS_H_
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
/* External declaration of L2L1 task that depend on the target */
|
||||
extern void *l2l1_task(void *arg);
|
||||
|
||||
int create_gNB_tasks(uint32_t gnb_nb);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* CREATE_TASKS_H_ */
|
||||
|
||||
@@ -22,13 +22,11 @@
|
||||
#ifndef CREATE_TASKS_H_
|
||||
#define CREATE_TASKS_H_
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
/* External declaration of L2L1 task that depend on the target */
|
||||
extern void *l2l1_task(void *arg);
|
||||
|
||||
int create_tasks(uint32_t enb_nb);
|
||||
int create_tasks_ue(uint32_t ue_nb);
|
||||
int create_tasks_mbms(uint32_t enb_nb);
|
||||
#endif
|
||||
|
||||
#endif /* CREATE_TASKS_H_ */
|
||||
|
||||
@@ -22,13 +22,11 @@
|
||||
#ifndef CREATE_TASKS_H_
|
||||
#define CREATE_TASKS_H_
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
/* External declaration of L2L1 task that depend on the target */
|
||||
extern void *l2l1_task(void *arg);
|
||||
|
||||
int create_tasks(uint32_t enb_nb);
|
||||
int create_tasks_ue(uint32_t ue_nb);
|
||||
int create_tasks_mbms(uint32_t enb_nb);
|
||||
#endif
|
||||
|
||||
#endif /* CREATE_TASKS_H_ */
|
||||
|
||||
@@ -273,7 +273,7 @@ void exit_function(const char *file, const char *function, const int line, const
|
||||
|
||||
static void get_options(void) {
|
||||
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||
get_common_options();
|
||||
get_common_options(SOFTMODEM_ENB_BIT );
|
||||
CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
|
||||
|
||||
if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
|
||||
|
||||
+25
-14
@@ -1582,21 +1582,32 @@ void *UE_thread(void *arg)
|
||||
if (is_synchronized == 0) {
|
||||
if (instance_cnt_synch < 0) { // we can invoke the synch
|
||||
// grab 10 ms of signal and wakeup synch thread
|
||||
if (UE->mode != loop_through_memory)
|
||||
for(int sf=0; sf<10; sf++) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf];
|
||||
|
||||
AssertFatal( UE->frame_parms.samples_per_tti ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
UE->frame_parms.samples_per_tti,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
if (IS_SOFTMODEM_RFSIM )
|
||||
if (UE->mode != loop_through_memory) {
|
||||
if (IS_SOFTMODEM_RFSIM ) {
|
||||
for(int sf=0; sf<10; sf++) {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][UE->frame_parms.samples_per_tti*sf];
|
||||
|
||||
AssertFatal( UE->frame_parms.samples_per_tti ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
UE->frame_parms.samples_per_tti,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
write_dummy(UE, timestamp);
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
|
||||
rxp[i] = (void *)&UE->common_vars.rxdata[i][0];
|
||||
|
||||
AssertFatal( UE->frame_parms.samples_per_tti*10 ==
|
||||
UE->rfdevice.trx_read_func(&UE->rfdevice,
|
||||
×tamp,
|
||||
rxp,
|
||||
UE->frame_parms.samples_per_tti*10,
|
||||
UE->frame_parms.nb_antennas_rx), "");
|
||||
}
|
||||
}
|
||||
AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
|
||||
instance_cnt_synch = ++UE->proc.instance_cnt_synch;
|
||||
|
||||
|
||||
@@ -79,10 +79,7 @@
|
||||
#include "UTIL/OTG/otg_vars.h"
|
||||
#endif
|
||||
|
||||
#if defined(ENABLE_ITTI)
|
||||
#include "create_tasks.h"
|
||||
#endif
|
||||
|
||||
#include "create_tasks.h"
|
||||
#include "system.h"
|
||||
|
||||
|
||||
@@ -300,7 +297,7 @@ static void get_options(void) {
|
||||
CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
|
||||
/* unknown parameters on command line will be checked in main
|
||||
after all init have been performed */
|
||||
get_common_options();
|
||||
get_common_options(SOFTMODEM_4GUE_BIT );
|
||||
get_uethreads_params();
|
||||
paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
|
||||
paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
|
||||
@@ -786,19 +783,11 @@ int main( int argc, char **argv ) {
|
||||
// wait for end of program
|
||||
printf("TYPE <CTRL-C> TO TERMINATE\n");
|
||||
//getchar();
|
||||
#if defined(ENABLE_ITTI)
|
||||
printf("Entering ITTI signals handler\n");
|
||||
itti_wait_tasks_end();
|
||||
printf("Returned from ITTI signal handler\n");
|
||||
oai_exit=1;
|
||||
printf("oai_exit=%d\n",oai_exit);
|
||||
#else
|
||||
|
||||
while (oai_exit==0)
|
||||
rt_sleep_ns(100000000ULL);
|
||||
|
||||
printf("Terminating application - oai_exit=%d\n",oai_exit);
|
||||
#endif
|
||||
|
||||
// stop threads
|
||||
if(IS_SOFTMODEM_DOFORMS)
|
||||
|
||||
Reference in New Issue
Block a user