laforge
/
openbts-osmo
Archived
1
0
Fork 0

uhd: add 52 MHz transceiver support

These are mostly identical changes as added to the non-52MHz
implementation with the exception of sample rate.

Signed-off-by: Thomas Tsou <ttsou@vt.edu>
This commit is contained in:
Thomas Tsou 2011-05-04 16:17:16 -04:00
parent 2e096d9e9c
commit 90d7633583
9 changed files with 800 additions and 33 deletions

View File

@ -32,6 +32,7 @@ SUBDIRS = \
GSM \
SMS \
Transceiver \
Transceiver52M \
TRXManager \
Control \
RRLP \
@ -40,10 +41,6 @@ SUBDIRS = \
smqueue
# SQL
if !UHD
SUBDIRS += Transceiver52M
endif
EXTRA_DIST = \
LEGAL \
COPYING \

View File

@ -20,7 +20,11 @@
include $(top_srcdir)/Makefile.common
if UHD
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(UHD_CFLAGS)
else
AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(USRP_CFLAGS)
endif
AM_CXXFLAGS = -O3 -g -lpthread
rev2dir = $(datadir)/usrp/rev2
@ -38,8 +42,7 @@ noinst_LTLIBRARIES = libtransceiver.la
libtransceiver_la_SOURCES = \
radioInterface.cpp \
sigProcLib.cpp \
Transceiver.cpp \
USRPDevice.cpp
Transceiver.cpp
noinst_PROGRAMS = \
USRPping \
@ -57,22 +60,31 @@ noinst_HEADERS = \
USRPping_SOURCES = USRPping.cpp
USRPping_LDADD = \
libtransceiver.la \
$(COMMON_LA) \
$(USRP_LIBS)
$(COMMON_LA)
transceiver_SOURCES = runTransceiver.cpp
transceiver_LDADD = \
libtransceiver.la \
$(GSM_LA) \
$(COMMON_LA) \
$(USRP_LIBS)
$(COMMON_LA)
sigProcLibTest_SOURCES = sigProcLibTest.cpp
sigProcLibTest_LDADD = \
libtransceiver.la \
$(GSM_LA) \
$(COMMON_LA) \
$(USRP_LIBS)
$(COMMON_LA)
if UHD
libtransceiver_la_SOURCES += UHDDevice.cpp
transceiver_LDADD += $(UHD_LIBS)
USRPping_LDADD += $(UHD_LIBS)
sigProcLibTest_LDADD += $(UHD_LIBS)
else
libtransceiver_la_SOURCES += USRPDevice.cpp
transceiver_LDADD += $(USRP_LIBS)
USRPping_LDADD += $(USRP_LIBS)
sigProcLibTest_LDADD += $(USRP_LIBS)
endif
MOSTLYCLEANFILES +=

View File

