Added Iris hardware support.
Signed-off-by: Rahman Doost <doost@rice.edu>
This commit is contained in:
committed by
Rahman Doost
parent
c1f7678e5b
commit
5832204fe1
@@ -551,6 +551,15 @@ set(TPLIB_ETHERNET_SOURCE
|
|||||||
)
|
)
|
||||||
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
|
add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} )
|
||||||
|
|
||||||
|
include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/")
|
||||||
|
set(option_HWIRISLIB_lib "-l SoapySDR")
|
||||||
|
set(HWLIB_IRIS_SOURCE
|
||||||
|
${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp
|
||||||
|
)
|
||||||
|
add_library(oai_irisdevif MODULE ${HWLIB_IRIS_SOURCE})
|
||||||
|
target_include_directories(oai_irisdevif PRIVATE /usr/local/lib/SoapySDR/modules0.6/)
|
||||||
|
target_link_libraries(oai_irisdevif SoapySDR)
|
||||||
|
|
||||||
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
|
include_directories("${OPENAIR_TARGETS}/ARCH/mobipass/")
|
||||||
set(TPLIB_MOBIPASS_SOURCE
|
set(TPLIB_MOBIPASS_SOURCE
|
||||||
${OPENAIR_TARGETS}/ARCH/mobipass/interface.c
|
${OPENAIR_TARGETS}/ARCH/mobipass/interface.c
|
||||||
@@ -1787,6 +1796,15 @@ include_directories(${CRYPTO_INCLUDE_DIRS})
|
|||||||
if (${RF_BOARD} STREQUAL "OAI_USRP")
|
if (${RF_BOARD} STREQUAL "OAI_USRP")
|
||||||
find_package(Boost REQUIRED)
|
find_package(Boost REQUIRED)
|
||||||
include_directories(${LIBBOOST_INCLUDE_DIR})
|
include_directories(${LIBBOOST_INCLUDE_DIR})
|
||||||
|
|
||||||
|
elseif (${RF_BOARD} STREQUAL "OAI_IRIS")
|
||||||
|
include_directories("${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/")
|
||||||
|
include_directories("/usr/local/include/")
|
||||||
|
set(HW_SOURCE ${HW_SOURCE}
|
||||||
|
${OPENAIR_TARGETS}/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp)
|
||||||
|
LINK_DIRECTORIES("/usr/local/lib")
|
||||||
|
set(option_HW_lib "-lSoapySDR -rdynamic -ldl")
|
||||||
|
|
||||||
endif (${RF_BOARD} STREQUAL "OAI_USRP")
|
endif (${RF_BOARD} STREQUAL "OAI_USRP")
|
||||||
|
|
||||||
pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2)
|
pkg_search_module(OPENPGM openpgm-5.1 openpgm-5.2)
|
||||||
|
|||||||
+22
-2
@@ -107,7 +107,7 @@ Options
|
|||||||
Rel8 limits the implementation to 3GPP Release 8 version
|
Rel8 limits the implementation to 3GPP Release 8 version
|
||||||
Rel10 limits the implementation to 3GPP Release 10 version
|
Rel10 limits the implementation to 3GPP Release 10 version
|
||||||
-w | --hardware
|
-w | --hardware
|
||||||
EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, None (Default)
|
EXMIMO, USRP, BLADERF, ETHERNET, LMSSDR, IRIS, None (Default)
|
||||||
Adds this RF board support (in external packages installation and in compilation)
|
Adds this RF board support (in external packages installation and in compilation)
|
||||||
-t | --transport protocol
|
-t | --transport protocol
|
||||||
ETHERNET , None
|
ETHERNET , None
|
||||||
@@ -231,7 +231,7 @@ function main() {
|
|||||||
-w | --hardware)
|
-w | --hardware)
|
||||||
HW="$2" #"${i#*=}"
|
HW="$2" #"${i#*=}"
|
||||||
# Use OAI_USRP as the key word USRP is used inside UHD driver
|
# Use OAI_USRP as the key word USRP is used inside UHD driver
|
||||||
if [ "$HW" != "BLADERF" -a "$HW" != "USRP" -a "$HW" != "LMSSDR" -a "$HW" != "None" -a "$HW" != "EXMIMO" ] ; then
|
if [ "$HW" != "BLADERF" -a "$HW" != "USRP" -a "$HW" != "LMSSDR" -a "$HW" != "None" -a "$HW" != "EXMIMO" -a "$HW" != "IRIS" ] ; then
|
||||||
echo_fatal "Unknown HW type $HW will exit..."
|
echo_fatal "Unknown HW type $HW will exit..."
|
||||||
else
|
else
|
||||||
if [ "$HW" == "USRP" ] ; then
|
if [ "$HW" == "USRP" ] ; then
|
||||||
@@ -243,6 +243,9 @@ function main() {
|
|||||||
if [ "$HW" == "LMSSDR" ] ; then
|
if [ "$HW" == "LMSSDR" ] ; then
|
||||||
HW="OAI_LMSSDR"
|
HW="OAI_LMSSDR"
|
||||||
fi
|
fi
|
||||||
|
if [ "$HW" == "IRIS" ] ; then
|
||||||
|
HW="OAI_IRIS"
|
||||||
|
fi
|
||||||
echo_info "Setting hardware to: $HW"
|
echo_info "Setting hardware to: $HW"
|
||||||
fi
|
fi
|
||||||
shift 2;;
|
shift 2;;
|
||||||
@@ -416,6 +419,8 @@ function main() {
|
|||||||
DEADLINE_SCHEDULER_FLAG_USER="False"
|
DEADLINE_SCHEDULER_FLAG_USER="False"
|
||||||
elif [ "$HW" = "OAI_LMSSDR" ] ; then
|
elif [ "$HW" = "OAI_LMSSDR" ] ; then
|
||||||
DEADLINE_SCHEDULER_FLAG_USER="False"
|
DEADLINE_SCHEDULER_FLAG_USER="False"
|
||||||
|
elif [ "$HW" = "OAI_IRIS" ] ; then
|
||||||
|
DEADLINE_SCHEDULER_FLAG_USER="False"
|
||||||
elif [ "$HW" = "None" ] ; then
|
elif [ "$HW" = "None" ] ; then
|
||||||
DEADLINE_SCHEDULER_FLAG_USER="False"
|
DEADLINE_SCHEDULER_FLAG_USER="False"
|
||||||
else
|
else
|
||||||
@@ -484,6 +489,13 @@ function main() {
|
|||||||
flash_firmware_bladerf
|
flash_firmware_bladerf
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
if [ "$HW" == "OAI_IRIS" ] ; then
|
||||||
|
echo_info "installing packages for IRIS support"
|
||||||
|
check_install_soapy
|
||||||
|
#if [ ! "$DISABLE_HARDWARE_DEPENDENCY" == "True" ]; then
|
||||||
|
# flash_firmware_iris
|
||||||
|
#fi
|
||||||
|
fi
|
||||||
echo_info "installing protobuf/protobuf-c for flexran agent support"
|
echo_info "installing protobuf/protobuf-c for flexran agent support"
|
||||||
install_protobuf_from_source
|
install_protobuf_from_source
|
||||||
install_protobuf_c_from_source
|
install_protobuf_c_from_source
|
||||||
@@ -756,6 +768,14 @@ function main() {
|
|||||||
ln -sf liboai_lmssdrdevif.so liboai_device.so
|
ln -sf liboai_lmssdrdevif.so liboai_device.so
|
||||||
ln -sf $dbin/liboai_lmssdrdevif.so.$REL $dbin/liboai_device.so
|
ln -sf $dbin/liboai_lmssdrdevif.so.$REL $dbin/liboai_device.so
|
||||||
echo_info "liboai_device.so is linked to LMSSDR device library"
|
echo_info "liboai_device.so is linked to LMSSDR device library"
|
||||||
|
elif [ "$HW" == "OAI_IRIS" ] ; then
|
||||||
|
compilations \
|
||||||
|
$build_dir oai_irisdevif \
|
||||||
|
liboai_irisdevif.so $dbin/liboai_irisdevif.so.$REL
|
||||||
|
|
||||||
|
ln -s liboai_irisdevif.so liboai_device.so
|
||||||
|
ln -s $dbin/liboai_irisdevif.so.$REL $dbin/liboai_device.so
|
||||||
|
echo_info "liboai_device.so is linked to IRIS device library"
|
||||||
else
|
else
|
||||||
echo_info "liboai_device.so is not linked to any device library"
|
echo_info "liboai_device.so is not linked to any device library"
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -379,6 +379,74 @@ check_install_lmssdr_driver(){
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
install_soapy_from_source(){
|
||||||
|
soapy_install_log=$OPENAIR_DIR/cmake_targets/log/soapy_install_log.txt
|
||||||
|
echo_info "\nInstalling Soapy EcoSystem from source. The log file for Soapy installation is here: $soapy_install_log "
|
||||||
|
(
|
||||||
|
cd /tmp
|
||||||
|
echo "Downloading SoapySDR"
|
||||||
|
rm -rf /tmp/soapysdr
|
||||||
|
git clone https://github.com/pothosware/SoapySDR.git
|
||||||
|
cd soapysdr
|
||||||
|
#git checkout tags/release_003_010_001_001
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
$CMAKE ../
|
||||||
|
echo "Compiling SoapySDR"
|
||||||
|
make -j`nproc`
|
||||||
|
$SUDO make install
|
||||||
|
$SUDO ldconfig
|
||||||
|
cd /tmp
|
||||||
|
echo "Downloading SoapyRemote"
|
||||||
|
rm -rf /tmp/soapyremote
|
||||||
|
git clone https://github.com/pothosware/SoapyRemote.git
|
||||||
|
cd soapyremote
|
||||||
|
#git checkout tags/release_003_010_001_001
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake ../
|
||||||
|
echo "Compiling SoapyRemote"
|
||||||
|
make -j`nproc`
|
||||||
|
$SUDO make install
|
||||||
|
$SUDO ldconfig
|
||||||
|
) >& $soapy_install_log
|
||||||
|
}
|
||||||
|
|
||||||
|
install_soapy_iris_from_source(){
|
||||||
|
iris_install_log=$OPENAIR_DIR/cmake_targets/log/iris_install_log.txt
|
||||||
|
echo_info "\nInstalling Iris driver from source. The log file for Iris driver installation is here: $iris_install_log "
|
||||||
|
(
|
||||||
|
cd /tmp
|
||||||
|
echo "Downloading SoapyIris"
|
||||||
|
rm -rf /tmp/sklk-soapyiris
|
||||||
|
git clone https://github.com/skylarkwireless/sklk-soapyiris.git
|
||||||
|
cd sklk-soapyiris
|
||||||
|
mkdir -p build
|
||||||
|
cd build
|
||||||
|
cmake ../
|
||||||
|
echo "Compiling SoapyIris"
|
||||||
|
make -j`nproc`
|
||||||
|
$SUDO make install
|
||||||
|
$SUDO ldconfig
|
||||||
|
) >& $iris_install_log
|
||||||
|
}
|
||||||
|
|
||||||
|
check_install_soapy () {
|
||||||
|
#if [[ "$OS_DISTRO" == "ubuntu" ]]; then
|
||||||
|
#first we remove old installation
|
||||||
|
$SUDO apt-get remove -y soapysdr soapysdr-server libsoapysdr-dev python-soapysdr python3-soapysdr soapysdr-module-remote || true
|
||||||
|
$SUDO add-apt-repository -y ppa:myriadrf/drivers
|
||||||
|
$SUDO apt-get update
|
||||||
|
$SUDO apt-get install -y soapysdr soapysdr-server libsoapysdr-dev python-soapysdr python3-soapysdr soapysdr-module-remote
|
||||||
|
|
||||||
|
#elif [[ "$OS_BASEDISTRO" == "fedora" ]]; then
|
||||||
|
# $SUDO $INSTALLER -y install software-properties-common python3-software-properties python-software-properties subversion git python3 python-numpy python3-numpy cmake swig python-dev
|
||||||
|
# install_soapy_from_source
|
||||||
|
#fi
|
||||||
|
install_soapy_iris_from_source
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
check_install_additional_tools (){
|
check_install_additional_tools (){
|
||||||
$SUDO $INSTALLER update -y
|
$SUDO $INSTALLER update -y
|
||||||
if [[ "$OS_DISTRO" == "ubuntu" ]]; then
|
if [[ "$OS_DISTRO" == "ubuntu" ]]; then
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ int set_device(openair0_device *device) {
|
|||||||
case USRP_B200_DEV:
|
case USRP_B200_DEV:
|
||||||
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
printf("[%s] has loaded USRP B200 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||||
break;
|
break;
|
||||||
case USRP_X300_DEV:
|
case USRP_X300_DEV:
|
||||||
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
printf("[%s] has loaded USRP X300 device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||||
break;
|
break;
|
||||||
case BLADERF_DEV:
|
case BLADERF_DEV:
|
||||||
@@ -57,6 +57,9 @@ case USRP_X300_DEV:
|
|||||||
case LMSSDR_DEV:
|
case LMSSDR_DEV:
|
||||||
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
printf("[%s] has loaded LMSSDR device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||||
break;
|
break;
|
||||||
|
case IRIS_DEV:
|
||||||
|
printf("[%s] has loaded Iris device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||||
|
break;
|
||||||
case NONE_DEV:
|
case NONE_DEV:
|
||||||
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
printf("[%s] has not loaded a HW device.\n",((device->host_type == RAU_HOST) ? "RAU": "RRU"));
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -95,6 +95,8 @@ typedef enum {
|
|||||||
BLADERF_DEV,
|
BLADERF_DEV,
|
||||||
/*!\brief device is LMSSDR (SoDeRa)*/
|
/*!\brief device is LMSSDR (SoDeRa)*/
|
||||||
LMSSDR_DEV,
|
LMSSDR_DEV,
|
||||||
|
/*!\brief device is Iris */
|
||||||
|
IRIS_DEV,
|
||||||
/*!\brief device is NONE*/
|
/*!\brief device is NONE*/
|
||||||
NONE_DEV,
|
NONE_DEV,
|
||||||
MAX_RF_DEV_TYPE
|
MAX_RF_DEV_TYPE
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
IRIS_OBJ += $(OPENAIR_TARGETS)/ARCH/IRIS/USERSPACE/LIB/iris_lib.o
|
||||||
|
IRIS_FILE_OBJ += $(OPENAIR_TARGETS)/ARCH/IRIS/USERSPACE/LIB/iris_lib.cpp
|
||||||
|
IRIS_CFLAGS += -I$(OPENAIR_TARGETS)/ARCH/COMMON -I$(OPENAIR_TARGETS)/ARCH/IRIS/USERSPACE/LIB/ -I$(OPENAIR_TARGETS)/COMMON
|
||||||
|
|
||||||
@@ -0,0 +1,847 @@
|
|||||||
|
|
||||||
|
/** iris_lib.cpp
|
||||||
|
*
|
||||||
|
* \author: Rahman Doost-Mohammady : doost@rice.edu
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <SoapySDR/Device.hpp>
|
||||||
|
#include <SoapySDR/Formats.hpp>
|
||||||
|
#include <SoapySDR/Time.hpp>
|
||||||
|
//#include <boost/format.hpp>
|
||||||
|
#include <iostream>
|
||||||
|
#include <complex>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <time.h>
|
||||||
|
#include <limits>
|
||||||
|
#include "common/utils/LOG/log_extern.h"
|
||||||
|
#include "common_lib.h"
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
|
#ifdef __SSE4_1__
|
||||||
|
# include <smmintrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __AVX2__
|
||||||
|
# include <immintrin.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SAMPLE_RATE_DOWN 1
|
||||||
|
|
||||||
|
/*! \brief Iris Configuration */
|
||||||
|
typedef struct {
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// variables for Iris configuration
|
||||||
|
// --------------------------------
|
||||||
|
//! Iris device pointer
|
||||||
|
std::vector<SoapySDR::Device *> iris;
|
||||||
|
int device_num;
|
||||||
|
int rx_num_channels;
|
||||||
|
int tx_num_channels;
|
||||||
|
//create a send streamer and a receive streamer
|
||||||
|
//! Iris TX Stream
|
||||||
|
std::vector<SoapySDR::Stream *> txStream;
|
||||||
|
//! Iris RX Stream
|
||||||
|
std::vector<SoapySDR::Stream *> rxStream;
|
||||||
|
|
||||||
|
//! Sampling rate
|
||||||
|
double sample_rate;
|
||||||
|
|
||||||
|
//! time offset between transmiter timestamp and receiver timestamp;
|
||||||
|
double tdiff;
|
||||||
|
|
||||||
|
//! TX forward samples.
|
||||||
|
int tx_forward_nsamps; //166 for 20Mhz
|
||||||
|
|
||||||
|
|
||||||
|
// --------------------------------
|
||||||
|
// Debug and output control
|
||||||
|
// --------------------------------
|
||||||
|
//! Number of underflows
|
||||||
|
int num_underflows;
|
||||||
|
//! Number of overflows
|
||||||
|
int num_overflows;
|
||||||
|
|
||||||
|
//! Number of sequential errors
|
||||||
|
int num_seq_errors;
|
||||||
|
//! tx count
|
||||||
|
int64_t tx_count;
|
||||||
|
//! rx count
|
||||||
|
int64_t rx_count;
|
||||||
|
//! timestamp of RX packet
|
||||||
|
openair0_timestamp rx_timestamp;
|
||||||
|
|
||||||
|
} iris_state_t;
|
||||||
|
|
||||||
|
/*! \brief Called to start the Iris lime transceiver. Return 0 if OK, < 0 if error
|
||||||
|
@param device pointer to the device structure specific to the RF hardware target
|
||||||
|
*/
|
||||||
|
static int trx_iris_start(openair0_device *device) {
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
|
||||||
|
long long timeNs = s->iris[0]->getHardwareTime("") + 500000;
|
||||||
|
int flags = 0;
|
||||||
|
//flags |= SOAPY_SDR_HAS_TIME;
|
||||||
|
int r;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
int ret = s->iris[r]->activateStream(s->rxStream[r], flags, timeNs, 0);
|
||||||
|
int ret2 = s->iris[r]->activateStream(s->txStream[r]);
|
||||||
|
if (ret < 0 | ret2 < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Stop Iris
|
||||||
|
* \param card refers to the hardware index to use
|
||||||
|
*/
|
||||||
|
int trx_iris_stop(openair0_device *device) {
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
int r;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
s->iris[r]->deactivateStream(s->txStream[r]);
|
||||||
|
s->iris[r]->deactivateStream(s->rxStream[r]);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Terminate operation of the Iris lime transceiver -- free all associated resources
|
||||||
|
* \param device the hardware to use
|
||||||
|
*/
|
||||||
|
static void trx_iris_end(openair0_device *device) {
|
||||||
|
LOG_I(HW, "Closing Iris device.\n");
|
||||||
|
trx_iris_stop(device);
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
int r;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
s->iris[r]->closeStream(s->txStream[r]);
|
||||||
|
s->iris[r]->closeStream(s->rxStream[r]);
|
||||||
|
SoapySDR::Device::unmake(s->iris[r]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Called to send samples to the Iris RF target
|
||||||
|
@param device pointer to the device structure specific to the RF hardware target
|
||||||
|
@param timestamp The timestamp at whicch the first sample MUST be sent
|
||||||
|
@param buff Buffer which holds the samples
|
||||||
|
@param nsamps number of samples to be sent
|
||||||
|
@param antenna_id index of the antenna if the device has multiple anteannas
|
||||||
|
@param flags flags must be set to TRUE if timestamp parameter needs to be applied
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
trx_iris_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
|
||||||
|
using namespace std::chrono;
|
||||||
|
static long long int loop = 0;
|
||||||
|
static long time_min = 0, time_max = 0, time_avg = 0;
|
||||||
|
struct timespec tp_start, tp_end;
|
||||||
|
long time_diff;
|
||||||
|
|
||||||
|
int ret = 0, ret_i = 0;
|
||||||
|
int flag = 0;
|
||||||
|
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
int nsamps2; // aligned to upper 32 or 16 byte boundary
|
||||||
|
#if defined(__x86_64) || defined(__i386__)
|
||||||
|
#ifdef __AVX2__
|
||||||
|
nsamps2 = (nsamps+7)>>3;
|
||||||
|
__m256i buff_tx[2][nsamps2];
|
||||||
|
#else
|
||||||
|
nsamps2 = (nsamps+3)>>2;
|
||||||
|
__m128i buff_tx[2][nsamps2];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// bring RX data into 12 LSBs for softmodem RX
|
||||||
|
for (int i=0; i<cc; i++) {
|
||||||
|
for (int j=0; j<nsamps2; j++) {
|
||||||
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
#ifdef __AVX2__
|
||||||
|
buff_tx[i][j] = _mm256_slli_epi16(((__m256i *)buff[i])[j],4);
|
||||||
|
#else
|
||||||
|
buff_tx[i][j] = _mm_slli_epi16(((__m128i *)buff[i])[j],4);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC_RAW, &tp_start);
|
||||||
|
|
||||||
|
// This hack was added by cws to help keep packets flowing
|
||||||
|
|
||||||
|
if (flags)
|
||||||
|
flag |= SOAPY_SDR_HAS_TIME;
|
||||||
|
else {
|
||||||
|
long long tempHack = s->iris[0]->getHardwareTime("");
|
||||||
|
return nsamps;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags == 2 || flags == 1) { // start of burst
|
||||||
|
|
||||||
|
} else if (flags == 3 | flags == 4) {
|
||||||
|
flag |= SOAPY_SDR_END_BURST;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long long timeNs = SoapySDR::ticksToTimeNs(timestamp, s->sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
uint32_t *samps[2]; //= (uint32_t **)buff;
|
||||||
|
int r;
|
||||||
|
int m = s->tx_num_channels;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
int samples_sent = 0;
|
||||||
|
samps[0] = (uint32_t *) buff_tx[m * r];
|
||||||
|
|
||||||
|
if (cc % 2 == 0)
|
||||||
|
samps[1] = (uint32_t *) buff_tx[m * r + 1]; //cws: it seems another thread can clobber these, so we need to save them locally.
|
||||||
|
#ifdef IRIS_DEBUG
|
||||||
|
int i;
|
||||||
|
for (i = 200; i < 216; i++)
|
||||||
|
printf("%d, ",((int16_t)(samps[0][i]>>16))>>4);
|
||||||
|
printf("\n");
|
||||||
|
//printf("\nHardware time before write: %lld, tx_time_stamp: %lld\n", s->iris[0]->getHardwareTime(""), timeNs);
|
||||||
|
#endif
|
||||||
|
ret = s->iris[r]->writeStream(s->txStream[r], (void **) samps, (size_t)(nsamps), flag, timeNs, 1000000);
|
||||||
|
|
||||||
|
if (ret < 0)
|
||||||
|
printf("Unable to write stream!\n");
|
||||||
|
else
|
||||||
|
samples_sent = ret;
|
||||||
|
|
||||||
|
|
||||||
|
if (samples_sent != nsamps)
|
||||||
|
printf("[xmit] tx samples %d != %d\n", samples_sent, nsamps);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return nsamps;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Receive samples from hardware.
|
||||||
|
* Read \ref nsamps samples from each channel to buffers. buff[0] is the array for
|
||||||
|
* the first channel. *ptimestamp is the time at which the first sample
|
||||||
|
* was received.
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \param[out] ptimestamp the time at which the first sample was received.
|
||||||
|
* \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps.
|
||||||
|
* \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte.
|
||||||
|
* \param antenna_id Index of antenna for which to receive samples
|
||||||
|
* \returns the number of sample read
|
||||||
|
*/
|
||||||
|
static int trx_iris_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
|
||||||
|
int ret = 0;
|
||||||
|
static long long nextTime;
|
||||||
|
static bool nextTimeValid = false;
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
bool time_set = false;
|
||||||
|
long long timeNs = 0;
|
||||||
|
int flags;
|
||||||
|
int samples_received;
|
||||||
|
uint32_t *samps[2]; //= (uint32_t **)buff;
|
||||||
|
|
||||||
|
int r;
|
||||||
|
int m = s->rx_num_channels;
|
||||||
|
int nsamps2; // aligned to upper 32 or 16 byte boundary
|
||||||
|
#if defined(__x86_64) || defined(__i386__)
|
||||||
|
#ifdef __AVX2__
|
||||||
|
nsamps2 = (nsamps+7)>>3;
|
||||||
|
__m256i buff_tmp[2][nsamps2];
|
||||||
|
#else
|
||||||
|
nsamps2 = (nsamps+3)>>2;
|
||||||
|
__m128i buff_tmp[2][nsamps2];
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
flags = 0;
|
||||||
|
samples_received = 0;
|
||||||
|
samps[0] = (uint32_t *) buff_tmp[m * r];
|
||||||
|
if (cc % 2 == 0)
|
||||||
|
samps[1] = (uint32_t *) buff_tmp[m * r + 1];
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
ret = s->iris[r]->readStream(s->rxStream[r], (void **) samps, (size_t)(nsamps), flags,
|
||||||
|
timeNs, 1000000);
|
||||||
|
if (ret < 0) {
|
||||||
|
if (ret == SOAPY_SDR_TIME_ERROR)
|
||||||
|
printf("[recv] Time Error in tx stream!\n");
|
||||||
|
else if (ret == SOAPY_SDR_OVERFLOW | (flags & SOAPY_SDR_END_ABRUPT))
|
||||||
|
printf("[recv] Overflow occured!\n");
|
||||||
|
else if (ret == SOAPY_SDR_TIMEOUT)
|
||||||
|
printf("[recv] Timeout occured!\n");
|
||||||
|
else if (ret == SOAPY_SDR_STREAM_ERROR)
|
||||||
|
printf("[recv] Stream (tx) error occured!\n");
|
||||||
|
else if (ret == SOAPY_SDR_CORRUPTION)
|
||||||
|
printf("[recv] Bad packet occured!\n");
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
samples_received = ret;
|
||||||
|
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
if (samples_received == ret) // first batch
|
||||||
|
{
|
||||||
|
if (flags & SOAPY_SDR_HAS_TIME) {
|
||||||
|
s->rx_timestamp = SoapySDR::timeNsToTicks(timeNs, s->sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
*ptimestamp = s->rx_timestamp;
|
||||||
|
nextTime = timeNs;
|
||||||
|
nextTimeValid = true;
|
||||||
|
time_set = true;
|
||||||
|
//printf("1) time set %llu \n", *ptimestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
if (samples_received == nsamps) {
|
||||||
|
|
||||||
|
if (flags & SOAPY_SDR_HAS_TIME) {
|
||||||
|
s->rx_timestamp = SoapySDR::timeNsToTicks(nextTime, s->sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
*ptimestamp = s->rx_timestamp;
|
||||||
|
nextTime = timeNs;
|
||||||
|
nextTimeValid = true;
|
||||||
|
time_set = true;
|
||||||
|
}
|
||||||
|
} else if (samples_received < nsamps)
|
||||||
|
printf("[recv] received %d samples out of %d\n", samples_received, nsamps);
|
||||||
|
|
||||||
|
s->rx_count += samples_received;
|
||||||
|
|
||||||
|
if (s->sample_rate != 0 && nextTimeValid) {
|
||||||
|
if (!time_set) {
|
||||||
|
s->rx_timestamp = SoapySDR::timeNsToTicks(nextTime, s->sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
*ptimestamp = s->rx_timestamp;
|
||||||
|
//printf("2) time set %llu, nextTime will be %llu \n", *ptimestamp, nextTime);
|
||||||
|
}
|
||||||
|
nextTime += SoapySDR::ticksToTimeNs(samples_received, s->sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// bring RX data into 12 LSBs for softmodem RX
|
||||||
|
for (int i=0; i<cc; i++) {
|
||||||
|
for (int j=0; j<nsamps2; j++) {
|
||||||
|
#if defined(__x86_64__) || defined(__i386__)
|
||||||
|
#ifdef __AVX2__
|
||||||
|
((__m256i *)buff[i])[j] = _mm256_srai_epi16(buff_tmp[i][j],4);
|
||||||
|
#else
|
||||||
|
((__m128i *)buff[i])[j] = _mm_srai_epi16(buff_tmp[i][j],4);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return samples_received;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Get current timestamp of Iris
|
||||||
|
* \param device the hardware to use
|
||||||
|
*/
|
||||||
|
openair0_timestamp get_iris_time(openair0_device *device) {
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
return SoapySDR::timeNsToTicks(s->iris[0]->getHardwareTime(""), s->sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Compares two variables within precision
|
||||||
|
* \param a first variable
|
||||||
|
* \param b second variable
|
||||||
|
*/
|
||||||
|
static bool is_equal(double a, double b) {
|
||||||
|
return std::fabs(a - b) < std::numeric_limits<double>::epsilon();
|
||||||
|
}
|
||||||
|
|
||||||
|
void *set_freq_thread(void *arg) {
|
||||||
|
|
||||||
|
openair0_device *device = (openair0_device *) arg;
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
int r, i;
|
||||||
|
printf("Setting Iris TX Freq %f, RX Freq %f\n", device->openair0_cfg[0].tx_freq[0],
|
||||||
|
device->openair0_cfg[0].rx_freq[0]);
|
||||||
|
// add check for the number of channels in the cfg
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
|
||||||
|
if (i < s->rx_num_channels)
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", device->openair0_cfg[0].rx_freq[i]);
|
||||||
|
}
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
|
||||||
|
if (i < s->tx_num_channels)
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", device->openair0_cfg[0].tx_freq[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Set frequencies (TX/RX)
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \param openair0_cfg RF frontend parameters set by application
|
||||||
|
* \param dummy dummy variable not used
|
||||||
|
* \returns 0 in success
|
||||||
|
*/
|
||||||
|
int trx_iris_set_freq(openair0_device *device, openair0_config_t *openair0_cfg, int dont_block) {
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
pthread_t f_thread;
|
||||||
|
if (dont_block)
|
||||||
|
pthread_create(&f_thread, NULL, set_freq_thread, (void *) device);
|
||||||
|
else {
|
||||||
|
int r, i;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
printf("Setting Iris TX Freq %f, RX Freq %f\n", openair0_cfg[0].tx_freq[0], openair0_cfg[0].rx_freq[0]);
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
|
||||||
|
if (i < s->rx_num_channels) {
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
|
||||||
|
if (i < s->tx_num_channels) {
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Set Gains (TX/RX)
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \param openair0_cfg RF frontend parameters set by application
|
||||||
|
* \returns 0 in success
|
||||||
|
*/
|
||||||
|
int trx_iris_set_gains(openair0_device *device,
|
||||||
|
openair0_config_t *openair0_cfg) {
|
||||||
|
iris_state_t *s = (iris_state_t *) device->priv;
|
||||||
|
int r;
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, 0, openair0_cfg[0].rx_gain[0]);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, 0, openair0_cfg[0].tx_gain[0]);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, 1, openair0_cfg[0].rx_gain[1]);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, 1, openair0_cfg[0].tx_gain[1]);
|
||||||
|
}
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Iris RX calibration table */
|
||||||
|
rx_gain_calib_table_t calib_table_iris[] = {
|
||||||
|
{3500000000.0, 83},
|
||||||
|
{2660000000.0, 83},
|
||||||
|
{2580000000.0, 83},
|
||||||
|
{2300000000.0, 83},
|
||||||
|
{1880000000.0, 83},
|
||||||
|
{816000000.0, 83},
|
||||||
|
{-1, 0}};
|
||||||
|
|
||||||
|
|
||||||
|
/*! \brief Set RX gain offset
|
||||||
|
* \param openair0_cfg RF frontend parameters set by application
|
||||||
|
* \param chain_index RF chain to apply settings to
|
||||||
|
* \returns 0 in success
|
||||||
|
*/
|
||||||
|
void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index, int bw_gain_adjust) {
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
// loop through calibration table to find best adjustment factor for RX frequency
|
||||||
|
double min_diff = 6e9, diff, gain_adj = 0.0;
|
||||||
|
if (bw_gain_adjust == 1) {
|
||||||
|
switch ((int) openair0_cfg[0].sample_rate) {
|
||||||
|
case 30720000:
|
||||||
|
break;
|
||||||
|
case 23040000:
|
||||||
|
gain_adj = 1.25;
|
||||||
|
break;
|
||||||
|
case 15360000:
|
||||||
|
gain_adj = 3.0;
|
||||||
|
break;
|
||||||
|
case 7680000:
|
||||||
|
gain_adj = 6.0;
|
||||||
|
break;
|
||||||
|
case 3840000:
|
||||||
|
gain_adj = 9.0;
|
||||||
|
break;
|
||||||
|
case 1920000:
|
||||||
|
gain_adj = 12.0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("unknown sampling rate %d\n", (int) openair0_cfg[0].sample_rate);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
while (openair0_cfg->rx_gain_calib_table[i].freq > 0) {
|
||||||
|
diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq);
|
||||||
|
printf("cal %d: freq %f, offset %f, diff %f\n",
|
||||||
|
i,
|
||||||
|
openair0_cfg->rx_gain_calib_table[i].freq,
|
||||||
|
openair0_cfg->rx_gain_calib_table[i].offset, diff);
|
||||||
|
if (min_diff > diff) {
|
||||||
|
min_diff = diff;
|
||||||
|
openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset + gain_adj;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief print the Iris statistics
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \returns 0 on success
|
||||||
|
*/
|
||||||
|
int trx_iris_get_stats(openair0_device *device) {
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Reset the Iris statistics
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \returns 0 on success
|
||||||
|
*/
|
||||||
|
int trx_iris_reset_stats(openair0_device *device) {
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
/*! \brief Initialize Openair Iris target. It returns 0 if OK
|
||||||
|
* \param device the hardware to use
|
||||||
|
* \param openair0_cfg RF frontend parameters set by application
|
||||||
|
*/
|
||||||
|
int device_init(openair0_device *device, openair0_config_t *openair0_cfg) {
|
||||||
|
|
||||||
|
size_t i, r, card;
|
||||||
|
int bw_gain_adjust = 0;
|
||||||
|
openair0_cfg[0].rx_gain_calib_table = calib_table_iris;
|
||||||
|
iris_state_t *s = (iris_state_t *) malloc(sizeof(iris_state_t));
|
||||||
|
memset(s, 0, sizeof(iris_state_t));
|
||||||
|
|
||||||
|
std::string devFE("DEV");
|
||||||
|
std::string cbrsFE("CBRS");
|
||||||
|
std::string wireFormat("WIRE");
|
||||||
|
|
||||||
|
// Initialize Iris device
|
||||||
|
device->openair0_cfg = openair0_cfg;
|
||||||
|
SoapySDR::Kwargs args;
|
||||||
|
args["driver"] = "iris";
|
||||||
|
char *iris_addrs = device->openair0_cfg[0].sdr_addrs;
|
||||||
|
if (iris_addrs == NULL)
|
||||||
|
{
|
||||||
|
s->iris.push_back(SoapySDR::Device::make(args));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char *serial = strtok(iris_addrs, ",");
|
||||||
|
while (serial != NULL) {
|
||||||
|
LOG_I(HW, "Attempting to open Iris device %s\n", serial);
|
||||||
|
args["serial"] = serial;
|
||||||
|
s->iris.push_back(SoapySDR::Device::make(args));
|
||||||
|
serial = strtok(NULL, ",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
s->device_num = s->iris.size();
|
||||||
|
device->type = IRIS_DEV;
|
||||||
|
|
||||||
|
|
||||||
|
switch ((int) openair0_cfg[0].sample_rate) {
|
||||||
|
case 30720000:
|
||||||
|
//openair0_cfg[0].samples_per_packet = 1024;
|
||||||
|
openair0_cfg[0].tx_sample_advance = 115;
|
||||||
|
openair0_cfg[0].tx_bw = 20e6;
|
||||||
|
openair0_cfg[0].rx_bw = 20e6;
|
||||||
|
break;
|
||||||
|
case 23040000:
|
||||||
|
//openair0_cfg[0].samples_per_packet = 1024;
|
||||||
|
openair0_cfg[0].tx_sample_advance = 113;
|
||||||
|
openair0_cfg[0].tx_bw = 15e6;
|
||||||
|
openair0_cfg[0].rx_bw = 15e6;
|
||||||
|
break;
|
||||||
|
case 15360000:
|
||||||
|
//openair0_cfg[0].samples_per_packet = 1024;
|
||||||
|
openair0_cfg[0].tx_sample_advance = 60;
|
||||||
|
openair0_cfg[0].tx_bw = 10e6;
|
||||||
|
openair0_cfg[0].rx_bw = 10e6;
|
||||||
|
break;
|
||||||
|
case 7680000:
|
||||||
|
//openair0_cfg[0].samples_per_packet = 1024;
|
||||||
|
openair0_cfg[0].tx_sample_advance = 30;
|
||||||
|
openair0_cfg[0].tx_bw = 5e6;
|
||||||
|
openair0_cfg[0].rx_bw = 5e6;
|
||||||
|
break;
|
||||||
|
case 1920000:
|
||||||
|
//openair0_cfg[0].samples_per_packet = 1024;
|
||||||
|
openair0_cfg[0].tx_sample_advance = 20;
|
||||||
|
openair0_cfg[0].tx_bw = 1.4e6;
|
||||||
|
openair0_cfg[0].rx_bw = 1.4e6;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Error: unknown sampling rate %f\n", openair0_cfg[0].sample_rate);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("tx_sample_advance %d\n", openair0_cfg[0].tx_sample_advance);
|
||||||
|
s->rx_num_channels = openair0_cfg[0].rx_num_channels;
|
||||||
|
s->tx_num_channels = openair0_cfg[0].tx_num_channels;
|
||||||
|
if ((s->rx_num_channels == 1 || s->rx_num_channels == 2) && (s->tx_num_channels == 1 || s->tx_num_channels == 2))
|
||||||
|
printf("Enabling %d rx and %d tx channel(s) on each device...\n", s->rx_num_channels, s->tx_num_channels);
|
||||||
|
else {
|
||||||
|
printf("Invalid rx or tx number of channels (%d, %d)\n", s->rx_num_channels, s->tx_num_channels);
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (r = 0; r < s->device_num; r++) {
|
||||||
|
switch ((int) openair0_cfg[0].sample_rate) {
|
||||||
|
case 1920000:
|
||||||
|
s->iris[r]->setMasterClockRate(256 * openair0_cfg[0].sample_rate);
|
||||||
|
break;
|
||||||
|
case 3840000:
|
||||||
|
s->iris[r]->setMasterClockRate(128 * openair0_cfg[0].sample_rate);
|
||||||
|
break;
|
||||||
|
case 7680000:
|
||||||
|
s->iris[r]->setMasterClockRate(64 * openair0_cfg[0].sample_rate);
|
||||||
|
break;
|
||||||
|
case 15360000:
|
||||||
|
s->iris[r]->setMasterClockRate(32 * openair0_cfg[0].sample_rate);
|
||||||
|
break;
|
||||||
|
case 30720000:
|
||||||
|
s->iris[r]->setMasterClockRate(16 * openair0_cfg[0].sample_rate);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf("Error: unknown sampling rate %f\n", openair0_cfg[0].sample_rate);
|
||||||
|
exit(-1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// display Iris settings
|
||||||
|
printf("Actual master clock: %fMHz...\n", (s->iris[r]->getMasterClockRate() / 1e6));
|
||||||
|
|
||||||
|
/* Setting TX/RX BW after streamers are created due to iris calibration issue */
|
||||||
|
for (i = 0; i < s->tx_num_channels; i++) {
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX)) {
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0)
|
||||||
|
s->iris[r]->setBandwidth(SOAPY_SDR_TX, i, 30e6);
|
||||||
|
else
|
||||||
|
s->iris[r]->setBandwidth(SOAPY_SDR_TX, i, openair0_cfg[0].tx_bw);
|
||||||
|
|
||||||
|
printf("Setting tx bandwidth on channel %lu/%lu: BW %f (readback %f)\n", i,
|
||||||
|
s->iris[r]->getNumChannels(SOAPY_SDR_TX), openair0_cfg[0].tx_bw / 1e6,
|
||||||
|
s->iris[r]->getBandwidth(SOAPY_SDR_TX, i) / 1e6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < s->rx_num_channels; i++) {
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX)) {
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0)
|
||||||
|
s->iris[r]->setBandwidth(SOAPY_SDR_TX, i, 30e6);
|
||||||
|
else
|
||||||
|
s->iris[r]->setBandwidth(SOAPY_SDR_RX, i, openair0_cfg[0].rx_bw);
|
||||||
|
printf("Setting rx bandwidth on channel %lu/%lu : BW %f (readback %f)\n", i,
|
||||||
|
s->iris[r]->getNumChannels(SOAPY_SDR_RX), openair0_cfg[0].rx_bw / 1e6,
|
||||||
|
s->iris[r]->getBandwidth(SOAPY_SDR_RX, i) / 1e6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
|
||||||
|
if (i < s->rx_num_channels) {
|
||||||
|
s->iris[r]->setSampleRate(SOAPY_SDR_RX, i, openair0_cfg[0].sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_RX, i, "RF", openair0_cfg[0].rx_freq[i]);
|
||||||
|
|
||||||
|
set_rx_gain_offset(&openair0_cfg[0], i, bw_gain_adjust);
|
||||||
|
//s->iris[r]->setGain(SOAPY_SDR_RX, i, openair0_cfg[0].rx_gain[i] - openair0_cfg[0].rx_gain_offset[i]);
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0) {
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "LNA", openair0_cfg[0].rx_gain[i] - openair0_cfg[0].rx_gain_offset[i]);
|
||||||
|
//s->iris[r]->setGain(SOAPY_SDR_RX, i, "LNA", 0);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "LNA1", 30);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "LNA2", 17);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "TIA", 0);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "PGA", 0);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "ATTN", 0);
|
||||||
|
} else {
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "LNA", openair0_cfg[0].rx_gain[i] - openair0_cfg[0].rx_gain_offset[i]); // [0,30]
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "TIA", 0); // [0,12,6]
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_RX, i, "PGA", 0); // [-12,19,1]
|
||||||
|
//s->iris[r]->setGain(SOAPY_SDR_RX, i, 50); // [-12,19,1]
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
s->iris[r]->setDCOffsetMode(SOAPY_SDR_RX, i, true); // move somewhere else
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
|
||||||
|
if (i < s->tx_num_channels) {
|
||||||
|
s->iris[r]->setSampleRate(SOAPY_SDR_TX, i, openair0_cfg[0].sample_rate / SAMPLE_RATE_DOWN);
|
||||||
|
s->iris[r]->setFrequency(SOAPY_SDR_TX, i, "RF", openair0_cfg[0].tx_freq[i]);
|
||||||
|
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) == 0) {
|
||||||
|
//s->iris[r]->setGain(SOAPY_SDR_TX, i, "PAD", openair0_cfg[0].tx_gain[i]);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "PAD", 52);
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "IAMP", 12);
|
||||||
|
//s->iris[r]->writeSetting("TX_ENABLE_DELAY", "0");
|
||||||
|
//s->iris[r]->writeSetting("TX_DISABLE_DELAY", "100");
|
||||||
|
} else {
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "ATTN", 0); // [-18, 0, 6] dB
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "IAMP", 9); // [-12, 12, 1] dB
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "PAD", 52); //openair0_cfg[0].tx_gain[i]);
|
||||||
|
//s->iris[r]->setGain(SOAPY_SDR_TX, i, "PAD", 35); // [0, 52, 1] dB
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "PA1", 9); // 17 ??? dB
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "PA2", 0); // [0, 17, 17] dB
|
||||||
|
s->iris[r]->setGain(SOAPY_SDR_TX, i, "PA3", 20); // 33 ??? dB
|
||||||
|
s->iris[r]->writeSetting("TX_ENABLE_DELAY", "0");
|
||||||
|
s->iris[r]->writeSetting("TX_DISABLE_DELAY", "100");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (openair0_cfg[0].duplex_mode == 0) {
|
||||||
|
// printf("\nFDD: Enable TX antenna override\n");
|
||||||
|
// s->iris[r]->writeSetting(SOAPY_SDR_TX, i, "TX_ENB_OVERRIDE",
|
||||||
|
// "true"); // From Josh: forces tx switching to be on always transmit regardless of bursts
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
|
||||||
|
if (i < s->rx_num_channels) {
|
||||||
|
|
||||||
|
//if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0) {
|
||||||
|
// printf("\nUsing SKLK calibration...\n");
|
||||||
|
// s->iris[r]->writeSetting(SOAPY_SDR_RX, i, "CALIBRATE", "SKLK");
|
||||||
|
//} else {
|
||||||
|
// s->iris[r]->writeSetting(SOAPY_SDR_RX, i, "CALIBRATE", "");
|
||||||
|
// printf("\nUsing LMS calibration...\n");
|
||||||
|
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_TX); i++) {
|
||||||
|
if (i < s->tx_num_channels) {
|
||||||
|
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0) {
|
||||||
|
printf("\nUsing SKLK calibration...\n");
|
||||||
|
s->iris[r]->writeSetting(SOAPY_SDR_TX, i, "CALIBRATE", "SKLK");
|
||||||
|
|
||||||
|
} else {
|
||||||
|
printf("\nUsing LMS calibration...\n");
|
||||||
|
s->iris[r]->writeSetting(SOAPY_SDR_TX, i, "CALIBRATE", "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) == 0) {
|
||||||
|
for (i = 0; i < s->iris[r]->getNumChannels(SOAPY_SDR_RX); i++) {
|
||||||
|
if (openair0_cfg[0].duplex_mode == 0) {
|
||||||
|
printf("\nFDD: Setting receive antenna to %s\n", s->iris[r]->listAntennas(SOAPY_SDR_RX, i)[1].c_str());
|
||||||
|
if (i < s->rx_num_channels)
|
||||||
|
s->iris[r]->setAntenna(SOAPY_SDR_RX, i, "RX");
|
||||||
|
} else {
|
||||||
|
printf("\nTDD: Setting receive antenna to %s\n", s->iris[r]->listAntennas(SOAPY_SDR_RX, i)[0].c_str());
|
||||||
|
if (i < s->rx_num_channels)
|
||||||
|
s->iris[r]->setAntenna(SOAPY_SDR_RX, i, "TRX");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//s->iris[r]->writeSetting("TX_SW_DELAY", std::to_string(
|
||||||
|
// -openair0_cfg[0].tx_sample_advance)); //should offset switching to compensate for RF path (Lime) delay -- this will eventually be automated
|
||||||
|
|
||||||
|
// create tx & rx streamer
|
||||||
|
//const SoapySDR::Kwargs &arg = SoapySDR::Kwargs();
|
||||||
|
std::map <std::string, std::string> rxStreamArgs;
|
||||||
|
rxStreamArgs["WIRE"] = SOAPY_SDR_CS16;
|
||||||
|
|
||||||
|
std::vector <size_t> channels;
|
||||||
|
for (i = 0; i < s->rx_num_channels; i++)
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX))
|
||||||
|
channels.push_back(i);
|
||||||
|
s->rxStream.push_back(s->iris[r]->setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, channels));//, rxStreamArgs));
|
||||||
|
|
||||||
|
std::vector <size_t> tx_channels = {};
|
||||||
|
for (i = 0; i < s->tx_num_channels; i++)
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX))
|
||||||
|
tx_channels.push_back(i);
|
||||||
|
s->txStream.push_back(s->iris[r]->setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, tx_channels)); //, arg));
|
||||||
|
//s->iris[r]->setHardwareTime(0, "");
|
||||||
|
|
||||||
|
std::cout << "Front end detected: " << s->iris[r]->getHardwareInfo()["frontend"] << "\n";
|
||||||
|
for (i = 0; i < s->rx_num_channels; i++) {
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_RX)) {
|
||||||
|
printf("RX Channel %lu\n", i);
|
||||||
|
printf("Actual RX sample rate: %fMSps...\n", (s->iris[r]->getSampleRate(SOAPY_SDR_RX, i) / 1e6));
|
||||||
|
printf("Actual RX frequency: %fGHz...\n", (s->iris[r]->getFrequency(SOAPY_SDR_RX, i) / 1e9));
|
||||||
|
printf("Actual RX gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i)));
|
||||||
|
printf("Actual RX LNA gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i, "LNA")));
|
||||||
|
printf("Actual RX PGA gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i, "PGA")));
|
||||||
|
printf("Actual RX TIA gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i, "TIA")));
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0) {
|
||||||
|
printf("Actual RX LNA1 gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i, "LNA1")));
|
||||||
|
printf("Actual RX LNA2 gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_RX, i, "LNA2")));
|
||||||
|
}
|
||||||
|
printf("Actual RX bandwidth: %fM...\n", (s->iris[r]->getBandwidth(SOAPY_SDR_RX, i) / 1e6));
|
||||||
|
printf("Actual RX antenna: %s...\n", (s->iris[r]->getAntenna(SOAPY_SDR_RX, i).c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < s->tx_num_channels; i++) {
|
||||||
|
if (i < s->iris[r]->getNumChannels(SOAPY_SDR_TX)) {
|
||||||
|
printf("TX Channel %lu\n", i);
|
||||||
|
printf("Actual TX sample rate: %fMSps...\n", (s->iris[r]->getSampleRate(SOAPY_SDR_TX, i) / 1e6));
|
||||||
|
printf("Actual TX frequency: %fGHz...\n", (s->iris[r]->getFrequency(SOAPY_SDR_TX, i) / 1e9));
|
||||||
|
printf("Actual TX gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i)));
|
||||||
|
printf("Actual TX PAD gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i, "PAD")));
|
||||||
|
printf("Actual TX IAMP gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i, "IAMP")));
|
||||||
|
if (s->iris[r]->getHardwareInfo()["frontend"].compare(devFE) != 0) {
|
||||||
|
printf("Actual TX PA1 gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i, "PA1")));
|
||||||
|
printf("Actual TX PA2 gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i, "PA2")));
|
||||||
|
printf("Actual TX PA3 gain: %f...\n", (s->iris[r]->getGain(SOAPY_SDR_TX, i, "PA3")));
|
||||||
|
}
|
||||||
|
printf("Actual TX bandwidth: %fM...\n", (s->iris[r]->getBandwidth(SOAPY_SDR_TX, i) / 1e6));
|
||||||
|
printf("Actual TX antenna: %s...\n", (s->iris[r]->getAntenna(SOAPY_SDR_TX, i).c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s->iris[0]->writeSetting("SYNC_DELAYS", "");
|
||||||
|
for (r = 0; r < s->device_num; r++)
|
||||||
|
s->iris[r]->setHardwareTime(0, "TRIGGER");
|
||||||
|
s->iris[0]->writeSetting("TRIGGER_GEN", "");
|
||||||
|
for (r = 0; r < s->device_num; r++)
|
||||||
|
printf("Device timestamp: %f...\n", (s->iris[r]->getHardwareTime("TRIGGER") / 1e9));
|
||||||
|
|
||||||
|
device->priv = s;
|
||||||
|
device->trx_start_func = trx_iris_start;
|
||||||
|
device->trx_write_func = trx_iris_write;
|
||||||
|
device->trx_read_func = trx_iris_read;
|
||||||
|
device->trx_get_stats_func = trx_iris_get_stats;
|
||||||
|
device->trx_reset_stats_func = trx_iris_reset_stats;
|
||||||
|
device->trx_end_func = trx_iris_end;
|
||||||
|
device->trx_stop_func = trx_iris_stop;
|
||||||
|
device->trx_set_freq_func = trx_iris_set_freq;
|
||||||
|
device->trx_set_gains_func = trx_iris_set_gains;
|
||||||
|
device->openair0_cfg = openair0_cfg;
|
||||||
|
|
||||||
|
s->sample_rate = openair0_cfg[0].sample_rate;
|
||||||
|
// TODO:
|
||||||
|
// init tx_forward_nsamps based iris_time_offset ex
|
||||||
|
if (is_equal(s->sample_rate, (double) 30.72e6))
|
||||||
|
s->tx_forward_nsamps = 176;
|
||||||
|
if (is_equal(s->sample_rate, (double) 15.36e6))
|
||||||
|
s->tx_forward_nsamps = 90;
|
||||||
|
if (is_equal(s->sample_rate, (double) 7.68e6))
|
||||||
|
s->tx_forward_nsamps = 50;
|
||||||
|
|
||||||
|
LOG_I(HW, "Finished initializing %d Iris device(s).\n", s->device_num);
|
||||||
|
fflush(stdout);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*@}*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
Active_eNBs = ( "eNB_Eurecom_LTEBox");
|
||||||
|
# Asn1_verbosity, choice in: none, info, annoying
|
||||||
|
Asn1_verbosity = "none";
|
||||||
|
|
||||||
|
eNBs =
|
||||||
|
(
|
||||||
|
{
|
||||||
|
////////// Identification parameters:
|
||||||
|
eNB_ID = 0xe00;
|
||||||
|
|
||||||
|
cell_type = "CELL_MACRO_ENB";
|
||||||
|
|
||||||
|
eNB_name = "eNB_Eurecom_LTEBox";
|
||||||
|
|
||||||
|
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||||
|
tracking_area_code = 1;
|
||||||
|
|
||||||
|
plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } );
|
||||||
|
|
||||||
|
tr_s_preference = "local_mac"
|
||||||
|
|
||||||
|
////////// Physical parameters:
|
||||||
|
|
||||||
|
component_carriers = (
|
||||||
|
{
|
||||||
|
node_function = "eNodeB_3GPP";
|
||||||
|
node_timing = "synch_to_ext_device";
|
||||||
|
node_synch_ref = 0;
|
||||||
|
frame_type = "TDD";
|
||||||
|
tdd_config = 3;
|
||||||
|
tdd_config_s = 0;
|
||||||
|
prefix_type = "NORMAL";
|
||||||
|
eutra_band = 38;
|
||||||
|
downlink_frequency = 2580000000L;
|
||||||
|
uplink_frequency_offset = 0;
|
||||||
|
Nid_cell = 10;
|
||||||
|
N_RB_DL = 25;
|
||||||
|
Nid_cell_mbsfn = 0;
|
||||||
|
nb_antenna_ports = 1;
|
||||||
|
nb_antennas_tx = 1;
|
||||||
|
nb_antennas_rx = 1;
|
||||||
|
tx_gain = 52; # [~50 for DEV-FE, ~30 for CBRS-FE]
|
||||||
|
rx_gain = 115; # [115 for DEV-FE, 90 for CBRS-FE]
|
||||||
|
pbch_repetition = "FALSE";
|
||||||
|
prach_root = 0;
|
||||||
|
prach_config_index = 0;
|
||||||
|
prach_high_speed = "DISABLE";
|
||||||
|
prach_zero_correlation = 1;
|
||||||
|
prach_freq_offset = 2;
|
||||||
|
pucch_delta_shift = 1;
|
||||||
|
pucch_nRB_CQI = 1;
|
||||||
|
pucch_nCS_AN = 0;
|
||||||
|
pucch_n1_AN = 32;
|
||||||
|
pdsch_referenceSignalPower = -30;
|
||||||
|
pdsch_p_b = 0;
|
||||||
|
pusch_n_SB = 1;
|
||||||
|
pusch_enable64QAM = "DISABLE";
|
||||||
|
pusch_hoppingMode = "interSubFrame";
|
||||||
|
pusch_hoppingOffset = 0;
|
||||||
|
pusch_groupHoppingEnabled = "ENABLE";
|
||||||
|
pusch_groupAssignment = 0;
|
||||||
|
pusch_sequenceHoppingEnabled = "DISABLE";
|
||||||
|
pusch_nDMRS1 = 1;
|
||||||
|
phich_duration = "NORMAL";
|
||||||
|
phich_resource = "ONESIXTH";
|
||||||
|
srs_enable = "DISABLE";
|
||||||
|
/* srs_BandwidthConfig =;
|
||||||
|
srs_SubframeConfig =;
|
||||||
|
srs_ackNackST =;
|
||||||
|
srs_MaxUpPts =;*/
|
||||||
|
|
||||||
|
pusch_p0_Nominal = -70;
|
||||||
|
pusch_alpha = "AL1";
|
||||||
|
pucch_p0_Nominal = -96;
|
||||||
|
msg3_delta_Preamble = 6;
|
||||||
|
pucch_deltaF_Format1 = "deltaF2";
|
||||||
|
pucch_deltaF_Format1b = "deltaF3";
|
||||||
|
pucch_deltaF_Format2 = "deltaF0";
|
||||||
|
pucch_deltaF_Format2a = "deltaF0";
|
||||||
|
pucch_deltaF_Format2b = "deltaF0";
|
||||||
|
|
||||||
|
rach_numberOfRA_Preambles = 64;
|
||||||
|
rach_preamblesGroupAConfig = "DISABLE";
|
||||||
|
/*
|
||||||
|
rach_sizeOfRA_PreamblesGroupA = ;
|
||||||
|
rach_messageSizeGroupA = ;
|
||||||
|
rach_messagePowerOffsetGroupB = ;
|
||||||
|
*/
|
||||||
|
rach_powerRampingStep = 4;
|
||||||
|
rach_preambleInitialReceivedTargetPower = -96;
|
||||||
|
rach_preambleTransMax = 10;
|
||||||
|
rach_raResponseWindowSize = 10;
|
||||||
|
rach_macContentionResolutionTimer = 48;
|
||||||
|
rach_maxHARQ_Msg3Tx = 4;
|
||||||
|
|
||||||
|
pcch_default_PagingCycle = 128;
|
||||||
|
pcch_nB = "oneT";
|
||||||
|
bcch_modificationPeriodCoeff = 2;
|
||||||
|
ue_TimersAndConstants_t300 = 1000;
|
||||||
|
ue_TimersAndConstants_t301 = 1000;
|
||||||
|
ue_TimersAndConstants_t310 = 1000;
|
||||||
|
ue_TimersAndConstants_t311 = 10000;
|
||||||
|
ue_TimersAndConstants_n310 = 20;
|
||||||
|
ue_TimersAndConstants_n311 = 1;
|
||||||
|
ue_TransmissionMode = 1;
|
||||||
|
|
||||||
|
//Parameters for SIB18
|
||||||
|
rxPool_sc_CP_Len = "normal";
|
||||||
|
rxPool_sc_Period = "sf40";
|
||||||
|
rxPool_data_CP_Len = "normal";
|
||||||
|
rxPool_ResourceConfig_prb_Num = 20;
|
||||||
|
rxPool_ResourceConfig_prb_Start = 5;
|
||||||
|
rxPool_ResourceConfig_prb_End = 44;
|
||||||
|
rxPool_ResourceConfig_offsetIndicator_present = "prSmall";
|
||||||
|
rxPool_ResourceConfig_offsetIndicator_choice = 0;
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_present = "prBs40";
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000";
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
|
||||||
|
/* rxPool_dataHoppingConfig_hoppingParameter = 0;
|
||||||
|
rxPool_dataHoppingConfig_numSubbands = "ns1";
|
||||||
|
rxPool_dataHoppingConfig_rbOffset = 0;
|
||||||
|
rxPool_commTxResourceUC-ReqAllowed = "TRUE";
|
||||||
|
*/
|
||||||
|
// Parameters for SIB19
|
||||||
|
discRxPool_cp_Len = "normal"
|
||||||
|
discRxPool_discPeriod = "rf32"
|
||||||
|
discRxPool_numRetx = 1;
|
||||||
|
discRxPool_numRepetition = 2;
|
||||||
|
discRxPool_ResourceConfig_prb_Num = 5;
|
||||||
|
discRxPool_ResourceConfig_prb_Start = 3;
|
||||||
|
discRxPool_ResourceConfig_prb_End = 21;
|
||||||
|
discRxPool_ResourceConfig_offsetIndicator_present = "prSmall";
|
||||||
|
discRxPool_ResourceConfig_offsetIndicator_choice = 0;
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_present = "prBs40";
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff";
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
srb1_parameters :
|
||||||
|
{
|
||||||
|
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
|
||||||
|
timer_poll_retransmit = 80;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
|
||||||
|
timer_reordering = 35;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
|
||||||
|
timer_status_prohibit = 0;
|
||||||
|
|
||||||
|
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
|
||||||
|
poll_pdu = 4;
|
||||||
|
|
||||||
|
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
|
||||||
|
poll_byte = 99999;
|
||||||
|
|
||||||
|
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
|
||||||
|
max_retx_threshold = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------- SCTP definitions
|
||||||
|
SCTP :
|
||||||
|
{
|
||||||
|
# Number of streams to use in input/output
|
||||||
|
SCTP_INSTREAMS = 2;
|
||||||
|
SCTP_OUTSTREAMS = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////// MME parameters:
|
||||||
|
mme_ip_address = ( { ipv4 = "127.0.0.20";
|
||||||
|
ipv6 = "fe80::d65d:dfff:fe1d:f4d4";
|
||||||
|
active = "yes";
|
||||||
|
preference = "ipv4";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
NETWORK_INTERFACES :
|
||||||
|
{
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1_MME = "eno1";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.10/8";
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1U = "enp5s0";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.10/8";
|
||||||
|
ENB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||||
|
|
||||||
|
ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.10/8";
|
||||||
|
ENB_PORT_FOR_X2C = 36422; # Spec 36422
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
MACRLCs = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_s_preference = "local_L1";
|
||||||
|
tr_n_preference = "local_RRC";
|
||||||
|
phy_test_mode = 0;
|
||||||
|
puSch10xSnr = 200;
|
||||||
|
puCch10xSnr = 200;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
L1s = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_n_preference = "local_mac";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
RUs = (
|
||||||
|
{
|
||||||
|
local_rf = "yes"
|
||||||
|
nb_tx = 1
|
||||||
|
nb_rx = 1
|
||||||
|
att_tx = 0
|
||||||
|
att_rx = 0;
|
||||||
|
bands = [7];
|
||||||
|
max_pdschReferenceSignalPower = -27;
|
||||||
|
max_rxgain = 125;
|
||||||
|
eNB_instances = [0];
|
||||||
|
#sdr_addrs = "RF3C000025";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
NETWORK_CONTROLLER :
|
||||||
|
{
|
||||||
|
FLEXRAN_ENABLED = "no";
|
||||||
|
FLEXRAN_INTERFACE_NAME = "lo";
|
||||||
|
FLEXRAN_IPV4_ADDRESS = "127.0.0.1";
|
||||||
|
FLEXRAN_PORT = 2210;
|
||||||
|
FLEXRAN_CACHE = "/mnt/oai_agent_cache";
|
||||||
|
FLEXRAN_AWAIT_RECONF = "no";
|
||||||
|
};
|
||||||
|
|
||||||
|
THREAD_STRUCT = (
|
||||||
|
{
|
||||||
|
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||||
|
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||||
|
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||||
|
worker_config = "WORKER_ENABLE";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
log_config :
|
||||||
|
{
|
||||||
|
global_log_level ="info";
|
||||||
|
global_log_verbosity ="medium";
|
||||||
|
hw_log_level ="info";
|
||||||
|
hw_log_verbosity ="medium";
|
||||||
|
phy_log_level ="info";
|
||||||
|
phy_log_verbosity ="medium";
|
||||||
|
mac_log_level ="info";
|
||||||
|
mac_log_verbosity ="high";
|
||||||
|
rlc_log_level ="info";
|
||||||
|
rlc_log_verbosity ="medium";
|
||||||
|
pdcp_log_level ="info";
|
||||||
|
pdcp_log_verbosity ="medium";
|
||||||
|
rrc_log_level ="info";
|
||||||
|
rrc_log_verbosity ="medium";
|
||||||
|
};
|
||||||
|
|
||||||
@@ -0,0 +1,264 @@
|
|||||||
|
Active_eNBs = ( "eNB_Eurecom_LTEBox");
|
||||||
|
# Asn1_verbosity, choice in: none, info, annoying
|
||||||
|
Asn1_verbosity = "none";
|
||||||
|
|
||||||
|
eNBs =
|
||||||
|
(
|
||||||
|
{
|
||||||
|
////////// Identification parameters:
|
||||||
|
eNB_ID = 0xe00;
|
||||||
|
|
||||||
|
cell_type = "CELL_MACRO_ENB";
|
||||||
|
|
||||||
|
eNB_name = "eNB_Eurecom_LTEBox";
|
||||||
|
|
||||||
|
// Tracking area code, 0x0000 and 0xfffe are reserved values
|
||||||
|
tracking_area_code = 1;
|
||||||
|
|
||||||
|
plmn_list = ( { mcc = 208; mnc = 92; mnc_length = 2; } );
|
||||||
|
|
||||||
|
tr_s_preference = "local_mac"
|
||||||
|
|
||||||
|
////////// Physical parameters:
|
||||||
|
|
||||||
|
component_carriers = (
|
||||||
|
{
|
||||||
|
node_function = "eNodeB_3GPP";
|
||||||
|
node_timing = "synch_to_ext_device";
|
||||||
|
node_synch_ref = 0;
|
||||||
|
frame_type = "FDD";
|
||||||
|
tdd_config = 3;
|
||||||
|
tdd_config_s = 0;
|
||||||
|
prefix_type = "NORMAL";
|
||||||
|
eutra_band = 7;
|
||||||
|
downlink_frequency = 2660000000L;
|
||||||
|
uplink_frequency_offset = -120000000;
|
||||||
|
Nid_cell = 10;
|
||||||
|
N_RB_DL = 25;
|
||||||
|
Nid_cell_mbsfn = 0;
|
||||||
|
nb_antenna_ports = 1;
|
||||||
|
nb_antennas_tx = 1;
|
||||||
|
nb_antennas_rx = 1;
|
||||||
|
tx_gain = 52; # [~50 for DEV-FE, ~30 for CBRS-FE]
|
||||||
|
rx_gain = 115; # [115 for DEV-FE, 90 for CBRS-FE]
|
||||||
|
pbch_repetition = "FALSE";
|
||||||
|
prach_root = 0;
|
||||||
|
prach_config_index = 0;
|
||||||
|
prach_high_speed = "DISABLE";
|
||||||
|
prach_zero_correlation = 1;
|
||||||
|
prach_freq_offset = 2;
|
||||||
|
pucch_delta_shift = 1;
|
||||||
|
pucch_nRB_CQI = 1;
|
||||||
|
pucch_nCS_AN = 0;
|
||||||
|
pucch_n1_AN = 32;
|
||||||
|
pdsch_referenceSignalPower = -30;
|
||||||
|
pdsch_p_b = 0;
|
||||||
|
pusch_n_SB = 1;
|
||||||
|
pusch_enable64QAM = "DISABLE";
|
||||||
|
pusch_hoppingMode = "interSubFrame";
|
||||||
|
pusch_hoppingOffset = 0;
|
||||||
|
pusch_groupHoppingEnabled = "ENABLE";
|
||||||
|
pusch_groupAssignment = 0;
|
||||||
|
pusch_sequenceHoppingEnabled = "DISABLE";
|
||||||
|
pusch_nDMRS1 = 1;
|
||||||
|
phich_duration = "NORMAL";
|
||||||
|
phich_resource = "ONESIXTH";
|
||||||
|
srs_enable = "DISABLE";
|
||||||
|
/* srs_BandwidthConfig =;
|
||||||
|
srs_SubframeConfig =;
|
||||||
|
srs_ackNackST =;
|
||||||
|
srs_MaxUpPts =;*/
|
||||||
|
|
||||||
|
pusch_p0_Nominal = -70;
|
||||||
|
pusch_alpha = "AL1";
|
||||||
|
pucch_p0_Nominal = -96;
|
||||||
|
msg3_delta_Preamble = 6;
|
||||||
|
pucch_deltaF_Format1 = "deltaF2";
|
||||||
|
pucch_deltaF_Format1b = "deltaF3";
|
||||||
|
pucch_deltaF_Format2 = "deltaF0";
|
||||||
|
pucch_deltaF_Format2a = "deltaF0";
|
||||||
|
pucch_deltaF_Format2b = "deltaF0";
|
||||||
|
|
||||||
|
rach_numberOfRA_Preambles = 64;
|
||||||
|
rach_preamblesGroupAConfig = "DISABLE";
|
||||||
|
/*
|
||||||
|
rach_sizeOfRA_PreamblesGroupA = ;
|
||||||
|
rach_messageSizeGroupA = ;
|
||||||
|
rach_messagePowerOffsetGroupB = ;
|
||||||
|
*/
|
||||||
|
rach_powerRampingStep = 4;
|
||||||
|
rach_preambleInitialReceivedTargetPower = -96;
|
||||||
|
rach_preambleTransMax = 10;
|
||||||
|
rach_raResponseWindowSize = 10;
|
||||||
|
rach_macContentionResolutionTimer = 48;
|
||||||
|
rach_maxHARQ_Msg3Tx = 4;
|
||||||
|
|
||||||
|
pcch_default_PagingCycle = 128;
|
||||||
|
pcch_nB = "oneT";
|
||||||
|
bcch_modificationPeriodCoeff = 2;
|
||||||
|
ue_TimersAndConstants_t300 = 1000;
|
||||||
|
ue_TimersAndConstants_t301 = 1000;
|
||||||
|
ue_TimersAndConstants_t310 = 1000;
|
||||||
|
ue_TimersAndConstants_t311 = 10000;
|
||||||
|
ue_TimersAndConstants_n310 = 20;
|
||||||
|
ue_TimersAndConstants_n311 = 1;
|
||||||
|
ue_TransmissionMode = 1;
|
||||||
|
|
||||||
|
//Parameters for SIB18
|
||||||
|
rxPool_sc_CP_Len = "normal";
|
||||||
|
rxPool_sc_Period = "sf40";
|
||||||
|
rxPool_data_CP_Len = "normal";
|
||||||
|
rxPool_ResourceConfig_prb_Num = 20;
|
||||||
|
rxPool_ResourceConfig_prb_Start = 5;
|
||||||
|
rxPool_ResourceConfig_prb_End = 44;
|
||||||
|
rxPool_ResourceConfig_offsetIndicator_present = "prSmall";
|
||||||
|
rxPool_ResourceConfig_offsetIndicator_choice = 0;
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_present = "prBs40";
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "00000000000000000000";
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
|
||||||
|
rxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
|
||||||
|
/* rxPool_dataHoppingConfig_hoppingParameter = 0;
|
||||||
|
rxPool_dataHoppingConfig_numSubbands = "ns1";
|
||||||
|
rxPool_dataHoppingConfig_rbOffset = 0;
|
||||||
|
rxPool_commTxResourceUC-ReqAllowed = "TRUE";
|
||||||
|
*/
|
||||||
|
// Parameters for SIB19
|
||||||
|
discRxPool_cp_Len = "normal"
|
||||||
|
discRxPool_discPeriod = "rf32"
|
||||||
|
discRxPool_numRetx = 1;
|
||||||
|
discRxPool_numRepetition = 2;
|
||||||
|
discRxPool_ResourceConfig_prb_Num = 5;
|
||||||
|
discRxPool_ResourceConfig_prb_Start = 3;
|
||||||
|
discRxPool_ResourceConfig_prb_End = 21;
|
||||||
|
discRxPool_ResourceConfig_offsetIndicator_present = "prSmall";
|
||||||
|
discRxPool_ResourceConfig_offsetIndicator_choice = 0;
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_present = "prBs40";
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_buf = "f0ffffffff";
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_size = 5;
|
||||||
|
discRxPool_ResourceConfig_subframeBitmap_choice_bs_bits_unused = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
srb1_parameters :
|
||||||
|
{
|
||||||
|
# timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
|
||||||
|
timer_poll_retransmit = 80;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
|
||||||
|
timer_reordering = 35;
|
||||||
|
|
||||||
|
# timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
|
||||||
|
timer_status_prohibit = 0;
|
||||||
|
|
||||||
|
# poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
|
||||||
|
poll_pdu = 4;
|
||||||
|
|
||||||
|
# poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
|
||||||
|
poll_byte = 99999;
|
||||||
|
|
||||||
|
# max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
|
||||||
|
max_retx_threshold = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
# ------- SCTP definitions
|
||||||
|
SCTP :
|
||||||
|
{
|
||||||
|
# Number of streams to use in input/output
|
||||||
|
SCTP_INSTREAMS = 2;
|
||||||
|
SCTP_OUTSTREAMS = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////// MME parameters:
|
||||||
|
mme_ip_address = ( { ipv4 = "127.0.0.20";
|
||||||
|
ipv6 = "fe80::d65d:dfff:fe1d:f4d4";
|
||||||
|
active = "yes";
|
||||||
|
preference = "ipv4";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
NETWORK_INTERFACES :
|
||||||
|
{
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1_MME = "lo";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1_MME = "127.0.0.10/8";
|
||||||
|
ENB_INTERFACE_NAME_FOR_S1U = "lo";
|
||||||
|
ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.10/8";
|
||||||
|
ENB_PORT_FOR_S1U = 2152; # Spec 2152
|
||||||
|
|
||||||
|
ENB_IPV4_ADDRESS_FOR_X2C = "127.0.0.10/8";
|
||||||
|
ENB_PORT_FOR_X2C = 36422; # Spec 36422
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
MACRLCs = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_s_preference = "local_L1";
|
||||||
|
tr_n_preference = "local_RRC";
|
||||||
|
phy_test_mode = 0;
|
||||||
|
puSch10xSnr = 200;
|
||||||
|
puCch10xSnr = 200;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
L1s = (
|
||||||
|
{
|
||||||
|
num_cc = 1;
|
||||||
|
tr_n_preference = "local_mac";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
RUs = (
|
||||||
|
{
|
||||||
|
local_rf = "yes"
|
||||||
|
nb_tx = 1
|
||||||
|
nb_rx = 1
|
||||||
|
att_tx = 0
|
||||||
|
att_rx = 0;
|
||||||
|
bands = [7];
|
||||||
|
max_pdschReferenceSignalPower = -27;
|
||||||
|
max_rxgain = 125;
|
||||||
|
eNB_instances = [0];
|
||||||
|
sdr_addrs = "RF3E000028";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
NETWORK_CONTROLLER :
|
||||||
|
{
|
||||||
|
FLEXRAN_ENABLED = "no";
|
||||||
|
FLEXRAN_INTERFACE_NAME = "lo";
|
||||||
|
FLEXRAN_IPV4_ADDRESS = "127.0.0.1";
|
||||||
|
FLEXRAN_PORT = 2210;
|
||||||
|
FLEXRAN_CACHE = "/mnt/oai_agent_cache";
|
||||||
|
FLEXRAN_AWAIT_RECONF = "no";
|
||||||
|
};
|
||||||
|
|
||||||
|
THREAD_STRUCT = (
|
||||||
|
{
|
||||||
|
#three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
|
||||||
|
parallel_config = "PARALLEL_RU_L1_TRX_SPLIT";
|
||||||
|
#two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
|
||||||
|
worker_config = "WORKER_ENABLE";
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
log_config :
|
||||||
|
{
|
||||||
|
global_log_level ="info";
|
||||||
|
global_log_verbosity ="medium";
|
||||||
|
hw_log_level ="info";
|
||||||
|
hw_log_verbosity ="medium";
|
||||||
|
phy_log_level ="info";
|
||||||
|
phy_log_verbosity ="medium";
|
||||||
|
mac_log_level ="info";
|
||||||
|
mac_log_verbosity ="high";
|
||||||
|
rlc_log_level ="info";
|
||||||
|
rlc_log_verbosity ="medium";
|
||||||
|
pdcp_log_level ="info";
|
||||||
|
pdcp_log_verbosity ="medium";
|
||||||
|
rrc_log_level ="info";
|
||||||
|
rrc_log_verbosity ="medium";
|
||||||
|
};
|
||||||
|
|
||||||
@@ -761,9 +761,9 @@ void rx_rf(RU_t *ru,int *frame,int *subframe) {
|
|||||||
proc->timestamp_rx = ts-ru->ts_offset;
|
proc->timestamp_rx = ts-ru->ts_offset;
|
||||||
|
|
||||||
// AssertFatal(rxs == fp->samples_per_tti,
|
// AssertFatal(rxs == fp->samples_per_tti,
|
||||||
// "rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
|
// "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
|
||||||
if(rxs != fp->samples_per_tti){
|
if(rxs != fp->samples_per_tti){
|
||||||
LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from USRP\n",fp->samples_per_tti,rxs);
|
LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
|
||||||
late_control=STATE_BURST_TERMINATE;
|
late_control=STATE_BURST_TERMINATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user