Merge branch 'next' into maint

master
ismagom 9 years ago
commit 3db5c062d2

@ -4,7 +4,7 @@ IF(NOT UHD_FOUND)
FIND_PATH(
UHD_INCLUDE_DIRS
NAMES uhd/config.hpp
NAMES uhd.h
HINTS $ENV{UHD_DIR}/include
PATHS /usr/local/include
/usr/include

@ -0,0 +1,27 @@
if(NOT BLADERF_FOUND)
pkg_check_modules (BLADERF_PKG libbladeRF)
find_path(BLADERF_INCLUDE_DIRS NAMES libbladeRF.h
PATHS
${BLADERF_PKG_INCLUDE_DIRS}
/usr/include
/usr/local/include
)
find_library(BLADERF_LIBRARIES NAMES bladeRF
PATHS
${BLADERF_PKG_LIBRARY_DIRS}
/usr/lib
/usr/local/lib
)
if(BLADERF_INCLUDE_DIRS AND BLADERF_LIBRARIES)
set(BLADERF_FOUND TRUE CACHE INTERNAL "libbladeRF found")
message(STATUS "Found libbladeRF: ${BLADERF_INCLUDE_DIRS}, ${BLADERF_LIBRARIES}")
else(BLADERF_INCLUDE_DIRS AND BLADERF_LIBRARIES)
set(BLADERF_FOUND FALSE CACHE INTERNAL "libbladeRF found")
message(STATUS "libbladeRF not found.")
endif(BLADERF_INCLUDE_DIRS AND BLADERF_LIBRARIES)
mark_as_advanced(BLADERF_LIBRARIES BLADERF_INCLUDE_DIRS)
endif(NOT BLADERF_FOUND)

@ -1,52 +0,0 @@
# - Try to find openLTE's liblte
find_package(PkgConfig)
pkg_check_modules(PC_OPENLTE QUIET srslte)
set(OPENLTE_DEFINITIONS ${PC_OPENLTE_CFLAGS_OTHER})
FIND_PATH(
OPENLTE_LIBLTE_DIRS
NAMES liblte_common.h typedefs.h
HINTS ${PC_OPENLTE_SRCDIR}/liblte/hdr
${PC_OPENLTE_INCLUDEDIR}
${PC_OPENLTE_INCLUDE_DIRS}
$ENV{OPENLTE_DIR}/liblte/hdr
PATHS /usr/local/include
/usr/include
)
FIND_PATH(
OPENLTE_COMMON_DIRS
NAMES typedefs.h
HINTS ${PC_OPENLTE_SRCDIR}/cmn_hdr
${PC_OPENLTE_INCLUDEDIR}
${PC_OPENLTE_INCLUDE_DIRS}
$ENV{OPENLTE_DIR}/liblte/hdr
PATHS /usr/local/include
/usr/include
)
FIND_LIBRARY(
OPENLTE_LIBRARIES
NAMES lte
HINTS ${PC_OPENLTE_BUILDDIR}/liblte
${CMAKE_INSTALL_PREFIX}/lib
${CMAKE_INSTALL_PREFIX}/lib64
$ENV{OPENLTE_DIR}/lib
PATHS /usr/local/lib
/usr/local/lib64
/usr/lib
/usr/lib64
)
IF(OPENLTE_LIBLTE_DIRS AND OPENLTE_COMMON_DIRS)
SET(OPENLTE_INCLUDE_DIRS ${OPENLTE_LIBLTE_DIRS} ${OPENLTE_COMMON_DIRS})
ENDIF(OPENLTE_LIBLTE_DIRS AND OPENLTE_COMMON_DIRS)
message(STATUS "OPENLTE LIBRARIES " ${OPENLTE_LIBRARIES})
message(STATUS "OPENLTE INCLUDE DIRS " ${OPENLTE_INCLUDE_DIRS})
INCLUDE(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OPENLTE DEFAULT_MSG OPENLTE_LIBRARIES OPENLTE_INCLUDE_DIRS)
MARK_AS_ADVANCED(OPENLTE_LIBRARIES OPENLTE_INCLUDE_DIRS)

@ -5,9 +5,9 @@ SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.3.6), libgcc1 (>= 1:4.1), libboost
SET(CPACK_PACKAGE_CONTACT "Ismael Gomez ")
SET(CPACK_PACKAGE_VENDOR "Software Radio Systems Limited")
SET(CPACK_PACKAGE_VERSION_MAJOR "0")
SET(CPACK_PACKAGE_VERSION_MINOR "1")
SET(CPACK_PACKAGE_VERSION_PATCH "0")
SET(CPACK_PACKAGE_VERSION_MAJOR ${SRSLTE_VERSION_MAJOR})
SET(CPACK_PACKAGE_VERSION_MINOR ${SRSLTE_VERSION_MINOR})
SET(CPACK_PACKAGE_VERSION_PATCH ${SRSLTE_VERSION_PATCH})
SET(VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
########################################################################

@ -19,6 +19,6 @@
#
SET(SRSLTE_VERSION_MAJOR 001)
SET(SRSLTE_VERSION_MINOR 000)
SET(SRSLTE_VERSION_MINOR 001)
SET(SRSLTE_VERSION_PATCH 000)
SET(SRSLTE_VERSION_STRING "${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}.${SRSLTE_VERSION_PATCH}")

@ -43,6 +43,13 @@ ADD_CUSTOM_TARGET (add_srslte_headers SOURCES ${HEADERS_ALL})
# Find Dependencies
########################################################################
FIND_PACKAGE(UHD)
FIND_PACKAGE(bladeRF)
IF(BLADERF_FOUND OR UHD_FOUND)
set(RF_FOUND TRUE CACHE INTERNAL "RF frontend found")
ELSE(BLADERF_FOUND OR UHD_FOUND)
set(RF_FOUND FALSE CACHE INTERNAL "RF frontend found")
ENDIF(BLADERF_FOUND OR UHD_FOUND)
########################################################################
# Add subdirectories

@ -40,12 +40,12 @@ target_link_libraries(pdsch_ue srslte pthread)
add_executable(pdsch_enodeb pdsch_enodeb.c)
target_link_libraries(pdsch_enodeb srslte pthread)
IF(UHD_FOUND)
target_link_libraries(pdsch_ue srslte_uhd)
target_link_libraries(pdsch_enodeb srslte_uhd)
ELSE(UHD_FOUND)
add_definitions(-DDISABLE_UHD)
ENDIF(UHD_FOUND)
IF(RF_FOUND)
target_link_libraries(pdsch_ue srslte_rf)
target_link_libraries(pdsch_enodeb srslte_rf)
ELSE(RF_FOUND)
add_definitions(-DDISABLE_RF)
ENDIF(RF_FOUND)
FIND_PACKAGE(SRSGUI)
@ -61,28 +61,28 @@ ENDIF(SRSGUI_FOUND)
# These examples need the UHD driver
#################################################################
IF(UHD_FOUND)
IF(RF_FOUND)
add_executable(cell_search cell_search.c)
target_link_libraries(cell_search srslte srslte_uhd)
target_link_libraries(cell_search srslte srslte_rf)
add_executable(cell_measurement cell_measurement.c)
target_link_libraries(cell_measurement srslte srslte_uhd)
target_link_libraries(cell_measurement srslte srslte_rf)
add_executable(usrp_capture usrp_capture.c)
target_link_libraries(usrp_capture srslte srslte_uhd)
target_link_libraries(usrp_capture srslte srslte_rf)
add_executable(usrp_capture_sync usrp_capture_sync.c)
target_link_libraries(usrp_capture_sync srslte srslte_uhd)
target_link_libraries(usrp_capture_sync srslte srslte_rf)
add_executable(usrp_txrx usrp_txrx.c)
target_link_libraries(usrp_txrx srslte srslte_uhd)
target_link_libraries(usrp_txrx srslte srslte_rf)
MESSAGE(STATUS " UHD examples will be installed.")
MESSAGE(STATUS " examples will be installed.")
ELSE(UHD_FOUND)
MESSAGE(STATUS " UHD examples NOT INSTALLED.")
ENDIF(UHD_FOUND)
ELSE(RF_FOUND)
MESSAGE(STATUS " examples will NOT BE INSTALLED.")
ENDIF(RF_FOUND)
# Add subdirectories
add_subdirectory(tutorial_examples)

@ -36,8 +36,8 @@
#include <signal.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/cuhd/cuhd_utils.h"
#include "srslte/rf/rf.h"
#include "srslte/rf/rf_utils.h"
cell_search_cfg_t cell_detect_config = {
5000, // maximum number of frames to receive for MIB decoding
@ -53,23 +53,23 @@ typedef struct {
int nof_subframes;
bool disable_plots;
int force_N_id_2;
char *uhd_args;
float uhd_freq;
float uhd_gain;
char *rf_args;
float rf_freq;
float rf_gain;
}prog_args_t;
void args_default(prog_args_t *args) {
args->nof_subframes = -1;
args->force_N_id_2 = -1; // Pick the best
args->uhd_args = "";
args->uhd_freq = -1.0;
args->uhd_gain = 50;
args->rf_args = "";
args->rf_freq = -1.0;
args->rf_gain = 50;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [aglnv] -f rx_frequency (in Hz)\n", prog);
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD RX gain [Default %.2f dB]\n", args->uhd_gain);
printf("\t-a RF args [Default %s]\n", args->rf_args);
printf("\t-g RF RX gain [Default %.2f dB]\n", args->rf_gain);
printf("\t-l Force N_id_2 [Default best]\n");
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
printf("\t-v [set srslte_verbose to debug, default none]\n");
@ -81,13 +81,13 @@ int parse_args(prog_args_t *args, int argc, char **argv) {
while ((opt = getopt(argc, argv, "aglnvf")) != -1) {
switch (opt) {
case 'a':
args->uhd_args = argv[optind];
args->rf_args = argv[optind];
break;
case 'g':
args->uhd_gain = atof(argv[optind]);
args->rf_gain = atof(argv[optind]);
break;
case 'f':
args->uhd_freq = atof(argv[optind]);
args->rf_freq = atof(argv[optind]);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
@ -103,7 +103,7 @@ int parse_args(prog_args_t *args, int argc, char **argv) {
return -1;
}
}
if (args->uhd_freq < 0) {
if (args->rf_freq < 0) {
usage(args, argv[0]);
return -1;
}
@ -123,9 +123,9 @@ void sig_int_handler(int signo)
}
}
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *q) {
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *q) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
return srslte_rf_recv(h, data, nsamples, 1);
}
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
@ -141,7 +141,7 @@ int main(int argc, char **argv) {
int64_t sf_cnt;
srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib;
void *uhd;
srslte_rf_t rf;
srslte_ue_dl_t ue_dl;
srslte_ofdm_t fft;
srslte_chest_dl_t chest;
@ -158,20 +158,20 @@ int main(int argc, char **argv) {
exit(-1);
}
if (prog_args.uhd_gain > 0) {
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, prog_args.rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
if (prog_args.rf_gain > 0) {
srslte_rf_set_rx_gain(&rf, prog_args.rf_gain);
} else {
printf("Opening UHD device with threaded RX Gain control ...\n");
if (cuhd_open_th(prog_args.uhd_args, &uhd, false)) {
fprintf(stderr, "Error opening uhd\n");
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, 50);
srslte_rf_set_rx_gain(&rf, 50);
}
sigset_t sigset;
@ -180,16 +180,18 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
srslte_rf_set_rx_freq(&rf, (double) prog_args.rf_freq);
srslte_rf_rx_wait_lo_locked(&rf);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.rf_freq/1000000);
cell_detect_config.init_agc = (prog_args.rf_gain<0);
uint32_t ntrial=0;
do {
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
@ -206,13 +208,13 @@ int main(int argc, char **argv) {
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_uhd = cuhd_set_rx_srate(uhd, (double) srate);
if (srate_uhd != srate) {
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
@ -221,11 +223,11 @@ int main(int argc, char **argv) {
exit(-1);
}
INFO("Stopping UHD and flushing buffer...\n",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
INFO("Stopping RF and flushing buffer...\n",0);
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf);
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
return -1;
}
@ -261,7 +263,7 @@ int main(int argc, char **argv) {
ce[i] = srslte_vec_malloc(sizeof(cf_t) * sf_re);
}
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&rf);
float rx_gain_offset = 0;
@ -333,10 +335,10 @@ int main(int argc, char **argv) {
if ((nframes%100) == 0 || rx_gain_offset == 0) {
if (cuhd_has_rssi(uhd)) {
rx_gain_offset = 10*log10(rssi)-cuhd_get_rssi(uhd);
if (srslte_rf_has_rssi(&rf)) {
rx_gain_offset = 10*log10(rssi)-srslte_rf_get_rssi(&rf);
} else {
rx_gain_offset = cuhd_get_rx_gain(uhd);
rx_gain_offset = srslte_rf_get_rx_gain(&rf);
}
}
@ -373,7 +375,7 @@ int main(int argc, char **argv) {
} // Main loop
srslte_ue_sync_free(&ue_sync);
cuhd_close(uhd);
srslte_rf_close(&rf);
printf("\nBye\n");
exit(0);
}

@ -37,11 +37,11 @@
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd_utils.h"
#include "srslte/rf/rf_utils.h"
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
#ifndef DISABLE_RF
#include "srslte/rf/rf.h"
#endif
#define MHZ 1000000
@ -70,13 +70,13 @@ struct cells {
};
struct cells results[1024];
float uhd_gain = 70.0;
char *uhd_args="";
float rf_gain = 70.0;
char *rf_args="";
void usage(char *prog) {
printf("Usage: %s [agsendtvb] -b band\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD gain [Default %.2f dB]\n", uhd_gain);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-g RF gain [Default %.2f dB]\n", rf_gain);
printf("\t-s earfcn_start [Default All]\n");
printf("\t-e earfcn_end [Default All]\n");
printf("\t-n nof_frames_total [Default 100]\n");
@ -89,7 +89,7 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "agsendtvb")) != -1) {
switch(opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'b':
band = atoi(argv[optind]);
@ -107,7 +107,7 @@ void parse_args(int argc, char **argv) {
config.threshold = atof(argv[optind]);
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'v':
srslte_verbose++;
@ -123,9 +123,9 @@ void parse_args(int argc, char **argv) {
}
}
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
return srslte_rf_recv((srslte_rf_t*) h, data, nsamples, 1);
}
bool go_exit = false;
@ -138,9 +138,13 @@ void sig_int_handler(int signo)
}
}
double srslte_rf_set_rx_gain_wrapper(void *h, double f) {
return srslte_rf_set_rx_gain((srslte_rf_t*) h, f);
}
int main(int argc, char **argv) {
int n;
void *uhd;
srslte_rf_t rf;
srslte_ue_cellsearch_t cs;
srslte_ue_cellsearch_result_t found_cells[3];
int nof_freqs;
@ -150,26 +154,26 @@ int main(int argc, char **argv) {
parse_args(argc, argv);
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
if (!config.init_agc) {
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, uhd_gain);
srslte_rf_set_rx_gain(&rf, rf_gain);
} else {
printf("Opening UHD device with threaded RX Gain control ...\n");
if (cuhd_open_th(uhd_args, &uhd, false)) {
fprintf(stderr, "Error opening uhd\n");
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, 50);
srslte_rf_set_rx_gain(&rf, 50);
}
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
// Supress UHD messages
cuhd_suppress_stdout();
// Supress RF messages
srslte_rf_suppress_stdout(&rf);
nof_freqs = srslte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
if (nof_freqs < 0) {
@ -185,10 +189,10 @@ int main(int argc, char **argv) {
for (freq=0;freq<nof_freqs && !go_exit;freq++) {
/* set uhd_freq */
cuhd_set_rx_freq(uhd, (double) channels[freq].fd * MHZ);
cuhd_rx_wait_lo_locked(uhd);
INFO("Set uhd_freq to %.3f MHz\n", (double) channels[freq].fd * MHZ/1000000);
/* set rf_freq */
srslte_rf_set_rx_freq(&rf, (double) channels[freq].fd * MHZ);
srslte_rf_rx_wait_lo_locked(&rf);
INFO("Set rf_freq to %.3f MHz\n", (double) channels[freq].fd * MHZ/1000000);
printf("[%3d/%d]: EARFCN %d Freq. %.2f MHz looking for PSS.\n", freq, nof_freqs,
channels[freq].id, channels[freq].fd);fflush(stdout);
@ -199,7 +203,7 @@ int main(int argc, char **argv) {
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init(&cs, cuhd_recv_wrapper, uhd)) {
if (srslte_ue_cellsearch_init(&cs, srslte_rf_recv_wrapper, (void*) &rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
exit(-1);
}
@ -211,13 +215,13 @@ int main(int argc, char **argv) {
srslte_ue_cellsearch_set_threshold(&cs, config.threshold);
}
if (config.init_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, cuhd_set_rx_gain, config.init_agc);
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_wrapper, config.init_agc);
}
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
srslte_rf_set_rx_srate(&rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0);
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&rf);
n = srslte_ue_cellsearch_scan(&cs, found_cells, NULL);
if (n < 0) {
@ -229,7 +233,7 @@ int main(int argc, char **argv) {
srslte_cell_t cell;
cell.id = found_cells[i].cell_id;
cell.cp = found_cells[i].cp;
int ret = cuhd_mib_decoder(uhd, &config, &cell);
int ret = rf_mib_decoder(&rf, &config, &cell);
if (ret < 0) {
fprintf(stderr, "Error decoding MIB\n");
exit(-1);
@ -266,7 +270,7 @@ int main(int argc, char **argv) {
printf("\nBye\n");
cuhd_close(uhd);
srslte_rf_close(&rf);
exit(0);
}

@ -40,11 +40,11 @@
#define UE_CRNTI 0x1234
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
void *uhd;
#ifndef DISABLE_RF
#include "srslte/rf/rf.h"
srslte_rf_t rf;
#else
#warning Compiling pdsch_ue with no UHD support
#warning Compiling pdsch_ue with no RF support
#endif
char *output_file_name = NULL;
@ -64,14 +64,14 @@ srslte_cell_t cell = {
SRSLTE_PHICH_NORM // PHICH length
};
int net_port = -1; // -1 generates random data
int net_port = -1; // -1 generates random dataThat means there is some problem sending samples to the device
uint32_t cfi=2;
uint32_t mcs_idx = 1, last_mcs_idx = 1;
int nof_frames = -1;
char *uhd_args = "";
float uhd_amp = 0.8, uhd_gain = 70.0, uhd_freq = 2400000000;
char *rf_args = "";
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
bool null_file_sink=false;
srslte_filesink_t fsink;
@ -101,15 +101,15 @@ int prbset_orig = 0;
void usage(char *prog) {
printf("Usage: %s [agmfoncvpu]\n", prog);
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-l UHD amplitude [Default %.2f]\n", uhd_amp);
printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain);
printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq / 1000000);
#ifndef DISABLE_RF
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-l RF amplitude [Default %.2f]\n", rf_amp);
printf("\t-g RF TX gain [Default %.2f dB]\n", rf_gain);
printf("\t-f RF TX frequency [Default %.1f MHz]\n", rf_freq / 1000000);
#else
printf("\t UHD is disabled. CUHD library not available\n");
printf("\t RF is disabled.\n");
#endif
printf("\t-o output_file [Default USRP]\n");
printf("\t-o output_file [Default use RF board]\n");
printf("\t-m MCS index [Default %d]\n", mcs_idx);
printf("\t-n number of frames [Default %d]\n", nof_frames);
printf("\t-c cell id [Default %d]\n", cell.id);
@ -123,16 +123,16 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "aglfmoncpvu")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'l':
uhd_amp = atof(argv[optind]);
rf_amp = atof(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 'o':
output_file_name = argv[optind];
@ -160,7 +160,7 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
#ifdef DISABLE_UHD
#ifdef DISABLE_RF
if (!output_file_name) {
usage(argv[0]);
exit(-1);
@ -171,12 +171,12 @@ void parse_args(int argc, char **argv) {
void base_init() {
/* init memory */
sf_buffer = malloc(sizeof(cf_t) * sf_n_re);
sf_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_re);
if (!sf_buffer) {
perror("malloc");
exit(-1);
}
output_buffer = malloc(sizeof(cf_t) * sf_n_samples);
output_buffer = srslte_vec_malloc(sizeof(cf_t) * sf_n_samples);
if (!output_buffer) {
perror("malloc");
exit(-1);
@ -193,14 +193,14 @@ void base_init() {
null_file_sink = true;
}
} else {
#ifndef DISABLE_UHD
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
#ifndef DISABLE_RF
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
#else
printf("Error UHD not available. Select an output file\n");
printf("Error RF not available. Select an output file\n");
exit(-1);
#endif
}
@ -287,8 +287,8 @@ void base_free() {
srslte_filesink_free(&fsink);
}
} else {
#ifndef DISABLE_UHD
cuhd_close(&uhd);
#ifndef DISABLE_RF
srslte_rf_close(&rf);
#endif
}
@ -464,7 +464,7 @@ int main(int argc, char **argv) {
uint32_t sfn;
srslte_chest_dl_t est;
#ifdef DISABLE_UHD
#ifdef DISABLE_RF
if (argc < 3) {
usage(argv[0]);
exit(-1);
@ -502,7 +502,7 @@ int main(int argc, char **argv) {
slot1_symbols[i] = &sf_buffer[SRSLTE_SLOT_LEN_RE(cell.nof_prb, cell.cp)];
}
#ifndef DISABLE_UHD
#ifndef DISABLE_RF
sigset_t sigset;
@ -516,13 +516,13 @@ int main(int argc, char **argv) {
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_uhd = cuhd_set_tx_srate(uhd, (double) srate);
if (srate_uhd != srate) {
float srate_rf = srslte_rf_set_tx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
@ -530,9 +530,9 @@ int main(int argc, char **argv) {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
exit(-1);
}
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, rf_gain));
printf("Set TX freq: %.2f MHz\n",
cuhd_set_tx_freq(uhd, uhd_freq) / 1000000);
srslte_rf_set_tx_freq(&rf, rf_freq) / 1000000);
}
#endif
@ -556,8 +556,11 @@ int main(int argc, char **argv) {
nf = 0;
bool send_data = false;
bool start_of_burst = true;
srslte_softbuffer_tx_reset(&softbuffer);
#ifndef DISABLE_RF
bool start_of_burst = true;
#endif
while ((nf < nof_frames || nof_frames == -1) && !go_exit) {
for (sf_idx = 0; sf_idx < SRSLTE_NSUBFRAMES_X_FRAME && (nf < nof_frames || nof_frames == -1); sf_idx++) {
@ -642,11 +645,11 @@ int main(int argc, char **argv) {
}
usleep(1000);
} else {
#ifndef DISABLE_UHD
#ifndef DISABLE_RF
// FIXME
float norm_factor = (float) cell.nof_prb/15/sqrtf(pdsch_cfg.grant.nof_prb);
srslte_vec_sc_prod_cfc(output_buffer, uhd_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
cuhd_send2(uhd, output_buffer, sf_n_samples, true, start_of_burst, false);
srslte_vec_sc_prod_cfc(output_buffer, rf_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_rf_send2(&rf, output_buffer, sf_n_samples, true, start_of_burst, false);
start_of_burst=false;
#endif
}

@ -40,9 +40,9 @@
#include "srslte/srslte.h"
#ifndef DISABLE_UHD
#include "srslte/cuhd/cuhd.h"
#include "srslte/cuhd/cuhd_utils.h"
#ifndef DISABLE_RF
#include "srslte/rf/rf.h"
#include "srslte/rf/rf_utils.h"
cell_search_cfg_t cell_detect_config = {
5000,
@ -50,7 +50,7 @@ cell_search_cfg_t cell_detect_config = {
10.0 // threshold
};
#else
#warning Compiling pdsch_ue with no UHD support
#warning Compiling pdsch_ue with no RF support
#endif
//#define STDOUT_COMPACT
@ -84,9 +84,9 @@ typedef struct {
uint32_t file_nof_prb;
uint32_t file_nof_ports;
uint32_t file_cell_id;
char *uhd_args;
float uhd_freq;
float uhd_gain;
char *rf_args;
double rf_freq;
float rf_gain;
int net_port;
char *net_address;
int net_port_signal;
@ -107,9 +107,9 @@ void args_default(prog_args_t *args) {
args->file_cell_id = 0;
args->file_offset_time = 0;
args->file_offset_freq = 0;
args->uhd_args = "";
args->uhd_freq = -1.0;
args->uhd_gain = -1.0;
args->rf_args = "";
args->rf_freq = -1.0;
args->rf_gain = -1.0;
args->net_port = -1;
args->net_address = "127.0.0.1";
args->net_port_signal = -1;
@ -118,13 +118,13 @@ void args_default(prog_args_t *args) {
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agpPoOcildDnruv] -f rx_frequency (in Hz) | -i input_file\n", prog);
#ifndef DISABLE_UHD
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD fix RX gain [Default AGC]\n");
#ifndef DISABLE_RF
printf("\t-a RF args [Default %s]\n", args->rf_args);
printf("\t-g RF fix RX gain [Default AGC]\n");
#else
printf("\t UHD is disabled. CUHD library not available\n");
printf("\t RF is disabled.\n");
#endif
printf("\t-i input_file [Default USRP]\n");
printf("\t-i input_file [Default use RF board]\n");
printf("\t-o offset frequency correction (in Hz) for input file [Default %.1f Hz]\n", args->file_offset_freq);
printf("\t-O offset samples for input file [Default %d]\n", args->file_offset_time);
printf("\t-p nof_prb for input file [Default %d]\n", args->file_nof_prb);
@ -172,10 +172,10 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
args->file_cell_id = atoi(argv[optind]);
break;
case 'a':
args->uhd_args = argv[optind];
args->rf_args = argv[optind];
break;
case 'g':
args->uhd_gain = atof(argv[optind]);
args->rf_gain = atof(argv[optind]);
break;
case 'C':
args->disable_cfo = true;
@ -184,7 +184,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
args->time_offset = atoi(argv[optind]);
break;
case 'f':
args->uhd_freq = atof(argv[optind]);
args->rf_freq = strtod(argv[optind], NULL);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
@ -221,7 +221,7 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
exit(-1);
}
}
if (args->uhd_freq < 0 && args->input_file_name == NULL) {
if (args->rf_freq < 0 && args->input_file_name == NULL) {
usage(args, argv[0]);
exit(-1);
}
@ -240,11 +240,16 @@ void sig_int_handler(int signo)
}
}
#ifndef DISABLE_UHD
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
#ifndef DISABLE_RF
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
return srslte_rf_recv(h, data, nsamples, 1);
}
double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) {
return srslte_rf_set_rx_gain_th((srslte_rf_t*) h, f);
}
#endif
extern float mean_exec_time;
@ -264,8 +269,8 @@ int main(int argc, char **argv) {
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_mib_t ue_mib;
#ifndef DISABLE_UHD
void *uhd;
#ifndef DISABLE_RF
srslte_rf_t rf;
#endif
uint32_t nof_trials = 0;
int n;
@ -290,24 +295,24 @@ int main(int argc, char **argv) {
srslte_netsink_set_nonblocking(&net_sink_signal);
}
#ifndef DISABLE_UHD
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, prog_args.rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
/* Set receiver gain */
if (prog_args.uhd_gain > 0) {
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, prog_args.uhd_gain);
if (prog_args.rf_gain > 0) {
srslte_rf_set_rx_gain(&rf, prog_args.rf_gain);
} else {
printf("Opening UHD device with threaded RX Gain control ...\n");
if (cuhd_open_th(prog_args.uhd_args, &uhd, false)) {
fprintf(stderr, "Error opening uhd\n");
printf("Starting AGC thread...\n");
if (srslte_rf_start_gain_thread(&rf, false)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_rx_gain(uhd, 50);
srslte_rf_set_rx_gain(&rf, 50);
cell_detect_config.init_agc = 50;
}
@ -317,16 +322,16 @@ int main(int argc, char **argv) {
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
printf("Tunning receiver to %.3f MHz\n", prog_args.rf_freq/1000000);
srslte_rf_set_rx_freq(&rf, prog_args.rf_freq);
srslte_rf_rx_wait_lo_locked(&rf);
uint32_t ntrial=0;
do {
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
ret = rf_search_and_decode_mib(&rf, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
@ -342,13 +347,13 @@ int main(int argc, char **argv) {
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_uhd = cuhd_set_rx_srate(uhd, (double) srate);
if (srate_uhd != srate) {
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
@ -357,9 +362,9 @@ int main(int argc, char **argv) {
exit(-1);
}
INFO("Stopping UHD and flushing buffer...\r",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
INFO("Stopping RF and flushing buffer...\r",0);
srslte_rf_stop_rx_stream(&rf);
srslte_rf_flush_buffer(&rf);
}
#endif
@ -380,8 +385,8 @@ int main(int argc, char **argv) {
}
} else {
#ifndef DISABLE_UHD
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
#ifndef DISABLE_RF
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
@ -413,9 +418,9 @@ int main(int argc, char **argv) {
}
#endif
#ifndef DISABLE_UHD
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&rf);
}
#endif
@ -424,9 +429,9 @@ int main(int argc, char **argv) {
float rsrp=0.0, rsrq=0.0, noise=0.0;
bool decode_pdsch = false;
#ifndef DISABLE_UHD
if (prog_args.uhd_gain < 0) {
srslte_ue_sync_start_agc(&ue_sync, cuhd_set_rx_gain_th, cell_detect_config.init_agc);
#ifndef DISABLE_RF
if (prog_args.rf_gain < 0) {
srslte_ue_sync_start_agc(&ue_sync, srslte_rf_set_rx_gain_th_wrapper, cell_detect_config.init_agc);
}
#endif
#ifdef PRINT_CHANGE_SCHEDULIGN
@ -531,7 +536,7 @@ int main(int argc, char **argv) {
// Plot and Printf
if (srslte_ue_sync_get_sfidx(&ue_sync) == 5) {
float gain = prog_args.uhd_gain;
float gain = prog_args.rf_gain;
if (gain < 0) {
gain = 10*log10(srslte_agc_get_gain(&ue_sync.agc));
}
@ -540,7 +545,7 @@ int main(int argc, char **argv) {
"PDCCH-Miss: %5.2f%%, PDSCH-BLER: %5.2f%%\r",
srslte_ue_sync_get_cfo(&ue_sync)/1000,
10*log10(rsrp/noise),
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
100*(1-(float) ue_dl.nof_detected/nof_trials),
(float) 100*ue_dl.pkt_errors/ue_dl.pkts_total);
}
@ -589,10 +594,10 @@ int main(int argc, char **argv) {
srslte_ue_dl_free(&ue_dl);
srslte_ue_sync_free(&ue_sync);
#ifndef DISABLE_UHD
#ifndef DISABLE_RF
if (!prog_args.input_file_name) {
srslte_ue_mib_free(&ue_mib);
cuhd_close(uhd);
srslte_rf_close(&rf);
}
#endif
printf("\nBye\n");

@ -26,10 +26,10 @@
IF(SRSGUI_FOUND AND UHD_FOUND)
add_executable(pss pss.c)
target_link_libraries(pss srslte ${SRSGUI_LIBRARIES} srslte_uhd)
target_link_libraries(pss srslte ${SRSGUI_LIBRARIES} srslte_rf)
add_executable(simple_tx simple_tx.c)
target_link_libraries(simple_tx srslte srslte_uhd)
target_link_libraries(simple_tx srslte srslte_rf)
ENDIF(SRSGUI_FOUND AND UHD_FOUND)

@ -35,7 +35,7 @@
#include <stdbool.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
#ifndef DISABLE_GRAPHICS
@ -47,8 +47,8 @@ void do_plots_sss(float *corr_m0, float *corr_m1);
bool disable_plots = false;
int cell_id = -1;
char *uhd_args="";
float uhd_gain=40.0, uhd_freq=-1.0;
char *rf_args="";
float rf_gain=40.0, rf_freq=-1.0;
int nof_frames = -1;
uint32_t fft_size=128;
float threshold = 0.4;
@ -57,8 +57,8 @@ srslte_cp_t cp=SRSLTE_CP_NORM;
void usage(char *prog) {
printf("Usage: %s [aedgtvnp] -f rx_frequency_hz -i cell_id\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD Gain [Default %.2f dB]\n", uhd_gain);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-n nof_frames [Default %d]\n", nof_frames);
printf("\t-l N_id_2 to sync [Default use cell_id]\n");
printf("\t-e Extended CP [Default Normal]\n", fft_size);
@ -77,13 +77,13 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 't':
threshold = atof(argv[optind]);
@ -114,7 +114,7 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
if (cell_id < 0 || uhd_freq < 0) {
if (cell_id < 0 || rf_freq < 0) {
usage(argv[0]);
exit(-1);
}
@ -124,7 +124,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
cf_t *buffer;
int frame_cnt, n;
void *uhd;
srslte_rf_t rf;
srslte_pss_synch_t pss;
srslte_cfo_t cfocorr, cfocorr64;
srslte_sss_synch_t sss;
@ -176,17 +176,17 @@ int main(int argc, char **argv) {
srslte_sss_synch_set_N_id_2(&sss, N_id_2);
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
printf("N_id_2: %d\n", N_id_2);
printf("Set RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, flen*2*100) / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
cuhd_rx_wait_lo_locked(uhd);
cuhd_start_rx_stream(uhd);
printf("Set RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&rf, flen*2*100) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
srslte_rf_rx_wait_lo_locked(&rf);
srslte_rf_start_rx_stream(&rf);
printf("Frame length %d samples\n", flen);
printf("PSS detection threshold: %.2f\n", threshold);
@ -208,7 +208,7 @@ int main(int argc, char **argv) {
while(frame_cnt < nof_frames || nof_frames == -1) {
peak_offset = 0;
n = cuhd_recv(uhd, buffer, flen - peak_offset, 1);
n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
exit(-1);
@ -320,7 +320,7 @@ int main(int argc, char **argv) {
srslte_pss_synch_free(&pss);
free(buffer);
cuhd_close(uhd);
srslte_rf_close(&rf);
printf("Ok\n");
exit(0);

@ -35,8 +35,8 @@
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
void *uhd;
#include "srslte/rf/rf.h"
srslte_rf_t rf;
char *output_file_name = NULL;
@ -50,8 +50,8 @@ srslte_cell_t cell = {
};
char *uhd_args = "";
float uhd_amp = 0.5, uhd_gain = 30.0, uhd_freq = 2400000000;
char *rf_args = "";
float rf_amp = 0.5, rf_gain = 30.0, rf_freq = 2400000000;
bool null_file_sink=false;
srslte_filesink_t fsink;
@ -64,10 +64,10 @@ cf_t *sf_buffer = NULL, *output_buffer = NULL;
void usage(char *prog) {
printf("Usage: %s [algfmv]\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-l UHD amplitude [Default %.2f]\n", uhd_amp);
printf("\t-g UHD TX gain [Default %.2f dB]\n", uhd_gain);
printf("\t-f UHD TX frequency [Default %.1f MHz]\n", uhd_freq / 1000000);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-l RF amplitude [Default %.2f]\n", rf_amp);
printf("\t-g RF TX gain [Default %.2f dB]\n", rf_gain);
printf("\t-f RF TX frequency [Default %.1f MHz]\n", rf_freq / 1000000);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
@ -77,16 +77,16 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "algfmv")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'l':
uhd_amp = atof(argv[optind]);
rf_amp = atof(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 'm':
switch(atoi(argv[optind])) {
@ -116,7 +116,7 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
#ifdef DISABLE_UHD
#ifdef DISABLE_RF
if (!output_file_name) {
usage(argv[0]);
exit(-1);
@ -137,9 +137,9 @@ void base_init() {
perror("malloc");
exit(-1);
}
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
@ -161,7 +161,7 @@ void base_free() {
if (output_buffer) {
free(output_buffer);
}
cuhd_close(&uhd);
srslte_rf_close(&rf);
}
@ -172,7 +172,7 @@ int main(int argc, char **argv) {
float sss_signal5[SRSLTE_SSS_LEN]; // for subframe 5
int i;
#ifdef DISABLE_UHD
#ifdef DISABLE_RF
if (argc < 3) {
usage(argv[0]);
exit(-1);
@ -196,10 +196,10 @@ int main(int argc, char **argv) {
srslte_sss_generate(sss_signal0, sss_signal5, cell.id);
printf("Set TX rate: %.2f MHz\n",
cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(cell.nof_prb)) / 1000000);
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
srslte_rf_set_tx_srate(&rf, srslte_sampling_freq_hz(cell.nof_prb)) / 1000000);
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, rf_gain));
printf("Set TX freq: %.2f MHz\n",
cuhd_set_tx_freq(uhd, uhd_freq) / 1000000);
srslte_rf_set_tx_freq(&rf, rf_freq) / 1000000);
uint32_t nbits;
@ -234,7 +234,7 @@ int main(int argc, char **argv) {
srslte_ofdm_tx_sf(&ifft, sf_buffer, output_buffer);
float norm_factor = (float) sqrtf(cell.nof_prb)/15;
srslte_vec_sc_prod_cfc(output_buffer, uhd_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_vec_sc_prod_cfc(output_buffer, rf_amp*norm_factor, output_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
} else {
#endif
@ -248,8 +248,8 @@ int main(int argc, char **argv) {
// }
/* send to usrp */
srslte_vec_sc_prod_cfc(output_buffer, uhd_amp, output_buffer, sf_n_samples);
cuhd_send(uhd, output_buffer, sf_n_samples, true);
srslte_vec_sc_prod_cfc(output_buffer, rf_amp, output_buffer, sf_n_samples);
srslte_rf_send(&rf, output_buffer, sf_n_samples, true);
}
}

@ -36,13 +36,13 @@
#include <stdbool.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
#include "srslte/io/filesink.h"
static bool keep_running = true;
char *output_file_name;
char *uhd_args="";
float uhd_gain=40.0, uhd_freq=-1.0, uhd_rate=0.96e6;
char *rf_args="";
float rf_gain=40.0, rf_freq=-1.0, rf_rate=0.96e6;
int nof_samples = -1;
void int_handler(int dummy) {
@ -51,9 +51,9 @@ void int_handler(int dummy) {
void usage(char *prog) {
printf("Usage: %s [agrnv] -f rx_frequency_hz -o output_file\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD Gain [Default %.2f dB]\n", uhd_gain);
printf("\t-r UHD Rate [Default %.6f Hz]\n", uhd_rate);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-r RF Rate [Default %.6f Hz]\n", rf_rate);
printf("\t-n nof_samples [Default %d]\n", nof_samples);
printf("\t-v srslte_verbose\n");
}
@ -66,16 +66,16 @@ void parse_args(int argc, char **argv) {
output_file_name = argv[optind];
break;
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'r':
uhd_rate = atof(argv[optind]);
rf_rate = atof(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 'n':
nof_samples = atoi(argv[optind]);
@ -88,7 +88,7 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
if (uhd_freq < 0) {
if (rf_freq < 0) {
usage(argv[0]);
exit(-1);
}
@ -97,7 +97,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
cf_t *buffer;
int sample_count, n;
void *uhd;
srslte_rf_t rf;
srslte_filesink_t sink;
int32_t buflen;
@ -116,42 +116,42 @@ int main(int argc, char **argv) {
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Set RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
printf("Set RX gain: %.2f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
float srate = cuhd_set_rx_srate(uhd, uhd_rate);
if (srate != uhd_rate) {
printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
printf("Set RX gain: %.2f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
float srate = srslte_rf_set_rx_srate(&rf, rf_rate);
if (srate != rf_rate) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*uhd_rate);
srslte_rf_set_master_clock_rate(&rf, 4*rf_rate);
} else {
cuhd_set_master_clock_rate(uhd, uhd_rate);
srslte_rf_set_master_clock_rate(&rf, rf_rate);
}
srate = cuhd_set_rx_srate(uhd, uhd_rate);
if (srate != uhd_rate) {
fprintf(stderr, "Errror setting samplign frequency %.2f MHz\n", uhd_rate*1e-6);
srate = srslte_rf_set_rx_srate(&rf, rf_rate);
if (srate != rf_rate) {
fprintf(stderr, "Errror setting samplign frequency %.2f MHz\n", rf_rate*1e-6);
exit(-1);
}
}
printf("Correctly RX rate: %.2f MHz\n", srate*1e-6);
cuhd_rx_wait_lo_locked(uhd);
cuhd_start_rx_stream(uhd);
srslte_rf_rx_wait_lo_locked(&rf);
srslte_rf_start_rx_stream(&rf);
while((sample_count < nof_samples || nof_samples == -1)
&& keep_running){
n = cuhd_recv(uhd, buffer, buflen, 1);
n = srslte_rf_recv(&rf, buffer, buflen, 1);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
exit(-1);
@ -163,7 +163,7 @@ int main(int argc, char **argv) {
srslte_filesink_free(&sink);
free(buffer);
cuhd_close(uhd);
srslte_rf_close(&rf);
printf("Ok - wrote %d samples\n", sample_count);
exit(0);

@ -36,12 +36,12 @@
#include <stdbool.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
static bool keep_running = true;
char *output_file_name = NULL;
char *uhd_args="";
float uhd_gain=60.0, uhd_freq=-1.0;
char *rf_args="";
float rf_gain=60.0, rf_freq=-1.0;
int nof_prb = 6;
int nof_subframes = -1;
int N_id_2 = -1;
@ -52,8 +52,8 @@ void int_handler(int dummy) {
void usage(char *prog) {
printf("Usage: %s [agrnv] -l N_id_2 -f rx_frequency_hz -o output_file\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD Gain [Default %.2f dB]\n", uhd_gain);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-p nof_prb [Default %d]\n", nof_prb);
printf("\t-n nof_subframes [Default %d]\n", nof_subframes);
printf("\t-v verbose\n");
@ -67,16 +67,16 @@ void parse_args(int argc, char **argv) {
output_file_name = argv[optind];
break;
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'p':
nof_prb = atoi(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 'n':
nof_subframes = atoi(argv[optind]);
@ -92,21 +92,21 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
if (uhd_freq < 0 || N_id_2 == -1 || output_file_name == NULL) {
if (&rf_freq < 0 || N_id_2 == -1 || output_file_name == NULL) {
usage(argv[0]);
exit(-1);
}
}
int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
int srslte_rf_recv_wrapper(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
return srslte_rf_recv(h, data, nsamples, 1);
}
int main(int argc, char **argv) {
cf_t *buffer;
int n;
void *uhd;
srslte_rf_t rf;
srslte_filesink_t sink;
srslte_ue_sync_t ue_sync;
srslte_cell_t cell;
@ -117,30 +117,30 @@ int main(int argc, char **argv) {
srslte_filesink_init(&sink, output_file_name, SRSLTE_COMPLEX_FLOAT_BIN);
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
printf("Set RX freq: %.6f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set RX freq: %.6f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
int srate = srslte_sampling_freq_hz(nof_prb);
if (srate != -1) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_uhd = cuhd_set_rx_srate(uhd, (double) srate);
if (srate_uhd != srate) {
float srate_rf = srslte_rf_set_rx_srate(&rf, (double) srate);
if (srate_rf != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
@ -148,15 +148,15 @@ int main(int argc, char **argv) {
fprintf(stderr, "Invalid number of PRB %d\n", nof_prb);
exit(-1);
}
cuhd_rx_wait_lo_locked(uhd);
cuhd_start_rx_stream(uhd);
srslte_rf_rx_wait_lo_locked(&rf);
srslte_rf_start_rx_stream(&rf);
cell.cp = SRSLTE_CP_NORM;
cell.id = N_id_2;
cell.nof_prb = nof_prb;
cell.nof_ports = 1;
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper, uhd)) {
if (srslte_ue_sync_init(&ue_sync, cell, srslte_rf_recv_wrapper, (void*) &rf)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
@ -191,7 +191,7 @@ int main(int argc, char **argv) {
}
srslte_filesink_free(&sink);
cuhd_close(uhd);
srslte_rf_close(&rf);
srslte_ue_sync_free(&ue_sync);
printf("Ok - wrote %d subframes\n", subframe_count);

@ -33,35 +33,37 @@
#include <time.h>
#include <complex.h>
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
#include "srslte/srslte.h"
uint32_t nof_prb = 25;
uint32_t nof_frames = 20;
float tone_offset_hz = 0;
float uhd_rx_gain=40, uhd_tx_gain=40, uhd_freq=2.4e9;
char *uhd_args="";
int time_adv_samples = 0;
float tone_offset_hz = 1e6;
float rf_rx_gain=40, srslte_rf_tx_gain=40, rf_freq=2.4e9;
char *rf_args="";
char *output_filename = NULL;
char *input_filename = NULL;
void usage(char *prog) {
printf("Usage: %s -o [rx_signal_file]\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-f UHD TX/RX frequency [Default %.2f MHz]\n", uhd_freq/1e6);
printf("\t-g UHD RX gain [Default %.1f dB]\n", uhd_rx_gain);
printf("\t-G UHD TX gain [Default %.1f dB]\n", uhd_tx_gain);
printf("\t-t Single tone offset (Hz) [Default %f]\n", tone_offset_hz);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-f RF TX/RX frequency [Default %.2f MHz]\n", rf_freq/1e6);
printf("\t-g RF RX gain [Default %.1f dB]\n", rf_rx_gain);
printf("\t-G RF TX gain [Default %.1f dB]\n", srslte_rf_tx_gain);
printf("\t-t Single tone offset (Hz) [Default %f]\n", tone_offset_hz);
printf("\t-T Time advance samples [Default %d]\n", time_adv_samples);
printf("\t-i File name to read signal from [Default single tone]\n");
printf("\t-p Number of UL RB [Default %d]\n", nof_prb);
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "ioafgpt")) != -1) {
while ((opt = getopt(argc, argv, "ioafgGptT")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'o':
output_filename = argv[optind];
@ -72,14 +74,17 @@ void parse_args(int argc, char **argv) {
case 't':
tone_offset_hz = atof(argv[optind]);
break;
case 'T':
time_adv_samples = atoi(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 'g':
uhd_rx_gain = atof(argv[optind]);
rf_rx_gain = atof(argv[optind]);
break;
case 'G':
uhd_tx_gain = atof(argv[optind]);
srslte_rf_tx_gain = atof(argv[optind]);
break;
case 'p':
nof_prb = atoi(argv[optind]);
@ -97,91 +102,91 @@ void parse_args(int argc, char **argv) {
usage(argv[0]);
exit(-1);
}
if (time_adv_samples < 0) {
printf("Time advance must be positive\n");
usage(argv[0]);
exit(-1);
}
}
int main(int argc, char **argv) {
parse_args(argc, argv);
uint32_t flen = srslte_sampling_freq_hz(nof_prb)/1000;
uint32_t nsamples_adv = 3000;
cf_t *rx_buffer = malloc(sizeof(cf_t)*flen*nof_frames);
if (!rx_buffer) {
perror("malloc");
exit(-1);
}
cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+nsamples_adv));
cf_t *tx_buffer = malloc(sizeof(cf_t)*(flen+time_adv_samples));
if (!tx_buffer) {
perror("malloc");
exit(-1);
}
bzero(tx_buffer, sizeof(cf_t)*(flen+nsamples_adv));
bzero(tx_buffer, sizeof(cf_t)*(flen+time_adv_samples));
cf_t *zeros = calloc(sizeof(cf_t),flen);
if (!zeros) {
perror("calloc");
exit(-1);
}
float time_adv_sec = (float) time_adv_samples/srslte_sampling_freq_hz(nof_prb);
// Send through UHD
void *uhd;
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
// Send through RF
srslte_rf_t rf;
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
cuhd_set_master_clock_rate(uhd, 30.72e6);
srslte_rf_set_master_clock_rate(&rf, 30.72e6);
int srate = srslte_sampling_freq_hz(nof_prb);
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
cuhd_set_rx_srate(uhd, (double) srate);
cuhd_set_tx_srate(uhd, (double) srate);
srslte_rf_set_rx_srate(&rf, (double) srate);
srslte_rf_set_tx_srate(&rf, (double) srate);
printf("Subframe len: %d samples\n", flen);
printf("Time advance: %f us\n",time_adv_sec*1e6);
printf("Set TX/RX rate: %.2f MHz\n", (float) srate / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_rx_gain));
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_tx_gain));
printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_rx_gain));
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&rf, srslte_rf_tx_gain));
printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
srslte_rf_set_tx_freq(&rf, rf_freq);
cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);
sleep(1);
if (input_filename) {
srslte_vec_load_file(input_filename, &tx_buffer[nsamples_adv], flen*sizeof(cf_t));
srslte_vec_load_file(input_filename, &tx_buffer[time_adv_samples], flen*sizeof(cf_t));
} else {
for (int i=0;i<flen-nsamples_adv;i++) {
tx_buffer[i+nsamples_adv] = cexpf(_Complex_I*2*M_PI*tone_offset_hz*(float) i/(float) srate);
for (int i=0;i<flen-time_adv_samples;i++) {
tx_buffer[i+time_adv_samples] = 0.3*cexpf(_Complex_I*2*M_PI*tone_offset_hz*((float) i/(float) srate));
}
srslte_vec_save_file("uhd_txrx_tone", tx_buffer, flen*sizeof(cf_t));
srslte_vec_save_file("srslte_rf_txrx_tone", tx_buffer, flen*sizeof(cf_t));
}
srslte_timestamp_t tstamp;
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&rf);
uint32_t nframe=0;
float burst_settle_time = (float) nsamples_adv/srslte_sampling_freq_hz(nof_prb);
printf("timeadv=%f\n",burst_settle_time);
while(nframe<nof_frames) {
printf("Rx subframe %d\n", nframe);
cuhd_recv_with_time(uhd, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
srslte_rf_recv_with_time(&rf, &rx_buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
nframe++;
if (nframe==9 || nframe==8) {
srslte_timestamp_add(&tstamp, 0, 2e-3-burst_settle_time);
if (nframe==8) {
//cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
printf("Transmitting zeros\n");
} else {
cuhd_send_timed2(uhd, tx_buffer, flen+nsamples_adv, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting Signal\n");
}
if (nframe==9) {
srslte_timestamp_add(&tstamp, 0, 2e-3-time_adv_sec);
srslte_rf_send_timed2(&rf, tx_buffer, flen+time_adv_samples, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting Signal\n");
}
}

@ -1,167 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include "srslte/config.h"
typedef void (*cuhd_msg_handler_t)(const char*);
SRSLTE_API int cuhd_open(char *args,
void **handler);
SRSLTE_API int cuhd_open_th(char *args,
void **handler,
bool tx_gain_same_rx);
SRSLTE_API int cuhd_close(void *h);
SRSLTE_API int cuhd_start_rx_stream(void *h);
SRSLTE_API int cuhd_start_rx_stream_nsamples(void *h,
uint32_t nsamples);
SRSLTE_API int cuhd_stop_rx_stream(void *h);
SRSLTE_API void cuhd_flush_buffer(void *h);
SRSLTE_API bool cuhd_has_rssi(void *h);
SRSLTE_API float cuhd_get_rssi(void *h);
SRSLTE_API bool cuhd_rx_wait_lo_locked(void *h);
SRSLTE_API void cuhd_set_master_clock_rate(void *h,
double rate);
SRSLTE_API bool cuhd_is_master_clock_dynamic(void *h);
SRSLTE_API double cuhd_set_rx_srate(void *h,
double freq);
SRSLTE_API double cuhd_set_rx_gain(void *h,
double gain);
SRSLTE_API void cuhd_set_tx_rx_gain_offset(void *h,
double offset);
SRSLTE_API double cuhd_set_rx_gain_th(void *h,
double gain);
SRSLTE_API double cuhd_set_tx_gain_th(void *h,
double gain);
SRSLTE_API float cuhd_get_rx_gain_offset(void *h);
SRSLTE_API double cuhd_get_rx_gain(void *h);
SRSLTE_API double cuhd_get_tx_gain(void *h);
SRSLTE_API void cuhd_suppress_stdout();
SRSLTE_API void cuhd_register_msg_handler(cuhd_msg_handler_t h);
SRSLTE_API double cuhd_set_rx_freq(void *h,
double freq);
SRSLTE_API double cuhd_set_rx_freq_offset(void *h,
double freq,
double off);
SRSLTE_API double cuhd_set_rx_freq_offset(void *h,
double freq,
double off);
SRSLTE_API int cuhd_recv(void *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int cuhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
SRSLTE_API double cuhd_set_tx_srate(void *h,
double freq);
SRSLTE_API double cuhd_set_tx_gain(void *h,
double gain);
SRSLTE_API double cuhd_set_tx_freq(void *h,
double freq);
SRSLTE_API double cuhd_set_tx_freq_offset(void *h,
double freq,
double offset);
SRSLTE_API void cuhd_get_time(void *h,
time_t *secs,
double *frac_secs);
SRSLTE_API int cuhd_send(void *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int cuhd_send2(void *h,
void *data,
uint32_t nsamples,
bool blocking,
bool start_of_burst,
bool end_of_burst);
SRSLTE_API int cuhd_send(void *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int cuhd_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs);
SRSLTE_API int cuhd_send_timed2(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst);
#ifdef __cplusplus
}
#endif

@ -0,0 +1,188 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef RF_H
#define RF_H
#include <sys/time.h>
#include <stdbool.h>
#include <stdint.h>
#include <pthread.h>
#include "srslte/config.h"
typedef struct {
void *handler;
void *dev;
// The following variables are for threaded RX gain control
pthread_t thread_gain;
pthread_cond_t cond;
pthread_mutex_t mutex;
double cur_rx_gain;
double new_rx_gain;
bool tx_gain_same_rx;
float tx_rx_gain_offset;
} srslte_rf_t;
typedef struct {
float dc_gain;
float dc_phase;
float iq_i;
float iq_q;
} srslte_rf_cal_t;
typedef struct {
enum {
SRSLTE_RF_ERROR_LATE,
SRSLTE_RF_ERROR_UNDERFLOW,
SRSLTE_RF_ERROR_OVERFLOW,
SRSLTE_RF_ERROR_OTHER
} type;
int opt;
const char *msg;
} srslte_rf_error_t;
typedef void (*srslte_rf_error_handler_t)(srslte_rf_error_t error);
SRSLTE_API int srslte_rf_open(srslte_rf_t *h,
char *args);
SRSLTE_API int srslte_rf_open_devname(srslte_rf_t *h,
char *devname,
char *args);
SRSLTE_API const char *srslte_rf_name(srslte_rf_t *h);
SRSLTE_API int srslte_rf_start_gain_thread(srslte_rf_t *rf,
bool tx_gain_same_rx);
SRSLTE_API int srslte_rf_close(srslte_rf_t *h);
SRSLTE_API void srslte_rf_set_tx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal);
SRSLTE_API void srslte_rf_set_rx_cal(srslte_rf_t *h, srslte_rf_cal_t *cal);
SRSLTE_API int srslte_rf_start_rx_stream(srslte_rf_t *h);
SRSLTE_API int srslte_rf_stop_rx_stream(srslte_rf_t *h);
SRSLTE_API void srslte_rf_flush_buffer(srslte_rf_t *h);
SRSLTE_API bool srslte_rf_has_rssi(srslte_rf_t *h);
SRSLTE_API float srslte_rf_get_rssi(srslte_rf_t *h);
SRSLTE_API bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *h);
SRSLTE_API void srslte_rf_set_master_clock_rate(srslte_rf_t *h,
double rate);
SRSLTE_API bool srslte_rf_is_master_clock_dynamic(srslte_rf_t *h);
SRSLTE_API double srslte_rf_set_rx_srate(srslte_rf_t *h,
double freq);
SRSLTE_API double srslte_rf_set_rx_gain(srslte_rf_t *h,
double gain);
SRSLTE_API void srslte_rf_set_tx_rx_gain_offset(srslte_rf_t *h,
double offset);
SRSLTE_API double srslte_rf_set_rx_gain_th(srslte_rf_t *h,
double gain);
SRSLTE_API double srslte_rf_get_rx_gain(srslte_rf_t *h);
SRSLTE_API double srslte_rf_get_tx_gain(srslte_rf_t *h);
SRSLTE_API void srslte_rf_suppress_stdout(srslte_rf_t *h);
SRSLTE_API void srslte_rf_register_error_handler(srslte_rf_t *h,
srslte_rf_error_handler_t error_handler);
SRSLTE_API double srslte_rf_set_rx_freq(srslte_rf_t *h,
double freq);
SRSLTE_API int srslte_rf_recv(srslte_rf_t *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int srslte_rf_recv_with_time(srslte_rf_t *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
SRSLTE_API double srslte_rf_set_tx_srate(srslte_rf_t *h,
double freq);
SRSLTE_API double srslte_rf_set_tx_gain(srslte_rf_t *h,
double gain);
SRSLTE_API double srslte_rf_set_tx_freq(srslte_rf_t *h,
double freq);
SRSLTE_API void srslte_rf_get_time(srslte_rf_t *h,
time_t *secs,
double *frac_secs);
SRSLTE_API int srslte_rf_send(srslte_rf_t *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int srslte_rf_send2(srslte_rf_t *h,
void *data,
uint32_t nsamples,
bool blocking,
bool start_of_burst,
bool end_of_burst);
SRSLTE_API int srslte_rf_send(srslte_rf_t *h,
void *data,
uint32_t nsamples,
bool blocking);
SRSLTE_API int srslte_rf_send_timed(srslte_rf_t *h,
void *data,
int nsamples,
time_t secs,
double frac_secs);
SRSLTE_API int srslte_rf_send_timed2(srslte_rf_t *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst);
#endif

@ -26,6 +26,7 @@
#include "srslte/srslte.h"
#include "srslte/rf/rf.h"
typedef struct SRSLTE_API {
uint32_t max_frames_pbch; // maximum number of 5ms frames to capture for MIB decoding
@ -34,23 +35,23 @@ typedef struct SRSLTE_API {
float init_agc; // 0 or negative to disable AGC
} cell_search_cfg_t;
SRSLTE_API int cuhd_rssi_scan(void *uhd,
SRSLTE_API int rf_rssi_scan(srslte_rf_t *rf,
float *freqs,
float *rssi,
int nof_bands,
double fs,
int nsamp);
SRSLTE_API int cuhd_mib_decoder(void *uhd,
SRSLTE_API int rf_mib_decoder(srslte_rf_t *rf,
cell_search_cfg_t *config,
srslte_cell_t *cell);
SRSLTE_API int cuhd_cell_search(void *uhd,
SRSLTE_API int rf_cell_search(srslte_rf_t *rf,
cell_search_cfg_t *config,
int force_N_id_2,
srslte_cell_t *cell);
SRSLTE_API int cuhd_search_and_decode_mib(void *uhd,
SRSLTE_API int rf_search_and_decode_mib(srslte_rf_t *rf,
cell_search_cfg_t *config,
int force_N_id_2,
srslte_cell_t *cell);

@ -79,6 +79,7 @@ typedef struct SRSLTE_API {
float mean_cfo;
int cfo_i;
bool find_cfo_i;
bool find_cfo_i_initiated;
float cfo_ema_alpha;
uint32_t nof_symbols;
uint32_t cp_len;

@ -59,26 +59,53 @@ FILE(GLOB modules *)
SET(SOURCES_ALL "")
FOREACH (_module ${modules})
IF(IS_DIRECTORY ${_module})
IF (NOT ${_module} MATCHES "cuhd")
IF (NOT ${_module} MATCHES "rf")
FILE(GLOB_RECURSE tmp "${_module}/src/*.c")
LIST(APPEND SOURCES_ALL ${tmp})
FILE(GLOB_RECURSE tmp2 "${_module}/src/*.cpp")
LIST(APPEND SOURCES_ALL ${tmp2})
ENDIF (NOT ${_module} MATCHES "cuhd")
ENDIF (NOT ${_module} MATCHES "rf")
ENDIF(IS_DIRECTORY ${_module})
ENDFOREACH()
ADD_LIBRARY(srslte SHARED ${SOURCES_ALL})
TARGET_LINK_LIBRARIES(srslte m ${FFTW3F_LIBRARIES})
SET_TARGET_PROPERTIES(srslte
PROPERTIES VERSION ${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}
)
IF(UHD_FOUND)
INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
ADD_LIBRARY(srslte_uhd SHARED ${CMAKE_CURRENT_SOURCE_DIR}/cuhd/src/cuhd_imp.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cuhd/src/cuhd_utils.c)
TARGET_LINK_LIBRARIES(srslte_uhd ${UHD_LIBRARIES})
INSTALL(TARGETS srslte_uhd DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srslte_uhd)
ENDIF(UHD_FOUND)
IF(RF_FOUND)
# Include common RF files
SET(SOURCES_RF "")
LIST(APPEND SOURCES_RF "rf/src/rf_imp.c" "rf/src/rf_utils.c")
IF (UHD_FOUND)
INCLUDE_DIRECTORIES(${UHD_INCLUDE_DIRS})
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
add_definitions(-DENABLE_UHD)
LIST(APPEND SOURCES_RF "rf/src/rf_uhd_imp.c" "rf/src/uhd_c_api.cpp")
ENDIF (UHD_FOUND)
IF (BLADERF_FOUND)
INCLUDE_DIRECTORIES(${BLADERF_INCLUDE_DIRS})
add_definitions(-DENABLE_BLADERF)
LIST(APPEND SOURCES_RF "rf/src/rf_blade_imp.c")
ENDIF (BLADERF_FOUND)
ADD_LIBRARY(srslte_rf SHARED ${SOURCES_RF})
SET_TARGET_PROPERTIES(srslte_rf
PROPERTIES VERSION ${SRSLTE_VERSION_MAJOR}.${SRSLTE_VERSION_MINOR}
)
IF (UHD_FOUND)
TARGET_LINK_LIBRARIES(srslte_rf ${UHD_LIBRARIES})
ENDIF (UHD_FOUND)
IF (BLADERF_FOUND)
TARGET_LINK_LIBRARIES(srslte_rf ${BLADERF_LIBRARIES})
ENDIF (BLADERF_FOUND)
INSTALL(TARGETS srslte_rf DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srslte_rf)
ENDIF(RF_FOUND)
INSTALL(TARGETS srslte DESTINATION ${LIBRARY_DIR})
SRSLTE_SET_PIC(srslte)

@ -124,11 +124,11 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
if (!q->uhd_handler) {
srslte_vec_sc_prod_cfc(signal, q->gain, signal, len);
} else {
if (q->gain < 1) {
q->gain = 1.0;
if (gain_db < 0) {
gain_db = 0.0;
}
if (isinf(gain_db) || isnan(gain_db)) {
q->gain = 10.0;
gain_db = 10.0;
} else {
gain_uhd_db = q->set_gain_callback(q->uhd_handler, gain_db);
q->gain = pow(10, gain_uhd_db/10);

@ -1,55 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <uhd/usrp/multi_usrp.hpp>
#include <pthread.h>
class cuhd_handler {
public:
uhd::usrp::multi_usrp::sptr usrp;
uhd::rx_streamer::sptr rx_stream;
bool rx_stream_enable;
uhd::tx_streamer::sptr tx_stream;
// The following variables are for threaded RX gain control
pthread_t thread_gain;
pthread_cond_t cond;
pthread_mutex_t mutex;
double cur_rx_gain;
double new_rx_gain;
double cur_tx_gain;
double new_tx_gain;
bool tx_gain_same_rx;
float tx_rx_gain_offset;
uhd::gain_range_t rx_gain_range;
uhd::gain_range_t tx_gain_range;
size_t rx_nof_samples;
size_t tx_nof_samples;
double tx_rate;
bool dynamic_rate;
};

@ -1,521 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <uhd/utils/thread_priority.hpp>
#include <uhd/usrp/multi_usrp.hpp>
#include <iostream>
#include <complex>
#include <cstdio>
#include <uhd/utils/msg.hpp>
#include <sys/time.h>
#include "cuhd_handler.hpp"
#include "srslte/cuhd/cuhd.h"
#include "srslte/srslte.h"
//#define METADATA_VERBOSE
cuhd_msg_handler_t msg_handler;
void suppress_handler(uhd::msg::type_t type, const std::string & msg)
{
//handle the message...
}
void translate_handler(uhd::msg::type_t type, const std::string & msg)
{
if(msg_handler)
msg_handler(msg.c_str());
}
typedef _Complex float complex_t;
#define SAMPLE_SZ sizeof(complex_t)
bool isLocked(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
std::vector < std::string > mb_sensors =
handler->usrp->get_mboard_sensor_names();
std::vector < std::string > rx_sensors =
handler->usrp->get_rx_sensor_names(0);
if (std::find(rx_sensors.begin(), rx_sensors.end(), "lo_locked") !=
rx_sensors.end()) {
return handler->usrp->get_rx_sensor("lo_locked", 0).to_bool();
} else if (std::find(mb_sensors.begin(), mb_sensors.end(), "ref_locked") !=
mb_sensors.end()) {
return handler->usrp->get_mboard_sensor("ref_locked", 0).to_bool();
} else {
usleep(500);
return true;
}
}
bool cuhd_rx_wait_lo_locked(void *h)
{
double report = 0.0;
while (isLocked(h) && report < 30.0) {
report += 0.1;
usleep(1000);
}
return isLocked(h);
}
int cuhd_start_rx_stream(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
cmd.time_spec = handler->usrp->get_time_now();
cmd.stream_now = true;
handler->usrp->issue_stream_cmd(cmd);
return 0;
}
int cuhd_stop_rx_stream(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
cmd.time_spec = handler->usrp->get_time_now();
cmd.stream_now = true;
handler->usrp->issue_stream_cmd(cmd);
return 0;
}
void cuhd_flush_buffer(void *h)
{
int n;
_Complex float tmp[1024];
do {
n = cuhd_recv(h, tmp, 1024, 0);
} while (n > 0);
}
bool cuhd_has_rssi(void *h) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
std::vector < std::string > mb_sensors = handler->usrp->get_mboard_sensor_names();
std::vector < std::string > rx_sensors = handler->usrp->get_rx_sensor_names(0);
if (std::find(rx_sensors.begin(), rx_sensors.end(), "rssi") != rx_sensors.end()) {
return true;
} else {
return false;
}
}
float cuhd_get_rssi(void *h) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
if (cuhd_has_rssi(h)) {
uhd::sensor_value_t value = handler->usrp->get_rx_sensor("rssi");
return value.to_real();
} else {
return 0;
}
}
int cuhd_start_rx_stream_nsamples(void *h, uint32_t nsamples)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::stream_cmd_t cmd(uhd::stream_cmd_t::STREAM_MODE_NUM_SAMPS_AND_MORE);
cmd.time_spec = handler->usrp->get_time_now();
cmd.stream_now = true;
cmd.num_samps = nsamples;
handler->usrp->issue_stream_cmd(cmd);
return 0;
}
double cuhd_set_rx_gain_th(void *h, double gain)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
gain = handler->rx_gain_range.clip(gain);
if (gain > handler->new_rx_gain + 0.5 || gain < handler->new_rx_gain - 0.5) {
pthread_mutex_lock(&handler->mutex);
handler->new_rx_gain = gain;
pthread_cond_signal(&handler->cond);
pthread_mutex_unlock(&handler->mutex);
}
return gain;
}
double cuhd_set_tx_gain_th(void *h, double gain)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
gain = handler->tx_gain_range.clip(gain);
if (gain > handler->new_tx_gain + 0.5 || gain < handler->new_tx_gain - 0.5) {
pthread_mutex_lock(&handler->mutex);
handler->new_tx_gain = gain;
pthread_cond_signal(&handler->cond);
pthread_mutex_unlock(&handler->mutex);
}
return gain;
}
void cuhd_set_tx_rx_gain_offset(void *h, double offset) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->tx_rx_gain_offset = offset;
}
/* This thread listens for set_rx_gain commands to the USRP */
static void* thread_gain_fcn(void *h) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
while(1) {
pthread_mutex_lock(&handler->mutex);
while(handler->cur_rx_gain == handler->new_rx_gain &&
handler->cur_tx_gain == handler->new_tx_gain)
{
pthread_cond_wait(&handler->cond, &handler->mutex);
}
if (handler->new_rx_gain != handler->cur_rx_gain) {
handler->cur_rx_gain = handler->new_rx_gain;
cuhd_set_rx_gain(h, handler->cur_rx_gain);
}
if (handler->tx_gain_same_rx) {
cuhd_set_tx_gain(h, handler->cur_rx_gain+handler->tx_rx_gain_offset);
} else if (handler->new_tx_gain != handler->cur_tx_gain) {
handler->cur_tx_gain = handler->new_tx_gain;
cuhd_set_tx_gain(h, handler->cur_tx_gain);
}
pthread_mutex_unlock(&handler->mutex);
}
}
float cuhd_get_rx_gain_offset(void *h) {
return 15;
}
void cuhd_suppress_stdout() {
uhd::msg::register_handler(suppress_handler);
}
void cuhd_register_msg_handler(cuhd_msg_handler_t h)
{
msg_handler = h;
uhd::msg::register_handler(translate_handler);
}
int cuhd_open_(char *args, void **h, bool create_thread_gain, bool tx_gain_same_rx)
{
*h = NULL;
/* Set priority to UHD threads */
uhd::set_thread_priority_safe();
/* Get multiusrp handler */
cuhd_handler *handler = new cuhd_handler();
std::string _args = std::string(args);
handler->usrp = uhd::usrp::multi_usrp::make(_args);// + ", recv_frame_size=9232,num_recv_frames=64,send_frame_size=9232,num_send_frames=64");
/* Initialize rx and tx stremers */
std::string otw, cpu;
otw = "sc16";
cpu = "fc32";
uhd::stream_args_t stream_args(cpu, otw);
handler->rx_stream = handler->usrp->get_rx_stream(stream_args);
handler->tx_stream = handler->usrp->get_tx_stream(stream_args);
handler->rx_nof_samples = handler->rx_stream->get_max_num_samps();
handler->tx_nof_samples = handler->tx_stream->get_max_num_samps();
handler->tx_gain_same_rx = tx_gain_same_rx;
handler->tx_rx_gain_offset = 0.0;
handler->rx_gain_range = handler->usrp->get_rx_gain_range();
handler->tx_gain_range = handler->usrp->get_tx_gain_range();
/* Create auxiliary thread and mutexes for AGC */
if (create_thread_gain) {
if (pthread_mutex_init(&handler->mutex, NULL)) {
return -1;
}
if (pthread_cond_init(&handler->cond, NULL)) {
return -1;
}
if (pthread_create(&handler->thread_gain, NULL, thread_gain_fcn, handler)) {
perror("pthread_create");
return -1;
}
}
/* Find out if the master clock rate is configurable */
double cur_clock = handler->usrp->get_master_clock_rate();
printf("Trying to dynamically change Master clock...\n");
handler->usrp->set_master_clock_rate(cur_clock/2);
if (handler->usrp->get_master_clock_rate() == cur_clock) {
handler->dynamic_rate = false;
/* Master clock rate is not configurable. Check if it is compatible with LTE */
int cur_clock_i = (int) cur_clock;
if (cur_clock_i % 1920000) {
fprintf(stderr, "Error: LTE sampling rates are not supported. Master clock rate is %.1f MHz\n", cur_clock/1e6);
return -1;
} else {
printf("Master clock is not configurable. Using standard symbol sizes and sampling rates.\n");
srslte_use_standard_symbol_size(true);
}
} else {
printf("Master clock is configurable. Using reduced symbol sizes and sampling rates.\n");
handler->dynamic_rate = true;
}
*h = handler;
return 0;
}
int cuhd_open(char *args, void **h) {
return cuhd_open_(args, h, false, false);
}
int cuhd_open_th(char *args, void **h, bool tx_gain_same_rx) {
return cuhd_open_(args, h, true, tx_gain_same_rx);
}
int cuhd_close(void *h)
{
cuhd_stop_rx_stream(h);
/** Something else to close the USRP?? */
return 0;
}
void cuhd_set_master_clock_rate(void *h, double rate) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
if (handler->dynamic_rate) {
handler->usrp->set_master_clock_rate(rate);
}
}
bool cuhd_is_master_clock_dynamic(void *h) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
return handler->dynamic_rate;
}
double cuhd_set_rx_srate(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_rx_rate(freq);
return handler->usrp->get_rx_rate();
}
double cuhd_set_rx_gain(void *h, double gain)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_rx_gain(gain);
return handler->usrp->get_rx_gain();
}
double cuhd_get_rx_gain(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
return handler->usrp->get_rx_gain();
}
double cuhd_get_tx_gain(void *h)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
return handler->usrp->get_tx_gain();
}
double cuhd_set_rx_freq(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_rx_freq(freq);
return freq;
}
double cuhd_set_rx_freq_offset(void *h, double freq, double off) {
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
handler->usrp->set_rx_freq(uhd::tune_request_t(freq, off));
return handler->usrp->get_rx_freq();
}
int cuhd_recv(void *h, void *data, uint32_t nsamples, bool blocking)
{
return cuhd_recv_with_time(h, data, nsamples, blocking, NULL, NULL);
}
int cuhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::rx_metadata_t md, md_first;
if (blocking) {
int n = 0, p;
complex_t *data_c = (complex_t *) data;
do {
size_t rx_samples = handler->rx_nof_samples;
if (rx_samples > nsamples - n) {
rx_samples = nsamples - n;
}
p = handler->rx_stream->recv(&data_c[n], rx_samples, n==0?md_first:md);
if (p == -1) {
return -1;
}
n += p;
#ifdef METADATA_VERBOSE
if (md.error_code != uhd::rx_metadata_t::ERROR_CODE_NONE) {
std::cout << "\nError code: " << md.to_pp_string() << "\n\n";
}
#endif
} while (n < nsamples &&
md.error_code == uhd::rx_metadata_t::ERROR_CODE_NONE);
} else {
return handler->rx_stream->recv(data, nsamples, md, 0.0);
}
if (secs) {
*secs = md_first.time_spec.get_full_secs();
}
if (frac_secs) {
*frac_secs = md_first.time_spec.get_frac_secs();
}
return nsamples;
}
double cuhd_set_tx_gain(void *h, double gain)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_tx_gain(gain);
return gain;
}
double cuhd_set_tx_srate(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_tx_rate(freq);
handler->tx_rate = handler->usrp->get_tx_rate();
return handler->tx_rate;
}
double cuhd_set_tx_freq(void *h, double freq)
{
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
handler->usrp->set_tx_freq(freq);
return handler->usrp->get_tx_freq();
}
double cuhd_set_tx_freq_offset(void *h, double freq, double off) {
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
handler->usrp->set_tx_freq(uhd::tune_request_t(freq, off));
return handler->usrp->get_tx_freq();
}
void cuhd_get_time(void *h, time_t *secs, double *frac_secs) {
cuhd_handler *handler = static_cast < cuhd_handler * >(h);
uhd::time_spec_t now = handler->usrp->get_time_now();
if (secs) {
*secs = now.get_full_secs();
}
if (frac_secs) {
*frac_secs = now.get_frac_secs();
}
}
int cuhd_send_timed3(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst)
{
cuhd_handler* handler = static_cast<cuhd_handler*>(h);
uhd::tx_metadata_t md;
md.has_time_spec = has_time_spec;
if (has_time_spec) {
md.time_spec = uhd::time_spec_t(secs, frac_secs);
}
if (blocking) {
int n = 0, p;
complex_t *data_c = (complex_t *) data;
do {
size_t tx_samples = handler->tx_nof_samples;
// First packet is start of burst if so defined, others are never
if (n == 0) {
md.start_of_burst = is_start_of_burst;
} else {
md.start_of_burst = false;
}
// middle packets are never end of burst, last one as defined
if (nsamples - n > tx_samples) {
md.end_of_burst = false;
} else {
tx_samples = nsamples - n;
md.end_of_burst = is_end_of_burst;
}
p = handler->tx_stream->send(&data_c[n], tx_samples, md);
if (p == -1) {
return -1;
}
// Increase time spec
md.time_spec += tx_samples/handler->tx_rate;
n += p;
} while (n < nsamples);
return nsamples;
} else {
return handler->tx_stream->send(data, nsamples, md, 0.0);
}
}
int cuhd_send(void *h, void *data, uint32_t nsamples, bool blocking)
{
return cuhd_send2(h, data, nsamples, blocking, true, true);
}
int cuhd_send2(void *h, void *data, uint32_t nsamples, bool blocking, bool start_of_burst, bool end_of_burst)
{
return cuhd_send_timed3(h, data, nsamples, 0, 0, false, blocking, start_of_burst, end_of_burst);
}
int cuhd_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs)
{
return cuhd_send_timed2(h, data, nsamples, secs, frac_secs, true, true);
}
int cuhd_send_timed2(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst)
{
return cuhd_send_timed3(h, data, nsamples, secs, frac_secs, true, true, is_start_of_burst, is_end_of_burst);
}

@ -195,5 +195,5 @@ BuildMex(MEXNAME prach SOURCES prach_test_mex.c LIBRARIES srslte srslte_mex)
IF(UHD_FOUND)
ADD_EXECUTABLE(prach_test_usrp prach_test_usrp.c)
TARGET_LINK_LIBRARIES(prach_test_usrp srslte_uhd srslte)
TARGET_LINK_LIBRARIES(prach_test_usrp srslte_rf srslte)
ENDIF(UHD_FOUND)

@ -33,7 +33,7 @@
#include <time.h>
#include <complex.h>
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
#include "srslte/srslte.h"
#define MAX_LEN 70176
@ -140,19 +140,18 @@ int main(int argc, char **argv) {
cf_t *buffer = malloc(sizeof(cf_t)*flen*nof_frames);
// Send through UHD
void *uhd;
srslte_rf_t uhd;
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
if (srslte_rf_open(&uhd, uhd_args)) {
fprintf(stderr, "Error opening &uhd\n");
exit(-1);
}
printf("Subframe len: %d samples\n", flen);
printf("Set TX/RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set TX gain: %.1f dB\n", cuhd_set_tx_gain(uhd, uhd_gain));
printf("Set TX/RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
cuhd_set_tx_srate(uhd, srslte_sampling_freq_hz(nof_prb));
cuhd_set_tx_freq_offset(uhd, uhd_freq, 8e6);
printf("Set TX/RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&uhd, srslte_sampling_freq_hz(nof_prb)) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&uhd, uhd_gain));
printf("Set TX gain: %.1f dB\n", srslte_rf_set_tx_gain(&uhd, uhd_gain));
printf("Set TX/RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&uhd, uhd_freq) / 1000000);
srslte_rf_set_tx_srate(&uhd, srslte_sampling_freq_hz(nof_prb));
sleep(1);
cf_t *zeros = calloc(sizeof(cf_t),flen);
@ -164,20 +163,20 @@ int main(int argc, char **argv) {
srslte_timestamp_t tstamp;
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&uhd);
uint32_t nframe=0;
while(nframe<nof_frames) {
printf("Rx subframe %d\n", nframe);
cuhd_recv_with_time(uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
srslte_rf_recv_with_time(&uhd, &buffer[flen*nframe], flen, true, &tstamp.full_secs, &tstamp.frac_secs);
nframe++;
if (nframe==9 || nframe==8) {
srslte_timestamp_add(&tstamp, 0, 2e-3);
if (nframe==8) {
cuhd_send_timed2(uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
srslte_rf_send_timed2(&uhd, zeros, flen, tstamp.full_secs, tstamp.frac_secs, true, false);
printf("Transmitting zeros\n");
} else {
cuhd_send_timed2(uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);
srslte_rf_send_timed2(&uhd, preamble, flen, tstamp.full_secs, tstamp.frac_secs, true, true);
printf("Transmitting PRACH\n");
}
}

@ -0,0 +1,497 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <libbladeRF.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "srslte/srslte.h"
#include "rf_blade_imp.h"
#include "srslte/rf/rf.h"
#define CONVERT_BUFFER_SIZE 240*1024
typedef struct {
struct bladerf *dev;
uint32_t rx_rate;
uint32_t tx_rate;
int16_t rx_buffer[CONVERT_BUFFER_SIZE];
int16_t tx_buffer[CONVERT_BUFFER_SIZE];
bool rx_stream_enabled;
bool tx_stream_enabled;
} rf_blade_handler_t;
srslte_rf_error_handler_t blade_error_handler = NULL;
void rf_blade_suppress_stdout(void *h) {
bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_SILENT);
}
void rf_blade_register_error_handler(void *notused, srslte_rf_error_handler_t new_handler)
{
new_handler = blade_error_handler;
}
bool rf_blade_rx_wait_lo_locked(void *h)
{
usleep(1000);
return true;
}
const unsigned int num_buffers = 256;
const unsigned int ms_buffer_size_rx = 1024;
const unsigned int buffer_size_tx = 1024;
const unsigned int num_transfers = 32;
const unsigned int timeout_ms = 4000;
int rf_blade_start_tx_stream(void *h)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_sync_config(handler->dev,
BLADERF_MODULE_TX,
BLADERF_FORMAT_SC16_Q11_META,
num_buffers,
buffer_size_tx,
num_transfers,
timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true);
if (status != 0) {
fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status));
return status;
}
handler->tx_stream_enabled = true;
return 0;
}
int rf_blade_start_rx_stream(void *h)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
/* Configure the device's RX module for use with the sync interface.
* SC16 Q11 samples *with* metadata are used. */
uint32_t buffer_size_rx = ms_buffer_size_rx*(handler->rx_rate/1000/1024);
status = bladerf_sync_config(handler->dev,
BLADERF_MODULE_RX,
BLADERF_FORMAT_SC16_Q11_META,
num_buffers,
buffer_size_rx,
num_transfers,
timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to configure RX sync interface: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_sync_config(handler->dev,
BLADERF_MODULE_TX,
BLADERF_FORMAT_SC16_Q11_META,
num_buffers,
buffer_size_tx,
num_transfers,
timeout_ms);
if (status != 0) {
fprintf(stderr, "Failed to configure TX sync interface: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, true);
if (status != 0) {
fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, true);
if (status != 0) {
fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status));
return status;
}
handler->rx_stream_enabled = true;
return 0;
}
int rf_blade_stop_rx_stream(void *h)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_enable_module(handler->dev, BLADERF_MODULE_RX, false);
if (status != 0) {
fprintf(stderr, "Failed to enable RX module: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_enable_module(handler->dev, BLADERF_MODULE_TX, false);
if (status != 0) {
fprintf(stderr, "Failed to enable TX module: %s\n", bladerf_strerror(status));
return status;
}
handler->rx_stream_enabled = false;
handler->tx_stream_enabled = false;
return 0;
}
void rf_blade_flush_buffer(void *h)
{
}
bool rf_blade_has_rssi(void *h)
{
return false;
}
float rf_blade_get_rssi(void *h)
{
return 0;
}
int rf_blade_open(char *args, void **h)
{
*h = NULL;
rf_blade_handler_t *handler = (rf_blade_handler_t*) malloc(sizeof(rf_blade_handler_t));
if (!handler) {
perror("malloc");
return -1;
}
*h = handler;
printf("Opening bladeRF...\n");
int status = bladerf_open(&handler->dev, args);
if (status) {
fprintf(stderr, "Unable to open device: %s\n", bladerf_strerror(status));
return status;
}
//bladerf_log_set_verbosity(BLADERF_LOG_LEVEL_VERBOSE);
/* Configure the gains of the RX LNA and RX VGA1*/
status = bladerf_set_lna_gain(handler->dev, BLADERF_LNA_GAIN_MAX);
if (status != 0) {
fprintf(stderr, "Failed to set RX LNA gain: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_set_rxvga1(handler->dev, 27);
if (status != 0) {
fprintf(stderr, "Failed to set RX VGA1 gain: %s\n", bladerf_strerror(status));
return status;
}
status = bladerf_set_txvga1(handler->dev, BLADERF_TXVGA1_GAIN_MAX);
if (status != 0) {
fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(status));
return status;
}
handler->rx_stream_enabled = false;
handler->tx_stream_enabled = false;
return 0;
}
int rf_blade_close(void *h)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
bladerf_close(handler->dev);
return 0;
}
void rf_blade_set_master_clock_rate(void *h, double rate)
{
}
bool rf_blade_is_master_clock_dynamic(void *h)
{
return true;
}
double rf_blade_set_rx_srate(void *h, double freq)
{
uint32_t bw;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_RX, (uint32_t) freq, &handler->rx_rate);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1;
}
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_RX, handler->rx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->rx_rate, bladerf_strerror(status));
return -1;
}
printf("Set RX sampling rate %.2f Mhz, filter BW: %.2f Mhz\n", (float) handler->rx_rate/1e6, (float) bw/1e6);
return (double) handler->rx_rate;
}
double rf_blade_set_tx_srate(void *h, double freq)
{
uint32_t bw;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
int status = bladerf_set_sample_rate(handler->dev, BLADERF_MODULE_TX, (uint32_t) freq, &handler->tx_rate);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n", (uint32_t) freq, bladerf_strerror(status));
return -1;
}
status = bladerf_set_bandwidth(handler->dev, BLADERF_MODULE_TX, handler->tx_rate, &bw);
if (status != 0) {
fprintf(stderr, "Failed to set bandwidth = %u: %s\n", handler->tx_rate, bladerf_strerror(status));
return -1;
}
return (double) handler->tx_rate;
}
double rf_blade_set_rx_gain(void *h, double gain)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_set_rxvga2(handler->dev, (int) gain);
if (status != 0) {
fprintf(stderr, "Failed to set RX VGA2 gain: %s\n", bladerf_strerror(status));
return -1;
}
return rf_blade_get_rx_gain(h);
}
double rf_blade_set_tx_gain(void *h, double gain)
{
int status;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_set_txvga2(handler->dev, (int) gain);
if (status != 0) {
fprintf(stderr, "Failed to set TX VGA2 gain: %s\n", bladerf_strerror(status));
return -1;
}
return rf_blade_get_tx_gain(h);
}
double rf_blade_get_rx_gain(void *h)
{
int status;
int gain;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_get_rxvga2(handler->dev, &gain);
if (status != 0) {
fprintf(stderr, "Failed to get RX VGA2 gain: %s\n",
bladerf_strerror(status));
return -1;
}
return gain; // Add rxvga1 and LNA
}
double rf_blade_get_tx_gain(void *h)
{
int status;
int gain;
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
status = bladerf_get_txvga2(handler->dev, &gain);
if (status != 0) {
fprintf(stderr, "Failed to get TX VGA2 gain: %s\n",
bladerf_strerror(status));
return -1;
}
return gain; // Add txvga1
}
double rf_blade_set_rx_freq(void *h, double freq)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
uint32_t f_int = (uint32_t) round(freq);
int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_RX, f_int);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n",
(uint32_t) freq, bladerf_strerror(status));
return -1;
}
return freq;
}
double rf_blade_set_tx_freq(void *h, double freq)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
uint32_t f_int = (uint32_t) round(freq);
int status = bladerf_set_frequency(handler->dev, BLADERF_MODULE_TX, f_int);
if (status != 0) {
fprintf(stderr, "Failed to set samplerate = %u: %s\n",
(uint32_t) freq, bladerf_strerror(status));
return -1;
}
return freq;
}
void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal) {
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_PHASE, cal->dc_gain);
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_FPGA_GAIN, cal->dc_phase);
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i);
bladerf_set_correction(handler->dev, BLADERF_MODULE_TX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q);
}
void rf_blade_set_rx_cal(void *h, srslte_rf_cal_t *cal) {
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_PHASE, cal->dc_gain);
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_FPGA_GAIN, cal->dc_phase);
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_I, cal->iq_i);
bladerf_set_correction(handler->dev, BLADERF_MODULE_RX, BLADERF_CORR_LMS_DCOFF_Q, cal->iq_q);
}
static void timestamp_to_secs(uint32_t rate, uint64_t timestamp, time_t *secs, double *frac_secs) {
double totalsecs = (double) timestamp/rate;
time_t secs_i = (time_t) totalsecs;
if (secs) {
*secs = secs_i;
}
if (frac_secs) {
*frac_secs = totalsecs-secs_i;
}
}
static void secs_to_timestamps(uint32_t rate, time_t secs, double frac_secs, uint64_t *timestamp) {
double totalsecs = (double) secs + frac_secs;
if (timestamp) {
*timestamp = rate * totalsecs;
}
}
void rf_blade_get_time(void *h, time_t *secs, double *frac_secs)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
int status = bladerf_get_timestamp(handler->dev, BLADERF_MODULE_RX, &meta.timestamp);
if (status != 0) {
fprintf(stderr, "Failed to get current RX timestamp: %s\n",
bladerf_strerror(status));
}
timestamp_to_secs(handler->rx_rate, meta.timestamp, secs, frac_secs);
}
int rf_blade_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
int status;
memset(&meta, 0, sizeof(meta));
meta.flags = BLADERF_META_FLAG_RX_NOW;
if (2*nsamples > CONVERT_BUFFER_SIZE) {
fprintf(stderr, "RX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
return -1;
}
status = bladerf_sync_rx(handler->dev, handler->rx_buffer, nsamples, &meta, 2000);
if (status) {
fprintf(stderr, "RX failed: %s\n\n", bladerf_strerror(status));
return -1;
} else if (meta.status & BLADERF_META_STATUS_OVERRUN) {
if (blade_error_handler) {
srslte_rf_error_t error;
error.opt = meta.actual_count;
error.type = SRSLTE_RF_ERROR_OVERFLOW;
blade_error_handler(error);
} else {
fprintf(stderr, "Overrun detected in scheduled RX. "
"%u valid samples were read.\n\n", meta.actual_count);
}
}
timestamp_to_secs(handler->rx_rate, meta.timestamp, secs, frac_secs);
srslte_vec_convert_if(handler->rx_buffer, data, 2048, 2*nsamples);
return nsamples;
}
int rf_blade_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst)
{
rf_blade_handler_t *handler = (rf_blade_handler_t*) h;
struct bladerf_metadata meta;
int status;
if (!handler->tx_stream_enabled) {
rf_blade_start_tx_stream(h);
}
if (2*nsamples > CONVERT_BUFFER_SIZE) {
fprintf(stderr, "TX failed: nsamples exceeds buffer size (%d>%d)\n", nsamples, CONVERT_BUFFER_SIZE);
return -1;
}
srslte_vec_convert_fi(data, handler->tx_buffer, 2048, 2*nsamples);
memset(&meta, 0, sizeof(meta));
if (is_start_of_burst) {
if (has_time_spec) {
secs_to_timestamps(handler->tx_rate, secs, frac_secs, &meta.timestamp);
} else {
meta.flags |= BLADERF_META_FLAG_TX_NOW;
}
meta.flags |= BLADERF_META_FLAG_TX_BURST_START;
}
if (is_end_of_burst) {
meta.flags |= BLADERF_META_FLAG_TX_BURST_END;
}
status = bladerf_sync_tx(handler->dev, handler->tx_buffer, nsamples, &meta, 2000);
if (status == BLADERF_ERR_TIME_PAST) {
if (blade_error_handler) {
srslte_rf_error_t error;
error.type = SRSLTE_RF_ERROR_LATE;
blade_error_handler(error);
} else {
fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
}
} else if (status) {
fprintf(stderr, "TX failed: %s\n", bladerf_strerror(status));
return status;
} else if (meta.status == BLADERF_META_STATUS_UNDERRUN) {
if (blade_error_handler) {
srslte_rf_error_t error;
error.type = SRSLTE_RF_ERROR_UNDERFLOW;
blade_error_handler(error);
} else {
fprintf(stderr, "TX warning: underflow detected.\n");
}
}
return nsamples;
}

@ -0,0 +1,110 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "srslte/config.h"
#include "srslte/rf/rf.h"
SRSLTE_API int rf_blade_open(char *args,
void **handler);
SRSLTE_API int rf_blade_close(void *h);
SRSLTE_API void rf_blade_set_tx_cal(void *h, srslte_rf_cal_t *cal);
SRSLTE_API void rf_blade_set_rx_cal(void *h, srslte_rf_cal_t *cal);
SRSLTE_API int rf_blade_start_rx_stream(void *h);
SRSLTE_API int rf_blade_start_rx_stream_nsamples(void *h,
uint32_t nsamples);
SRSLTE_API int rf_blade_stop_rx_stream(void *h);
SRSLTE_API void rf_blade_flush_buffer(void *h);
SRSLTE_API bool rf_blade_has_rssi(void *h);
SRSLTE_API float rf_blade_get_rssi(void *h);
SRSLTE_API bool rf_blade_rx_wait_lo_locked(void *h);
SRSLTE_API void rf_blade_set_master_clock_rate(void *h,
double rate);
SRSLTE_API bool rf_blade_is_master_clock_dynamic(void *h);
SRSLTE_API double rf_blade_set_rx_srate(void *h,
double freq);
SRSLTE_API double rf_blade_set_rx_gain(void *h,
double gain);
SRSLTE_API float rf_blade_get_rx_gain_offset(void *h);
SRSLTE_API double rf_blade_get_rx_gain(void *h);
SRSLTE_API double rf_blade_get_tx_gain(void *h);
SRSLTE_API void rf_blade_suppress_stdout(void *h);
SRSLTE_API void rf_blade_register_error_handler(void *h,
srslte_rf_error_handler_t error_handler);
SRSLTE_API double rf_blade_set_rx_freq(void *h,
double freq);
SRSLTE_API int rf_blade_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
SRSLTE_API double rf_blade_set_tx_srate(void *h,
double freq);
SRSLTE_API double rf_blade_set_tx_gain(void *h,
double gain);
SRSLTE_API double rf_blade_set_tx_freq(void *h,
double freq);
SRSLTE_API void rf_blade_get_time(void *h,
time_t *secs,
double *frac_secs);
SRSLTE_API int rf_blade_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);

@ -0,0 +1,141 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/* RF frontend API */
typedef struct {
const char *name;
bool (*srslte_rf_rx_wait_lo_locked) (void*);
int (*srslte_rf_start_rx_stream)(void *h);
int (*srslte_rf_stop_rx_stream)(void *h);
void (*srslte_rf_flush_buffer)(void *h);
bool (*srslte_rf_has_rssi)(void *h);
float (*srslte_rf_get_rssi)(void *h);
void (*srslte_rf_suppress_stdout)(void *h);
void (*srslte_rf_register_error_handler)(void *h, srslte_rf_error_handler_t error_handler);
int (*srslte_rf_open)(char *args, void **h);
int (*srslte_rf_close)(void *h);
void (*srslte_rf_set_master_clock_rate)(void *h, double rate);
bool (*srslte_rf_is_master_clock_dynamic)(void *h);
double (*srslte_rf_set_rx_srate)(void *h, double freq);
double (*srslte_rf_set_rx_gain)(void *h, double gain);
double (*srslte_rf_set_tx_gain)(void *h, double gain);
double (*srslte_rf_get_rx_gain)(void *h);
double (*srslte_rf_get_tx_gain)(void *h);
double (*srslte_rf_set_rx_freq)(void *h, double freq);
double (*srslte_rf_set_tx_srate)(void *h, double freq);
double (*srslte_rf_set_tx_freq)(void *h, double freq);
void (*srslte_rf_get_time)(void *h, time_t *secs, double *frac_secs);
int (*srslte_rf_recv_with_time)(void *h, void *data, uint32_t nsamples,
bool blocking, time_t *secs,double *frac_secs);
int (*srslte_rf_send_timed)(void *h, void *data, int nsamples,
time_t secs, double frac_secs, bool has_time_spec,
bool blocking, bool is_start_of_burst, bool is_end_of_burst);
void (*srslte_rf_set_tx_cal)(void *h, srslte_rf_cal_t *cal);
void (*srslte_rf_set_rx_cal)(void *h, srslte_rf_cal_t *cal);
} rf_dev_t;
/* Define implementation for UHD */
#ifdef ENABLE_UHD
#include "rf_uhd_imp.h"
static rf_dev_t dev_uhd = {
"UHD",
rf_uhd_rx_wait_lo_locked,
rf_uhd_start_rx_stream,
rf_uhd_stop_rx_stream,
rf_uhd_flush_buffer,
rf_uhd_has_rssi,
rf_uhd_get_rssi,
rf_uhd_suppress_stdout,
rf_uhd_register_error_handler,
rf_uhd_open,
rf_uhd_close,
rf_uhd_set_master_clock_rate,
rf_uhd_is_master_clock_dynamic,
rf_uhd_set_rx_srate,
rf_uhd_set_rx_gain,
rf_uhd_set_tx_gain,
rf_uhd_get_rx_gain,
rf_uhd_get_tx_gain,
rf_uhd_set_rx_freq,
rf_uhd_set_tx_srate,
rf_uhd_set_tx_freq,
rf_uhd_get_time,
rf_uhd_recv_with_time,
rf_uhd_send_timed,
rf_uhd_set_tx_cal,
rf_uhd_set_rx_cal
};
#endif
/* Define implementation for bladeRF */
#ifdef ENABLE_BLADERF
#include "rf_blade_imp.h"
static rf_dev_t dev_blade = {
"bladeRF",
rf_blade_rx_wait_lo_locked,
rf_blade_start_rx_stream,
rf_blade_stop_rx_stream,
rf_blade_flush_buffer,
rf_blade_has_rssi,
rf_blade_get_rssi,
rf_blade_suppress_stdout,
rf_blade_register_error_handler,
rf_blade_open,
rf_blade_close,
rf_blade_set_master_clock_rate,
rf_blade_is_master_clock_dynamic,
rf_blade_set_rx_srate,
rf_blade_set_rx_gain,
rf_blade_set_tx_gain,
rf_blade_get_rx_gain,
rf_blade_get_tx_gain,
rf_blade_set_rx_freq,
rf_blade_set_tx_srate,
rf_blade_set_tx_freq,
rf_blade_get_time,
rf_blade_recv_with_time,
rf_blade_send_timed,
rf_blade_set_tx_cal,
rf_blade_set_rx_cal
};
#endif
static rf_dev_t *available_devices[] = {
#ifdef ENABLE_UHD
&dev_uhd,
#endif
#ifdef ENABLE_BLADERF
&dev_blade,
#endif
NULL
};

@ -0,0 +1,309 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <string.h>
#include "srslte/rf/rf.h"
#include "srslte/srslte.h"
#include "rf_dev.h"
int rf_get_available_devices(char **devnames, int max_strlen) {
int i=0;
while(available_devices[i]->name) {
strncpy(devnames[i], available_devices[i]->name, max_strlen);
i++;
}
return i;
}
double srslte_rf_set_rx_gain_th(srslte_rf_t *rf, double gain)
{
if (gain > rf->new_rx_gain + 0.5 || gain < rf->new_rx_gain - 0.5) {
pthread_mutex_lock(&rf->mutex);
rf->new_rx_gain = gain;
pthread_cond_signal(&rf->cond);
pthread_mutex_unlock(&rf->mutex);
}
return gain;
}
void srslte_rf_set_tx_rx_gain_offset(srslte_rf_t *rf, double offset) {
rf->tx_rx_gain_offset = offset;
}
/* This thread listens for set_rx_gain commands to the USRP */
static void* thread_gain_fcn(void *h) {
srslte_rf_t* rf = (srslte_rf_t*) h;
while(1) {
pthread_mutex_lock(&rf->mutex);
while(rf->cur_rx_gain == rf->new_rx_gain)
{
pthread_cond_wait(&rf->cond, &rf->mutex);
}
if (rf->new_rx_gain != rf->cur_rx_gain) {
rf->cur_rx_gain = rf->new_rx_gain;
srslte_rf_set_rx_gain(h, rf->cur_rx_gain);
}
if (rf->tx_gain_same_rx) {
srslte_rf_set_tx_gain(h, rf->cur_rx_gain+rf->tx_rx_gain_offset);
}
pthread_mutex_unlock(&rf->mutex);
}
return NULL;
}
/* Create auxiliary thread and mutexes for AGC */
int srslte_rf_start_gain_thread(srslte_rf_t *rf, bool tx_gain_same_rx) {
rf->tx_gain_same_rx = tx_gain_same_rx;
rf->tx_rx_gain_offset = 0.0;
if (pthread_mutex_init(&rf->mutex, NULL)) {
return -1;
}
if (pthread_cond_init(&rf->cond, NULL)) {
return -1;
}
if (pthread_create(&rf->thread_gain, NULL, thread_gain_fcn, rf)) {
perror("pthread_create");
return -1;
}
return 0;
}
const char* srslte_rf_get_devname(srslte_rf_t *rf) {
return ((rf_dev_t*) rf->dev)->name;
}
int srslte_rf_open_devname(srslte_rf_t *rf, char *devname, char *args) {
/* Try to open the device if name is provided */
if (devname) {
if (devname[0] != '\0') {
int i=0;
while(available_devices[i] != NULL) {
if (!strcmp(available_devices[i]->name, devname)) {
rf->dev = available_devices[i];
return available_devices[i]->srslte_rf_open(args, &rf->handler);
}
i++;
}
printf("Device %s not found. Switching to auto mode\n", devname);
}
}
/* If in auto mode or provided device not found, try to open in order of apperance in available_devices[] array */
int i=0;
while(available_devices[i] != NULL) {
if (!available_devices[i]->srslte_rf_open(args, &rf->handler)) {
rf->dev = available_devices[i];
return 0;
}
i++;
}
fprintf(stderr, "No compatible RF frontend found\n");
return -1;
}
void srslte_rf_set_tx_cal(srslte_rf_t *rf, srslte_rf_cal_t *cal) {
return ((rf_dev_t*) rf->dev)->srslte_rf_set_tx_cal(rf->handler, cal);
}
void srslte_rf_set_rx_cal(srslte_rf_t *rf, srslte_rf_cal_t *cal) {
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_cal(rf->handler, cal);
}
const char* srslte_rf_name(srslte_rf_t *rf) {
return ((rf_dev_t*) rf->dev)->name;
}
bool srslte_rf_rx_wait_lo_locked(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_rx_wait_lo_locked(rf->handler);
}
int srslte_rf_start_rx_stream(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_start_rx_stream(rf->handler);
}
int srslte_rf_stop_rx_stream(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_stop_rx_stream(rf->handler);
}
void srslte_rf_flush_buffer(srslte_rf_t *rf)
{
((rf_dev_t*) rf->dev)->srslte_rf_flush_buffer(rf->handler);
}
bool srslte_rf_has_rssi(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_has_rssi(rf->handler);
}
float srslte_rf_get_rssi(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_get_rssi(rf->handler);
}
void srslte_rf_suppress_stdout(srslte_rf_t *rf)
{
((rf_dev_t*) rf->dev)->srslte_rf_suppress_stdout(rf->handler);
}
void srslte_rf_register_error_handler(srslte_rf_t *rf, srslte_rf_error_handler_t error_handler)
{
((rf_dev_t*) rf->dev)->srslte_rf_register_error_handler(rf->handler, error_handler);
}
int srslte_rf_open(srslte_rf_t *h, char *args)
{
return srslte_rf_open_devname(h, NULL, args);
}
int srslte_rf_close(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_close(rf->handler);
}
void srslte_rf_set_master_clock_rate(srslte_rf_t *rf, double rate)
{
((rf_dev_t*) rf->dev)->srslte_rf_set_master_clock_rate(rf->handler, rate);
}
bool srslte_rf_is_master_clock_dynamic(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_is_master_clock_dynamic(rf->handler);
}
double srslte_rf_set_rx_srate(srslte_rf_t *rf, double freq)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_srate(rf->handler, freq);
}
double srslte_rf_set_rx_gain(srslte_rf_t *rf, double gain)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_gain(rf->handler, gain);
}
double srslte_rf_get_rx_gain(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_get_rx_gain(rf->handler);
}
double srslte_rf_get_tx_gain(srslte_rf_t *rf)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_get_tx_gain(rf->handler);
}
double srslte_rf_set_rx_freq(srslte_rf_t *rf, double freq)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_rx_freq(rf->handler, freq);
}
int srslte_rf_recv(srslte_rf_t *rf, void *data, uint32_t nsamples, bool blocking)
{
return srslte_rf_recv_with_time(rf, data, nsamples, blocking, NULL, NULL);
}
int srslte_rf_recv_with_time(srslte_rf_t *rf,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_recv_with_time(rf->handler, data, nsamples, blocking, secs, frac_secs);
}
double srslte_rf_set_tx_gain(srslte_rf_t *rf, double gain)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_tx_gain(rf->handler, gain);
}
double srslte_rf_set_tx_srate(srslte_rf_t *rf, double freq)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_tx_srate(rf->handler, freq);
}
double srslte_rf_set_tx_freq(srslte_rf_t *rf, double freq)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_set_tx_freq(rf->handler, freq);
}
void srslte_rf_get_time(srslte_rf_t *rf, time_t *secs, double *frac_secs)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_get_time(rf->handler, secs, frac_secs);
}
int srslte_rf_send_timed3(srslte_rf_t *rf,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst)
{
return ((rf_dev_t*) rf->dev)->srslte_rf_send_timed(rf->handler, data, nsamples, secs, frac_secs,
has_time_spec, blocking, is_start_of_burst, is_end_of_burst);
}
int srslte_rf_send(srslte_rf_t *rf, void *data, uint32_t nsamples, bool blocking)
{
return srslte_rf_send2(rf, data, nsamples, blocking, true, true);
}
int srslte_rf_send2(srslte_rf_t *rf, void *data, uint32_t nsamples, bool blocking, bool start_of_burst, bool end_of_burst)
{
return srslte_rf_send_timed3(rf, data, nsamples, 0, 0, false, blocking, start_of_burst, end_of_burst);
}
int srslte_rf_send_timed(srslte_rf_t *rf,
void *data,
int nsamples,
time_t secs,
double frac_secs)
{
return srslte_rf_send_timed2(rf, data, nsamples, secs, frac_secs, true, true);
}
int srslte_rf_send_timed2(srslte_rf_t *rf,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool is_start_of_burst,
bool is_end_of_burst)
{
return srslte_rf_send_timed3(rf, data, nsamples, secs, frac_secs, true, true, is_start_of_burst, is_end_of_burst);
}

@ -0,0 +1,523 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <uhd.h>
#include <sys/time.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include "srslte/srslte.h"
#include "rf_uhd_imp.h"
#include "srslte/rf/rf.h"
#include "uhd_c_api.h"
typedef struct {
uhd_usrp_handle usrp;
uhd_rx_streamer_handle rx_stream;
uhd_tx_streamer_handle tx_stream;
uhd_rx_metadata_handle rx_md, rx_md_first;
uhd_tx_metadata_handle tx_md;
uhd_meta_range_handle rx_gain_range;
size_t rx_nof_samples;
size_t tx_nof_samples;
double tx_rate;
bool dynamic_rate;
} rf_uhd_handler_t;
void suppress_handler(const char *x)
{
// do nothing
}
srslte_rf_error_handler_t uhd_error_handler = NULL;
void msg_handler(const char *msg)
{
srslte_rf_error_t error;
if(0 == strcmp(msg, "O")) {
error.type = SRSLTE_RF_ERROR_OVERFLOW;
} else if(0 == strcmp(msg, "D")) {
error.type = SRSLTE_RF_ERROR_OVERFLOW;
}else if(0 == strcmp(msg, "U")) {
error.type = SRSLTE_RF_ERROR_UNDERFLOW;
} else if(0 == strcmp(msg, "L")) {
error.type = SRSLTE_RF_ERROR_LATE;
}
if (uhd_error_handler) {
uhd_error_handler(error);
}
}
void rf_uhd_suppress_stdout(void *h) {
rf_uhd_register_msg_handler_c(suppress_handler);
}
void rf_uhd_register_error_handler(void *notused, srslte_rf_error_handler_t new_handler)
{
uhd_error_handler = new_handler;
rf_uhd_register_msg_handler_c(msg_handler);
}
static bool find_string(uhd_string_vector_handle h, char *str)
{
char buff[128];
size_t n;
uhd_string_vector_size(h, &n);
for (int i=0;i<n;i++) {
uhd_string_vector_at(h, i, buff, 128);
if (strstr(buff, str)) {
return true;
}
}
return false;
}
static bool isLocked(rf_uhd_handler_t *handler, char *sensor_name, uhd_sensor_value_handle *value_h)
{
bool val_out = false;
if (sensor_name) {
uhd_usrp_get_rx_sensor(handler->usrp, sensor_name, 0, value_h);
uhd_sensor_value_to_bool(*value_h, &val_out);
} else {
usleep(500);
val_out = true;
}
return val_out;
}
bool rf_uhd_rx_wait_lo_locked(void *h)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_string_vector_handle mb_sensors;
uhd_string_vector_handle rx_sensors;
char *sensor_name;
uhd_sensor_value_handle value_h;
uhd_string_vector_make(&mb_sensors);
uhd_string_vector_make(&rx_sensors);
uhd_sensor_value_make_from_bool(&value_h, "", true, "True", "False");
uhd_usrp_get_mboard_sensor_names(handler->usrp, 0, &mb_sensors);
uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &rx_sensors);
if (find_string(rx_sensors, "lo_locked")) {
sensor_name = "lo_locked";
} else if (find_string(mb_sensors, "ref_locked")) {
sensor_name = "ref_locked";
} else {
sensor_name = NULL;
}
double report = 0.0;
while (!isLocked(handler, sensor_name, &value_h) && report < 30.0) {
report += 0.1;
usleep(1000);
}
bool val = isLocked(handler, sensor_name, &value_h);
uhd_string_vector_free(&mb_sensors);
uhd_string_vector_free(&rx_sensors);
uhd_sensor_value_free(&value_h);
return val;
}
void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal)
{
}
void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal)
{
}
int rf_uhd_start_rx_stream(void *h)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_stream_cmd_t stream_cmd = {
.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS,
.stream_now = true
};
uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd);
return 0;
}
int rf_uhd_stop_rx_stream(void *h)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_stream_cmd_t stream_cmd = {
.stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS,
.stream_now = true
};
uhd_rx_streamer_issue_stream_cmd(handler->rx_stream, &stream_cmd);
return 0;
}
void rf_uhd_flush_buffer(void *h)
{
int n;
cf_t tmp[1024];
do {
n = rf_uhd_recv_with_time(h, tmp, 1024, 0, NULL, NULL);
} while (n > 0);
}
bool rf_uhd_has_rssi(void *h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_string_vector_handle rx_sensors;
uhd_string_vector_make(&rx_sensors);
uhd_usrp_get_rx_sensor_names(handler->usrp, 0, &rx_sensors);
bool ret = find_string(rx_sensors, "rssi");
uhd_string_vector_free(&rx_sensors);
return ret;
}
float rf_uhd_get_rssi(void *h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_sensor_value_handle value;
uhd_sensor_value_make_from_realnum(&value, "rssi", 0, "dBm", "%f");
uhd_usrp_get_rx_sensor(handler->usrp, "rssi", 0, &value);
double val_out;
uhd_sensor_value_to_realnum(value, &val_out);
uhd_sensor_value_free(&value);
return val_out;
}
int rf_uhd_open(char *args, void **h)
{
if (h) {
*h = NULL;
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) malloc(sizeof(rf_uhd_handler_t));
if (!handler) {
perror("malloc");
return -1;
}
*h = handler;
/* Set priority to UHD threads */
uhd_set_thread_priority(uhd_default_thread_priority, true);
/* Set correct options for the USRP device */
uhd_string_vector_handle devices_str;
uhd_string_vector_make(&devices_str);
uhd_usrp_find("", &devices_str);
// Allow NULL parameter
if (args == NULL) {
args = "";
}
/* If device type or name not given in args, choose a B200 */
if (args[0]=='\0') {
// If B200 is available, use it
if (find_string(devices_str, "type=b200") && !strstr(args, "recv_frame_size")) {
args = "type=b200,recv_frame_size=9232,send_frame_size=9232";
}
}
/* Create UHD handler */
printf("Opening USRP with args: %s\n", args);
uhd_error error = uhd_usrp_make(&handler->usrp, args);
if (error) {
fprintf(stderr, "Error opening UHD: code %d\n", error);
return -1;
}
size_t channel = 0;
uhd_stream_args_t stream_args = {
.cpu_format = "fc32",
.otw_format = "sc16",
.args = "",
.channel_list = &channel,
.n_channels = 1
};
/* Initialize rx and tx stremers */
uhd_rx_streamer_make(&handler->rx_stream);
error = uhd_usrp_get_rx_stream(handler->usrp, &stream_args, handler->rx_stream);
if (error) {
fprintf(stderr, "Error opening RX stream: %d\n", error);
return -1;
}
uhd_tx_streamer_make(&handler->tx_stream);
error = uhd_usrp_get_tx_stream(handler->usrp, &stream_args, handler->tx_stream);
if (error) {
fprintf(stderr, "Error opening TX stream: %d\n", error);
return -1;
}
uhd_rx_streamer_max_num_samps(handler->rx_stream, &handler->rx_nof_samples);
uhd_tx_streamer_max_num_samps(handler->tx_stream, &handler->tx_nof_samples);
uhd_meta_range_make(&handler->rx_gain_range);
uhd_usrp_get_rx_gain_range(handler->usrp, "", 0, handler->rx_gain_range);
// Make metadata objects for RX/TX
uhd_rx_metadata_make(&handler->rx_md);
uhd_rx_metadata_make(&handler->rx_md_first);
uhd_tx_metadata_make(&handler->tx_md, false, 0, 0, false, false);
/* Find out if the master clock rate is configurable */
double cur_clock, new_clock;
uhd_usrp_get_master_clock_rate(handler->usrp, 0, &cur_clock);
printf("Trying to dynamically change Master clock...\n");
uhd_usrp_set_master_clock_rate(handler->usrp, cur_clock/2, 0);
uhd_usrp_get_master_clock_rate(handler->usrp, 0, &new_clock);
if (new_clock == cur_clock) {
handler->dynamic_rate = false;
/* Master clock rate is not configurable. Check if it is compatible with LTE */
int cur_clock_i = (int) cur_clock;
if (cur_clock_i % 1920000) {
fprintf(stderr, "Error: LTE sampling rates are not supported. Master clock rate is %.1f MHz\n", cur_clock/1e6);
return -1;
} else {
printf("Master clock is not configurable. Using standard symbol sizes and sampling rates.\n");
srslte_use_standard_symbol_size(true);
}
} else {
printf("Master clock is configurable. Using reduced symbol sizes and sampling rates.\n");
handler->dynamic_rate = true;
}
return 0;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
}
int rf_uhd_close(void *h)
{
rf_uhd_stop_rx_stream(h);
/** Something else to close the USRP?? */
return 0;
}
void rf_uhd_set_master_clock_rate(void *h, double rate) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
if (handler->dynamic_rate) {
uhd_usrp_set_master_clock_rate(handler->usrp, rate, 0);
}
}
bool rf_uhd_is_master_clock_dynamic(void *h) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
return handler->dynamic_rate;
}
double rf_uhd_set_rx_srate(void *h, double freq)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_rx_rate(handler->usrp, freq, 0);
uhd_usrp_get_rx_rate(handler->usrp, 0, &freq);
return freq;
}
double rf_uhd_set_tx_srate(void *h, double freq)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_tx_rate(handler->usrp, freq, 0);
uhd_usrp_get_tx_rate(handler->usrp, 0, &freq);
handler->tx_rate = freq;
return freq;
}
double rf_uhd_set_rx_gain(void *h, double gain)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_rx_gain(handler->usrp, gain, 0, "");
uhd_usrp_get_rx_gain(handler->usrp, 0, "", &gain);
return gain;
}
double rf_uhd_set_tx_gain(void *h, double gain)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_tx_gain(handler->usrp, gain, 0, "");
uhd_usrp_get_tx_gain(handler->usrp, 0, "", &gain);
return gain;
}
double rf_uhd_get_rx_gain(void *h)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
double gain;
uhd_usrp_get_rx_gain(handler->usrp, 0, "", &gain);
return gain;
}
double rf_uhd_get_tx_gain(void *h)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
double gain;
uhd_usrp_get_tx_gain(handler->usrp, 0, "", &gain);
return gain;
}
double rf_uhd_set_rx_freq(void *h, double freq)
{
uhd_tune_request_t tune_request = {
.target_freq = freq,
.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
};
uhd_tune_result_t tune_result;
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_rx_freq(handler->usrp, &tune_request, 0, &tune_result);
uhd_usrp_get_rx_freq(handler->usrp, 0, &freq);
return freq;
}
double rf_uhd_set_tx_freq(void *h, double freq)
{
uhd_tune_request_t tune_request = {
.target_freq = freq,
.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
};
uhd_tune_result_t tune_result;
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_set_tx_freq(handler->usrp, &tune_request, 0, &tune_result);
uhd_usrp_get_tx_freq(handler->usrp, 0, &freq);
return freq;
}
void rf_uhd_get_time(void *h, time_t *secs, double *frac_secs) {
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
uhd_usrp_get_time_now(handler->usrp, 0, secs, frac_secs);
}
int rf_uhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs)
{
rf_uhd_handler_t *handler = (rf_uhd_handler_t*) h;
size_t rxd_samples;
uhd_rx_metadata_handle *md = &handler->rx_md_first;
if (blocking) {
int n = 0;
cf_t *data_c = (cf_t*) data;
do {
size_t rx_samples = handler->rx_nof_samples;
if (rx_samples > nsamples - n) {
rx_samples = nsamples - n;
}
void *buff = (void*) &data_c[n];
void **buffs_ptr = (void**) &buff;
uhd_error error = uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr,
rx_samples, md, 5.0, false, &rxd_samples);
if (error) {
fprintf(stderr, "Error receiving from UHD: %d\n", error);
return -1;
}
md = &handler->rx_md;
n += rxd_samples;
} while (n < nsamples);
} else {
void **buffs_ptr = (void**) &data;
return uhd_rx_streamer_recv(handler->rx_stream, buffs_ptr,
nsamples, md, 0.0, false, &rxd_samples);
}
if (secs && frac_secs) {
uhd_rx_metadata_time_spec(handler->rx_md_first, secs, frac_secs);
}
return nsamples;
}
int rf_uhd_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst)
{
rf_uhd_handler_t* handler = (rf_uhd_handler_t*) h;
size_t txd_samples;
if (has_time_spec) {
uhd_tx_metadata_set_time_spec(&handler->tx_md, secs, frac_secs);
}
if (blocking) {
int n = 0;
cf_t *data_c = (cf_t*) data;
do {
size_t tx_samples = handler->tx_nof_samples;
// First packet is start of burst if so defined, others are never
if (n == 0) {
uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst);
} else {
uhd_tx_metadata_set_start(&handler->tx_md, false);
}
// middle packets are never end of burst, last one as defined
if (nsamples - n > tx_samples) {
uhd_tx_metadata_set_end(&handler->tx_md, false);
} else {
tx_samples = nsamples - n;
uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst);
}
void *buff = (void*) &data_c[n];
const void **buffs_ptr = (const void**) &buff;
uhd_error error = uhd_tx_streamer_send(handler->tx_stream, buffs_ptr,
tx_samples, &handler->tx_md, 3.0, &txd_samples);
if (error) {
fprintf(stderr, "Error sending to UHD: %d\n", error);
return -1;
}
// Increase time spec
uhd_tx_metadata_add_time_spec(&handler->tx_md, txd_samples/handler->tx_rate);
n += txd_samples;
} while (n < nsamples);
return nsamples;
} else {
const void **buffs_ptr = (const void**) &data;
uhd_tx_metadata_set_start(&handler->tx_md, is_start_of_burst);
uhd_tx_metadata_set_end(&handler->tx_md, is_end_of_burst);
return uhd_tx_streamer_send(handler->tx_stream, buffs_ptr, nsamples, &handler->tx_md, 0.0, &txd_samples);
}
}