@ -0,0 +1,754 @@
/*
* Copyright 2008, 2009, 2010 Free Software Foundation, Inc.
*
* This software is distributed under the terms of the GNU Affero Public License.
* See the COPYING file in the main directory for details.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL 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 Affero 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 Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "radioDevice.h"
#include "Threads.h"
#include "Logger.h"
#include <uhd/usrp/single_usrp.hpp>
#include <uhd/utils/thread_priority.hpp>
/*
use_ext_ref - Enable external 10MHz clock reference
master_clk_rt - Master clock frequency
rx_smpl_offset - Timing correction in seconds between receive and
transmit timestamps. This value corrects for delays on
on the RF side of the timestamping point of the device.
smpl_buf_sz - The receive sample buffer size in bytes.
*/
const bool use_ext_ref = false;
const double master_clk_rt = 52e6;
const double rx_smpl_offset = .00005;
const size_t smpl_buf_sz = (1 << 20);
/** Timestamp conversion
@param timestamp a UHD or OpenBTS timestamp
@param rate sample rate
@return the converted timestamp
*/
uhd::time_spec_t convert_time(TIMESTAMP ticks, double rate)
{
double secs = (double) ticks / rate;
return uhd::time_spec_t(secs);
}
TIMESTAMP convert_time(uhd::time_spec_t ts, double rate)
{
size_t ticks = ts.get_full_secs() * rate;
return ts.get_tick_count(rate) + ticks;
}
/*
Sample Buffer - Allows reading and writing of timed samples using OpenBTS
or UHD style timestamps. Time conversions are handled
internally or accessable through the static convert calls.
*/
class smpl_buf {
public:
/** Sample buffer constructor
@param len number of 32-bit samples the buffer should hold
@param rate sample clockrate
@param timestamp
*/
smpl_buf(size_t len, double rate);
~smpl_buf();
/** Query number of samples available for reading
@param timestamp time of first sample
@return number of available samples or error
*/
ssize_t avail_smpls(TIMESTAMP timestamp) const;
ssize_t avail_smpls(uhd::time_spec_t timestamp) const;
/** Read and write
@param buf pointer to buffer
@param len number of samples desired to read or write
@param timestamp time of first stample
@return number of actual samples read or written or error
*/
ssize_t read(void *buf, size_t len, TIMESTAMP timestamp);
ssize_t read(void *buf, size_t len, uhd::time_spec_t timestamp);
ssize_t write(void *buf, size_t len, TIMESTAMP timestamp);
ssize_t write(void *buf, size_t len, uhd::time_spec_t timestamp);
/** Buffer status string
@return a formatted string describing internal buffer state
*/
std::string str_status() const;
/** Formatted error string
@param code an error code
@return a formatted error string
*/
static std::string str_code(ssize_t code);
enum err_code {
ERROR_TIMESTAMP = -1,
ERROR_READ = -2,
ERROR_WRITE = -3,
ERROR_OVERFLOW = -4
};
private:
uint32_t *data;
size_t buf_len;
double clk_rt;
TIMESTAMP time_start;
TIMESTAMP time_end;
size_t data_start;
size_t data_end;
};
/*
uhd_device - UHD implementation of the Device interface. Timestamped samples
are sent to and received from the device. An intermediate buffer
on the receive side collects and aligns packets of samples.
Events and errors such as underruns are reported asynchronously
by the device and received in a separate thread.
*/
class uhd_device : public RadioDevice {
public:
uhd_device(double rate, bool skip_rx);
~uhd_device();
bool open();
bool start();
bool stop();
void setPriority();
int readSamples(short *buf, int len, bool *overrun,
TIMESTAMP timestamp, bool *underrun, unsigned *RSSI);
int writeSamples(short *buf, int len, bool *underrun,
TIMESTAMP timestamp, bool isControl);
bool updateAlignment(TIMESTAMP timestamp);
bool setTxFreq(double wFreq);
bool setRxFreq(double wFreq);
inline TIMESTAMP initialWriteTimestamp() { return 0; }
inline TIMESTAMP initialReadTimestamp() { return 0; }
inline double fullScaleInputValue() { return 13500.0; }
inline double fullScaleOutputValue() { return 9450.0; }
double setRxGain(double dB) { return 0; }
double getRxGain(void) { return 0; }
double maxRxGain(void) { return 0; }
double minRxGain(void) { return 0; }
double setTxGain(double dB) { return 0; }
double maxTxGain(void) { return 0; }
double minTxGain(void) { return 0; }
double getTxFreq() { return 0; }
double getRxFreq() { return 0; }
inline double getSampleRate() { return actual_smpl_rt; }
inline double numberRead() { return rx_pkt_cnt; }
inline double numberWritten() { return 0; }
/** Receive and process asynchronous message
@return true if message received or false on timeout or error
*/
bool recv_async_msg();
private:
uhd::usrp::single_usrp::sptr usrp_dev;
double desired_smpl_rt;
double actual_smpl_rt;
size_t tx_spp;
size_t rx_spp;
bool started;
bool aligned;
bool skip_rx;
size_t rx_pkt_cnt;
size_t drop_cnt;
uhd::time_spec_t prev_ts;
TIMESTAMP ts_offset;
smpl_buf *rx_smpl_buf;
std::string str_code(uhd::rx_metadata_t metadata);
std::string str_code(uhd::async_metadata_t metadata);
Thread async_event_thrd;
};
void *async_event_loop(uhd_device *dev)
{
while (1) {
dev->recv_async_msg();
pthread_testcancel();
}
}
uhd_device::uhd_device(double rate, bool skip_rx)
: desired_smpl_rt(rate), actual_smpl_rt(0), tx_spp(0), rx_spp(0),
started(false), aligned(true), rx_pkt_cnt(0), drop_cnt(0),
prev_ts(0,0), ts_offset(0), rx_smpl_buf(NULL)
{
this->skip_rx = skip_rx;
}
uhd_device::~uhd_device()
{
stop();
if (rx_smpl_buf)
delete rx_smpl_buf;
}
static double set_usrp_rates(uhd::usrp::single_usrp::sptr dev, double rate)
{
double actual_rate;
dev->set_tx_rate(rate);
dev->set_rx_rate(rate);
actual_rate = dev->get_tx_rate();
if (actual_rate != rate) {
LOG(ERROR) << "Actual sample rate differs from desired rate";
return -1.0;
}
if (dev->get_rx_rate() != actual_rate) {
LOG(ERROR) << "Transmit and receive sample rates do not match";
return -1.0;
}
return actual_rate;
}
static void set_usrp_tx_gain(uhd::usrp::single_usrp::sptr dev, double)
{
uhd::gain_range_t range = dev->get_tx_gain_range();
dev->set_tx_gain((range.start() + range.stop()) / 2);
}
static void set_usrp_rx_gain(uhd::usrp::single_usrp::sptr dev, double)
{
uhd::gain_range_t range = dev->get_rx_gain_range();
dev->set_rx_gain((range.start() + range.stop()) / 2);
}
static void set_usrp_ref_clk(uhd::usrp::single_usrp::sptr dev, bool ext_clk)
{
uhd::clock_config_t clk_cfg;
clk_cfg.pps_source = uhd::clock_config_t::PPS_SMA;
clk_cfg.pps_polarity = uhd::clock_config_t::PPS_NEG;
if (ext_clk)
clk_cfg.ref_source = uhd::clock_config_t::REF_SMA;
else
clk_cfg.ref_source = uhd::clock_config_t::REF_INT;
dev->set_clock_config(clk_cfg);
}
bool uhd_device::open()
{
LOG(INFO) << "creating USRP device...";
// Use the first available USRP2 / N210
uhd::device_addr_t dev_addr("type=usrp2");
try {
usrp_dev = uhd::usrp::single_usrp::make(dev_addr);
}
catch(...) {
LOG(ERROR) << "USRP make failed";
return false;
}
// Set master clock rate
usrp_dev->set_master_clock_rate(master_clk_rt);
// Number of samples per over-the-wire packet
tx_spp = usrp_dev->get_device()->get_max_send_samps_per_packet();
rx_spp = usrp_dev->get_device()->get_max_recv_samps_per_packet();
// Set rates
actual_smpl_rt = set_usrp_rates(usrp_dev, desired_smpl_rt);
if (actual_smpl_rt < 0)
return false;
// Create receive buffer
size_t buf_len = smpl_buf_sz / sizeof(uint32_t);
rx_smpl_buf = new smpl_buf(buf_len, actual_smpl_rt);
// Set receive chain sample offset
ts_offset = (TIMESTAMP)(rx_smpl_offset * actual_smpl_rt);
// Set gains to midpoint
set_usrp_tx_gain(usrp_dev, 0.0);
// Set reference clock
set_usrp_ref_clk(usrp_dev, use_ext_ref);
// Print configuration
LOG(INFO) << usrp_dev->get_pp_string();
return true;
}
bool uhd_device::start()
{
LOG(INFO) << "Starting USRP...";
if (started) {
LOG(ERROR) << "Device already started";
return false;
}
setPriority();
// Start asynchronous event (underrun check) loop
async_event_thrd.start((void * (*)(void*))async_event_loop, (void*)this);
// Start streaming
uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
cmd.stream_now = true;
usrp_dev->set_time_now(uhd::time_spec_t(0.0));
if (!skip_rx)
usrp_dev->issue_stream_cmd(cmd);
// Display usrp time
double time_now = usrp_dev->get_time_now().get_real_secs();
LOG(INFO) << "The current time is " << time_now << " seconds";
started = true;
return true;
}
bool uhd_device::stop()
{
uhd::stream_cmd_t stream_cmd =
uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
usrp_dev->issue_stream_cmd(stream_cmd);
started = false;
return true;
}
void uhd_device::setPriority()
{
uhd::set_thread_priority_safe();
return;
}
static int check_rx_md_err(uhd::rx_metadata_t &md, uhd::time_spec_t &prev_ts)
{
// Missing timestamp
if (!md.has_time_spec) {
LOG(ERROR) << "UHD: Received packet missing timestamp";
return -1;
}
// Monotonicity check
if (md.time_spec < prev_ts) {
LOG(ERROR) << "Loss of monotonicity";
return -1;
} else {
prev_ts = md.time_spec;
}
return 0;
}
int uhd_device::readSamples(short *buf, int len, bool *overrun,
TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
{
ssize_t rc;
uhd::time_spec_t ts;
uhd::rx_metadata_t metadata;
uint32_t pkt_buf[rx_spp];
if (skip_rx)
return 0;
// Shift read time with respect to transmit clock
timestamp += ts_offset;
ts = convert_time(timestamp, actual_smpl_rt);
LOG(DEEPDEBUG) << "Requested timestamp = " << ts.get_real_secs();
// Check that timestamp is valid
rc = rx_smpl_buf->avail_smpls(timestamp);
if (rc < 0) {
LOG(ERROR) << rx_smpl_buf->str_code(rc);
LOG(ERROR) << rx_smpl_buf->str_status();
return 0;
}
// Receive samples from the usrp until we have enough
while (rx_smpl_buf->avail_smpls(timestamp) < len) {
size_t num_smpls = usrp_dev->get_device()->recv(
(void*)pkt_buf,
rx_spp,
metadata,
uhd::io_type_t::COMPLEX_INT16,
uhd::device::RECV_MODE_ONE_PACKET);
rx_pkt_cnt++;
// Recv error in UHD
if (!num_smpls) {
LOG(ERROR) << str_code(metadata);
return 0;
}
// Other metadata timing checks
if (check_rx_md_err(metadata, prev_ts) < 0)
return 0;
ts = metadata.time_spec;
LOG(DEEPDEBUG) << "Received timestamp = " << ts.get_real_secs();
rc = rx_smpl_buf->write(pkt_buf,
num_smpls,
metadata.time_spec);
// Continue on local overrun, exit on other errors
if ((rc < 0)) {
LOG(ERROR) << rx_smpl_buf->str_code(rc);
LOG(ERROR) << rx_smpl_buf->str_status();
if (rc != smpl_buf::ERROR_OVERFLOW)
return 0;
}
}
// We have enough samples
rc = rx_smpl_buf->read(buf, len, timestamp);
if ((rc < 0) || (rc != len)) {
LOG(ERROR) << rx_smpl_buf->str_code(rc);
LOG(ERROR) << rx_smpl_buf->str_status();
return 0;
}
return len;
}
int uhd_device::writeSamples(short *buf, int len, bool *underrun,
unsigned long long timestamp,bool isControl)
{
uhd::tx_metadata_t metadata;
metadata.has_time_spec = true;
metadata.start_of_burst = false;
metadata.end_of_burst = false;
metadata.time_spec = convert_time(timestamp, actual_smpl_rt);
// No control packets
if (isControl) {
LOG(ERROR) << "Control packets not supported";
return 0;
}
// Drop a fixed number of packets (magic value)
if (!aligned) {
drop_cnt++;
if (drop_cnt == 1) {
LOG(DEBUG) << "Aligning transmitter: stop burst";
metadata.end_of_burst = true;
} else if (drop_cnt < 30) {
LOG(DEEPDEBUG) << "Aligning transmitter: packet advance";
*underrun = true;
return len;
} else {
LOG(DEBUG) << "Aligning transmitter: start burst";
metadata.start_of_burst = true;
aligned = true;
drop_cnt = 0;
}
}
size_t num_smpls = usrp_dev->get_device()->send(buf,
len,
metadata,
uhd::io_type_t::COMPLEX_INT16,
uhd::device::SEND_MODE_FULL_BUFF);
if (num_smpls != (unsigned)len)
LOG(ERROR) << "UHD: Sent fewer samples than requested";
return num_smpls;
}
bool uhd_device::updateAlignment(TIMESTAMP timestamp)
{
/* NOP */
return true;
}
bool uhd_device::setTxFreq(double wFreq)
{
uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq);
LOG(INFO) << tr.to_pp_string();
return true;
}
bool uhd_device::setRxFreq(double wFreq)
{
uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq);
LOG(INFO) << tr.to_pp_string();
return true;
}
bool uhd_device::recv_async_msg()
{
uhd::async_metadata_t metadata;
if (!usrp_dev->get_device()->recv_async_msg(metadata))
return false;
// Assume that any error requires resynchronization
if (metadata.event_code != uhd::async_metadata_t::EVENT_CODE_BURST_ACK) {
aligned = false;
LOG(INFO) << str_code(metadata);
}
return true;
}
std::string uhd_device::str_code(uhd::rx_metadata_t metadata)
{
std::ostringstream ost("UHD: ");
switch (metadata.error_code) {
case uhd::rx_metadata_t::ERROR_CODE_NONE:
ost << "No error";
break;
case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
ost << "No packet received, implementation timed-out";
break;
case uhd::rx_metadata_t::ERROR_CODE_LATE_COMMAND:
ost << "A stream command was issued in the past";
break;
case uhd::rx_metadata_t::ERROR_CODE_BROKEN_CHAIN:
ost << "Expected another stream command";
break;
case uhd::rx_metadata_t::ERROR_CODE_OVERFLOW:
ost << "An internal receive buffer has filled";
break;
case uhd::rx_metadata_t::ERROR_CODE_BAD_PACKET:
ost << "The packet could not be parsed";
break;
default:
ost << "Unknown error " << metadata.error_code;
}
if (metadata.has_time_spec)
ost << " at " << metadata.time_spec.get_real_secs() << " sec.";
return ost.str();
}
std::string uhd_device::str_code(uhd::async_metadata_t metadata)
{
std::ostringstream ost("UHD: ");
switch (metadata.event_code) {
case uhd::async_metadata_t::EVENT_CODE_BURST_ACK:
ost << "A packet was successfully transmitted";
break;
case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW:
ost << "An internal send buffer has emptied";
break;
case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR:
ost << "Packet loss between host and device";
break;
case uhd::async_metadata_t::EVENT_CODE_TIME_ERROR:
ost << "Packet time was too late or too early";
break;
case uhd::async_metadata_t::EVENT_CODE_UNDERFLOW_IN_PACKET:
ost << "Underflow occurred inside a packet";
break;
case uhd::async_metadata_t::EVENT_CODE_SEQ_ERROR_IN_BURST:
ost << "Packet loss within a burst";
break;
default:
ost << "Unknown error " << metadata.event_code;
}
if (metadata.has_time_spec)
ost << " at " << metadata.time_spec.get_real_secs() << " sec.";
return ost.str();
}
smpl_buf::smpl_buf(size_t len, double rate)
: buf_len(len), clk_rt(rate),
time_start(0), time_end(0), data_start(0), data_end(0)
{
data = new uint32_t[len];
}
smpl_buf::~smpl_buf()
{
delete[] data;
}
ssize_t smpl_buf::avail_smpls(TIMESTAMP timestamp) const
{
if (timestamp < time_start)
return ERROR_TIMESTAMP;
else if (timestamp >= time_end)
return 0;
else
return time_end - timestamp;
}
ssize_t smpl_buf::avail_smpls(uhd::time_spec_t timespec) const
{
return avail_smpls(convert_time(timespec, clk_rt));
}
ssize_t smpl_buf::read(void *buf, size_t len, TIMESTAMP timestamp)
{
// Check for valid read
if (timestamp < time_start)
return ERROR_TIMESTAMP;
if (timestamp >= time_end)
return 0;
if (len >= buf_len)
return ERROR_READ;
// How many samples should be copied
size_t num_smpls = time_end - timestamp;
if (num_smpls > len);
num_smpls = len;
// Starting index
size_t read_start = data_start + (timestamp - time_start);
// Read it
if (read_start + num_smpls < buf_len) {
size_t numBytes = len * 2 * sizeof(short);
memcpy(buf, data + read_start, numBytes);
} else {
size_t first_cp = (buf_len - read_start) * 2 * sizeof(short);
size_t second_cp = len * 2 * sizeof(short) - first_cp;
memcpy(buf, data + read_start, first_cp);
memcpy((char*) buf + first_cp, data, second_cp);
}
data_start = (read_start + len) % buf_len;
time_start = timestamp + len;
if (time_start > time_end)
return ERROR_READ;
else
return num_smpls;
}
ssize_t smpl_buf::read(void *buf, size_t len, uhd::time_spec_t ts)
{
return read(buf, len, convert_time(ts, clk_rt));
}
ssize_t smpl_buf::write(void *buf, size_t len, TIMESTAMP timestamp)
{
// Check for valid write
if ((len == 0) || (len >= buf_len))
return ERROR_WRITE;
if ((timestamp + len) <= time_end)
return ERROR_TIMESTAMP;
// Starting index
size_t write_start = (data_start + (timestamp - time_start)) % buf_len;
// Write it
if ((write_start + len) < buf_len) {
size_t numBytes = len * 2 * sizeof(short);
memcpy(data + write_start, buf, numBytes);
} else {
size_t first_cp = (buf_len - write_start) * 2 * sizeof(short);
size_t second_cp = len * 2 * sizeof(short) - first_cp;
memcpy(data + write_start, buf, first_cp);
memcpy(data, (char*) buf + first_cp, second_cp);
}
data_end = (write_start + len) % buf_len;
time_end = timestamp + len;
if (((write_start + len) > buf_len) && (data_end > data_start))
return ERROR_OVERFLOW;
else if (time_end <= time_start)
return ERROR_WRITE;
else
return len;
}
ssize_t smpl_buf::write(void *buf, size_t len, uhd::time_spec_t ts)
{
return write(buf, len, convert_time(ts, clk_rt));
}
std::string smpl_buf::str_status() const
{
std::ostringstream ost("Sample buffer: ");
ost << "length = " << buf_len;
ost << ", time_start = " << time_start;
ost << ", time_end = " << time_end;
ost << ", data_start = " << data_start;
ost << ", data_end = " << data_end;
return ost.str();
}
std::string smpl_buf::str_code(ssize_t code)
{
switch (code) {
case ERROR_TIMESTAMP:
return "Sample buffer: Requested timestamp is not valid";
case ERROR_READ:
return "Sample buffer: Read error";
case ERROR_WRITE:
return "Sample buffer: Write error";
case ERROR_OVERFLOW:
return "Sample buffer: Overrun";
default:
return "Sample buffer: Unknown error";
}
}
RadioDevice *RadioDevice::make(double smpl_rt, bool skip_rx)
{
return new uhd_device(smpl_rt, skip_rx);
}

