initial libxtrx support
This commit is contained in:
parent
aa60dda99a
commit
8176f8b811
|
@ -0,0 +1,51 @@
|
|||
cmake_minimum_required(VERSION 2.8)
|
||||
project(osmo-trx C CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
|
||||
# Set the version information here
|
||||
set(MAJOR_VERSION 0)
|
||||
set(API_COMPAT 0)
|
||||
set(MINOR_VERSION 1)
|
||||
set(MAINT_VERSION git)
|
||||
|
||||
set(LIBVER "${MAJOR_VERSION}.${API_COMPAT}.${MINOR_VERSION}")
|
||||
|
||||
include_directories(CommonLibs)
|
||||
include_directories(GSM)
|
||||
|
||||
add_definitions(-Wall -g)
|
||||
|
||||
#set(BUILD_SHARED_LIBS ON)
|
||||
|
||||
CONFIGURE_FILE(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake.in
|
||||
${CMAKE_CURRENT_BINARY_DIR}/config.h
|
||||
@ONLY)
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
option(TRANS_FULL_VERSION "Compile with all Multichannel/Resampler support" OFF)
|
||||
#option(SQLITE_CONFIG "Use config values from SQLite3 database" OFF)
|
||||
set(SQLITE_CONFIG ON)
|
||||
|
||||
if(TRANS_FULL_VERSION)
|
||||
find_package(FFTW)
|
||||
endif(TRANS_FULL_VERSION)
|
||||
|
||||
find_package(XTRX)
|
||||
|
||||
if(SQLITE_CONFIG)
|
||||
find_library(sqlite3 sqlite3)
|
||||
else(SQLITE_CONFIG)
|
||||
add_definitions(-DNO_SQLITE_CONFIG)
|
||||
endif(SQLITE_CONFIG)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||
|
||||
|
||||
add_subdirectory(CommonLibs)
|
||||
add_subdirectory(GSM)
|
||||
add_subdirectory(Transceiver52M)
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
#
|
||||
# Copyright 2008, 2009 Free Software Foundation, Inc.
|
||||
# Copyright 2011, 2012 Range Networks, Inc.
|
||||
#
|
||||
# This software is distributed under the terms of the GNU Public License.
|
||||
# See the COPYING file in the main directory for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
set(EXTRA_DIST example.config README.common)
|
||||
|
||||
set(libcommon_files
|
||||
BitVector.cpp
|
||||
LinkedLists.cpp
|
||||
Sockets.cpp
|
||||
Threads.cpp
|
||||
Timeval.cpp
|
||||
Logger.cpp)
|
||||
|
||||
if(SQLITE_CONFIG)
|
||||
set(libcommon_files
|
||||
${libcommon_files}
|
||||
Configuration.cpp
|
||||
sqlite3util.cpp)
|
||||
endif(SQLITE_CONFIG)
|
||||
|
||||
add_library(common ${libcommon_files})
|
||||
|
||||
add_executable(InterthreadTest InterthreadTest.cpp)
|
||||
target_link_libraries(InterthreadTest common pthread)
|
||||
|
||||
add_executable(SocketsTest SocketsTest.cpp)
|
||||
target_link_libraries(SocketsTest common pthread)
|
||||
|
||||
add_executable(TimevalTest TimevalTest.cpp)
|
||||
target_link_libraries(TimevalTest common)
|
||||
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# Copyright 2008, 2009 Free Software Foundation, Inc.
|
||||
#
|
||||
# This software is distributed under the terms of the GNU Public License.
|
||||
# See the COPYING file in the main directory for details.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program 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 General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
set(libGSM_files GSMCommon.cpp)
|
||||
add_library(GSM ${libGSM_files})
|
||||
|
34
INSTALLATION
34
INSTALLATION
|
@ -1,33 +1 @@
|
|||
Installation Requirements
|
||||
|
||||
|
||||
|
||||
OpenBTS compiles to a simple Unix binary and does not require special
|
||||
installation.
|
||||
|
||||
One some systems (Ubuntu), you will need to define LIBS = -lpthread prior to
|
||||
running configure.
|
||||
|
||||
To run OpenBTS, the following should be installed:
|
||||
|
||||
Asterisk (http://www.asterisk.org), running SIP on port 5060.
|
||||
|
||||
libosip2 (http://www.gnu.org/software/osip/)
|
||||
|
||||
libortp (http://freshmeat.net/projects/ortp/)
|
||||
|
||||
libusrp (http://gnuradio.org).
|
||||
This is part of the GNURadio installation.
|
||||
It is the only part used by OpenBTS.
|
||||
|
||||
|
||||
OpenBTS logs to syslogd as facility LOG_LOCAL7. Please set your /etc/syslog.conf
|
||||
accordingly.
|
||||
|
||||
|
||||
For information on specific executables, see tests/README.tests and
|
||||
apps/README.apps.
|
||||
|
||||
See http://gnuradio.org/redmine/wiki/gnuradio/OpenBTS/BuildingAndRunning for more
|
||||
information.
|
||||
|
||||
This is special branch for XTRX support. It should be configured with cmake, autoconf isn't supported yet.
|
|
@ -0,0 +1,67 @@
|
|||
if(NOT TRANS_FULL_VERSION)
|
||||
add_definitions(-DNO_RESAMPLER)
|
||||
add_definitions(-DNO_MULTIARFCN)
|
||||
endif()
|
||||
|
||||
|
||||
add_subdirectory(x86)
|
||||
include_directories(common)
|
||||
include_directories(".")
|
||||
|
||||
set(COMMON_FILES
|
||||
radioInterface.cpp
|
||||
radioVector.cpp
|
||||
radioClock.cpp
|
||||
radioBuffer.cpp
|
||||
sigProcLib.cpp
|
||||
signalVector.cpp
|
||||
Transceiver.cpp)
|
||||
|
||||
set(libtransceiver_files
|
||||
Resampler.cpp
|
||||
${COMMON_FILES})
|
||||
|
||||
if(TRANS_FULL_VERSION)
|
||||
set(libtransceiver_files
|
||||
${libtransceiver_files}
|
||||
radioInterfaceResamp.cpp
|
||||
radioInterfaceMulti.cpp
|
||||
ChannelizerBase.cpp
|
||||
Channelizer.cpp
|
||||
Synthesis.cpp
|
||||
common/fft.c
|
||||
radioInterfaceDiversity.cpp)
|
||||
endif(TRANS_FULL_VERSION)
|
||||
|
||||
set(noinst_HEADERS
|
||||
Complex.h
|
||||
radioInterface.h
|
||||
radioVector.h
|
||||
radioClock.h
|
||||
radioDevice.h
|
||||
radioBuffer.h
|
||||
sigProcLib.h
|
||||
signalVector.h
|
||||
Transceiver.h
|
||||
USRPDevice.h
|
||||
Resampler.h
|
||||
ChannelizerBase.h
|
||||
Channelizer.h
|
||||
Synthesis.h
|
||||
common/convolve.h
|
||||
common/convert.h
|
||||
common/scale.h
|
||||
common/mult.h
|
||||
common/fft.h)
|
||||
|
||||
add_library(transceiver ${libtransceiver_files})
|
||||
|
||||
|
||||
set(DEVICE XTRXDevice.cpp)
|
||||
set(DEVICE_LIBS ${XTRX_LIBRARIES})
|
||||
set(DEVICE_INC ${XTRX_INCLUDES})
|
||||
|
||||
include_directories(${DEVICE_INC})
|
||||
add_executable(osmo-trx osmo-trx.cpp ${DEVICE})
|
||||
target_link_libraries(osmo-trx transceiver arch GSM common ${sqlite3} ${FFTW_LIBRARIES} ${DEVICE_LIBS} pthread dl)
|
||||
|
|
@ -0,0 +1,397 @@
|
|||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "Threads.h"
|
||||
#include "XTRXDevice.h"
|
||||
|
||||
#include <Logger.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
using namespace std;
|
||||
|
||||
const double defaultRXBandwidth = 2e6;
|
||||
const double defaultTXBandwidth = 3e6;
|
||||
|
||||
static int time_tx_corr = 60; //20+20+20+20+20;
|
||||
|
||||
XTRXDevice::XTRXDevice(size_t txsps, size_t rxsps)
|
||||
{
|
||||
LOG(INFO) << "creating XTRX device...";
|
||||
|
||||
this->txsps = txsps;
|
||||
this->rxsps = rxsps;
|
||||
|
||||
rxGain = 0;
|
||||
|
||||
loopback = false;
|
||||
device = NULL;
|
||||
}
|
||||
|
||||
static int parse_config(const char* line, const char* argument, int default_value)
|
||||
{
|
||||
const char* arg_found = strstr(line, argument);
|
||||
if (!arg_found)
|
||||
return default_value;
|
||||
|
||||
const char* qe_pos = strchr(arg_found, '=');
|
||||
if (!qe_pos)
|
||||
return default_value;
|
||||
|
||||
int res = strtol(qe_pos + 1, NULL, 10);
|
||||
if (res == 0 && errno) {
|
||||
return default_value;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int XTRXDevice::open(const std::string &args, int ref, bool swap_channels)
|
||||
{
|
||||
LOG(INFO) << "opening XTRX device '" << args << "'..";
|
||||
|
||||
int loglevel = parse_config(args.c_str(), "loglevel", 3);
|
||||
int lb_param = parse_config(args.c_str(), "loopback", 0);
|
||||
time_tx_corr = parse_config(args.c_str(), "tcorr", time_tx_corr);
|
||||
int fref = parse_config(args.c_str(), "refclk", 30720000);
|
||||
int rxdec = parse_config(args.c_str(), "rxdec", 0);
|
||||
|
||||
char xtrx_name[500];
|
||||
const char* lend = strchr(args.c_str(), ',');
|
||||
int len = (lend) ? (lend - args.c_str()) : sizeof(xtrx_name) - 1;
|
||||
strncpy(xtrx_name, args.c_str(), len);
|
||||
xtrx_name[len] = 0;
|
||||
|
||||
if (lb_param) {
|
||||
LOG(ALERT) << "XTRX LOOPBACK mode is set!";
|
||||
loopback = true;
|
||||
}
|
||||
|
||||
int res = xtrx_open(xtrx_name, loglevel, &device);
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX creating failed, device " << xtrx_name << " code " << res;
|
||||
return -1;
|
||||
}
|
||||
double actualMasterClock = 0;
|
||||
|
||||
if (fref > 0) {
|
||||
xtrx_set_ref_clk(device, fref, XTRX_CLKSRC_INT);
|
||||
}
|
||||
|
||||
res = xtrx_set_samplerate(device,
|
||||
GSMRATE * (double) std::min(txsps, rxsps) * 32 * 4 * ((rxdec) ? 2 : 1),
|
||||
GSMRATE * (double) rxsps,
|
||||
GSMRATE * (double) txsps,
|
||||
(rxdec) ? XTRX_SAMPLERATE_FORCE_RX_DECIM : 0,
|
||||
&actualMasterClock,
|
||||
&actualRXSampleRate,
|
||||
&actualTXSampleRate);
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX failed to set samplerate RX: " << GSMRATE * (double) rxsps
|
||||
<< " TX: " << GSMRATE * (double) txsps
|
||||
<< " res: " << res;
|
||||
return -1;
|
||||
} else {
|
||||
LOG(INFO) << "XTRX set samplerate Master: " << actualMasterClock
|
||||
<< " RX: " << actualRXSampleRate
|
||||
<< " TX: " << actualTXSampleRate;
|
||||
}
|
||||
|
||||
|
||||
int i;
|
||||
double bw;
|
||||
double actualbw;
|
||||
|
||||
actualbw = 0;
|
||||
bw = defaultRXBandwidth;
|
||||
for (i = 0, res = -1; res && (i < 4); i++, bw *= 1.5) {
|
||||
res = xtrx_tune_rx_bandwidth(device, XTRX_CH_AB, bw, &actualbw);
|
||||
}
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX failed to set RX bandwidth: " << bw
|
||||
<< " res: " << res;
|
||||
return -1;
|
||||
} else {
|
||||
LOG(INFO) << "XTRX set RX bandwidth: " << actualbw;
|
||||
}
|
||||
|
||||
actualbw = 0;
|
||||
bw = defaultTXBandwidth;
|
||||
for (i = 0, res = -1; res && (i < 4); i++, bw *= 1.1) {
|
||||
res = xtrx_tune_tx_bandwidth(device, XTRX_CH_AB, bw, &actualbw);
|
||||
}
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX failed to set TX bandwidth: " << bw
|
||||
<< " res: " << res;
|
||||
return -1;
|
||||
} else {
|
||||
LOG(INFO) << "XTRX set TX bandwidth: " << actualbw;
|
||||
}
|
||||
|
||||
samplesRead = 0;
|
||||
samplesWritten = 0;
|
||||
started = false;
|
||||
|
||||
return NORMAL;
|
||||
}
|
||||
|
||||
XTRXDevice::~XTRXDevice()
|
||||
{
|
||||
if (device) {
|
||||
xtrx_close(device);
|
||||
}
|
||||
}
|
||||
|
||||
bool XTRXDevice::start()
|
||||
{
|
||||
LOG(INFO) << "starting XTRX...";
|
||||
if (started) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dataStart = 0;
|
||||
dataEnd = 0;
|
||||
timeStart = 0;
|
||||
timeEnd = 0;
|
||||
timeRx = initialReadTimestamp();
|
||||
timestampOffset = 0;
|
||||
latestWriteTimestamp = 0;
|
||||
lastPktTimestamp = 0;
|
||||
hi32Timestamp = 0;
|
||||
isAligned = false;
|
||||
|
||||
//xtrx_stop(device, XTRX_TX);
|
||||
//xtrx_stop(device, XTRX_RX);
|
||||
|
||||
xtrx_set_antenna(device, XTRX_TX_L);
|
||||
xtrx_set_antenna(device, XTRX_RX_L);
|
||||
|
||||
xtrx_run_params_t params;
|
||||
params.dir = XTRX_TRX;
|
||||
params.nflags = (loopback) ? XTRX_RUN_DIGLOOPBACK : 0;
|
||||
|
||||
params.rx.chs = XTRX_CH_AB;
|
||||
params.rx.flags = XTRX_RSP_SISO_MODE;
|
||||
params.rx.hfmt = XTRX_IQ_INT16;
|
||||
params.rx.wfmt = XTRX_WF_16;
|
||||
params.rx.paketsize = 625 * rxsps;
|
||||
|
||||
params.tx.chs = XTRX_CH_AB;
|
||||
params.tx.flags = XTRX_RSP_SISO_MODE;
|
||||
params.tx.hfmt = XTRX_IQ_INT16;
|
||||
params.tx.wfmt = XTRX_WF_16;
|
||||
params.tx.paketsize = 625 * txsps;
|
||||
|
||||
if (loopback) {
|
||||
params.tx.flags |= XTRX_RSP_SWAP_AB | XTRX_RSP_SWAP_IQ;
|
||||
}
|
||||
|
||||
params.tx_repeat_buf = NULL;
|
||||
params.rx_stream_start = initialReadTimestamp();
|
||||
|
||||
int res = xtrx_run_ex(device, ¶ms);
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX start failed res: " << res;
|
||||
} else {
|
||||
LOG(INFO) << "XTRX started";
|
||||
started = true;
|
||||
}
|
||||
return started;
|
||||
}
|
||||
|
||||
bool XTRXDevice::stop()
|
||||
{
|
||||
if (started) {
|
||||
int res = xtrx_stop(device, XTRX_TRX);
|
||||
if (res) {
|
||||
LOG(ALERT) << "XTRX stop failed res: " << res;
|
||||
} else {
|
||||
LOG(INFO) << "XTRX stopped";
|
||||
started = false;
|
||||
}
|
||||
}
|
||||
return !started;
|
||||
}
|
||||
|
||||
TIMESTAMP XTRXDevice::initialWriteTimestamp()
|
||||
{
|
||||
if (/*(iface == MULTI_ARFCN) || */(rxsps == txsps))
|
||||
return initialReadTimestamp();
|
||||
else
|
||||
return initialReadTimestamp() * txsps;
|
||||
}
|
||||
|
||||
double XTRXDevice::maxTxGain()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
double XTRXDevice::minTxGain()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double XTRXDevice::maxRxGain()
|
||||
{
|
||||
return 30;
|
||||
}
|
||||
|
||||
double XTRXDevice::minRxGain()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
double XTRXDevice::setTxGain(double dB, size_t chan)
|
||||
{
|
||||
if (chan) {
|
||||
LOG(ALERT) << "Invalid channel " << chan;
|
||||
return 0.0;
|
||||
}
|
||||
double actual = 0;
|
||||
LOG(NOTICE) << "Setting TX gain to " << dB << " dB.";
|
||||
|
||||
int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_TX_PAD_GAIN, -10, &actual);
|
||||
if (res) {
|
||||
LOG(ERR) << "Error setting TX gain res: " << res;
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
|
||||
double XTRXDevice::setRxGain(double dB, size_t chan)
|
||||
{
|
||||
if (chan) {
|
||||
LOG(ALERT) << "Invalid channel " << chan;
|
||||
return 0.0;
|
||||
}
|
||||
double actual = 0;
|
||||
LOG(NOTICE) << "Setting RX gain to " << dB << " dB.";
|
||||
|
||||
int res = xtrx_set_gain(device, XTRX_CH_AB, XTRX_RX_LNA_GAIN, 25, &actual);
|
||||
if (res) {
|
||||
LOG(ERR) << "Error setting RX gain res: " << res;
|
||||
}
|
||||
|
||||
return actual;
|
||||
}
|
||||
|
||||
// NOTE: Assumes sequential reads
|
||||
int XTRXDevice::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
|
||||
TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
|
||||
{
|
||||
if (!started)
|
||||
return -1;
|
||||
|
||||
if (RSSI) {
|
||||
*RSSI = 10; // TODO
|
||||
}
|
||||
|
||||
struct xtrx_recv_ex_info ri;
|
||||
ri.samples = len;
|
||||
ri.buffer_count = bufs.size();
|
||||
ri.buffers = (void* const*)&bufs[0];
|
||||
ri.flags = 0;
|
||||
|
||||
int res = xtrx_recv_sync_ex(device, &ri);
|
||||
if (res) {
|
||||
LOG(ALERT) << "xtrx_recv_sync failed res " << res << " current TS " << timeRx << " req TS" << timestamp;
|
||||
return -1;
|
||||
}
|
||||
timeRx += len;
|
||||
|
||||
// TODO: remove this
|
||||
int i;
|
||||
for (i = 0; i < len * 2; i++)
|
||||
bufs[0][i] <<= 4;
|
||||
|
||||
if (underrun) {
|
||||
*underrun = (ri.out_events & RCVEX_EVENT_FILLED_ZERO);
|
||||
}
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
int XTRXDevice::writeSamples(std::vector<short *> &bufs, int len,
|
||||
bool *underrun, unsigned long long timestamp,
|
||||
bool isControl)
|
||||
{
|
||||
if (!started)
|
||||
return 0;
|
||||
|
||||
xtrx_send_ex_info_t nfo;
|
||||
nfo.buffers = (const void* const*)&bufs[0];
|
||||
nfo.buffer_count = bufs.size();
|
||||
nfo.flags = XTRX_TX_DONT_BUFFER;
|
||||
nfo.samples = len;
|
||||
nfo.ts = timestamp - time_tx_corr;
|
||||
|
||||
int res = xtrx_send_sync_ex(device, &nfo);
|
||||
if (res != 0) {
|
||||
LOG(ALERT) << "xtrx_send_sync_ex returned " << res << " len=" << len << " ts=" << timestamp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (*underrun) {
|
||||
*underrun = (nfo.out_flags & XTRX_TX_DISCARDED_TO);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool XTRXDevice::updateAlignment(TIMESTAMP timestamp)
|
||||
{
|
||||
LOG(ALERT) << "Update Aligment " << timestamp;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XTRXDevice::setTxFreq(double wFreq, size_t chan)
|
||||
{
|
||||
int res;
|
||||
double actual = 0;
|
||||
|
||||
if (chan) {
|
||||
LOG(ALERT) << "Invalid channel " << chan;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((res = xtrx_tune(device, XTRX_TUNE_TX_FDD, wFreq, &actual)) == 0) {
|
||||
LOG(INFO) << "set RX: " << wFreq << std::endl
|
||||
<< " actual freq: " << actual << std::endl;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG(ALERT) << "set RX: " << wFreq << "failed (code: " << res << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool XTRXDevice::setRxFreq(double wFreq, size_t chan)
|
||||
{
|
||||
int res;
|
||||
double actual = 0;
|
||||
|
||||
if (chan) {
|
||||
LOG(ALERT) << "Invalid channel " << chan;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((res = xtrx_tune(device, XTRX_TUNE_RX_FDD, wFreq, &actual)) == 0) {
|
||||
LOG(INFO) << "set RX: " << wFreq << std::endl
|
||||
<< " actual freq: " << actual << std::endl;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
LOG(ALERT) << "set RX: " << wFreq << "failed (code: " << res << ")" << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
RadioDevice *RadioDevice::make(size_t tx_sps, size_t rx_sps, InterfaceType type,
|
||||
size_t chans, double offset)
|
||||
{
|
||||
return new XTRXDevice(tx_sps, rx_sps);
|
||||
}
|
|
@ -0,0 +1,166 @@
|
|||
#ifndef _XTRX_DEVICE_H_
|
||||
#define _XTRX_DEVICE_H_
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "radioDevice.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
#include "Threads.h"
|
||||
#include <xtrx_api.h>
|
||||
|
||||
class XTRXDevice: public RadioDevice {
|
||||
private:
|
||||
int txsps;
|
||||
int rxsps;
|
||||
double actualTXSampleRate; ///< the actual XTRX sampling rate
|
||||
double actualRXSampleRate; ///< the actual XTRX sampling rate
|
||||
//unsigned int decimRate; ///< the XTRX decimation rate
|
||||
//unsigned int interRate; ///< the XTRX decimation rate
|
||||
|
||||
unsigned long long samplesRead; ///< number of samples read from XTRX
|
||||
unsigned long long samplesWritten; ///< number of samples sent to XTRX
|
||||
|
||||
bool started; ///< flag indicates XTRX has started
|
||||
|
||||
short *data;
|
||||
unsigned long dataStart;
|
||||
unsigned long dataEnd;
|
||||
TIMESTAMP timeStart;
|
||||
TIMESTAMP timeEnd;
|
||||
|
||||
TIMESTAMP timeRx;
|
||||
bool isAligned;
|
||||
|
||||
Mutex writeLock;
|
||||
|
||||
short *currData; ///< internal data buffer when reading from XTRX
|
||||
TIMESTAMP currTimestamp; ///< timestamp of internal data buffer
|
||||
unsigned currLen; ///< size of internal data buffer
|
||||
|
||||
TIMESTAMP timestampOffset; ///< timestamp offset b/w Tx and Rx blocks
|
||||
TIMESTAMP latestWriteTimestamp; ///< timestamp of most recent ping command
|
||||
TIMESTAMP pingTimestamp; ///< timestamp of most recent ping response
|
||||
|
||||
unsigned long hi32Timestamp;
|
||||
unsigned long lastPktTimestamp;
|
||||
|
||||
double rxGain;
|
||||
bool loopback;
|
||||
|
||||
#ifdef SWLOOPBACK
|
||||
short loopbackBuffer[1000000];
|
||||
int loopbackBufferSize;
|
||||
double samplePeriod;
|
||||
|
||||
struct timeval startTime;
|
||||
struct timeval lastReadTime;
|
||||
bool firstRead;
|
||||
#endif
|
||||
|
||||
xtrx_dev* device;
|
||||
public:
|
||||
|
||||
/** Object constructor */
|
||||
XTRXDevice(size_t txsps, size_t rxsps);
|
||||
|
||||
~XTRXDevice();
|
||||
|
||||
/** Instantiate the XTRX */
|
||||
int open(const std::string &args, int ref, bool swap_channels);
|
||||
|
||||
/** Start the XTRX */
|
||||
bool start();
|
||||
|
||||
/** Stop the XTRX */
|
||||
bool stop();
|
||||
|
||||
/** Set priority not supported */
|
||||
void setPriority(float prio = 0.5) { }
|
||||
|
||||
enum TxWindowType getWindowType() { return TX_WINDOW_FIXED; }
|
||||
|
||||
/**
|
||||
Read samples from the XTRX.
|
||||
@param buf preallocated buf to contain read result
|
||||
@param len number of samples desired
|
||||
@param overrun Set if read buffer has been overrun, e.g. data not being read fast enough
|
||||
@param timestamp The timestamp of the first samples to be read
|
||||
@param underrun Set if XTRX does not have data to transmit, e.g. data not being sent fast enough
|
||||
@param RSSI The received signal strength of the read result
|
||||
@return The number of samples actually read
|
||||
*/
|
||||
int readSamples(std::vector<short *> &buf, int len, bool *overrun,
|
||||
TIMESTAMP timestamp = 0xffffffff, bool *underrun = NULL,
|
||||
unsigned *RSSI = NULL);
|
||||
/**
|
||||
Write samples to the XTRX.
|
||||
@param buf Contains the data to be written.
|
||||
@param len number of samples to write.
|
||||
@param underrun Set if XTRX does not have data to transmit, e.g. data not being sent fast enough
|
||||
@param timestamp The timestamp of the first sample of the data buffer.
|
||||
@param isControl Set if data is a control packet, e.g. a ping command
|
||||
@return The number of samples actually written
|
||||
*/
|
||||
int writeSamples(std::vector<short *> &bufs, int len, bool *underrun,
|
||||
TIMESTAMP timestamp = 0xffffffff, bool isControl = false);
|
||||
|
||||
/** Update the alignment between the read and write timestamps */
|
||||
bool updateAlignment(TIMESTAMP timestamp);
|
||||
|
||||
/** Set the transmitter frequency */
|
||||
bool setTxFreq(double wFreq, size_t chan = 0);
|
||||
|
||||
/** Set the receiver frequency */
|
||||
bool setRxFreq(double wFreq, size_t chan = 0);
|
||||
|
||||
/** Returns the starting write Timestamp*/
|
||||
TIMESTAMP initialWriteTimestamp(void);
|
||||
|
||||
/** Returns the starting read Timestamp*/
|
||||
TIMESTAMP initialReadTimestamp(void) { return 20000;}
|
||||
|
||||
/** returns the full-scale transmit amplitude **/
|
||||
double fullScaleInputValue() {return (double) 32767*0.7;}
|
||||
|
||||
/** returns the full-scale receive amplitude **/
|
||||
double fullScaleOutputValue() {return (double) 32767;}
|
||||
|
||||
/** sets the receive chan gain, returns the gain setting **/
|
||||
double setRxGain(double dB, size_t chan = 0);
|
||||
|
||||
/** get the current receive gain */
|
||||
double getRxGain(size_t chan = 0) { return rxGain; }
|
||||
|
||||
/** return maximum Rx Gain **/
|
||||
double maxRxGain(void);
|
||||
|
||||
/** return minimum Rx Gain **/
|
||||
double minRxGain(void);
|
||||
|
||||
/** sets the transmit chan gain, returns the gain setting **/
|
||||
double setTxGain(double dB, size_t chan = 0);
|
||||
|
||||
/** return maximum Tx Gain **/
|
||||
double maxTxGain(void);
|
||||
|
||||
/** return minimum Rx Gain **/
|
||||
double minTxGain(void);
|
||||
|
||||
/** Return internal status values */
|
||||
inline double getTxFreq(size_t chan = 0) { return 0; }
|
||||
inline double getRxFreq(size_t chan = 0) { return 0; }
|
||||
inline double getSampleRate() { return actualTXSampleRate; }
|
||||
inline double numberRead() { return samplesRead; }
|
||||
inline double numberWritten() { return samplesWritten; }
|
||||
|
||||
};
|
||||
|
||||
#endif // _XTRX_DEVICE_H_
|
||||
|
|
@ -169,15 +169,19 @@ RadioInterface *makeRadioInterface(struct trx_config *config,
|
|||
radio = new RadioInterface(usrp, config->tx_sps,
|
||||
config->rx_sps, config->chans);
|
||||
break;
|
||||
#ifndef NO_RESAMPLER
|
||||
case RadioDevice::RESAMP_64M:
|
||||
case RadioDevice::RESAMP_100M:
|
||||
radio = new RadioInterfaceResamp(usrp, config->tx_sps,
|
||||
config->rx_sps);
|
||||
break;
|
||||
#endif
|
||||
#ifndef NO_MULTIARFCN
|
||||
case RadioDevice::MULTI_ARFCN:
|
||||
radio = new RadioInterfaceMulti(usrp, config->tx_sps,
|
||||
config->rx_sps, config->chans);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
LOG(ALERT) << "Unsupported radio interface configuration";
|
||||
return NULL;
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
include_directories(../common)
|
||||
|
||||
set(libarch_files
|
||||
../common/convert_base.c
|
||||
../common/convolve_base.c
|
||||
convert.c
|
||||
convolve.c)
|
||||
|
||||
# TODO move to cmakedef
|
||||
add_definitions(-DHAVE___BUILTIN_CPU_SUPPORTS)
|
||||
|
||||
if(HAVE_SSE4_1)
|
||||
add_definitions(-DHAVE_SSE4_1)
|
||||
set(libarch_files ${libarch_files} convert_sse_4_1.c)
|
||||
endif(HAVE_SSE4_1)
|
||||
|
||||
if(HAVE_SSE3)
|
||||
add_definitions(-HAVE_SSE3)
|
||||
set(libarch_files ${libarch_files} convert_sse_3.c convert_sse_3.c)
|
||||
endif(HAVE_SSE3)
|
||||
|
||||
|
||||
add_library(arch ${libarch_files})
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
# - Find the FFTW library
|
||||
#
|
||||
# Usage:
|
||||
# find_package(FFTW [REQUIRED] [QUIET] )
|
||||
#
|
||||
# It sets the following variables:
|
||||
# FFTW_FOUND ... true if fftw is found on the system
|
||||
# FFTW_LIBRARIES ... full path to fftw library
|
||||
# FFTW_INCLUDES ... fftw include directory
|
||||
#
|
||||
# The following variables will be checked by the function
|
||||
# FFTW_USE_STATIC_LIBS ... if true, only static libraries are found
|
||||
# FFTW_ROOT ... if set, the libraries are exclusively searched
|
||||
# under this path
|
||||
# FFTW_LIBRARY ... fftw library to use
|
||||
# FFTW_INCLUDE_DIR ... fftw include directory
|
||||
#
|
||||
#If environment variable FFTWDIR is specified, it has same effect as FFTW_ROOT
|
||||
if( NOT FFTW_ROOT AND ENV{FFTWDIR} )
|
||||
set( FFTW_ROOT $ENV{FFTWDIR} )
|
||||
endif()
|
||||
# Check if we can use PkgConfig
|
||||
find_package(PkgConfig)
|
||||
#Determine from PKG
|
||||
if( PKG_CONFIG_FOUND AND NOT FFTW_ROOT )
|
||||
pkg_check_modules( PKG_FFTW QUIET "fftw3" )
|
||||
endif()
|
||||
#Check whether to search static or dynamic libs
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES} )
|
||||
if( ${FFTW_USE_STATIC_LIBS} )
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} )
|
||||
else()
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX} )
|
||||
endif()
|
||||
if( FFTW_ROOT )
|
||||
#find libs
|
||||
find_library(
|
||||
FFTW_LIB
|
||||
NAMES "fftw3"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_library(
|
||||
FFTWF_LIB
|
||||
NAMES "fftw3f"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
find_library(
|
||||
FFTWL_LIB
|
||||
NAMES "fftw3l"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
#find includes
|
||||
find_path(
|
||||
FFTW_INCLUDES
|
||||
NAMES "fftw3.h"
|
||||
PATHS ${FFTW_ROOT}
|
||||
PATH_SUFFIXES "include"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
else()
|
||||
find_library(
|
||||
FFTW_LIB
|
||||
NAMES "fftw3"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
find_library(
|
||||
FFTWF_LIB
|
||||
NAMES "fftw3f"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
find_library(
|
||||
FFTWL_LIB
|
||||
NAMES "fftw3l"
|
||||
PATHS ${PKG_FFTW_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
find_path(
|
||||
FFTW_INCLUDES
|
||||
NAMES "fftw3.h"
|
||||
PATHS ${PKG_FFTW_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
endif( FFTW_ROOT )
|
||||
set(FFTW_LIBRARIES ${FFTW_LIB} ${FFTWF_LIB})
|
||||
if(FFTWL_LIB)
|
||||
set(FFTW_LIBRARIES ${FFTW_LIBRARIES} ${FFTWL_LIB})
|
||||
endif()
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} )
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FFTW DEFAULT_MSG
|
||||
FFTW_INCLUDES FFTW_LIBRARIES)
|
||||
mark_as_advanced(FFTW_INCLUDES FFTW_LIBRARIES FFTW_LIB FFTWF_LIB FFTWL_LIB)
|
|
@ -0,0 +1,69 @@
|
|||
# - Find the XTRX library
|
||||
#
|
||||
# Usage:
|
||||
# find_package(XTRX [REQUIRED] [QUIET] )
|
||||
#
|
||||
# It sets the following variables:
|
||||
# XTRX_FOUND ... true if XTRX is found on the system
|
||||
# XTRX_LIBRARIES ... full path to XTRX library
|
||||
# XTRX_INCLUDES ... XTRX include directory
|
||||
#
|
||||
# The following variables will be checked by the function
|
||||
# XTRX_USE_STATIC_LIBS ... if true, only static libraries are found
|
||||
# XTRX_ROOT ... if set, the libraries are exclusively searched
|
||||
# under this path
|
||||
# XTRX_LIBRARY ... XTRX library to use
|
||||
# XTRX_INCLUDE_DIR ... XTRX include directory
|
||||
#
|
||||
#If environment variable XTRXDIR is specified, it has same effect as XTRX_ROOT
|
||||
if( NOT XTRX_ROOT AND ENV{XTRXDIR} )
|
||||
set( XTRX_ROOT $ENV{XTRXDIR} )
|
||||
endif()
|
||||
# Check if we can use PkgConfig
|
||||
find_package(PkgConfig)
|
||||
#Determine from PKG
|
||||
if( PKG_CONFIG_FOUND AND NOT XTRX_ROOT )
|
||||
pkg_check_modules( PKG_XTRX QUIET "libxtrx" )
|
||||
endif()
|
||||
#Check whether to search static or dynamic libs
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES_SAV ${CMAKE_FIND_LIBRARY_SUFFIXES} )
|
||||
if( ${XTRX_USE_STATIC_LIBS} )
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} )
|
||||
else()
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX} )
|
||||
endif()
|
||||
if( XTRX_ROOT )
|
||||
#find libs
|
||||
find_library(
|
||||
XTRX_LIB
|
||||
NAMES "xtrx"
|
||||
PATHS ${XTRX_ROOT}
|
||||
PATH_SUFFIXES "lib" "lib64"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
#find includes
|
||||
find_path(
|
||||
XTRX_INCLUDES
|
||||
NAMES "xtrx_api.h"
|
||||
PATHS ${XTRX_ROOT}
|
||||
PATH_SUFFIXES "include"
|
||||
NO_DEFAULT_PATH
|
||||
)
|
||||
else()
|
||||
find_library(
|
||||
XTRX_LIB
|
||||
NAMES "xtrx"
|
||||
PATHS ${PKG_XTRX_LIBRARY_DIRS} ${LIB_INSTALL_DIR}
|
||||
)
|
||||
find_path(
|
||||
XTRX_INCLUDES
|
||||
NAMES "xtrx_api.h"
|
||||
PATHS ${PKG_XTRX_INCLUDE_DIRS} ${INCLUDE_INSTALL_DIR}
|
||||
)
|
||||
endif( XTRX_ROOT )
|
||||
set(XTRX_LIBRARIES ${XTRX_LIB})
|
||||
set( CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES_SAV} )
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(XTRX DEFAULT_MSG
|
||||
XTRX_INCLUDES XTRX_LIBRARIES)
|
||||
mark_as_advanced(XTRX_INCLUDES XTRX_LIBRARIES XTRX_LIB XTRXF_LIB XTRXL_LIB)
|
Loading…
Reference in New Issue