Commit 10a3565d authored by frtabu's avatar frtabu

usrp device cleanup, record player as run-time option

parent 81933116
...@@ -186,7 +186,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU ...@@ -186,7 +186,7 @@ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${CMAKE_CU
# these changes are related to hardcoded path to include .h files # these changes are related to hardcoded path to include .h files
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3") set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3")
set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g3 -DMALLOC_CHECK_=3 -O2")
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS} -O3")
set(GIT_BRANCH "UNKNOWN") set(GIT_BRANCH "UNKNOWN")
set(GIT_COMMIT_HASH "UNKNOWN") set(GIT_COMMIT_HASH "UNKNOWN")
...@@ -531,7 +531,9 @@ foreach(USRPSOURCE ${USRPSRCVARIANT}) ...@@ -531,7 +531,9 @@ foreach(USRPSOURCE ${USRPSRCVARIANT})
# ) # )
get_filename_component(USRPVERSION ${USRPSOURCE} NAME_WE) get_filename_component(USRPVERSION ${USRPSOURCE} NAME_WE)
string(REPLACE "usrp_lib" "" USRPVERSION ${USRPVERSION} ) string(REPLACE "usrp_lib" "" USRPVERSION ${USRPVERSION} )
add_library(oai_usrpdevif${USRPVERSION} MODULE ${USRPSOURCE} )
add_library(oai_usrpdevif${USRPVERSION} MODULE ${USRPSOURCE} ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib_config.c)
target_link_libraries(oai_usrpdevif${USRPVERSION} uhd) target_link_libraries(oai_usrpdevif${USRPVERSION} uhd)
endforeach(USRPSOURCE) endforeach(USRPSOURCE)
......
...@@ -223,7 +223,7 @@ function main() { ...@@ -223,7 +223,7 @@ function main() {
CMAKE_BUILD_TYPE="Debug" CMAKE_BUILD_TYPE="Debug"
echo_info "Will Compile with gdb symbols and disable compiler optimization" echo_info "Will Compile with gdb symbols and disable compiler optimization"
CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug" CMAKE_CMD="$CMAKE_CMD -DCMAKE_BUILD_TYPE=Debug"
if [ "$1" == "Debug" ] ; then if [ "$2" == "Debug" ] ; then
shift shift
fi fi
;; ;;
......
...@@ -386,13 +386,13 @@ int config_setdefault_string(paramdef_t *cfgoptions, char *prefix) { ...@@ -386,13 +386,13 @@ int config_setdefault_string(paramdef_t *cfgoptions, char *prefix) {
status=1; status=1;
if (cfgoptions->numelt == 0 ) { if (cfgoptions->numelt == 0 ) {
config_check_valptr(cfgoptions, (char **)(cfgoptions->strptr), sizeof(char *)); // config_check_valptr(cfgoptions, (char **)(cfgoptions->strptr), sizeof(char *));
config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(cfgoptions->defstrval)+1); config_check_valptr(cfgoptions, cfgoptions->strptr, strlen(cfgoptions->defstrval)+1);
sprintf(*(cfgoptions->strptr), "%s",cfgoptions->defstrval); sprintf(*(cfgoptions->strptr), "%s",cfgoptions->defstrval);
printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, *(cfgoptions->strptr)); printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, *(cfgoptions->strptr));
} else { } else {
sprintf((char *)*(cfgoptions->strptr), "%s",cfgoptions->defstrval); sprintf((char *)(cfgoptions->strptr), "%s",cfgoptions->defstrval);
printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (char *)*(cfgoptions->strptr)); printf_params("[CONFIG] %s.%s set to default value \"%s\"\n", ((prefix == NULL) ? "" : prefix), cfgoptions->optname, (char *)(cfgoptions->strptr));
} }
} }
......
...@@ -302,5 +302,12 @@ typedef struct protocol_ctxt_s { ...@@ -302,5 +302,12 @@ typedef struct protocol_ctxt_s {
#define CHECK_CTXT_ARGS(CTXT_Pp) #define CHECK_CTXT_ARGS(CTXT_Pp)
#define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg) #define exit_fun(msg) exit_function(__FILE__,__FUNCTION__,__LINE__,msg)
#ifdef __cplusplus
extern "C"
{
#endif
void exit_function(const char *file, const char *function, const int line, const char *s); void exit_function(const char *file, const char *function, const int line, const char *s);
#ifdef __cplusplus
}
#endif
#endif #endif
...@@ -48,9 +48,10 @@ ...@@ -48,9 +48,10 @@
#include "common/utils/LOG/log.h" #include "common/utils/LOG/log.h"
#include "common_lib.h" #include "common_lib.h"
#include "assertions.h" #include "assertions.h"
#include <sys/sysinfo.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <executables/softmodem-common.h> #include <executables/softmodem-common.h>
#include "usrp_lib.h"
#ifdef __SSE4_1__ #ifdef __SSE4_1__
#include <smmintrin.h> #include <smmintrin.h>
...@@ -68,7 +69,7 @@ ...@@ -68,7 +69,7 @@
* @{ * @{
*/ */
/*! \brief USRP Configuration */
typedef struct { typedef struct {
// -------------------------------- // --------------------------------
...@@ -107,7 +108,8 @@ typedef struct { ...@@ -107,7 +108,8 @@ typedef struct {
int first_tx; int first_tx;
//! timestamp of RX packet //! timestamp of RX packet
openair0_timestamp rx_timestamp; openair0_timestamp rx_timestamp;
uint32_t recplay_mode;
recplay_state_t *recplay_state;
} usrp_state_t; } usrp_state_t;
//void print_notes(void) //void print_notes(void)
...@@ -263,55 +265,15 @@ static int sync_to_gps(openair0_device *device) { ...@@ -263,55 +265,15 @@ static int sync_to_gps(openair0_device *device) {
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
#if defined(USRP_REC_PLAY)
#include "usrp_lib.h"
static FILE *pFile = NULL;
int mmapfd = 0;
int iqfd = 0;
int use_mmap = 1; // default is to use mmap
struct stat sb;
iqrec_t *ms_sample = NULL; // memory for all subframes
unsigned int nb_samples = 0;
unsigned int cur_samples = 0;
int64_t wrap_count = 0;
int64_t wrap_ts = 0;
unsigned int u_sf_mode = 0; // 1=record, 2=replay
unsigned int u_sf_record = 0; // record mode
unsigned int u_sf_replay = 0; // replay mode
char u_sf_filename[1024] = ""; // subframes file path
unsigned int u_sf_max = DEF_NB_SF; // max number of recorded subframes
unsigned int u_sf_loops = DEF_SF_NB_LOOP; // number of loops in replay mode
unsigned int u_sf_read_delay = DEF_SF_DELAY_READ; // read delay in replay mode
unsigned int u_sf_write_delay = DEF_SF_DELAY_WRITE; // write delay in replay mode
char config_opt_sf_file[] = CONFIG_OPT_SF_FILE;
char config_def_sf_file[] = DEF_SF_FILE;
char config_hlp_sf_file[] = CONFIG_HLP_SF_FILE;
char config_opt_sf_rec[] = CONFIG_OPT_SF_REC;
char config_hlp_sf_rec[] = CONFIG_HLP_SF_REC;
char config_opt_sf_rep[] = CONFIG_OPT_SF_REP;
char config_hlp_sf_rep[] = CONFIG_HLP_SF_REP;
char config_opt_sf_max[] = CONFIG_OPT_SF_MAX;
char config_hlp_sf_max[] = CONFIG_HLP_SF_MAX;
char config_opt_sf_loops[] = CONFIG_OPT_SF_LOOPS;
char config_hlp_sf_loops[] = CONFIG_HLP_SF_LOOPS;
char config_opt_sf_rdelay[] = CONFIG_OPT_SF_RDELAY;
char config_hlp_sf_rdelay[] = CONFIG_HLP_SF_RDELAY;
char config_opt_sf_wdelay[] = CONFIG_OPT_SF_WDELAY;
char config_hlp_sf_wdelay[] = CONFIG_HLP_SF_WDELAY;
#endif
/*! \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) {
#if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode
#endif
uhd::set_thread_priority_safe(1.0);
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
if ( s->recplay_mode == RECPLAY_REPLAYMODE)
return 0;
// setup GPIO for TDD, GPIO(4) = ATR_RX // setup GPIO for TDD, GPIO(4) = ATR_RX
//set data direction register (DDR) to output //set data direction register (DDR) to output
s->usrp->set_gpio_attr("FP0", "DDR", 0x7f, 0x7f); s->usrp->set_gpio_attr("FP0", "DDR", 0x7f, 0x7f);
...@@ -341,94 +303,79 @@ static int trx_usrp_start(openair0_device *device) { ...@@ -341,94 +303,79 @@ static int trx_usrp_start(openair0_device *device) {
s->rx_count = 0; s->rx_count = 0;
s->tx_count = 0; s->tx_count = 0;
s->rx_timestamp = 0; s->rx_timestamp = 0;
#if defined(USRP_REC_PLAY)
}
#endif
return 0; return 0;
} }
/*! \brief Terminate operation of the USRP transceiver -- free all associated resources /*! \brief Terminate operation of the USRP transceiver -- free all associated resources
* \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) {
#if defined(USRP_REC_PLAY) // For some ugly reason, this can be called several times... if (device == NULL)
static int done = 0; return;
if (done == 1) return; usrp_state_t *s = (usrp_state_t *)device->priv;
done = 1; if (s == NULL)
return;
if (u_sf_mode != 2) { // not subframes replay if (s->recplay_mode != RECPLAY_REPLAYMODE) { // not subframes replay
#endif
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 //send a mini EOB packet
s->tx_md.end_of_burst = true; s->tx_md.end_of_burst = true;
s->tx_stream->send("", 0, s->tx_md); s->tx_stream->send("", 0, s->tx_md);
s->tx_md.end_of_burst = false; s->tx_md.end_of_burst = false;
sleep(1); sleep(1);
#if defined(USRP_REC_PLAY)
} }
#endif if (s->recplay_mode == RECPLAY_RECORDMODE) { // subframes store
#if defined(USRP_REC_PLAY) s->recplay_state->pFile = fopen (s->recplay_state->u_sf_filename,"wb+");
if (u_sf_mode == 1) { // subframes store
pFile = fopen (u_sf_filename,"wb+");
if (pFile == NULL) { if (s->recplay_state->pFile == NULL) {
std::cerr << "Cannot open " << u_sf_filename << std::endl; std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << std::endl;
} else { } else {
unsigned int i = 0; unsigned int i = 0;
unsigned int modu = 0; unsigned int modu = 0;
if ((modu = nb_samples % 10) != 0) { if ((modu = s->recplay_state->nb_samples % 10) != 0) {
nb_samples -= modu; // store entire number of frames s->recplay_state->nb_samples -= modu; // store entire number of frames
} }
std::cerr << "Writing " << nb_samples << " subframes to " << u_sf_filename << " ..." << std::endl; std::cerr << "Writing " << s->recplay_state->nb_samples << " subframes to " << s->recplay_state->u_sf_filename << " ..." << std::endl;
for (i = 0; i < nb_samples; i++) { for (i = 0; i < s->recplay_state->nb_samples; i++) {
fwrite(ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), pFile); fwrite(s->recplay_state->ms_sample+i, sizeof(unsigned char), sizeof(iqrec_t), s->recplay_state->pFile);
} }
fclose (pFile); fclose (s->recplay_state->pFile);
std::cerr << "File " << u_sf_filename << " closed." << std::endl; std::cerr << "File " << s->recplay_state->u_sf_filename << " closed." << std::endl;
}
} }
if (u_sf_mode == 1) { // record if (s->recplay_state->ms_sample != NULL) {
if (ms_sample != NULL) { free((void *)s->recplay_state->ms_sample);
free((void *)ms_sample); s->recplay_state->ms_sample = NULL;
ms_sample = NULL;
} }
} else if (s->recplay_mode == RECPLAY_REPLAYMODE) { // replay
if (s->recplay_state->use_mmap) {
if (s->recplay_state->ms_sample != MAP_FAILED) {
munmap(s->recplay_state->ms_sample, s->recplay_state->mapsize);
s->recplay_state->ms_sample = NULL;
} }
if (u_sf_mode == 2) { // replay if (s->recplay_state->mmapfd != 0) {
if (use_mmap) { close(s->recplay_state->mmapfd);
if (ms_sample != MAP_FAILED) { s->recplay_state->mmapfd = 0;
munmap(ms_sample, sb.st_size);
ms_sample = NULL;
}
if (mmapfd != 0) {
close(mmapfd);
mmapfd = 0;
} }
} else { } else {
if (ms_sample != NULL) { if (s->recplay_state->ms_sample != NULL) {
free(ms_sample); free(s->recplay_state->ms_sample);
ms_sample = NULL; s->recplay_state->ms_sample = NULL;
} }
if (iqfd != 0) { if (s->recplay_state->iqfd != 0) {
close(iqfd); close(s->recplay_state->iqfd);
iqfd = 0; s->recplay_state->iqfd = 0;
} }
} }
} }
#endif
} }
/*! \brief Called to send samples to the USRP RF target /*! \brief Called to send samples to the USRP RF target
...@@ -441,11 +388,9 @@ static void trx_usrp_end(openair0_device *device) { ...@@ -441,11 +388,9 @@ static void trx_usrp_end(openair0_device *device) {
*/ */
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; int ret=0;
#if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode
#endif
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
if (s->recplay_mode != RECPLAY_REPLAYMODE) { // not replay mode
int nsamps2; // aligned to upper 32 or 16 byte boundary 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__
...@@ -565,20 +510,117 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, ...@@ -565,20 +510,117 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
} /* end of developnr code */ } /* end of developnr code */
if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps); if (ret != nsamps) LOG_E(HW,"[xmit] tx samples %d != %d\n",ret,nsamps);
#if defined(USRP_REC_PLAY)
} else { } else {
struct timespec req; struct timespec req;
req.tv_sec = 0; req.tv_sec = 0;
req.tv_nsec = u_sf_write_delay * 1000; req.tv_nsec = s->recplay_state->u_sf_write_delay * 1000;
nanosleep(&req, NULL); nanosleep(&req, NULL);
ret = nsamps; ret = nsamps;
} }
#endif
return ret; return ret;
} }
/*! \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_usrp_read_recplay(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;
usrp_state_t *s = (usrp_state_t *)device->priv;
if (cur_samples == s->recplay_state->nb_samples) {
cur_samples = 0;
wrap_count++;
if (wrap_count == s->recplay_state->u_sf_loops) {
std::cerr << "USRP device terminating subframes replay mode after " << s->recplay_state->u_sf_loops << " loops." << std::endl;
exit_function(__FILE__, __FUNCTION__, __LINE__,"replay ended, triggering process termination\n");
}
wrap_ts = wrap_count * (s->recplay_state->nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000));
if (!s->recplay_state->use_mmap) {
if (lseek(s->recplay_state->iqfd, 0, SEEK_SET) == 0) {
std::cerr << "Seeking at the beginning of IQ file" << std::endl;
} else {
std::cerr << "Problem seeking at the beginning of IQ file" << std::endl;
}
}
}
if (s->recplay_state->use_mmap) {
if (cur_samples < s->recplay_state->nb_samples) {
*ptimestamp = (s->recplay_state->ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
}
memcpy(buff[0], &s->recplay_state->ms_sample[cur_samples].samples[0], nsamps*4);
cur_samples++;
}
} else {
// read sample from file
if (read(s->recplay_state->iqfd, s->recplay_state->ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl;
close(s->recplay_state->iqfd);
free(s->recplay_state->ms_sample);
s->recplay_state->ms_sample = NULL;
s->recplay_state->iqfd = 0;
exit(-1);
}
if (cur_samples < s->recplay_state->nb_samples) {
static int64_t ts0 = 0;
if ((cur_samples == 0) && (wrap_count == 0)) {
ts0 = s->recplay_state->ms_sample->ts;
}
*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
}
memcpy(buff[0], &s->recplay_state->ms_sample->samples[0], nsamps*4);
cur_samples++;
// Prepare for next read
off_t where = lseek(s->recplay_state->iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
if (where < 0) {
LOG_E(HW,"Cannot lseek in iqfile: %s\n",strerror(errno));
}
}
}
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = s->recplay_state->u_sf_read_delay * 1000;
nanosleep(&req, NULL);
return nsamps;
return samples_received;
}
/*! \brief Receive samples from hardware. /*! \brief Receive samples from hardware.
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for * 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 * the first channel. *ptimestamp is the time at which the first sample
...@@ -594,10 +636,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -594,10 +636,6 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
usrp_state_t *s = (usrp_state_t *)device->priv; usrp_state_t *s = (usrp_state_t *)device->priv;
int samples_received=0; int samples_received=0;
int nsamps2; // aligned to upper 32 or 16 byte boundary int nsamps2; // aligned to upper 32 or 16 byte boundary
#if defined(USRP_REC_PLAY)
if (u_sf_mode != 2) { // not replay mode
#endif
#if defined(__x86_64) || defined(__i386__) #if defined(__x86_64) || defined(__i386__)
#ifdef __AVX2__ #ifdef __AVX2__
nsamps2 = (nsamps+7)>>3; nsamps2 = (nsamps+7)>>3;
...@@ -683,97 +721,17 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp ...@@ -683,97 +721,17 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
s->rx_count += nsamps; s->rx_count += nsamps;
s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate);
*ptimestamp = s->rx_timestamp; *ptimestamp = s->rx_timestamp;
#if defined (USRP_REC_PLAY)
}
#endif if (s->recplay_mode == RECPLAY_RECORDMODE) { // record mode
#if defined(USRP_REC_PLAY)
if (u_sf_mode == 1) { // record mode
// Copy subframes to memory (later dump on a file) // Copy subframes to memory (later dump on a file)
if (nb_samples < u_sf_max) { if (s->recplay_state->nb_samples < s->recplay_state->u_sf_max) {
(ms_sample+nb_samples)->header = BELL_LABS_IQ_HEADER; (s->recplay_state->ms_sample+s->recplay_state->nb_samples)->header = BELL_LABS_IQ_HEADER;
(ms_sample+nb_samples)->ts = *ptimestamp; (s->recplay_state->ms_sample+s->recplay_state->nb_samples)->ts = *ptimestamp;
memcpy((ms_sample+nb_samples)->samples, buff[0], nsamps*4); memcpy((s->recplay_state->ms_sample+s->recplay_state->nb_samples)->samples, buff[0], nsamps*4);
nb_samples++; s->recplay_state->nb_samples++;
} } else exit_function(__FILE__, __FUNCTION__, __LINE__,"Recording reaches max iq limit\n");
} else if (u_sf_mode == 2) { // replay mode
if (cur_samples == nb_samples) {
cur_samples = 0;
wrap_count++;
if (wrap_count == u_sf_loops) {
std::cerr << "USRP device terminating subframes replay mode after " << u_sf_loops << " loops." << std::endl;
return 0; // should make calling process exit
}
wrap_ts = wrap_count * (nb_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000));
if (!use_mmap) {
if (lseek(iqfd, 0, SEEK_SET) == 0) {
std::cerr << "Seeking at the beginning of IQ file" << std::endl;
} else {
std::cerr << "Problem seeking at the beginning of IQ file" << std::endl;
}
}
}
if (use_mmap) {
if (cur_samples < nb_samples) {
*ptimestamp = (ms_sample[0].ts + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000))) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
}
memcpy(buff[0], &ms_sample[cur_samples].samples[0], nsamps*4);
cur_samples++;
}
} else {
// read sample from file
if (read(iqfd, ms_sample, sizeof(iqrec_t)) != sizeof(iqrec_t)) {
std::cerr << "pb reading iqfile at index " << sizeof(iqrec_t)*cur_samples << std::endl;
close(iqfd);
free(ms_sample);
ms_sample = NULL;
iqfd = 0;
exit(-1);
}
if (cur_samples < nb_samples) {
static int64_t ts0 = 0;
if ((cur_samples == 0) && (wrap_count == 0)) {
ts0 = ms_sample->ts;
}
*ptimestamp = ts0 + (cur_samples * (((int)(device->openair0_cfg[0].sample_rate)) / 1000)) + wrap_ts;
if (cur_samples == 0) {
std::cerr << "starting subframes file with wrap_count=" << wrap_count << " wrap_ts=" << wrap_ts
<< " ts=" << *ptimestamp << std::endl;
}
memcpy(buff[0], &ms_sample->samples[0], nsamps*4);
cur_samples++;
// Prepare for next read
off_t where = lseek(iqfd, cur_samples * sizeof(iqrec_t), SEEK_SET);
}
} }
struct timespec req;
req.tv_sec = 0;
req.tv_nsec = u_sf_read_delay * 1000;
nanosleep(&req, NULL);
return nsamps;
}
#endif
return samples_received; return samples_received;
} }
...@@ -974,114 +932,25 @@ static void uhd_set_thread_priority(void) { ...@@ -974,114 +932,25 @@ static void uhd_set_thread_priority(void) {
uhd::set_thread_priority_safe(1.0); uhd::set_thread_priority_safe(1.0);
} }
#if defined(USRP_REC_PLAY)
extern "C" {
/*! \brief Initializer for USRP record/playback config
* \param parameter array description
* \returns 0 on success
*/
int trx_usrp_recplay_config_init(paramdef_t *usrp_recplay_params) {
// --subframes-file
memcpy(usrp_recplay_params[0].optname, config_opt_sf_file, strlen(config_opt_sf_file));
usrp_recplay_params[0].helpstr = config_hlp_sf_file;
usrp_recplay_params[0].paramflags=PARAMFLAG_NOFREE;
usrp_recplay_params[0].strptr=(char **)&u_sf_filename;
usrp_recplay_params[0].defstrval = NULL;
usrp_recplay_params[0].type=TYPE_STRING;
usrp_recplay_params[0].numelt=sizeof(u_sf_filename);
// --subframes-record
memcpy(usrp_recplay_params[1].optname, config_opt_sf_rec, strlen(config_opt_sf_rec));
usrp_recplay_params[1].helpstr = config_hlp_sf_rec;
usrp_recplay_params[1].paramflags=PARAMFLAG_BOOL;
usrp_recplay_params[1].uptr=&u_sf_record;
usrp_recplay_params[1].defuintval=0;
usrp_recplay_params[1].type=TYPE_UINT;
usrp_recplay_params[1].numelt=0;
// --subframes-replay
memcpy(usrp_recplay_params[2].optname, config_opt_sf_rep, strlen(config_opt_sf_rep));
usrp_recplay_params[2].helpstr = config_hlp_sf_rep;
usrp_recplay_params[2].paramflags=PARAMFLAG_BOOL;
usrp_recplay_params[2].uptr=&u_sf_replay;
usrp_recplay_params[2].defuintval=0;
usrp_recplay_params[2].type=TYPE_UINT;
usrp_recplay_params[2].numelt=0;
// --subframes-max
memcpy(usrp_recplay_params[3].optname, config_opt_sf_max, strlen(config_opt_sf_max));
usrp_recplay_params[3].helpstr = config_hlp_sf_max;
usrp_recplay_params[3].paramflags=0;
usrp_recplay_params[3].uptr=&u_sf_max;
usrp_recplay_params[3].defuintval=DEF_NB_SF;
usrp_recplay_params[3].type=TYPE_UINT;
usrp_recplay_params[3].numelt=0;
// --subframes-loops
memcpy(usrp_recplay_params[4].optname, config_opt_sf_loops, strlen(config_opt_sf_loops));
usrp_recplay_params[4].helpstr = config_hlp_sf_loops;
usrp_recplay_params[4].paramflags=0;
usrp_recplay_params[4].uptr=&u_sf_loops;
usrp_recplay_params[4].defuintval=DEF_SF_NB_LOOP;
usrp_recplay_params[4].type=TYPE_UINT;
usrp_recplay_params[4].numelt=0;
// --subframes-read-delay
memcpy(usrp_recplay_params[5].optname, config_opt_sf_rdelay, strlen(config_opt_sf_rdelay));
usrp_recplay_params[5].helpstr = config_hlp_sf_rdelay;
usrp_recplay_params[5].paramflags=0;
usrp_recplay_params[5].uptr=&u_sf_read_delay;
usrp_recplay_params[5].defuintval=DEF_SF_DELAY_READ;
usrp_recplay_params[5].type=TYPE_UINT;
usrp_recplay_params[5].numelt=0;
// --subframes-write-delay
memcpy(usrp_recplay_params[6].optname, config_opt_sf_wdelay, strlen(config_opt_sf_wdelay));
usrp_recplay_params[6].helpstr = config_hlp_sf_wdelay;
usrp_recplay_params[6].paramflags=0;
usrp_recplay_params[6].uptr=&u_sf_write_delay;
usrp_recplay_params[6].defuintval=DEF_SF_DELAY_WRITE;
usrp_recplay_params[6].type=TYPE_UINT;
usrp_recplay_params[6].numelt=0;
return 0; // always ok
}
}
#endif
extern "C" { extern "C" {
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
#if defined(USRP_REC_PLAY) LOG_D(HW, "openair0_cfg[0].sdr_addrs == '%s'\n", openair0_cfg[0].sdr_addrs);
paramdef_t usrp_recplay_params[7]; LOG_D(HW, "openair0_cfg[0].clock_source == '%d'\n", openair0_cfg[0].clock_source);
struct sysinfo systeminfo; usrp_state_t *s ;
// to check
static int done = 0;
if (done == 1) { if ( device->priv == NULL) {
s=(usrp_state_t *)calloc(sizeof(usrp_state_t),1);
device->priv = s;
} else {
LOG_E(HW, "multiple device init detected\n");
return 0; return 0;
} // prevent from multiple init
done = 1;
// end to check
// Use mmap for IQ files for systems with less than 6GB total RAM
sysinfo(&systeminfo);
if (systeminfo.totalram < 6144000000) {
use_mmap = 0;
} }
memset(usrp_recplay_params, 0, 7*sizeof(paramdef_t)); device->openair0_cfg = openair0_cfg;
memset(&u_sf_filename[0], 0, 1024); read_usrpconfig(&(s->recplay_mode), &(s->recplay_state));
if (trx_usrp_recplay_config_init(usrp_recplay_params) != 0) {
std::cerr << "USRP device record/replay mode configuration error exiting" << std::endl;
return -1;
}
config_process_cmdline(usrp_recplay_params,sizeof(usrp_recplay_params)/sizeof(paramdef_t),NULL);
if (strlen(u_sf_filename) == 0) {
(void) strcpy(u_sf_filename, DEF_SF_FILE);
}
if (u_sf_replay == 1) u_sf_mode = 2;
if (u_sf_record == 1) u_sf_mode = 1;
if (u_sf_mode == 2) { if (s!=NULL && s->recplay_mode == RECPLAY_REPLAYMODE) {
// Replay subframes from from file // Replay subframes from from file
int bw_gain_adjust=0; int bw_gain_adjust=0;
device->openair0_cfg = openair0_cfg; device->openair0_cfg = openair0_cfg;
...@@ -1094,10 +963,9 @@ extern "C" { ...@@ -1094,10 +963,9 @@ extern "C" {
openair0_cfg[0].iq_txshift = 4;//shift openair0_cfg[0].iq_txshift = 4;//shift
openair0_cfg[0].iq_rxrescale = 15;//rescale iqs openair0_cfg[0].iq_rxrescale = 15;//rescale iqs
set_rx_gain_offset(&openair0_cfg[0],0,bw_gain_adjust); set_rx_gain_offset(&openair0_cfg[0],0,bw_gain_adjust);
device->priv = NULL;
device->trx_start_func = trx_usrp_start; device->trx_start_func = trx_usrp_start;
device->trx_write_func = trx_usrp_write; device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read; device->trx_read_func = trx_usrp_read_recplay;
device->trx_get_stats_func = trx_usrp_get_stats; device->trx_get_stats_func = trx_usrp_get_stats;
device->trx_reset_stats_func = trx_usrp_reset_stats; device->trx_reset_stats_func = trx_usrp_reset_stats;
device->trx_end_func = trx_usrp_end; device->trx_end_func = trx_usrp_end;
...@@ -1106,22 +974,17 @@ extern "C" { ...@@ -1106,22 +974,17 @@ extern "C" {
device->trx_set_gains_func = trx_usrp_set_gains; device->trx_set_gains_func = trx_usrp_set_gains;
device->openair0_cfg = openair0_cfg; device->openair0_cfg = openair0_cfg;
device->uhd_set_thread_priority = uhd_set_thread_priority; device->uhd_set_thread_priority = uhd_set_thread_priority;
std::cerr << "USRP device initialized in subframes replay mode for " << u_sf_loops << " loops. Use mmap=" std::cerr << "USRP device initialized in subframes replay mode for " << s->recplay_state->u_sf_loops << " loops. Use mmap="
<< use_mmap << std::endl; << s->recplay_state->use_mmap << std::endl;
} else { } else {
#endif
usrp_state_t *s = (usrp_state_t *)calloc(sizeof(usrp_state_t),1);
// Initialize USRP device // Initialize USRP device
device->openair0_cfg = openair0_cfg;
int vers=0,subvers=0,subsubvers=0; int vers=0,subvers=0,subsubvers=0;
int bw_gain_adjust=0; int bw_gain_adjust=0;
#if defined(USRP_REC_PLAY)
if (u_sf_mode == 1) { if (s->recplay_mode == RECPLAY_RECORDMODE) {
std::cerr << "USRP device initialized in subframes record mode" << std::endl; std::cerr << "USRP device initialized in subframes record mode" << std::endl;
} }
#endif
sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers);
LOG_I(HW,"UHD version %s (%d.%d.%d)\n", LOG_I(HW,"UHD version %s (%d.%d.%d)\n",
uhd::get_version_string().c_str(),vers,subvers,subsubvers); uhd::get_version_string().c_str(),vers,subvers,subsubvers);
...@@ -1177,7 +1040,6 @@ extern "C" { ...@@ -1177,7 +1040,6 @@ extern "C" {
} }
s->usrp = uhd::usrp::multi_usrp::make(args); s->usrp = uhd::usrp::multi_usrp::make(args);
device->priv = s;
if (args.find("clock_source")==std::string::npos) { if (args.find("clock_source")==std::string::npos) {
LOG_I(HW, "Using clock_source == '%d'\n", openair0_cfg[0].clock_source); LOG_I(HW, "Using clock_source == '%d'\n", openair0_cfg[0].clock_source);
...@@ -1219,9 +1081,7 @@ extern "C" { ...@@ -1219,9 +1081,7 @@ extern "C" {
if (device->type==USRP_X300_DEV) { if (device->type==USRP_X300_DEV) {
openair0_cfg[0].rx_gain_calib_table = calib_table_x310; openair0_cfg[0].rx_gain_calib_table = calib_table_x310;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info std::cerr << "-- Using calibration table: calib_table_x310" << std::endl; // Bell Labs info
#endif
LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate); LOG_I(HW,"%s() sample_rate:%u\n", __FUNCTION__, (int)openair0_cfg[0].sample_rate);
switch ((int)openair0_cfg[0].sample_rate) { switch ((int)openair0_cfg[0].sample_rate) {
...@@ -1301,15 +1161,11 @@ extern "C" { ...@@ -1301,15 +1161,11 @@ extern "C" {
if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210; openair0_cfg[0].rx_gain_calib_table = calib_table_b210;
bw_gain_adjust=0; bw_gain_adjust=0;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info std::cerr << "-- Using calibration table: calib_table_b210" << std::endl; // Bell Labs info
#endif
} else { } else {
openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38;
bw_gain_adjust=1; bw_gain_adjust=1;
#if defined(USRP_REC_PLAY)
std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info std::cerr << "-- Using calibration table: calib_table_b210_38" << std::endl; // Bell Labs info
#endif
} }
switch ((int)openair0_cfg[0].sample_rate) { switch ((int)openair0_cfg[0].sample_rate) {
...@@ -1462,7 +1318,6 @@ extern "C" { ...@@ -1462,7 +1318,6 @@ extern "C" {
} }
LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs()); LOG_I(HW,"Device timestamp: %f...\n", s->usrp->get_time_now().get_real_secs());
device->priv = s;
device->trx_start_func = trx_usrp_start; device->trx_start_func = trx_usrp_start;
device->trx_write_func = trx_usrp_write; device->trx_write_func = trx_usrp_write;
device->trx_read_func = trx_usrp_read; device->trx_read_func = trx_usrp_read;
...@@ -1486,86 +1341,82 @@ extern "C" { ...@@ -1486,86 +1341,82 @@ extern "C" {
if(is_equal(s->sample_rate, (double)7.68e6)) if(is_equal(s->sample_rate, (double)7.68e6))
s->tx_forward_nsamps = 50; s->tx_forward_nsamps = 50;
#if defined(USRP_REC_PLAY)
} }
#endif if (s->recplay_mode == RECPLAY_RECORDMODE) { // record mode
#if defined(USRP_REC_PLAY) s->recplay_state->ms_sample = (iqrec_t *) malloc(s->recplay_state->u_sf_max * sizeof(iqrec_t));
if (u_sf_mode == 1) { // record mode
ms_sample = (iqrec_t *) malloc(u_sf_max * sizeof(iqrec_t));
if (ms_sample == NULL) { if (s->recplay_state->ms_sample == NULL) {
std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl; std::cerr<< "Memory allocation failed for subframe record or replay mode." << std::endl;
exit(-1); exit(-1);
} }
memset(ms_sample, 0, u_sf_max * BELL_LABS_IQ_BYTES_PER_SF); memset(s->recplay_state->ms_sample, 0, s->recplay_state->u_sf_max * BELL_LABS_IQ_BYTES_PER_SF);
} } else if (s->recplay_mode == RECPLAY_REPLAYMODE) {
if (s->recplay_state->use_mmap) {
if (u_sf_mode == 2) {
if (use_mmap) {
// use mmap // use mmap
mmapfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE); s->recplay_state->mmapfd = open(s->recplay_state->u_sf_filename, O_RDONLY | O_LARGEFILE);
if (mmapfd != 0) { if (s->recplay_state->mmapfd != 0) {
fstat(mmapfd, &sb); struct stat sb;
std::cerr << "Loading subframes using mmap() from " << u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl; fstat(s->recplay_state->mmapfd, &sb);
ms_sample = (iqrec_t *) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, mmapfd, 0); s->recplay_state->mapsize=sb.st_size;
std::cerr << "Loading subframes using mmap() from " << s->recplay_state->u_sf_filename << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
s->recplay_state->ms_sample = (iqrec_t *) mmap(NULL, sb.st_size, PROT_WRITE, MAP_PRIVATE, s->recplay_state->mmapfd, 0);
if (ms_sample != MAP_FAILED) { if (s->recplay_state->ms_sample != MAP_FAILED) {
nb_samples = (sb.st_size / sizeof(iqrec_t)); s->recplay_state->nb_samples = (sb.st_size / sizeof(iqrec_t));
int aligned = (((unsigned long)ms_sample & 31) == 0)? 1:0; int aligned = (((unsigned long)s->recplay_state->ms_sample & 31) == 0)? 1:0;
std::cerr<< "Loaded "<< nb_samples << " subframes." << std::endl; std::cerr<< "Loaded "<< s->recplay_state->nb_samples << " subframes." << std::endl;
if (aligned == 0) { if (aligned == 0) {
std::cerr<< "mmap address is not 32 bytes aligned, exiting." << std::endl; std::cerr<< "mmap address is not 32 bytes aligned, exiting." << std::endl;
close(mmapfd); close(s->recplay_state->mmapfd);
exit(-1); exit(-1);
} }
} else { } else {
std::cerr << "Cannot mmap file, exiting." << std::endl; std::cerr << "Cannot mmap file, exiting." << std::endl;
close(mmapfd); close(s->recplay_state->mmapfd);
exit(-1); exit(-1);
} }
} else { } else {
std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl; std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << " , exiting." << std::endl;
exit(-1); exit(-1);
} }
} else { } else {
iqfd = open(u_sf_filename, O_RDONLY | O_LARGEFILE); s->recplay_state->iqfd = open(s->recplay_state->u_sf_filename, O_RDONLY | O_LARGEFILE);
if (iqfd != 0) { if (s->recplay_state->iqfd != 0) {
fstat(iqfd, &sb); struct stat sb;
nb_samples = (sb.st_size / sizeof(iqrec_t)); fstat(s->recplay_state->iqfd, &sb);
std::cerr << "Loading " << nb_samples << " subframes from " << u_sf_filename s->recplay_state->mapsize=sb.st_size;
s->recplay_state->nb_samples = (sb.st_size / sizeof(iqrec_t));
std::cerr << "Loading " << s->recplay_state->nb_samples << " subframes from " << s->recplay_state->u_sf_filename
<< " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl; << " size=" << (uint64_t)sb.st_size << " bytes ..." << std::endl;
// allocate buffer for 1 sample at a time // allocate buffer for 1 sample at a time
ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t)); s->recplay_state->ms_sample = (iqrec_t *) malloc(sizeof(iqrec_t));
if (ms_sample == NULL) { if (s->recplay_state->ms_sample == NULL) {
std::cerr<< "Memory allocation failed for individual subframe replay mode." << std::endl; std::cerr<< "Memory allocation failed for individual subframe replay mode." << std::endl;
close(iqfd); close(s->recplay_state->iqfd);
exit(-1); exit(-1);
} }
memset(ms_sample, 0, sizeof(iqrec_t)); memset(s->recplay_state->ms_sample, 0, sizeof(iqrec_t));
// point at beginning of file // point at beginning of file
if (lseek(iqfd, 0, SEEK_SET) == 0) { if (lseek(s->recplay_state->iqfd, 0, SEEK_SET) == 0) {
std::cerr << "Initial seek at beginning of the file" << std::endl; std::cerr << "Initial seek at beginning of the file" << std::endl;
} else { } else {
std::cerr << "Problem initial seek at beginning of the file" << std::endl; std::cerr << "Problem initial seek at beginning of the file" << std::endl;
} }
} else { } else {
std::cerr << "Cannot open " << u_sf_filename << " , exiting." << std::endl; std::cerr << "Cannot open " << s->recplay_state->u_sf_filename << " , exiting." << std::endl;
exit(-1); exit(-1);
} }
} }
} }
#endif
return 0; return 0;
} }
......
...@@ -26,8 +26,6 @@ ...@@ -26,8 +26,6 @@
* \author: bruno.mongazon-cazavet@nokia-bell-labs.com * \author: bruno.mongazon-cazavet@nokia-bell-labs.com
*/ */
#if defined (USRP_REC_PLAY)
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -35,6 +33,29 @@ ...@@ -35,6 +33,29 @@
#include "common/config/config_paramdesc.h" #include "common/config/config_paramdesc.h"
#include "common/config/config_userapi.h" #include "common/config/config_userapi.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define CONFIG_OPT_RECPLAY "enable_recplay"
#define CONFIG_HLP_RECPLAY "Allow record player"
#define USRP_SECTION "device.usrp"
/* inclusion for device configuration */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters for USRP record/playback */
/* optname helpstr paramflags XXXptr defXXXval type numelt */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define USRP_DEVICE_PARAMS_DESC { \
{CONFIG_OPT_RECPLAY, CONFIG_HLP_RECPLAY, PARAMFLAG_BOOL, uptr:&enable_recplay, defuintval:0, TYPE_UINT, 0} \
}
/* inclusions for record player */
#define RECPLAY_DISABLED 0
#define RECPLAY_RECORDMODE 1
#define RECPLAY_REPLAYMODE 2
#define BELL_LABS_IQ_HEADER 0xabababababababab #define BELL_LABS_IQ_HEADER 0xabababababababab
#define BELL_LABS_IQ_PER_SF 7680 // Up to 5MHz bw for now #define BELL_LABS_IQ_PER_SF 7680 // Up to 5MHz bw for now
#define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4) #define BELL_LABS_IQ_BYTES_PER_SF (BELL_LABS_IQ_PER_SF * 4)
...@@ -46,13 +67,13 @@ typedef struct { ...@@ -46,13 +67,13 @@ typedef struct {
unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe unsigned char samples[BELL_LABS_IQ_BYTES_PER_SF]; // iq's for one subframe
} iqrec_t; } iqrec_t;
#define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz) #define DEF_NB_SF 120000 // default nb of sf or ms to capture (2 minutes at 5MHz)
#define DEF_SF_FILE "/home/nokia/iqfile" // default subframes file name #define DEF_SF_FILE "/tmp/iqfile" // default subframes file name
#define DEF_SF_DELAY_READ 700 // default read delay µs (860=real) #define DEF_SF_DELAY_READ 700 // default read delay µs (860=real)
#define DEF_SF_DELAY_WRITE 15 // default write delay µs (15=real) #define DEF_SF_DELAY_WRITE 15 // default write delay µs (15=real)
#define DEF_SF_NB_LOOP 5 // default nb loops #define DEF_SF_NB_LOOP 5 // default nb loops
/* help strings definition for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ /* 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_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_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_REP "Replay subframes into USRP driver from a file"
...@@ -61,7 +82,7 @@ typedef struct { ...@@ -61,7 +82,7 @@ typedef struct {
#define CONFIG_HLP_SF_RDELAY "Delay in microseconds to read a subframe in replay mode" #define CONFIG_HLP_SF_RDELAY "Delay in microseconds to read a subframe in replay mode"
#define CONFIG_HLP_SF_WDELAY "Delay in microseconds to write a subframe in replay mode" #define CONFIG_HLP_SF_WDELAY "Delay in microseconds to write a subframe in replay mode"
/* keyword strings for command line options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */ /* keyword strings for config options, used in CMDLINE_XXX_DESC macros and printed when -h option is used */
#define CONFIG_OPT_SF_FILE "subframes-file" #define CONFIG_OPT_SF_FILE "subframes-file"
#define CONFIG_OPT_SF_REC "subframes-record" #define CONFIG_OPT_SF_REC "subframes-record"
#define CONFIG_OPT_SF_REP "subframes-replay" #define CONFIG_OPT_SF_REP "subframes-replay"
...@@ -70,20 +91,42 @@ typedef struct { ...@@ -70,20 +91,42 @@ typedef struct {
#define CONFIG_OPT_SF_RDELAY "subframes-read-delay" #define CONFIG_OPT_SF_RDELAY "subframes-read-delay"
#define CONFIG_OPT_SF_WDELAY "subframes-write-delay" #define CONFIG_OPT_SF_WDELAY "subframes-write-delay"
#define USRP_RECPLAY_SECTION "device.recplay"
/* For information only - the macro is not usable in C++ */ /* For information only - the macro is not usable in C++ */
/*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/* command line parameters for USRP record/playback */ /* 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 { \ #define USRP_RECPLAY_PARAMS_DESC { \
{"subframes-file", CONFIG_HLP_SF_FILE, 0, strptr:(char **)&u_sf_filename, defstrval:DEF_SF_FILE, TYPE_STRING, sizeof(u_sf_filename)}, \ {CONFIG_OPT_SF_FILE, CONFIG_HLP_SF_FILE, 0, strptr:(char **)((*recplay_state)->u_sf_filename), defstrval:DEF_SF_FILE, TYPE_STRING, 1024}, \
{"subframes-record", CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&u_sf_record, defuintval:0, TYPE_UINT, 0}, \ {CONFIG_OPT_SF_REC, CONFIG_HLP_SF_REC, PARAMFLAG_BOOL, uptr:&(u_sf_record), defuintval:0, TYPE_UINT, 0}, \
{"subframes-replay", CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&u_sf_replay, defuintval:0, TYPE_UINT, 0}, \ {CONFIG_OPT_SF_REP, CONFIG_HLP_SF_REP, PARAMFLAG_BOOL, uptr:&(u_sf_replay), defuintval:0, TYPE_UINT, 0}, \
{"subframes-max", CONFIG_HLP_SF_MAX, 0, uptr:&u_sf_max, defintval:DEF_NB_SF, 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}, \
{"subframes-loops", CONFIG_HLP_SF_LOOPS, 0, uptr:&u_sf_loops, defintval:DEF_SF_NB_LOOP, 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}, \
{"subframes-read-delay", CONFIG_HLP_SF_RDELAY, 0, uptr:&u_sf_read_delay, defintval:DEF_SF_DELAY_READ, 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}, \
{"subframes-write-delay", CONFIG_HLP_SF_WDELAY, 0, uptr:&u_sf_write_delay, defintval:DEF_SF_DELAY_WRITE, 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}, \
}/*! \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;
unsigned int u_sf_mode; // 1=record, 2=replay
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_state_t;
extern int read_usrpconfig(uint32_t *recplay_mode, recplay_state_t **recplay_state);
#ifdef __cplusplus
} }
#endif // BELL_LABS_MUST #endif
#endif // __USRP_LIB_H #endif // __USRP_LIB_H
...@@ -1320,7 +1320,7 @@ static inline int wakeup_prach_ru(RU_t *ru) { ...@@ -1320,7 +1320,7 @@ static inline int wakeup_prach_ru(RU_t *ru) {
} }
inline int wakeup_prach_ru_br(RU_t *ru) { static inline int wakeup_prach_ru_br(RU_t *ru) {
int ret; int ret;
struct timespec wait; struct timespec wait;
int time_ns = 5000000L; int time_ns = 5000000L;
......
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