View File

@ -148,7 +148,8 @@ bool USRPDevice::rx_setFreq(double freq, double *actual_freq)
}
USRPDevice::USRPDevice (double _desiredSampleRate)
USRPDevice::USRPDevice (double _desiredSampleRate, bool skipRx)
: skipRx(skipRx)
{
LOG(INFO) << "creating USRP device...";
decimRate = (unsigned int) round(masterClockRate/_desiredSampleRate);
@ -163,13 +164,11 @@ USRPDevice::USRPDevice (double _desiredSampleRate)
#endif
}
bool USRPDevice::make(bool wSkipRx)
bool USRPDevice::open()
{
skipRx = wSkipRx;
writeLock.unlock();
LOG(INFO) << "making USRP device..";
LOG(INFO) << "opening USRP device..";
#ifndef SWLOOPBACK
string rbf = "std_inband.rbf";
//string rbf = "inband_1rxhb_1tx.rbf";
@ -630,3 +629,8 @@ bool USRPDevice::setRxFreq(double wFreq) {
bool USRPDevice::setTxFreq(double wFreq) { return true;};
bool USRPDevice::setRxFreq(double wFreq) { return true;};
#endif
RadioDevice *RadioDevice::make(double desiredSampleRate, bool skipRx)
{
return new USRPDevice(desiredSampleRate, skipRx);
}

View File

@ -177,10 +177,10 @@ private:
public:
/** Object constructor */
USRPDevice (double _desiredSampleRate);
USRPDevice (double _desiredSampleRate, bool skipRx);
/** Instantiate the USRP */
bool make(bool skipRx = false);
bool open();
/** Start the USRP */
bool start();

View File

@ -28,7 +28,7 @@
#include <stdio.h>
#include <Logger.h>
#include <Configuration.h>
#include "USRPDevice.h"
#include "radioDevice.h"
ConfigurationTable gConfig;
@ -41,9 +41,9 @@ int main(int argc, char *argv[]) {
else gLogInit("INFO");
if (argc>2) gSetLogFile(argv[2]);
USRPDevice *usrp = new USRPDevice(52.0e6/192.0);
RadioDevice *usrp = RadioDevice::make(52.0e6/192.0);
usrp->make();
usrp->open();
TIMESTAMP timestamp;

View File

@ -37,6 +37,9 @@ typedef unsigned long long TIMESTAMP;
class RadioDevice {
public:
static RadioDevice *make(double desiredSampleRate, bool skipRx = false);
virtual bool open()=0;
/** Start the USRP */
virtual bool start()=0;
@ -55,9 +58,9 @@ class RadioDevice {
@return The number of samples actually read
*/
virtual int readSamples(short *buf, int len, bool *overrun,
TIMESTAMP timestamp,
bool *underrun,
unsigned *RSSI=NULL)=0;
TIMESTAMP timestamp = 0xffffffff,
bool *underrun = 0,
unsigned *RSSI = 0)=0;
/**
Write samples to the radio.
@param buf Contains the data to be written.

View File

@ -25,7 +25,7 @@
#include "Transceiver.h"
#include "USRPDevice.h"
#include "radioDevice.h"
#include <time.h>
#include <signal.h>
@ -72,9 +72,9 @@ int main(int argc, char *argv[])
srandom(time(NULL));
USRPDevice *usrp = new USRPDevice(1625.0e3/6.0); //533.333333333e3); //400e3);
if (!usrp->make()) {
delete usrp;
RadioDevice *usrp = RadioDevice::make(1625e3/6.0);
if (!usrp->open()) {
//delete usrp;
return EXIT_FAILURE;
}
RadioInterface* radio = new RadioInterface(usrp,3);

View File

@ -107,6 +107,7 @@ AC_CONFIG_FILES([\
SIP/Makefile \
SMS/Makefile \
Transceiver/Makefile \
Transceiver52M/Makefile \
TRXManager/Makefile \
CLI/Makefile \
HLR/Makefile \
@ -114,10 +115,6 @@ AC_CONFIG_FILES([\
smqueue/Makefile \
])
AS_IF([test "x$with_uhd" != "xyes"], [
AC_CONFIG_FILES([Transceiver52M/Makefile])
])
# SQL/Makefile \
AC_OUTPUT