@ -0,0 +1,108 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdbool.h>
#include <stdint.h>
#include "srslte/config.h"
#include "srslte/rf/rf.h"
SRSLTE_API int rf_uhd_open(char *args,
void **handler);
SRSLTE_API int rf_uhd_close(void *h);
SRSLTE_API void rf_uhd_set_tx_cal(void *h, srslte_rf_cal_t *cal);
SRSLTE_API void rf_uhd_set_rx_cal(void *h, srslte_rf_cal_t *cal);
SRSLTE_API int rf_uhd_start_rx_stream(void *h);
SRSLTE_API int rf_uhd_start_rx_stream_nsamples(void *h,
uint32_t nsamples);
SRSLTE_API int rf_uhd_stop_rx_stream(void *h);
SRSLTE_API void rf_uhd_flush_buffer(void *h);
SRSLTE_API bool rf_uhd_has_rssi(void *h);
SRSLTE_API float rf_uhd_get_rssi(void *h);
SRSLTE_API bool rf_uhd_rx_wait_lo_locked(void *h);
SRSLTE_API void rf_uhd_set_master_clock_rate(void *h,
double rate);
SRSLTE_API bool rf_uhd_is_master_clock_dynamic(void *h);
SRSLTE_API double rf_uhd_set_rx_srate(void *h,
double freq);
SRSLTE_API double rf_uhd_set_rx_gain(void *h,
double gain);
SRSLTE_API double rf_uhd_get_rx_gain(void *h);
SRSLTE_API double rf_uhd_get_tx_gain(void *h);
SRSLTE_API void rf_uhd_suppress_stdout(void *h);
SRSLTE_API void rf_uhd_register_error_handler(void *h, srslte_rf_error_handler_t error_handler);
SRSLTE_API double rf_uhd_set_rx_freq(void *h,
double freq);
SRSLTE_API int rf_uhd_recv_with_time(void *h,
void *data,
uint32_t nsamples,
bool blocking,
time_t *secs,
double *frac_secs);
SRSLTE_API double rf_uhd_set_tx_srate(void *h,
double freq);
SRSLTE_API double rf_uhd_set_tx_gain(void *h,
double gain);
SRSLTE_API double rf_uhd_set_tx_freq(void *h,
double freq);
SRSLTE_API void rf_uhd_get_time(void *h,
time_t *secs,
double *frac_secs);
SRSLTE_API int rf_uhd_send_timed(void *h,
void *data,
int nsamples,
time_t secs,
double frac_secs,
bool has_time_spec,
bool blocking,
bool is_start_of_burst,
bool is_end_of_burst);

