aboutsummaryrefslogtreecommitdiffstats
path: root/Transceiver52M
diff options
context:
space:
mode:
authorThomas Tsou <tom@tsou.cc>2013-04-26 19:30:55 -0400
committerAlexander Chemeris <Alexander.Chemeris@gmail.com>2013-06-24 01:51:03 +0400
commit48f8fb34aadc9872f95805ba3f1d2ca3b39b3327 (patch)
treec074b07b12d2fa4d7a77367ff3133167afcfa888 /Transceiver52M
parent40c3d0a6d93a4ba9c3f83206fa726b0292ddd5ec (diff)
Transceiver52M: Setup UmTRX dual carrier support
Diffstat (limited to 'Transceiver52M')
-rw-r--r--Transceiver52M/DriveLoop.cpp4
-rw-r--r--Transceiver52M/DriveLoop.h7
-rw-r--r--Transceiver52M/Makefile.am14
-rw-r--r--Transceiver52M/Transceiver.cpp27
-rw-r--r--Transceiver52M/Transceiver.h12
-rw-r--r--Transceiver52M/UHDDevice.cpp207
-rw-r--r--Transceiver52M/multiTRX.cpp125
-rw-r--r--Transceiver52M/radioDevice.h16
-rw-r--r--Transceiver52M/radioInterface.cpp96
-rw-r--r--Transceiver52M/radioInterface.h54
-rw-r--r--Transceiver52M/radioInterfaceResamp.cpp332
-rw-r--r--Transceiver52M/runTransceiver.cpp2
12 files changed, 227 insertions, 669 deletions
diff --git a/Transceiver52M/DriveLoop.cpp b/Transceiver52M/DriveLoop.cpp
index 1f1ea7c..cd84d03 100644
--- a/Transceiver52M/DriveLoop.cpp
+++ b/Transceiver52M/DriveLoop.cpp
@@ -26,9 +26,9 @@
#include <Logger.h>
DriveLoop::DriveLoop(int wBasePort, const char *TRXAddress,
+ RadioInterface *wRadioInterface,
int wChanM, int wC0, int wSamplesPerSymbol,
- GSM::Time wTransmitLatency,
- RadioInterface *wRadioInterface)
+ GSM::Time wTransmitLatency)
:mClockSocket(wBasePort, TRXAddress, wBasePort + 100), mC0(wC0)
{
mChanM = wChanM;
diff --git a/Transceiver52M/DriveLoop.h b/Transceiver52M/DriveLoop.h
index f97bb1d..7a2dfc3 100644
--- a/Transceiver52M/DriveLoop.h
+++ b/Transceiver52M/DriveLoop.h
@@ -104,9 +104,10 @@ public:
@param radioInterface associated radioInterface object
*/
DriveLoop(int wBasePort, const char *TRXAddress,
- int wChanM, int wC0, int wSamplesPerSymbol,
- GSM::Time wTransmitLatency,
- RadioInterface *wRadioInterface);
+ RadioInterface *wRadioInterface,
+ int wChanM = 1, int wC0 = 0,
+ int wSamplesPerSymbol = SAMPSPERSYM,
+ GSM::Time wTransmitLatency = GSM::Time(3, 0));
/** Destructor */
~DriveLoop();
diff --git a/Transceiver52M/Makefile.am b/Transceiver52M/Makefile.am
index 6fcef7c..1103e6e 100644
--- a/Transceiver52M/Makefile.am
+++ b/Transceiver52M/Makefile.am
@@ -52,15 +52,14 @@ COMMON_SOURCES = \
radioVector.cpp \
radioClock.cpp \
sigProcLib.cpp \
+ DriveLoop.cpp \
Transceiver.cpp \
DummyLoad.cpp
libtransceiver_la_SOURCES = \
- $(COMMON_SOURCES) \
- radioInterfaceResamp.cpp
+ $(COMMON_SOURCES)
noinst_PROGRAMS = \
- USRPping \
transceiver \
sigProcLibTest
@@ -77,12 +76,7 @@ noinst_HEADERS = \
rcvLPF_651.h \
sendLPF_961.h
-USRPping_SOURCES = USRPping.cpp
-USRPping_LDADD = \
- libtransceiver.la \
- $(COMMON_LA) $(SQLITE_LA)
-
-transceiver_SOURCES = runTransceiver.cpp
+transceiver_SOURCES = multiTRX.cpp
transceiver_LDADD = \
libtransceiver.la \
$(GSM_LA) \
@@ -98,13 +92,11 @@ sigProcLibTest_LDADD = \
if UHD
libtransceiver_la_SOURCES += UHDDevice.cpp
transceiver_LDADD += $(UHD_LIBS)
-USRPping_LDADD += $(UHD_LIBS)
sigProcLibTest_LDADD += $(UHD_LIBS)
else
if USRP1
libtransceiver_la_SOURCES += USRPDevice.cpp
transceiver_LDADD += $(USRP_LIBS)
-USRPping_LDADD += $(USRP_LIBS)
sigProcLibTest_LDADD += $(USRP_LIBS)
else
#we should never be here, as one of the above mustbe defined for us to build
diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp
index b8d9d9d..3895ae5 100644
--- a/Transceiver52M/Transceiver.cpp
+++ b/Transceiver52M/Transceiver.cpp
@@ -48,23 +48,18 @@ using namespace GSM;
#define INIT_ENERGY_THRSHD 5.0f
-Transceiver::Transceiver(int wBasePort,
- const char *TRXAddress,
- int wSamplesPerSymbol,
- RadioInterface *wRadioInterface,
- DriveLoop *wDriveLoop,
- int wChannel, bool wPrimary)
+Transceiver::Transceiver(int wBasePort, const char *TRXAddress,
+ DriveLoop *wDriveLoop, RadioInterface *wRadioInterface,
+ int wSamplesPerSymbol, int wChannel, bool wPrimary)
:mDataSocket(wBasePort+2,TRXAddress,wBasePort+102),
mControlSocket(wBasePort+1,TRXAddress,wBasePort+101),
- mDriveLoop(wDriveLoop), mTransmitPriorityQueue(NULL),
- mChannel(wChannel), mPrimary(wPrimary), mTSC(-1)
+ mDriveLoop(wDriveLoop), mRadioInterface(wRadioInterface),
+ mSamplesPerSymbol(wSamplesPerSymbol), mTransmitPriorityQueue(NULL),
+ mChannel(wChannel), mPrimary(wPrimary)
{
mFIFOServiceLoopThread = NULL;
mControlServiceLoopThread = NULL;
mTransmitPriorityQueueServiceLoopThread = NULL;
-
- mSamplesPerSymbol = wSamplesPerSymbol;
- mRadioInterface = wRadioInterface;
mMaxExpectedDelay = 0;
// generate pulse and setup up signal processing library
@@ -89,11 +84,7 @@ Transceiver::Transceiver(int wBasePort,
mRunning = false;
mTxFreq = 0.0;
mRxFreq = 0.0;
-
- if (mPrimary)
- mFreqOffset = mChannel * CHAN_RATE;
- else
- mFreqOffset = 0.0;
+ mFreqOffset = 0.0;
mPower = -10;
mEnergyThreshold = INIT_ENERGY_THRSHD;
@@ -461,7 +452,7 @@ void Transceiver::driveControl()
int freqKhz;
sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz);
mRxFreq = freqKhz * 1.0e3 + mFreqOffset;
- if (mPrimary && (!mRadioInterface->tuneRx(mRxFreq))) {
+ if (!mRadioInterface->tuneRx(mRxFreq, mChannel)) {
LOG(ALERT) << "RX failed to tune";
sprintf(response,"RSP RXTUNE 1 %d",freqKhz);
} else {
@@ -474,7 +465,7 @@ void Transceiver::driveControl()
sscanf(buffer,"%3s %s %d",cmdcheck,command,&freqKhz);
//freqKhz = 890e3;
mTxFreq = freqKhz * 1.0e3 + mFreqOffset;
- if (mPrimary && (!mRadioInterface->tuneTx(mTxFreq))) {
+ if (!mRadioInterface->tuneTx(mTxFreq, mChannel)) {
LOG(ALERT) << "TX failed to tune";
sprintf(response,"RSP TXTUNE 1 %d",freqKhz);
} else {
diff --git a/Transceiver52M/Transceiver.h b/Transceiver52M/Transceiver.h
index 56acd9c..c58ca8c 100644
--- a/Transceiver52M/Transceiver.h
+++ b/Transceiver52M/Transceiver.h
@@ -97,7 +97,6 @@ private:
double mRxFreq; ///< the receive frequency
double mFreqOffset; ///< RF frequency offset
int mPower; ///< the transmit power in dB
- int mTSC; ///< the midamble sequence code
double mEnergyThreshold; ///< threshold to determine if received data is potentially a GSM burst
GSM::Time prevFalseDetectionTime; ///< last timestamp of a false energy detection
unsigned mMaxExpectedDelay; ///< maximum expected time-of-arrival offset in GSM symbols
@@ -121,12 +120,11 @@ public:
@param wTransmitLatency initial setting of transmit latency
@param radioInterface associated radioInterface object
*/
- Transceiver(int wBasePort,
- const char *TRXAddress,
- int wSamplesPerSymbol,
- RadioInterface *wRadioInterface,
- DriveLoop *wDriveLoop,
- int wChannel, bool wPrimary);
+ Transceiver(int wBasePort, const char *TRXAddress,
+ DriveLoop *wDriveLoop, RadioInterface *wRadioInterface,
+ int wSamplesPerSymbol = SAMPSPERSYM,
+ int wChannel = 0, bool wPrimary = true);
+
/** Destructor */
~Transceiver();
diff --git a/Transceiver52M/UHDDevice.cpp b/Transceiver52M/UHDDevice.cpp
index 61cc76e..fc31231 100644
--- a/Transceiver52M/UHDDevice.cpp
+++ b/Transceiver52M/UHDDevice.cpp
@@ -33,6 +33,7 @@
#endif
#define NUM_TX_CHANS 2
+#define NUM_RX_CHANS NUM_TX_CHANS
#define TX_CHAN_OFFSET 2e6
#define B100_CLK_RT 52e6
#define USRP2_BASE_RT 400e3
@@ -75,7 +76,7 @@ static struct uhd_dev_offset uhd_offsets[NUM_USRP_TYPES * 3] = {
{ B100, 1, 9.4778e-5 },
{ B100, 2, 5.1100e-5 },
{ B100, 4, 2.9418e-5 },
- { UMTRX, 1, 0.0 },
+ { UMTRX, 1, 9.1738e-5 },
{ UMTRX, 2, 0.0 },
{ UMTRX, 4, 0.0 },
};
@@ -115,7 +116,7 @@ static double select_rate(uhd_dev_type type, int sps)
return USRP2_BASE_RT * sps;
break;
case B100:
- case UmTRX:
+ case UMTRX:
return GSMRATE * sps;
break;
}
@@ -224,16 +225,16 @@ public:
void setPriority();
enum TxWindowType getWindowType() { return tx_window; }
- int readSamples(short *buf, int len, bool *overrun,
- TIMESTAMP timestamp, bool *underrun, unsigned *RSSI);
+ int readSamples(short **buf, int chans, int len, TIMESTAMP timestamp,
+ bool *overrun, bool *underrun, unsigned *RSSI);
- int writeSamples(short *buf, int len, bool *underrun,
- TIMESTAMP timestamp, bool isControl);
+ int writeSamples(short **buf, int chans, int len, TIMESTAMP timestamp,
+ bool *underrun, bool isControl);
bool updateAlignment(TIMESTAMP timestamp);
- bool setTxFreq(double wFreq);
- bool setRxFreq(double wFreq);
+ bool setTxFreq(double wFreq, int chan);
+ bool setRxFreq(double wFreq, int chan);
inline TIMESTAMP initialWriteTimestamp() { return init_rd_ts; }
inline TIMESTAMP initialReadTimestamp() { return init_rd_ts; }
@@ -298,7 +299,7 @@ private:
uhd::time_spec_t prev_ts;
TIMESTAMP ts_offset;
- smpl_buf *rx_smpl_buf;
+ smpl_buf *rx_smpl_buf[NUM_RX_CHANS];
void init_gains();
void set_ref_clk(bool ext_clk);
@@ -349,19 +350,23 @@ uhd_device::uhd_device(int sps, bool skip_rx)
rx_gain(0.0), rx_gain_min(0.0), rx_gain_max(0.0),
tx_freq(0.0), rx_freq(0.0), tx_spp(0), rx_spp(0),
started(false), aligned(false), rx_pkt_cnt(0), drop_cnt(0),
- prev_ts(0,0), ts_offset(0), rx_smpl_buf(NULL)
- async_event_thrd(NULL)
+ prev_ts(0,0), ts_offset(0), async_event_thrd(NULL)
{
this->sps = sps;
this->skip_rx = skip_rx;
+
+ for (int i = 0; i < NUM_RX_CHANS; i++)
+ rx_smpl_buf[i] = NULL;
}
uhd_device::~uhd_device()
{
stop();
- if (rx_smpl_buf)
- delete rx_smpl_buf;
+ for (int i = 0; i < NUM_RX_CHANS; i++) {
+ if (rx_smpl_buf)
+ delete rx_smpl_buf;
+ }
}
void uhd_device::init_gains()
@@ -463,10 +468,11 @@ double uhd_device::setTxGain(double db)
double uhd_device::setRxGain(double db)
{
- usrp_dev->set_rx_gain(db);
- rx_gain = usrp_dev->get_rx_gain();
-
- LOG(INFO) << "Set RX gain to " << rx_gain << "dB";
+ for (int i = 0; i < NUM_RX_CHANS; i++) {
+ usrp_dev->set_rx_gain(db);
+ rx_gain = usrp_dev->get_rx_gain();
+ LOG(INFO) << "Set RX gain to " << rx_gain << "dB";
+ }
return rx_gain;
}
@@ -509,8 +515,8 @@ bool uhd_device::parse_dev_type()
usrp1_str = dev_str.find("USRP1");
usrp2_str = dev_str.find("USRP2");
+ umtrx_str = dev_str.find("UmTRX");
b100_str = mboard_str.find("B100");
- umtrx_str = mboard_str.find("UmTRX");
if (usrp1_str != std::string::npos) {
LOG(ALERT) << "USRP1 is not supported using the UHD driver";
@@ -572,28 +578,29 @@ int uhd_device::open(const std::string &args)
if (NUM_TX_CHANS == 2) {
uhd::usrp::subdev_spec_t subdev_spec("A:0 B:0");
usrp_dev->set_tx_subdev_spec(subdev_spec);
+ usrp_dev->set_rx_subdev_spec(subdev_spec);
}
+ // Set rates
+ desired_smpl_rt = select_rate(dev_type, sps);
+ if (set_rates(desired_smpl_rt) < 0)
+ return -1;
+
// Create TX and RX streamers
uhd::stream_args_t stream_args("sc16");
- rx_stream = usrp_dev->get_rx_stream(stream_args);
-
for (int i = 0; i < NUM_TX_CHANS; i++)
stream_args.channels.push_back(i);
tx_stream = usrp_dev->get_tx_stream(stream_args);
+ rx_stream = usrp_dev->get_rx_stream(stream_args);
// Number of samples per over-the-wire packet
tx_spp = tx_stream->get_max_num_samps();
rx_spp = rx_stream->get_max_num_samps();
- // Set rates
- desired_smpl_rt = select_rate(dev_type, sps);
- if (set_rates(desired_smpl_rt) < 0)
- return -1;
-
// Create receive buffer
size_t buf_len = SAMPLE_BUF_SZ / sizeof(uint32_t);
- rx_smpl_buf = new smpl_buf(buf_len, actual_smpl_rt);
+ for (int i = 0; i < NUM_RX_CHANS; i++)
+ rx_smpl_buf[i] = new smpl_buf(buf_len, actual_smpl_rt);
// Set receive chain sample offset
double offset = get_dev_offset(dev_type, sps);
@@ -620,14 +627,19 @@ bool uhd_device::flush_recv(size_t num_pkts)
{
uhd::rx_metadata_t md;
size_t num_smpls;
- uint32_t buff[rx_spp];
float timeout;
// Use .01 sec instead of the default .1 sec
timeout = .01;
+ std::vector<std::vector<std::complex<short> > > bufs(
+ NUM_RX_CHANS, std::vector<std::complex<short> >(rx_spp));
+ std::vector<std::complex<short> *> buf_ptrs;
+ for (int i = 0; i < bufs.size(); i++)
+ buf_ptrs.push_back(&bufs[i].front());
+
for (size_t i = 0; i < num_pkts; i++) {
- num_smpls = rx_stream->recv(buff, rx_spp, md,
+ num_smpls = rx_stream->recv(buf_ptrs, rx_spp, md,
timeout, true);
if (!num_smpls) {
switch (md.error_code) {
@@ -644,30 +656,15 @@ bool uhd_device::flush_recv(size_t num_pkts)
void uhd_device::restart(uhd::time_spec_t ts)
{
- uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
- usrp_dev->issue_stream_cmd(cmd);
-
- flush_recv(50);
-
usrp_dev->set_time_now(ts);
aligned = false;
- cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
- cmd.stream_now = true;
+ uhd::stream_cmd_t cmd = uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS;
+ cmd.time_spec = uhd::time_spec_t(0.1);
+ cmd.stream_now = false;
usrp_dev->issue_stream_cmd(cmd);
uhd::rx_metadata_t md;
- uint32_t buff[rx_spp];
-
- for (int i = 0; i < 50; i++) {
- usrp_dev->get_device()->recv(buff,
- rx_spp,
- md,
- uhd::io_type_t::COMPLEX_INT16,
- uhd::device::RECV_MODE_ONE_PACKET);
- }
-
- init_rd_ts = convert_time(md.time_spec, actual_smpl_rt);
}
bool uhd_device::start()
@@ -760,39 +757,48 @@ int uhd_device::check_rx_md_err(uhd::rx_metadata_t &md, ssize_t num_smpls)
return 0;
}
-int uhd_device::readSamples(short *buf, int len, bool *overrun,
- TIMESTAMP timestamp, bool *underrun, unsigned *RSSI)
+int uhd_device::readSamples(short **buf, int chans, int len,
+ TIMESTAMP timestamp, bool *overrun,
+ 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)
+ if (skip_rx) {
+ LOG(INFO) << "Skipping Rx";
return 0;
+ }
+
+ if (chans != NUM_RX_CHANS) {
+ LOG(ERR) << "Number of requested channels does not match build";
+ return -1;
+ }
// Shift read time with respect to transmit clock
timestamp += ts_offset;
ts = convert_time(timestamp, actual_smpl_rt);
- LOG(DEBUG) << "Requested timestamp = " << ts.get_real_secs();
+ LOG(DEBUG) << "Requested UHD timestamp = " << ts.get_real_secs();
// Check that timestamp is valid
- rc = rx_smpl_buf->avail_smpls(timestamp);
+ rc = rx_smpl_buf[0]->avail_smpls(timestamp);
if (rc < 0) {
- LOG(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
+ LOG(ERR) << rx_smpl_buf[0]->str_code(rc);
+ LOG(ERR) << rx_smpl_buf[0]->str_status();
return 0;
}
+ std::vector<std::vector<std::complex<short> > > bufs(
+ NUM_RX_CHANS, std::vector<std::complex<short> >(rx_spp));
+ std::vector<std::complex<short> *> buf_ptrs;
+ for (int i = 0; i < bufs.size(); i++)
+ buf_ptrs.push_back(&bufs[i].front());
+
// Receive samples from the usrp until we have enough
- while (rx_smpl_buf->avail_smpls(timestamp) < len) {
- size_t num_smpls = rx_stream->recv(
- (void*)pkt_buf,
- rx_spp,
- metadata,
- 0.1,
- true);
+ while (rx_smpl_buf[0]->avail_smpls(timestamp) < len) {
+ size_t num_smpls = rx_stream->recv(buf_ptrs, rx_spp,
+ metadata, 0.1, true);
rx_pkt_cnt++;
// Check for errors
@@ -805,39 +811,45 @@ int uhd_device::readSamples(short *buf, int len, bool *overrun,
case ERROR_TIMING:
restart(prev_ts);
case ERROR_UNHANDLED:
+ LOG(ALERT) << "UHD: Unhandled error";
continue;
}
-
ts = metadata.time_spec;
- LOG(DEBUG) << "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(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
- if (rc != smpl_buf::ERROR_OVERFLOW)
- return 0;
+ LOG(DEBUG) << "Received " << num_smpls << " samples "
+ << "with timestamp = " << ts.get_real_secs();
+
+ for (int i = 0; i < NUM_RX_CHANS; i++) {
+ rc = rx_smpl_buf[i]->write((short *) &bufs[i].front(),
+ num_smpls,
+ metadata.time_spec);
+
+ // Continue on local overrun, exit on other errors
+ if ((rc < 0)) {
+ LOG(ERR) << rx_smpl_buf[i]->str_code(rc);
+ LOG(ERR) << rx_smpl_buf[i]->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(ERR) << rx_smpl_buf->str_code(rc);
- LOG(ERR) << rx_smpl_buf->str_status();
- return 0;
+ for (int i = 0; i < NUM_RX_CHANS; i++) {
+ rc = rx_smpl_buf[i]->read(buf[i], len, timestamp);
+ if ((rc < 0) || (rc != len)) {
+ LOG(ERR) << rx_smpl_buf[i]->str_code(rc);
+ LOG(ERR) << rx_smpl_buf[i]->str_status();
+ return 0;
+ }
}
return len;
}
-int uhd_device::writeSamples(short *buf, int len, bool *underrun,
- unsigned long long timestamp,bool isControl)
+int uhd_device::writeSamples(short **buf, int chans, int len,
+ TIMESTAMP timestamp, bool *underrun,
+ bool isControl)
{
uhd::tx_metadata_t metadata;
metadata.has_time_spec = true;
@@ -870,9 +882,11 @@ int uhd_device::writeSamples(short *buf, int len, bool *underrun,
}
}
- std::vector<short *> bufs(NUM_TX_CHANS, buf);
- size_t num_smpls = tx_stream->send(bufs, len, metadata);
+ std::vector<short *> bufs(NUM_TX_CHANS);
+ for (int i = 0; i < NUM_TX_CHANS; i++)
+ bufs[i] = buf[i];
+ size_t num_smpls = tx_stream->send(bufs, len, metadata);
if (num_smpls != (unsigned) len) {
LOG(ALERT) << "UHD: Device send timed out";
LOG(ALERT) << "UHD: Version " << uhd::get_version_string();
@@ -888,25 +902,30 @@ bool uhd_device::updateAlignment(TIMESTAMP timestamp)
return true;
}
-bool uhd_device::setTxFreq(double wFreq)
+bool uhd_device::setTxFreq(double wFreq, int chan)
{
- for (int i = 0; i < NUM_TX_CHANS; i++) {
- if (i)
- wFreq += TX_CHAN_OFFSET;
-
- uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, i);
- LOG(INFO) << "\n" << tr.to_pp_string();
- tx_freq = usrp_dev->get_tx_freq(i);
+ if (chan >= NUM_TX_CHANS) {
+ LOG(ALERT) << "Attempting to tune non-existent channel";
+ return false;
}
+ uhd::tune_result_t tr = usrp_dev->set_tx_freq(wFreq, chan);
+ LOG(INFO) << "\n" << tr.to_pp_string();
+ tx_freq = usrp_dev->get_tx_freq(chan);
+
return true;
}
-bool uhd_device::setRxFreq(double wFreq)
+bool uhd_device::setRxFreq(double wFreq, int chan)
{
- uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq);
+ if (chan >= NUM_RX_CHANS) {
+ LOG(ALERT) << "Attempting to tune non-existent channel";
+ return false;
+ }
+
+ uhd::tune_result_t tr = usrp_dev->set_rx_freq(wFreq, chan);
LOG(INFO) << "\n" << tr.to_pp_string();
- rx_freq = usrp_dev->get_rx_freq();
+ rx_freq = usrp_dev->get_rx_freq(chan);
return true;
}
diff --git a/Transceiver52M/multiTRX.cpp b/Transceiver52M/multiTRX.cpp
index 04e2c95..e988eec 100644
--- a/Transceiver52M/multiTRX.cpp
+++ b/Transceiver52M/multiTRX.cpp
@@ -26,13 +26,11 @@
#include "Transceiver.h"
#include "radioDevice.h"
-#define DEVICERATE (400e3 * CHAN_M)
-
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");
volatile bool gbShutdown = false;
-int Transceiver::mTSC = 0;
+int Transceiver::mTSC = -1;
static void sigHandler(int signum)
{
@@ -50,72 +48,26 @@ static int setupSignals()
if (sigaction(SIGINT, &action, NULL) < 0)
return -1;
-
if (sigaction(SIGTERM, &action, NULL) < 0)
return -1;
return 0;
}
-/*
- * Generate the channel-transceiver ordering. Attempt to match the RAD1
- * ordering where the active channels are centered in the overall device
- * bandwidth. C0 is always has the lowest ARFCN with increasing subsequent
- * channels. When an even number of channels is selected, the carriers will
- * be offset from the RF center by -200 kHz, or half ARFCN spacing.
- */
-static void genChanMap(int numARFCN, int chanM, int *chans)
-{
- int i, n;
-
- chans[0] = numARFCN / 2;
-
- for (i = 1, n = 1; i < numARFCN; i++) {
- if (!chans[i - 1])
- chans[i] = chanM - 1;
- else
- chans[i] = chans[i - 1] - 1;
- }
-}
-
-static void createTrx(Transceiver **trx, int *map, int num,
- RadioInterface *radio, DriveLoop *drive)
-{
- int i;
- bool primary = true;
-
- for (i = 0; i < num; i++) {
- LOG(NOTICE) << "Creating TRX" << i
- << " attached on channel " << map[i];
-
- radio->activateChan(map[i]);
- trx[i] = new Transceiver(5700 + 2 * i, "127.0.0.1",
- SAMPSPERSYM, radio, drive,
- map[i], primary);
- trx[i]->start();
- primary = false;
- }
-}
-
int main(int argc, char *argv[])
{
- int i, chanM, numARFCN = 1;
- int chanMap[CHAN_MAX];
- RadioDevice *usrp;
- RadioInterface* radio;
- DriveLoop *drive;
- Transceiver *trx[CHAN_MAX];
-
- gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);
+ int numARFCN = 1;
if (argc > 1) {
numARFCN = atoi(argv[1]);
- if (numARFCN > (CHAN_MAX - 1)) {
- LOG(ALERT) << numARFCN << " channels not supported with current build";
+ if (numARFCN > CHAN_MAX) {
+ LOG(ALERT) << numARFCN << " channels not supported "
+ << " with with current build";
exit(-1);
}
}
+ gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);
srandom(time(NULL));
if (setupSignals() < 0) {
@@ -123,58 +75,49 @@ int main(int argc, char *argv[])
exit(-1);
}
- /*
- * Select the number of channels according to the number of ARFCNs's
- * and generate ARFCN-to-channelizer path mappings. The channelizer
- * aliases and extracts 'M' equally spaced channels to baseband. The
- * number of ARFCN's must be less than the number of channels in the
- * channelizer.
- */
- switch (numARFCN) {
- case 1:
- chanM = 1;
- break;
- case 2:
- case 3:
- chanM = 5;
- break;
- default:
- chanM = 10;
+ RadioDevice *device = RadioDevice::make(SAMPSPERSYM);
+ int radioType = device->open("");
+ if (radioType < 0) {
+ LOG(ALERT) << "Failed to open device, exiting...";
+ return EXIT_FAILURE;
}
- genChanMap(numARFCN, chanM, chanMap);
- usrp = RadioDevice::make(DEVICERATE);
- if (!usrp->open()) {
- LOG(ALERT) << "Failed to open device, exiting...";
+ RadioInterface *radio;
+ switch (radioType) {
+ case RadioDevice::NORMAL:
+ radio = new RadioInterface(device, numARFCN);
+ break;
+ case RadioDevice::RESAMP:
+ default:
+ LOG(ALERT) << "Unsupported configuration";
return EXIT_FAILURE;
}
- radio = new RadioInterface(usrp, chanM, 3, SAMPSPERSYM, 0, false);
- drive = new DriveLoop(5700, "127.0.0.1", chanM, chanMap[0],
- SAMPSPERSYM, GSM::Time(3,0), radio);
+ DriveLoop *drive = new DriveLoop(5700, "127.0.0.1", radio, numARFCN, 0);
- /* Create, attach, and activate all transceivers */
- createTrx(trx, chanMap, numARFCN, radio, drive);
+ Transceiver *trx[CHAN_MAX];
+ bool primary = true;
+ for (int i = 0; i < numARFCN; i++) {
+ trx[i] = new Transceiver(5700 + 2 * i, "127.0.0.1",
+ drive, radio, SAMPSPERSYM,
+ i, primary);
+ trx[i]->start();
+ primary = false;
+ }
- while (!gbShutdown) {
+ while (!gbShutdown)
sleep(1);
- }
LOG(NOTICE) << "Shutting down transceivers...";
- for (i = 0; i < numARFCN; i++) {
+ for (int i = 0; i < numARFCN; i++)
trx[i]->shutdown();
- }
- /*
- * Allow time for threads to end before we start freeing objects
- */
+ /* Allow time for threads to end before we start freeing objects */
sleep(2);
- for (i = 0; i < numARFCN; i++) {
+ for (int i = 0; i < numARFCN; i++)
delete trx[i];
- }
-
delete drive;
delete radio;
- delete usrp;
+ delete device;
}
diff --git a/Transceiver52M/radioDevice.h b/Transceiver52M/radioDevice.h
index 39f1de2..35cc82b 100644
--- a/Transceiver52M/radioDevice.h
+++ b/Transceiver52M/radioDevice.h
@@ -65,10 +65,9 @@ class RadioDevice {
@param RSSI The received signal strength of the read result
@return The number of samples actually read
*/
- virtual int readSamples(short *buf, int len, bool *overrun,
- TIMESTAMP timestamp = 0xffffffff,
- bool *underrun = 0,
- unsigned *RSSI = 0)=0;
+ virtual int readSamples(short **buf, int chans, int len, TIMESTAMP timestamp,
+ bool *overrun = NULL, bool *underrun = NULL,
+ unsigned *RSSI = NULL)=0;
/**
Write samples to the radio.
@param buf Contains the data to be written.
@@ -78,18 +77,17 @@ class RadioDevice {
@param isControl Set if data is a control packet, e.g. a ping command
@return The number of samples actually written
*/
- virtual int writeSamples(short *buf, int len, bool *underrun,
- TIMESTAMP timestamp,
- bool isControl=false)=0;
+ virtual int writeSamples(short **buf, int chans, int len, TIMESTAMP timestamp,
+ bool *underrun = NULL, bool isControl = false)=0;
/** Update the alignment between the read and write timestamps */
virtual bool updateAlignment(TIMESTAMP timestamp)=0;
/** Set the transmitter frequency */
- virtual bool setTxFreq(double wFreq)=0;
+ virtual bool setTxFreq(double wFreq, int chan = 0)=0;
/** Set the receiver frequency */
- virtual bool setRxFreq(double wFreq)=0;
+ virtual bool setRxFreq(double wFreq, int chan = 0)=0;
/** Returns the starting write Timestamp*/
virtual TIMESTAMP initialWriteTimestamp(void)=0;
diff --git a/Transceiver52M/radioInterface.cpp b/Transceiver52M/radioInterface.cpp
index b3bc07c..40826e9 100644
--- a/Transceiver52M/radioInterface.cpp
+++ b/Transceiver52M/radioInterface.cpp
@@ -28,8 +28,8 @@
bool started = false;
/* Device side buffers */
-static short rx_buf[OUTCHUNK * 2 * 2];
-static short tx_buf[INCHUNK * 2 * 2];
+static short *rx_buf[CHAN_MAX];
+static short *tx_buf[CHAN_MAX];
/* Complex float to short conversion */
static void floatToShort(short *out, float *in, int num)
@@ -51,34 +51,25 @@ static void shortToFloat(float *out, short *in, int num)
RadioInterface::RadioInterface(RadioDevice *wRadio,
int wChanM,
- int wReceiveOffset,
int wSPS,
+ int wReceiveOffset,
GSM::Time wStartTime)
: mChanM(wChanM), underrun(false), sendCursor(0), rcvCursor(0), mOn(false),
- mRadio(wRadio), receiveOffset(wReceiveOffset),
- samplesPerSymbol(wSPS), powerScaling(1.0),
- loadTest(false)
+ mRadio(wRadio), receiveOffset(wReceiveOffset), samplesPerSymbol(wSPS),
+ powerScaling(1.0), loadTest(false)
{
- int i;
-
mClock.set(wStartTime);
-
- for (i = 0; i < mChanM; i++) {
- chanActive[i] = false;
- }
}
RadioInterface::~RadioInterface(void)
{
- int i;
-
if (mOn) {
mRadio->stop();
close();
delete mAlignRadioServiceLoopThread;
- for (i = 0; i < mChanM; i++) {
+ for (int i = 0; i < mChanM; i++) {
if (rcvBuffer[i] != NULL)
delete rcvBuffer[i];
if (sendBuffer[i] != NULL)
@@ -145,14 +136,14 @@ int RadioInterface::unRadioifyVector(float *floatVector, int offset,
return newVector.size();
}
-bool RadioInterface::tuneTx(double freq)
+bool RadioInterface::tuneTx(double freq, int chan)
{
- return mRadio->setTxFreq(freq);
+ return mRadio->setTxFreq(freq, chan);
}
-bool RadioInterface::tuneRx(double freq)
+bool RadioInterface::tuneRx(double freq, int chan)
{
- return mRadio->setRxFreq(freq);
+ return mRadio->setRxFreq(freq, chan);
}
@@ -220,10 +211,8 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur
return;
for (i = 0; i < mChanM; i++) {
- if (chanActive[i]) {
- radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor,
- powerScaling, zeroBurst[i]);
- }
+ radioifyVector(*radioBurst[i], sendBuffer[i] + 2 * sendCursor,
+ powerScaling, zeroBurst[i]);
}
/*
@@ -235,15 +224,10 @@ void RadioInterface::driveTransmitRadio(signalVector **radioBurst, bool *zeroBur
pushBuffer();
}
-void shiftRxBuffers(float **buf, int offset, int len, int chanM, bool *active)
+static inline void shiftRxBuffers(float **buf, int offset, int len, int chanM)
{
- int i;
-
- for (i = 0; i < chanM; i++) {
- if (active[i]) {
+ for (int i = 0; i < chanM; i++)
memmove(buf[i], buf[i] + offset, sizeof(float) * len);
- }
- }
}
void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst,
@@ -252,12 +236,10 @@ void RadioInterface::loadVectors(unsigned tN, int samplesPerBurst,
int i;
for (i = 0; i < mChanM; i++) {
- if (chanActive[i]) {
- signalVector rxVector(samplesPerBurst);
- unRadioifyVector(rcvBuffer[i], idx * 2, rxVector);
- radioVector *rxBurst = new radioVector(rxVector, rxClock);
- mReceiveFIFO[i].write(rxBurst);
- }
+ signalVector rxVector(samplesPerBurst);
+ unRadioifyVector(rcvBuffer[i], idx * 2, rxVector);
+ radioVector *rxBurst = new radioVector(rxVector, rxClock);
+ mReceiveFIFO[i].write(rxBurst);
}
}
@@ -299,18 +281,10 @@ void RadioInterface::driveReceiveRadio()
if (readSz > 0) {
rcvCursor -= readSz;
- shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, mChanM, chanActive);
+ shiftRxBuffers(rcvBuffer, 2 * readSz, 2 * rcvCursor, mChanM);
}
}
-bool RadioInterface::isUnderrun()
-{
- bool retVal = underrun;
- underrun = false;
-
- return retVal;
-}
-
double RadioInterface::setRxGain(double dB)
{
if (mRadio)
@@ -327,14 +301,29 @@ double RadioInterface::getRxGain()
return -1;
}
+bool RadioInterface::init()
+{
+ for (int i = 0; i < CHAN_MAX; i++) {
+ rx_buf[i] = new short[2 * OUTCHUNK];
+ tx_buf[i] = new short[4 * 2 * INCHUNK];
+ }
+}
+
+void RadioInterface::close()
+{
+ for (int i = 0; i < CHAN_MAX; i++) {
+ delete rx_buf[i];
+ delete tx_buf[i];
+ }
+}
+
/* Receive a timestamped chunk from the device */
void RadioInterface::pullBuffer()
{
bool local_underrun;
/* Read samples. Fail if we don't get what we want. */
- int num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun,
- readTimestamp, &local_underrun);
+ int num_rd = mRadio->readSamples(rx_buf, mChanM, OUTCHUNK, readTimestamp);
LOG(DEBUG) << "Rx read " << num_rd << " samples from device";
assert(num_rd == OUTCHUNK);
@@ -342,7 +331,9 @@ void RadioInterface::pullBuffer()
underrun |= local_underrun;
readTimestamp += (TIMESTAMP) num_rd;
- shortToFloat(rcvBuffer + 2 * rcvCursor, rx_buf, num_rd);
+ for (int i = 0; i < mChanM; i++)
+ shortToFloat(rcvBuffer[i] + 2 * rcvCursor, rx_buf[i], num_rd);
+
rcvCursor += num_rd;
}
@@ -352,13 +343,12 @@ void RadioInterface::pushBuffer()
if (sendCursor < INCHUNK)
return;
- floatToShort(tx_buf, sendBuffer, sendCursor);
+ for (int i = 0; i < mChanM; i++)
+ floatToShort(tx_buf[i], sendBuffer[i], sendCursor);
/* Write samples. Fail if we don't get what we want. */
- int num_smpls = mRadio->writeSamples(tx_buf,
- sendCursor,
- &underrun,
- writeTimestamp);
+ int num_smpls = mRadio->writeSamples(tx_buf, mChanM, sendCursor,
+ writeTimestamp, &underrun);
assert(num_smpls == sendCursor);
writeTimestamp += (TIMESTAMP) num_smpls;
diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h
index f301511..b02cadc 100644
--- a/Transceiver52M/radioInterface.h
+++ b/Transceiver52M/radioInterface.h
@@ -26,7 +26,7 @@
#define SAMPSPERSYM 1
#define INCHUNK (625)
#define OUTCHUNK (625)
-#define CHAN_M 5
+#define CHAN_MAX 2
static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods
@@ -49,8 +49,6 @@ protected:
float *rcvBuffer[CHAN_MAX];
unsigned rcvCursor;
- bool chanActive[CHAN_MAX];
-
bool underrun; ///< indicates writes to USRP are too slow
bool overrun; ///< indicates reads from USRP are too slow
TIMESTAMP writeTimestamp; ///< sample timestamp of next packet written to USRP
@@ -103,11 +101,11 @@ public:
void close();
/** constructor */
- RadioInterface(RadioDevice* wRadio = NULL,
+ RadioInterface(RadioDevice* wRadio,
int wChanM = 1,
- int receiveOffset = 3,
int wSPS = SAMPSPERSYM,
- GSM::Time wStartTime = GSM::Time(0));
+ int receiveOffset = 3,
+ GSM::Time wStartTime = GSM::Time(0, 0));
/** destructor */
~RadioInterface();
@@ -115,10 +113,7 @@ public:
void setSamplesPerSymbol(int wSamplesPerSymbol) {if (!mOn) samplesPerSymbol = wSamplesPerSymbol;}
int getSamplesPerSymbol() { return samplesPerSymbol;}
-
- /** check for underrun, resets underrun value */
- bool isUnderrun();
-
+
/** return the receive FIFO */
VectorFIFO* receiveFIFO(int num) { return &mReceiveFIFO[num];}
@@ -126,10 +121,10 @@ public:
RadioClock* getClock(void) { return &mClock;};
/** set transmit frequency */
- bool tuneTx(double freq);
+ bool tuneTx(double freq, int chan = 0);
/** set receive frequency */
- bool tuneRx(double freq);
+ bool tuneRx(double freq, int chan = 0);
/** set receive gain */
double setRxGain(double dB);
@@ -156,41 +151,6 @@ public:
/** get transport window type of attached device */
enum RadioDevice::TxWindowType getWindowType() { return mRadio->getWindowType(); }
-
-#if USRP1
-protected:
-
- /** drive synchronization of Tx/Rx of USRP */
- void alignRadio();
-
- /** reset the interface */
- void reset();
-
- /** interface status */
- bool on() { return mOn; }
-
- friend void *AlignRadioServiceLoopAdapter(RadioInterface*);
-#endif
-};
-
-#if USRP1
-/** synchronization thread loop */
-void *AlignRadioServiceLoopAdapter(RadioInterface*);
-#endif
-
-class RadioInterfaceResamp : public RadioInterface {
-
-private:
-
- void pushBuffer();
- void pullBuffer();
-
-public:
-
- RadioInterfaceResamp(RadioDevice* wRadio = NULL,
- int receiveOffset = 3,
- int wSPS = SAMPSPERSYM,
- GSM::Time wStartTime = GSM::Time(0));
};
#endif /* _RADIOINTEFACE_H_ */
diff --git a/Transceiver52M/radioInterfaceResamp.cpp b/Transceiver52M/radioInterfaceResamp.cpp
deleted file mode 100644
index c7f17ea..0000000
--- a/Transceiver52M/radioInterfaceResamp.cpp
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Radio device interface with sample rate conversion
- * Written by Thomas Tsou <ttsou@vt.edu>
- *
- * Copyright 2011 Free Software Foundation, Inc.
- *
- * 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/>.
- * See the COPYING file in the main directory for details.
- */
-
-#include <radioInterface.h>
-#include <Logger.h>
-
-/* New chunk sizes for resampled rate */
-#ifdef INCHUNK
- #undef INCHUNK
-#endif
-#ifdef OUTCHUNK
- #undef OUTCHUNK
-#endif
-
-/* Resampling parameters */
-#define INRATE 65 * SAMPSPERSYM
-#define INHISTORY INRATE * 2
-#define INCHUNK INRATE * 9
-
-#define OUTRATE 96 * SAMPSPERSYM
-#define OUTHISTORY OUTRATE * 2
-#define OUTCHUNK OUTRATE * 9
-
-/* Resampler low pass filters */
-signalVector *tx_lpf = 0;
-signalVector *rx_lpf = 0;
-
-/* Resampler history */
-signalVector *tx_hist = 0;
-signalVector *rx_hist = 0;
-
-/* Resampler input buffer */
-signalVector *tx_vec = 0;
-signalVector *rx_vec = 0;
-
-/*
- * High rate (device facing) buffers
- *
- * Transmit side samples are pushed after each burst so accomodate
- * a resampled burst plus up to a chunk left over from the previous
- * resampling operation.
- *
- * Receive side samples always pulled with a fixed size.
- */
-short tx_buf[INCHUNK * 2 * 4];
-short rx_buf[OUTCHUNK * 2 * 2];
-
-/*
- * Utilities and Conversions
- *
- * Manipulate signal vectors dynamically for two reasons. For one,
- * it's simpler. And two, it doesn't make any reasonable difference
- * relative to the high overhead generated by the resampling.
- */
-
-/* Concatenate signal vectors. Deallocate input vectors. */
-signalVector *concat(signalVector *a, signalVector *b)
-{
- signalVector *vec = new signalVector(*a, *b);
- delete a;
- delete b;
-
- return vec;
-}
-
-/* Segment a signal vector. Deallocate the input vector. */
-signalVector *segment(signalVector *a, int indx, int sz)
-{
- signalVector *vec = new signalVector(sz);
- a->segmentCopyTo(*vec, indx, sz);
- delete a;
-
- return vec;
-}
-
-/* Create a new signal vector from a short array. */
-signalVector *short_to_sigvec(short *smpls, size_t sz)
-{
- int i;
- signalVector *vec = new signalVector(sz);
- signalVector::iterator itr = vec->begin();
-
- for (i = 0; i < sz; i++) {
- *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]);
- }
-
- return vec;
-}
-
-/* Convert and deallocate a signal vector into a short array. */
-int sigvec_to_short(signalVector *vec, short *smpls)
-{
- int i;
- signalVector::iterator itr = vec->begin();
-
- for (i = 0; i < vec->size(); i++) {
- smpls[2 * i + 0] = itr->real();
- smpls[2 * i + 1] = itr->imag();
- itr++;
- }
- delete vec;
-
- return i;
-}
-
-/* Create a new signal vector from a float array. */
-signalVector *float_to_sigvec(float *smpls, int sz)
-{
- int i;
- signalVector *vec = new signalVector(sz);
- signalVector::iterator itr = vec->begin();
-
- for (i = 0; i < sz; i++) {
- *itr++ = Complex<float>(smpls[2 * i + 0], smpls[2 * i + 1]);
- }
-
- return vec;
-}
-
-/* Convert and deallocate a signal vector into a float array. */
-int sigvec_to_float(signalVector *vec, float *smpls)
-{
- int i;
- signalVector::iterator itr = vec->begin();
-
- for (i = 0; i < vec->size(); i++) {
- smpls[2 * i + 0] = itr->real();
- smpls[2 * i + 1] = itr->imag();
- itr++;
- }
- delete vec;
-
- return i;
-}
-
-/* Initialize resampling signal vectors */
-void init_resampler(signalVector **lpf,
- signalVector **buf,
- signalVector **hist,
- int tx)
-{
- int P, Q, taps, hist_len;
- float cutoff_freq;
-
- if (tx) {
- LOG(INFO) << "Initializing Tx resampler";
- P = OUTRATE;
- Q = INRATE;
- taps = 651;
- hist_len = INHISTORY;
- } else {
- LOG(INFO) << "Initializing Rx resampler";
- P = INRATE;
- Q = OUTRATE;
- taps = 961;
- hist_len = OUTHISTORY;
- }
-
- if (!*lpf) {
- cutoff_freq = (P < Q) ? (1.0/(float) Q) : (1.0/(float) P);
- *lpf = createLPF(cutoff_freq, taps, P);
- }
-
- if (!*buf) {
- *buf = new signalVector();
- }
-
- if (!*hist);
- *hist = new signalVector(hist_len);
-}
-
-/* Resample a signal vector
- *
- * The input vector is deallocated and the pointer returned with a vector
- * of any unconverted samples.
- */
-signalVector *resmpl_sigvec(signalVector *hist, signalVector **vec,
- signalVector *lpf, double in_rate,
- double out_rate, int chunk_sz)
-{
- signalVector *resamp_vec;
- int num_chunks = (*vec)->size() / chunk_sz;
-
- /* Truncate to a chunk multiple */
- signalVector trunc_vec(num_chunks * chunk_sz);
- (*vec)->segmentCopyTo(trunc_vec, 0, num_chunks * chunk_sz);
-
- /* Update sample buffer with remainder */
- *vec = segment(*vec, trunc_vec.size(), (*vec)->size() - trunc_vec.size());
-
- /* Add history and resample */
- signalVector input_vec(*hist, trunc_vec);
- resamp_vec = polyphaseResampleVector(input_vec, in_rate,
- out_rate, lpf);
-
- /* Update history */
- trunc_vec.segmentCopyTo(*hist, trunc_vec.size() - hist->size(),
- hist->size());
- return resamp_vec;
-}
-
-/* Wrapper for receive-side integer-to-float array resampling */
- int rx_resmpl_int_flt(float *smpls_out, short *smpls_in, int num_smpls)
-{
- int num_resmpld, num_chunks;
- signalVector *convert_vec, *resamp_vec, *trunc_vec;
-
- if (!rx_lpf || !rx_vec || !rx_hist)
- init_resampler(&rx_lpf, &rx_vec, &rx_hist, false);
-
- /* Convert and add samples to the receive buffer */
- convert_vec = short_to_sigvec(smpls_in, num_smpls);
- rx_vec = concat(rx_vec, convert_vec);
-
- num_chunks = rx_vec->size() / OUTCHUNK;
- if (num_chunks < 1)
- return 0;
-
- /* Resample */
- resamp_vec = resmpl_sigvec(rx_hist, &rx_vec, rx_lpf,
- INRATE, OUTRATE, OUTCHUNK);
- /* Truncate */
- trunc_vec = segment(resamp_vec, INHISTORY,
- resamp_vec->size() - INHISTORY);
- /* Convert */
- num_resmpld = sigvec_to_float(trunc_vec, smpls_out);
-
- return num_resmpld;
-}
-
-/* Wrapper for transmit-side float-to-int array resampling */
-int tx_resmpl_flt_int(short *smpls_out, float *smpls_in, int num_smpls)
-{
- int num_resmpl, num_chunks;
- signalVector *convert_vec, *resamp_vec;
-
- if (!tx_lpf || !tx_vec || !tx_hist)
- init_resampler(&tx_lpf, &tx_vec, &tx_hist, true);
-
- /* Convert and add samples to the transmit buffer */
- convert_vec = float_to_sigvec(smpls_in, num_smpls);
- tx_vec = concat(tx_vec, convert_vec);
-
- num_chunks = tx_vec->size() / INCHUNK;
- if (num_chunks < 1)
- return 0;
-
- /* Resample and convert to an integer array */
- resamp_vec = resmpl_sigvec(tx_hist, &tx_vec, tx_lpf,
- OUTRATE, INRATE, INCHUNK);
- num_resmpl = sigvec_to_short(resamp_vec, smpls_out);
-
- return num_resmpl;
-}
-
-RadioInterfaceResamp::RadioInterfaceResamp(RadioDevice *wRadio,
- int wReceiveOffset,
- int wSPS,
- GSM::Time wStartTime)
- : RadioInterface(wRadio, wReceiveOffset, wSPS, wStartTime)
-{
-}
-
-/* Receive a timestamped chunk from the device */
-void RadioInterfaceResamp::pullBuffer()
-{
- int num_cv, num_rd;
- bool local_underrun;
-
- /* Read samples. Fail if we don't get what we want. */
- num_rd = mRadio->readSamples(rx_buf, OUTCHUNK, &overrun,
- readTimestamp, &local_underrun);
-
- LOG(DEBUG) << "Rx read " << num_rd << " samples from device";
- assert(num_rd == OUTCHUNK);
-
- underrun |= local_underrun;
- readTimestamp += (TIMESTAMP) num_rd;
-
- /* Convert and resample */
- num_cv = rx_resmpl_int_flt(rcvBuffer + 2 * rcvCursor,
- rx_buf, num_rd);
-
- LOG(DEBUG) << "Rx read " << num_cv << " samples from resampler";
-
- rcvCursor += num_cv;
-}
-
-/* Send a timestamped chunk to the device */
-void RadioInterfaceResamp::pushBuffer()
-{
- int num_cv, num_wr;
-
- if (sendCursor < INCHUNK)
- return;
-
- LOG(DEBUG) << "Tx wrote " << sendCursor << " samples to resampler";
-
- /* Resample and convert */
- num_cv = tx_resmpl_flt_int(tx_buf, sendBuffer, sendCursor);
- assert(num_cv > sendCursor);
-
- /* Write samples. Fail if we don't get what we want. */
- num_wr = mRadio->writeSamples(tx_buf + OUTHISTORY * 2,
- num_cv - OUTHISTORY,
- &underrun,
- writeTimestamp);
-
- LOG(DEBUG) << "Tx wrote " << num_wr << " samples to device";
- assert(num_wr == num_wr);
-
- writeTimestamp += (TIMESTAMP) num_wr;
- sendCursor = 0;
-}
diff --git a/Transceiver52M/runTransceiver.cpp b/Transceiver52M/runTransceiver.cpp
index acbea72..6a05100 100644
--- a/Transceiver52M/runTransceiver.cpp
+++ b/Transceiver52M/runTransceiver.cpp
@@ -109,8 +109,6 @@ int main(int argc, char *argv[])
radio = new RadioInterface(usrp, 3, SAMPSPERSYM, false);
break;
case RadioDevice::RESAMP:
- radio = new RadioInterfaceResamp(usrp, 3, SAMPSPERSYM, false);
- break;
default:
LOG(ALERT) << "Unsupported configuration";
return EXIT_FAILURE;