diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 5905d8368c9003b1bd54b961dca78d5a300932f7..9bb062ba20279d0cb277dddd4786a311d0c8b3cf 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -333,7 +333,7 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4") add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4") -add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "CPRIGW") +add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "CPRIGW") if (${RF_BOARD} STREQUAL "EXMIMO") set(DRIVER2013) @@ -352,6 +352,16 @@ elseif (${RF_BOARD} STREQUAL "OAI_USRP") set(option_HW_lib "uhd") set(LOWLATENCY False) +elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") + include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") + include_directories("${OPENAIR2_DIR}/UTIL/LOG") + include_directories("/usr/include") + set(HW_SOURCE ${HW_SOURCE} + ${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c + ) + LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu/") + set(option_HW_lib "bladeRF") + elseif (${RF_BOARD} STREQUAL "ETHERNET") include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") set(HW_SOURCE ${HW_SOURCE} diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 0796460ffd853cfdf926e6cd3c14d90e9ff6fb2d..7331bbd7f581221c9c46f8832774133f66ff3ccf 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -77,7 +77,7 @@ Options default is Rel10, Rel8 limits the implementation to 3GPP Release 8 version -w | --hardware - EXMIMO (Default), USRP, None + EXMIMO (Default), USRP, BLADERF, None Adds this RF board support (in external packages installation and in compilation) --oaisim Makes the oaisim simulator @@ -143,7 +143,12 @@ function main() { -w | --hardware) HW="$2" #"${i#*=}" # Use OAI_USRP as the key word USRP is used inside UHD driver - [ "$HW" == "USRP" ] && HW=OAI_USRP + if [ "$HW" == "USRP" ] ; then + HW="OAI_USRP" + fi + if [ "$HW" == "BLADERF" ] ; then + HW="OAI_BLADERF" + fi echo_info "setting hardware to: $HW" shift 2;; --oaisim) @@ -225,6 +230,11 @@ function main() { echo_info "installing packages for USRP support" check_install_usrp_uhd_driver fi + if [ "$HW" == "OAI_BLADERF" ] ; then + echo_info "installing packages for BALDERF support" + check_install_bladerf_driver + fi + fi if [ "$INSTALL_OPTIONAL" = "1" ] ; then diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 8e82bd5aa1f22eb8015a172376bc764e75ba8a47..6f6d3600dd5ebdba70c7a85c39d49fe4fb75584b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -242,6 +242,11 @@ check_install_usrp_uhd_driver(){ $SUDO apt-get -y install python python-tk libboost-all-dev libusb-1.0-0-dev $SUDO apt-get -y install -t `lsb_release -cs` uhd --force-yes } +check_install_bladerf_driver(){ + $SUDO add-apt-repository -y ppa:bladerf/bladerf + $SUDO apt-get update + $SUDO apt-get install -y bladerf libbladerf-dev +} check_install_additional_tools (){ $SUDO apt-get update diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c new file mode 100644 index 0000000000000000000000000000000000000000..e74b9d8030e70e1526fe95c1ec4190b0a3093816 --- /dev/null +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -0,0 +1,273 @@ + + +#include <stdio.h> +#include <stdlib.h> +#include <inttypes.h> +#include "bladerf_lib.h" +#include "common_lib.h" +#include "log.h" +#define SAMPLE_LEN samples_per_frame*sizeof(int32_t) + +int num_devices=0; +/*These items configure the underlying asynch stream used by the the sync interface. + */ +unsigned int num_buffers; +unsigned int buffer_size; +unsigned int num_transfers; +unsigned int timeout_ms; + + +int trx_brf_init(openair0_device *openair0) { + +} + +struct bladerf * open_bladerf_from_serial(const char *serial) { + + int status; + struct bladerf *dev; + struct bladerf_devinfo info; + /* Initialize all fields to "don't care" wildcard values. + * + * Immediately passing this to bladerf_open_with_devinfo() would cause + * libbladeRF to open any device on any available backend. */ + bladerf_init_devinfo(&info); + /* Specify the desired device's serial number, while leaving all other + * fields in the info structure wildcard values */ + strncpy(info.serial, serial, BLADERF_SERIAL_LENGTH - 1); + info.serial[BLADERF_SERIAL_LENGTH - 1] = '\0'; + status = bladerf_open_with_devinfo(&dev, &info); + + if (status == BLADERF_ERR_NODEV) { + printf("No devices available with serial=%s\n", serial); + return NULL; + } else if (status != 0) { + fprintf(stderr, "Failed to open device with serial=%s (%s)\n", serial, bladerf_strerror(status)); + return NULL; + } else { + return dev; + } +} + + + + + +int trx_brf_start(openair0_device *openair0) { + +} + +int trx_brf_write(openair0_device *device,openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + int status; + struct bladerf_metadata meta; + int16_t zeros[] = { 0, 0, 0, 0 }; + struct bladerf *dev = (struct bladerf*) device->priv; + + /* BRF has only 1 rx/tx chaine : is it correct? */ + void *sample = (void*)buff[0]; + + /* Retrieve the current timestamp */ + if ((status=bladerf_get_timestamp(dev, BLADERF_MODULE_TX, &meta.timestamp)) != 0) { + fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status)); + } else { + *ptimestamp = meta.timestamp; + printf("Current TX timestamp: 0x%016"PRIx64"\n", meta.timestamp); + } + + meta.flags |= BLADERF_META_FLAG_RX_NOW; + + status = bladerf_sync_tx(dev, sample, nsamps, &meta, timeout_ms); + if (status != 0) { + fprintf(stderr, "Failed to TX sample: %s\n", bladerf_strerror(status)); + brf_error(status); + } + + +} + +int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { + int status, ret; + struct bladerf_metadata meta; + unsigned int i; + struct bladerf *dev = (struct bladerf*) device->priv; + /* BRF has only onerx/tx chain: is it correct? */ + void *sample = (void*)buff[0]; + + /* Retrieve the current timestamp */ + if ((status=bladerf_get_timestamp(dev, BLADERF_MODULE_RX, &meta.timestamp)) != 0) { + fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status)); + } else { + *ptimestamp = meta.timestamp; + printf("Current RX timestamp: 0x%016"PRIx64"\n", meta.timestamp); + } + + meta.flags |= BLADERF_META_FLAG_RX_NOW; + //fflush(stdout); + + status = bladerf_sync_rx(dev, sample, nsamps, &meta, timeout_ms); + + /*if (meta.actual_count < nsamps ) { + printf("[BRF][RX] received %d samples out of %d\n", meta.actual_count, nsamps); + }*/ + + if (status != 0) { + fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status)); + } else if (meta.status & BLADERF_META_STATUS_OVERRUN) { + fprintf(stderr, "Overrun detected in RX. %u valid samples were read \n", meta.actual_count); + } else if (meta.status & BLADERF_META_STATUS_UNDERRUN) { + fprintf(stderr, "Underrun detected in RX. %u valid samples were read \n", meta.actual_count); + }else { + printf("Got %u samples at t=0x%016"PRIx64"\n", meta.actual_count, meta.timestamp); + } + + return meta.actual_count; + +} + +int trx_brf_end(openair0_device *device) { + + int status; + struct bladerf *dev = (struct bladerf*) device->priv; + // Disable RX module, shutting down our underlying RX stream + if ((status=bladerf_enable_module(device->priv, BLADERF_MODULE_RX, false)) != 0) { + fprintf(stderr, "Failed to disable RX module: %s\n", bladerf_strerror(status)); + } + if ((status=bladerf_enable_module(device->priv, BLADERF_MODULE_TX, false)) != 0) { + fprintf(stderr, "Failed to disable TX module: %s\n", bladerf_strerror(status)); + } + bladerf_close(dev); + return 0; +} + +//int openair0_device_brf_init(openair0_device *device, openair0_config_t *openair0_cfg) { +int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) { + + int status; + int card=0; + //struct bladerf_version *version; + //printf("Opening the brf device (version %s)...\n", bladerf_version(version)); + + // opaque data struct + struct bladerf *dev;// = (struct bladerf*)malloc(sizeof(struct bladerf)); + //memset(dev, 0, sizeof(struct bladerf)); + + if ((status=bladerf_open(&dev, "")) != 0 ) { + fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status)); + brf_error(status); + } + printf("[BRF] device speed is %d\n",bladerf_device_speed(dev) ); + + // RX + if ((status=bladerf_set_frequency(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_freq[0])) != 0){ + fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_sample_rate(dev, BLADERF_MODULE_RX, openair0_cfg[card].sample_rate, NULL)) != 0){ + fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_bandwidth(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_bw, NULL)) != 0){ + fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_gain(dev, BLADERF_MODULE_RX, openair0_cfg[card].rx_gain[0])) != 0) { + fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status)); + brf_error(status); + } + + /* Configure the device's RX module for use with the sync interface. + * SC16 Q11 samples *with* metadata are used. */ + if ((status=bladerf_sync_config(dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,num_buffers,buffer_size,num_transfers,timeout_ms)) != 0 ) { + fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); + brf_error(status); + } + + /* We must always enable the RX module after calling bladerf_sync_config(), and + * before attempting to RX samples via bladerf_sync_rx(). */ + if ((status=bladerf_enable_module(dev, BLADERF_MODULE_RX, true)) != 0) { + fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); + brf_error(status); + } + + // TX + if ((status=bladerf_set_frequency(dev, BLADERF_MODULE_TX, openair0_cfg[card].tx_freq[0])) != 0){ + fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_sample_rate(dev, BLADERF_MODULE_TX, openair0_cfg[card].sample_rate, NULL)) != 0){ + fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_bandwidth(dev, BLADERF_MODULE_TX,openair0_cfg[card].tx_bw, NULL)) != 0){ + fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); + brf_error(status); + } + if ((status=bladerf_set_gain(dev, BLADERF_MODULE_TX, openair0_cfg[card].tx_gain[0])) != 0) { + fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status)); + brf_error(status); + } + + /* Configure the device's TX module for use with the sync interface. + * SC16 Q11 samples *with* metadata are used. */ + if ((status=bladerf_sync_config(dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,num_buffers,buffer_size,num_transfers,timeout_ms)) != 0 ) { + fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); + brf_error(status); + } + + /* We must always enable the TX module after calling bladerf_sync_config(), and + * before attempting to TX samples via bladerf_sync_tx(). */ + if ((status=bladerf_enable_module(dev, BLADERF_MODULE_TX, true)) != 0) { + fprintf(stderr,"Failed to enable TX module: %s\n", bladerf_strerror(status)); + brf_error(status); + } + + num_buffers = 16; + buffer_size = openair0_cfg[card].samples_per_packet*sizeof(int32_t); + num_transfers = 8; // ? device->openair0_cfg.samples_per_packets + timeout_ms = 1; + + + bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level)); + + printf("BLADERF: Initializing openair0_device\n"); + device->priv = dev; + device->Mod_id = num_devices++; + device->trx_start_func = trx_brf_start; + device->trx_end_func = trx_brf_end; + device->trx_read_func = trx_brf_read; + device->trx_write_func = trx_brf_write; + memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); +} + +void brf_error(int status) { + + exit(-1); +} + +int get_brf_log_level(int log_level){ + + int level=BLADERF_LOG_LEVEL_INFO; + + switch(log_level) { + case LOG_DEBUG: + level=BLADERF_LOG_LEVEL_DEBUG; + break; + case LOG_INFO: + level= BLADERF_LOG_LEVEL_INFO; + break; + case LOG_WARNING: + level=BLADERF_LOG_LEVEL_WARNING; + break; + case LOG_ERR: + level=BLADERF_LOG_LEVEL_ERROR; + break; + case LOG_CRIT: + level=BLADERF_LOG_LEVEL_CRITICAL; + break; + case LOG_EMERG: + level = BLADERF_LOG_LEVEL_SILENT; + break; + default: + break; + } + return level; +} diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h new file mode 100644 index 0000000000000000000000000000000000000000..7267653813305dba68fe2d51c09086fc2d71f611 --- /dev/null +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h @@ -0,0 +1,45 @@ + +#include <libbladeRF.h> +/* +enum brf_err_num{ + BLADERF_ERR_MIN=0, + BLADERF_ERR_UNEXPECTED=-1, + BLADERF_ERR_RANGE=-2, + BLADERF_ERR_INVAL=-3, + BLADERF_ERR_MEM=-4, + BLADERF_ERR_IO=-5, + BLADERF_ERR_TIMEOUT=-6, + BLADERF_ERR_NODEV=-7, + BLADERF_ERR_UNSUPPORTED=-8, + BLADERF_ERR_MISALIGNED=-9, + BLADERF_ERR_CHECKSUM=-10, + BLADERF_ERR_NO_FILE=-11, + BLADERF_ERR_UPDATE_FPGA=-12, + BLADERF_ERR_UPDATE_FW=-13, + BLADERF_ERR_TIME_PAST=-14, + BLADERF_ERR_MAX=-15, +} +mapping brf_err_names[] = { + {"BLADERF_OK", BLADERF_ERR_MIN}, + {"BLADERF_ERR_UNEXPECTED",BLADERF_ERR_UNEXPECTED}, + {"BLADERF_ERR_RANGE",BLADERF_ERR_RANGE}, + {"BLADERF_ERR_INVAL",BLADERF_ERR_INVAL}, + {"BLADERF_ERR_MEM",BLADERF_ERR_MEM}, + {"BLADERF_ERR_IO",BLADERF_ERR_IO}, + {"BLADERF_ERR_TIMEOUT",BLADERF_ERR_TIMEOUT}, + {"BLADERF_ERR_NODEV",BLADERF_ERR_NODEV}, + {"BLADERF_ERR_UNSUPPORTED",BLADERF_ERR_UNSUPPORTED}, + {"BLADERF_ERR_MISALIGNED",BLADERF_ERR_MISALIGNED}, + {"BLADERF_ERR_CHECKSUM",BLADERF_ERR_CHECKSUM}, + {"BLADERF_ERR_NO_FILE",BLADERF_ERR_NO_FILE}, + {"BLADERF_ERR_UPDATE_FPGA",BLADERF_ERR_UPDATE_FPGA}, + {"BLADERF_ERR_UPDATE_FW",BLADERF_ERR_UPDATE_FW}, + {"BLADERF_ERR_TIME_PAST",BLADERF_ERR_TIME_PAST}, + {NULL, BLADERF_ERR_MAX} +}; +*/ +/* + * func prototypes + */ + +void brf_error(int status); diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 21b8ab78875ba9b9a3fad4c3b392aff25ef3c58d..56490b65aada4ed67c91a4e05255ade5674b2476 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -54,6 +54,8 @@ typedef enum { typedef struct { //! Module ID for this configuration int Mod_id; + // device log level + int log_level; //! the sample rate for both transmit and receive. double sample_rate; //! number of samples per RX/TX packet (USRP + Ethernet) @@ -71,7 +73,7 @@ typedef struct { //! mode for rxgain (ExpressMIMO2) rx_gain_t rxg_mode[4]; //! \brief Gain for RX in dB. - //! index: [0..rx_num_channels[ + //! index: [0..rx_num_channels] double rx_gain[4]; //! gain for TX in dB double tx_gain[4]; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 03538459c64606a2510a6cf4ef3958f363d746d7..a9b63c72caabaeae7db0c8fa1ff4a75c484f4dcb 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -2740,7 +2740,7 @@ int main( int argc, char **argv ) } printf("Initializing openair0 ..."); - + openair0_cfg[0].log_level = glog_level; if (openair0_device_init(&openair0, &openair0_cfg[0]) <0) { printf("Exiting, cannot initialize device\n"); exit(-1);