@ -36,35 +36,35 @@
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/cuhd/cuhd_utils.h"
#include "srslte/rf/rf.h"
#include "srslte/rf/rf_utils.h"
int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) {
int rf_rssi_scan(srslte_rf_t *rf, float *freqs, float *rssi, int nof_bands, double fs, int nsamp) {
int i, j;
int ret = -1;
_Complex float *buffer;
cf_t *buffer;
double f;
buffer = calloc(nsamp, sizeof(_Complex float));
buffer = calloc(nsamp, sizeof(cf_t));
if (!buffer) {
goto free_and_exit;
}
cuhd_set_rx_gain(uhd, 20.0);
cuhd_set_rx_srate(uhd, fs);
srslte_rf_set_rx_gain(rf, 20.0);
srslte_rf_set_rx_srate(rf, fs);
for (i=0;i<nof_bands;i++) {
cuhd_stop_rx_stream(uhd);
srslte_rf_stop_rx_stream(rf);
f = (double) freqs[i];
cuhd_set_rx_freq(uhd, f);
cuhd_rx_wait_lo_locked(uhd);
srslte_rf_set_rx_freq(rf, f);
srslte_rf_rx_wait_lo_locked(rf);
usleep(10000);
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(rf);
/* discard first samples */
for (j=0;j<2;j++) {
if (cuhd_recv(uhd, buffer, nsamp, 1) != nsamp) {
if (srslte_rf_recv(rf, buffer, nsamp, 1) != nsamp) {
goto free_and_exit;
}
}
@ -74,7 +74,7 @@ int cuhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double f
printf("\n");
}
}
cuhd_stop_rx_stream(uhd);
srslte_rf_stop_rx_stream(rf);
ret = 0;
free_and_exit:
@ -83,34 +83,38 @@ free_and_exit:
}
int cuhd_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
int srslte_rf_recv_wrapper_cs(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *t) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv(h, data, nsamples, 1);
return srslte_rf_recv(h, data, nsamples, 1);
}
/** This function is simply a wrapper to the ue_cell_search module for cuhd devices
double srslte_rf_set_rx_gain_th_wrapper(void *h, double f) {
return srslte_rf_set_rx_gain_th((srslte_rf_t*) h, f);
}
/** This function is simply a wrapper to the ue_cell_search module for rf devices
* Return 1 if the MIB is decoded, 0 if not or -1 on error.
*/
int cuhd_mib_decoder(void *uhd, cell_search_cfg_t *config, srslte_cell_t *cell) {
int rf_mib_decoder(srslte_rf_t *rf, cell_search_cfg_t *config, srslte_cell_t *cell) {
int ret = SRSLTE_ERROR;
srslte_ue_mib_sync_t ue_mib;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
if (srslte_ue_mib_sync_init(&ue_mib, cell->id, cell->cp, cuhd_recv_wrapper_cs, uhd)) {
if (srslte_ue_mib_sync_init(&ue_mib, cell->id, cell->cp, srslte_rf_recv_wrapper_cs, (void*) rf)) {
fprintf(stderr, "Error initiating srslte_ue_mib_sync\n");
goto clean_exit;
}
if (config->init_agc > 0) {
srslte_ue_sync_start_agc(&ue_mib.ue_sync, cuhd_set_rx_gain_th, config->init_agc);
srslte_ue_sync_start_agc(&ue_mib.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc);
}
int srate = srslte_sampling_freq_hz(SRSLTE_UE_MIB_NOF_PRB);
INFO("Setting sampling frequency %.2f MHz for PSS search\n", (float) srate/1000000);
cuhd_set_rx_srate(uhd, (float) srate);
srslte_rf_set_rx_srate(rf, (float) srate);
INFO("Starting receiver...\n", 0);
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(rf);
/* Find and decody MIB */
ret = srslte_ue_mib_sync_decode(&ue_mib, config->max_frames_pss, bch_payload, &cell->nof_ports, NULL);
@ -129,15 +133,15 @@ int cuhd_mib_decoder(void *uhd, cell_search_cfg_t *config, srslte_cell_t *cell)
clean_exit:
cuhd_stop_rx_stream(uhd);
srslte_rf_stop_rx_stream(rf);
srslte_ue_mib_sync_free(&ue_mib);
return ret;
}
/** This function is simply a wrapper to the ue_cell_search module for cuhd devices
/** This function is simply a wrapper to the ue_cell_search module for rf devices
*/
int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
int rf_cell_search(srslte_rf_t *rf, cell_search_cfg_t *config,
int force_N_id_2, srslte_cell_t *cell)
{
int ret = SRSLTE_ERROR;
@ -146,7 +150,7 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init(&cs, cuhd_recv_wrapper_cs, uhd)) {
if (srslte_ue_cellsearch_init(&cs, srslte_rf_recv_wrapper_cs, (void*) rf)) {
fprintf(stderr, "Error initiating UE cell detect\n");
return SRSLTE_ERROR;
}
@ -159,14 +163,14 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
}
if (config->init_agc > 0) {
srslte_ue_sync_start_agc(&cs.ue_sync, cuhd_set_rx_gain_th, config->init_agc);
srslte_ue_sync_start_agc(&cs.ue_sync, srslte_rf_set_rx_gain_th_wrapper, config->init_agc);
}
INFO("Setting sampling frequency %.2f MHz for PSS search\n", SRSLTE_CS_SAMP_FREQ/1000000);
cuhd_set_rx_srate(uhd, SRSLTE_CS_SAMP_FREQ);
srslte_rf_set_rx_srate(rf, SRSLTE_CS_SAMP_FREQ);
INFO("Starting receiver...\n", 0);
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(rf);
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
uint32_t max_peak_cell = 0;
@ -207,7 +211,7 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
config->init_agc = srslte_agc_get_gain(&cs.ue_sync.agc);
}
cuhd_stop_rx_stream(uhd);
srslte_rf_stop_rx_stream(rf);
srslte_ue_cellsearch_free(&cs);
return ret;
@ -219,15 +223,15 @@ int cuhd_cell_search(void *uhd, cell_search_cfg_t *config,
* 0 if no cell was found or MIB could not be decoded,
* -1 on error
*/
int cuhd_search_and_decode_mib(void *uhd, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell)
int rf_search_and_decode_mib(srslte_rf_t *rf, cell_search_cfg_t *config, int force_N_id_2, srslte_cell_t *cell)
{
int ret = SRSLTE_ERROR;
printf("Searching for cell...\n");
ret = cuhd_cell_search(uhd, config, force_N_id_2, cell);
ret = rf_cell_search(rf, config, force_N_id_2, cell);
if (ret > 0) {
printf("Decoding PBCH for cell %d (N_id_2=%d)\n", cell->id, cell->id%3);
ret = cuhd_mib_decoder(uhd, config, cell);
ret = rf_mib_decoder(rf, config, cell);
if (ret < 0) {
fprintf(stderr, "Could not decode PBCH from CELL ID %d\n", cell->id);
return SRSLTE_ERROR;

@ -0,0 +1,46 @@
/* This file implements a few features not currently provided by the UHD C-API */
#include <uhd.h>
#include <uhd/usrp/multi_usrp.hpp>
extern "C" {
#include "srslte/rf/rf.h"
#include "uhd_c_api.h"
}
static void (*handler)(const char*);
void translate_handler(uhd::msg::type_t type, const std::string & msg)
{
if(handler)
handler(msg.c_str());
}
void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*))
{
handler = new_handler;
uhd::msg::register_handler(translate_handler);
}
void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs)
{
(*md)->tx_metadata_cpp.time_spec = uhd::time_spec_t(secs, frac_secs);
(*md)->tx_metadata_cpp.has_time_spec = true;
}
void uhd_tx_metadata_set_start(uhd_tx_metadata_handle *md, bool is_start_of_burst)
{
(*md)->tx_metadata_cpp.start_of_burst = is_start_of_burst;
}
void uhd_tx_metadata_set_end(uhd_tx_metadata_handle *md, bool is_end_of_burst)
{
(*md)->tx_metadata_cpp.end_of_burst = is_end_of_burst;
}
void uhd_tx_metadata_add_time_spec(uhd_tx_metadata_handle *md, double frac_secs)
{
(*md)->tx_metadata_cpp.time_spec += frac_secs;
}

@ -0,0 +1,11 @@
#include <uhd.h>
#include "srslte/config.h"
#include "srslte/rf/rf.h"
/* Declare functions not currently provided by the C-API */
SRSLTE_API void rf_uhd_register_msg_handler_c(void (*new_handler)(const char*));
SRSLTE_API void uhd_tx_metadata_set_time_spec(uhd_tx_metadata_handle *md, time_t secs, double frac_secs);
SRSLTE_API void uhd_tx_metadata_set_start(uhd_tx_metadata_handle *md, bool is_start_of_burst);
SRSLTE_API void uhd_tx_metadata_set_end(uhd_tx_metadata_handle *md, bool is_end_of_burst);
SRSLTE_API void uhd_tx_metadata_add_time_spec(uhd_tx_metadata_handle *md, double frac_secs);

@ -66,6 +66,7 @@ int srslte_sync_init(srslte_sync_t *q, uint32_t frame_size, uint32_t max_offset,
q->N_id_1 = 1000;
q->cfo_i = 0;
q->find_cfo_i = false;
q->find_cfo_i_initiated = false;
q->cfo_ema_alpha = CFO_EMA_ALPHA;
q->fft_size = fft_size;
q->frame_size = frame_size;
@ -137,14 +138,17 @@ void srslte_sync_set_threshold(srslte_sync_t *q, float threshold) {
void srslte_sync_cfo_i_detec_en(srslte_sync_t *q, bool enabled) {
q->find_cfo_i = enabled;
for (int i=0;i<2;i++) {
int offset=(i==0)?-1:1;
if (srslte_pss_synch_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) {
fprintf(stderr, "Error initializing PSS object\n");
}
for (int t=0;t<q->frame_size;t++) {
q->cfo_i_corr[i][t] = cexpf(-2*_Complex_I*M_PI*offset*(float) t/q->fft_size);
if (enabled && !q->find_cfo_i_initiated) {
for (int i=0;i<2;i++) {
int offset=(i==0)?-1:1;
if (srslte_pss_synch_init_fft_offset(&q->pss_i[i], q->max_offset, q->fft_size, offset)) {
fprintf(stderr, "Error initializing PSS object\n");
}
for (int t=0;t<q->frame_size;t++) {
q->cfo_i_corr[i][t] = cexpf(-2*_Complex_I*M_PI*offset*(float) t/q->fft_size);
}
}
q->find_cfo_i_initiated = true;
}
}
@ -343,7 +347,6 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
fft_size_isvalid(q->fft_size))
{
int peak_pos;
float correct_cfo = 0;
ret = SRSLTE_SUCCESS;
@ -358,7 +361,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
float cfo = -carg(cp_corr_max) / M_PI / 2;
/* compute cumulative moving average CFO */
DEBUG("cp_offset_pos=%d, abs=%f, cfo=%f, mean_cfo=%f, nof_symb=%d\n",
INFO("cp_offset_pos=%d, abs=%f, cfo=%f, mean_cfo=%f, nof_symb=%d\n",
cp_offset, cabs(cp_corr_max), cfo, q->mean_cfo, q->nof_symbols);
if (q->mean_cfo) {
q->mean_cfo = SRSLTE_VEC_EMA(cfo, q->mean_cfo, q->cfo_ema_alpha);
@ -367,16 +370,9 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
}
/* Correct CFO with the averaged CFO estimation */
correct_cfo = q->mean_cfo;
if (!q->find_cfo_i) {
correct_cfo = q->cfo_i + q->mean_cfo;
DEBUG("cfo_i disabled, correct_cfo=%d+%f=%f\n",q->cfo_i, q->mean_cfo, correct_cfo);
}
srslte_cfo_correct(&q->cfocorr, input, input, -correct_cfo / q->fft_size);
srslte_cfo_correct(&q->cfocorr, input, input, -q->mean_cfo / q->fft_size);
}
srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2);
if (q->find_cfo_i && q->enable_cfo_corr) {
float peak_value;
float max_peak_value = -99;
@ -393,21 +389,16 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
}
}
if (q->cfo_i != 0) {
correct_cfo = q->cfo_i+q->mean_cfo;
srslte_vec_prod_ccc(input, q->cfo_i_corr[q->cfo_i<0?0:1], input, q->frame_size);
DEBUG("Compensating cfo_i=%d, total_cfo=%f\n", q->cfo_i, correct_cfo);
INFO("Compensating cfo_i=%d\n", q->cfo_i);
}
} else {
srslte_pss_synch_set_N_id_2(&q->pss, q->N_id_2);
peak_pos = srslte_pss_synch_find_pss(&q->pss, &input[find_offset], &q->peak_value);
if (peak_pos < 0) {
fprintf(stderr, "Error calling finding PSS sequence\n");
return SRSLTE_ERROR;
}
if (q->max_offset<128) {
float temp[128];
srslte_vec_sc_prod_fff(q->pss.conv_output_avg, 1e8, temp, q->max_offset);
srslte_vec_fprint_f(stdout, temp, q->max_offset);
}
}
q->mean_peak_value = SRSLTE_VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA);
@ -443,7 +434,7 @@ int srslte_sync_find(srslte_sync_t *q, cf_t *input, uint32_t find_offset, uint32
}
DEBUG("SYNC ret=%d N_id_2=%d find_offset=%d pos=%d peak=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n",
ret, q->N_id_2, find_offset, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*correct_cfo);
ret, q->N_id_2, find_offset, peak_pos, q->peak_value, q->threshold, q->sf_idx, 15*(q->cfo_i+q->mean_cfo));
} else if (srslte_N_id_2_isvalid(q->N_id_2)) {
fprintf(stderr, "Must call srslte_sync_set_N_id_2() first!\n");

@ -33,7 +33,7 @@ ENDIF(SRSGUI_FOUND)
IF(UHD_FOUND)
ADD_EXECUTABLE(pss_usrp pss_usrp.c)
TARGET_LINK_LIBRARIES(pss_usrp srslte srslte_uhd)
TARGET_LINK_LIBRARIES(pss_usrp srslte srslte_rf)
IF(SRSGUI_FOUND)
target_link_libraries(pss_usrp ${SRSGUI_LIBRARIES})
ELSE(SRSGUI_FOUND)

@ -35,7 +35,7 @@
#include <stdbool.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/rf/rf.h"
#ifndef DISABLE_GRAPHICS
@ -47,8 +47,8 @@ void do_plots_sss(float *corr_m0, float *corr_m1);
bool disable_plots = false;
int cell_id = -1;
char *uhd_args="";
float uhd_gain=40.0, uhd_freq=-1.0;
char *rf_args="";
float rf_gain=40.0, rf_freq=-1.0;
int nof_frames = -1;
uint32_t fft_size=64;
float threshold = 0.4;
@ -57,8 +57,8 @@ srslte_cp_t cp=SRSLTE_CP_NORM;
void usage(char *prog) {
printf("Usage: %s [aedgtvnp] -f rx_frequency_hz -i cell_id\n", prog);
printf("\t-a UHD args [Default %s]\n", uhd_args);
printf("\t-g UHD Gain [Default %.2f dB]\n", uhd_gain);
printf("\t-a RF args [Default %s]\n", rf_args);
printf("\t-g RF Gain [Default %.2f dB]\n", rf_gain);
printf("\t-n nof_frames [Default %d]\n", nof_frames);
printf("\t-l N_id_2 to sync [Default use cell_id]\n");
printf("\t-e Extended CP [Default Normal]\n", fft_size);
@ -77,13 +77,13 @@ void parse_args(int argc, char **argv) {
while ((opt = getopt(argc, argv, "adgetvsfil")) != -1) {
switch (opt) {
case 'a':
uhd_args = argv[optind];
rf_args = argv[optind];
break;
case 'g':
uhd_gain = atof(argv[optind]);
rf_gain = atof(argv[optind]);
break;
case 'f':
uhd_freq = atof(argv[optind]);
rf_freq = atof(argv[optind]);
break;
case 't':
threshold = atof(argv[optind]);
@ -114,7 +114,7 @@ void parse_args(int argc, char **argv) {
exit(-1);
}
}
if (cell_id < 0 || uhd_freq < 0) {
if (cell_id < 0 || rf_freq < 0) {
usage(argv[0]);
exit(-1);
}
@ -124,7 +124,7 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
cf_t *buffer;
int frame_cnt, n;
void *uhd;
srslte_rf_t rf;
srslte_pss_synch_t pss;
srslte_cfo_t cfocorr, cfocorr64;
srslte_sss_synch_t sss;
@ -152,22 +152,22 @@ int main(int argc, char **argv) {
flen = srate*5/1000;
printf("Opening UHD device...\n");
if (cuhd_open(uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
printf("Opening RF device...\n");
if (srslte_rf_open(&rf, rf_args)) {
fprintf(stderr, "Error opening rf\n");
exit(-1);
}
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
srslte_rf_set_master_clock_rate(&rf, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
srslte_rf_set_master_clock_rate(&rf, srate);
}
printf("Set RX rate: %.2f MHz\n", cuhd_set_rx_srate(uhd, srate) / 1000000);
printf("Set RX gain: %.1f dB\n", cuhd_set_rx_gain(uhd, uhd_gain));
printf("Set RX freq: %.2f MHz\n", cuhd_set_rx_freq(uhd, uhd_freq) / 1000000);
cuhd_rx_wait_lo_locked(uhd);
printf("Set RX rate: %.2f MHz\n", srslte_rf_set_rx_srate(&rf, srate) / 1000000);
printf("Set RX gain: %.1f dB\n", srslte_rf_set_rx_gain(&rf, rf_gain));
printf("Set RX freq: %.2f MHz\n", srslte_rf_set_rx_freq(&rf, rf_freq) / 1000000);
srslte_rf_rx_wait_lo_locked(&rf);
buffer = malloc(sizeof(cf_t) * flen * 2);
if (!buffer) {
@ -197,7 +197,7 @@ int main(int argc, char **argv) {
printf("N_id_2: %d\n", N_id_2);
cuhd_start_rx_stream(uhd);
srslte_rf_start_rx_stream(&rf);
printf("Frame length %d samples\n", flen);
printf("PSS detection threshold: %.2f\n", threshold);
@ -218,7 +218,7 @@ int main(int argc, char **argv) {
ssync.fft_size = fft_size;
while(frame_cnt < nof_frames || nof_frames == -1) {
n = cuhd_recv(uhd, buffer, flen - peak_offset, 1);
n = srslte_rf_recv(&rf, buffer, flen - peak_offset, 1);
if (n < 0) {
fprintf(stderr, "Error receiving samples\n");
exit(-1);
@ -330,7 +330,7 @@ int main(int argc, char **argv) {
srslte_pss_synch_free(&pss);
free(buffer);
cuhd_close(uhd);
srslte_rf_close(&rf);
printf("Ok\n");
exit(0);

@ -252,18 +252,18 @@ int pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t *format
*format = SRSLTE_PUCCH_FORMAT_2;
}
// CQI + 1-bit ACK
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 1) {
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1) {
*format = SRSLTE_PUCCH_FORMAT_2A;
pucch2_bits[0] = uci_data->uci_ack;
}
// CQI + 2-bit ACK
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 2) {
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 2) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data->uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) {
else if (uci_data->uci_cqi_len > 0 && uci_data->uci_ack_len == 1 && SRSLTE_CP_ISEXT(cp)) {
*format = SRSLTE_PUCCH_FORMAT_2B;
pucch2_bits[0] = uci_data->uci_ack;
pucch2_bits[1] = uci_data->uci_ack_2;

@ -241,7 +241,7 @@ void srslte_vec_convert_if(int16_t *x, float *z, float scale, uint32_t len) {
#ifndef HAVE_VOLK_CONVERT_IF_FUNCTION
int i;
for (i=0;i<len;i++) {
z[i] = ((float) x[i])*scale;
z[i] = ((float) x[i])/scale;
}
#else
volk_16i_s32f_convert_32f(z,x,scale,len);
@ -398,7 +398,7 @@ void srslte_vec_fprint_hex(FILE *stream, uint8_t *x, uint32_t len) {
uint32_t i, nbytes;
uint8_t byte;
nbytes = len/8;
fprintf(stream, "[", len);
fprintf(stream, "[");
for (i=0;i<nbytes;i++) {
byte = (uint8_t) srslte_bit_pack(&x, 8);
fprintf(stream, "%02x ", byte);

@ -217,8 +217,8 @@ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len)
__m128 ret1, ret2;
for(;number < eighthPoints; number++){
inputVal1 = _mm_load_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal2 = _mm_load_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal1 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
inputVal2 = _mm_loadu_ps(inputVectorPtr); inputVectorPtr += 4;
ret1 = _mm_mul_ps(inputVal1, vScalar);
ret2 = _mm_mul_ps(inputVal2, vScalar);
@ -228,7 +228,7 @@ void srslte_vec_convert_fi_simd(float *x, int16_t *z, float scale, uint32_t len)
intInputVal1 = _mm_packs_epi32(intInputVal1, intInputVal2);
_mm_store_si128((__m128i*)outputVectorPtr, intInputVal1);
_mm_storeu_si128((__m128i*)outputVectorPtr, intInputVal1);
outputVectorPtr += 8;
}

Loading…
Cancel
Save